@lobehub/chat 1.12.4 → 1.12.6
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/.env.example +1 -1
- package/CHANGELOG.md +50 -0
- package/Dockerfile.database +1 -0
- package/docs/self-hosting/advanced/auth.mdx +8 -10
- package/docs/self-hosting/advanced/s3/cloudflare-r2.mdx +2 -2
- package/docs/self-hosting/advanced/s3/cloudflare-r2.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/s3.mdx +39 -0
- package/docs/self-hosting/advanced/s3.zh-CN.mdx +1 -1
- package/docs/self-hosting/server-database/docker.mdx +32 -22
- package/docs/self-hosting/server-database/docker.zh-CN.mdx +2 -2
- package/docs/self-hosting/server-database/vercel.mdx +4 -4
- package/docs/self-hosting/server-database/vercel.zh-CN.mdx +6 -6
- package/docs/self-hosting/server-database.mdx +10 -37
- package/locales/ar/error.json +4 -1
- package/locales/bg-BG/error.json +4 -1
- package/locales/de-DE/error.json +4 -1
- package/locales/en-US/error.json +4 -1
- package/locales/es-ES/error.json +4 -1
- package/locales/fr-FR/error.json +4 -1
- package/locales/it-IT/error.json +4 -1
- package/locales/ja-JP/error.json +4 -1
- package/locales/ko-KR/error.json +4 -1
- package/locales/nl-NL/error.json +4 -1
- package/locales/pl-PL/error.json +4 -1
- package/locales/pt-BR/error.json +4 -1
- package/locales/ru-RU/error.json +4 -1
- package/locales/tr-TR/error.json +4 -1
- package/locales/vi-VN/error.json +4 -1
- package/locales/zh-CN/error.json +4 -1
- package/locales/zh-TW/error.json +4 -1
- package/package.json +2 -2
- package/src/components/DragUpload/useDragUpload.test.tsx +130 -0
- package/src/components/DragUpload/useDragUpload.tsx +9 -0
- package/src/config/file.ts +16 -1
- package/src/locales/default/error.ts +3 -0
- package/src/server/modules/S3/index.ts +1 -0
- package/src/server/routers/lambda/file.ts +1 -3
- package/src/server/utils/files.ts +1 -1
- package/src/services/file/server.ts +4 -0
- package/src/services/upload.ts +6 -2
- package/src/store/file/slices/chat/action.ts +27 -4
package/.env.example
CHANGED
|
@@ -150,7 +150,7 @@ OPENAI_API_KEY=sk-xxxxxxxxx
|
|
|
150
150
|
#S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
151
151
|
|
|
152
152
|
# Public access domain for the bucket
|
|
153
|
-
#
|
|
153
|
+
#S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
154
154
|
|
|
155
155
|
# Bucket region, such as us-west-1, generally not needed to add
|
|
156
156
|
# but some service providers may require configuration
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.12.6](https://github.com/lobehub/lobe-chat/compare/v1.12.5...v1.12.6)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-08-22**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor s3 env and support path-style for minio.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Code refactoring
|
|
19
|
+
|
|
20
|
+
- **misc**: Refactor s3 env and support path-style for minio, closes [#3559](https://github.com/lobehub/lobe-chat/issues/3559) ([1658403](https://github.com/lobehub/lobe-chat/commit/1658403))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 1.12.5](https://github.com/lobehub/lobe-chat/compare/v1.12.4...v1.12.5)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2024-08-22**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: Fix clipboard copy issue and improve upload cors feedback.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: Fix clipboard copy issue and improve upload cors feedback, closes [#3557](https://github.com/lobehub/lobe-chat/issues/3557) ([86c5a99](https://github.com/lobehub/lobe-chat/commit/86c5a99))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
### [Version 1.12.4](https://github.com/lobehub/lobe-chat/compare/v1.12.3...v1.12.4)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2024-08-22**</sup>
|
package/Dockerfile.database
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: LobeChat
|
|
3
|
-
description:
|
|
4
|
-
Learn about LobeChat's support for configuring external identity verification
|
|
5
|
-
services for centralized user authorization within enterprises/organizations.
|
|
6
|
-
Explore supported services like Auth0, Microsoft Entra ID, Authentik, Github,
|
|
7
|
-
and ZITADEL.
|
|
2
|
+
title: LobeChat Authentication Service Configuration
|
|
3
|
+
description: Learn how to configure external authentication services using Clerk or Next Auth for centralized user authorization management. Supported authentication services include Auth0, Azure ID, etc.
|
|
8
4
|
tags:
|
|
9
|
-
-
|
|
5
|
+
- Authentication Service
|
|
10
6
|
- Next Auth
|
|
7
|
+
- SSO
|
|
11
8
|
- Clerk
|
|
12
9
|
---
|
|
13
10
|
|
|
14
|
-
#
|
|
11
|
+
# Authentication Service
|
|
15
12
|
|
|
16
|
-
LobeChat supports the configuration of external
|
|
13
|
+
LobeChat supports the configuration of external authentication services using Clerk or Next Auth for internal use within enterprises/organizations to centrally manage user authorization.
|
|
17
14
|
|
|
18
15
|
## Clerk
|
|
19
16
|
|
|
@@ -21,7 +18,7 @@ Clerk is a comprehensive identity verification solution that has recently gained
|
|
|
21
18
|
|
|
22
19
|
LobeChat has deeply integrated with Clerk to provide users with a more secure and convenient login and registration experience. It also relieves developers from the burden of managing authentication logic. Clerk's concise and modern design philosophy aligns perfectly with LobeChat's goals, making user management on the entire platform more efficient and reliable.
|
|
23
20
|
|
|
24
|
-
By setting the environment variables NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY in LobeChat's environment, you can enable and use Clerk.
|
|
21
|
+
By setting the environment variables `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` in LobeChat's environment, you can enable and use Clerk.
|
|
25
22
|
|
|
26
23
|
## Next Auth
|
|
27
24
|
|
|
@@ -45,6 +42,7 @@ Currently supported identity verification services include:
|
|
|
45
42
|
<Card href={'/docs/self-hosting/advanced/sso-providers/github'} title={'Github'} />
|
|
46
43
|
<Card href={'/docs/self-hosting/advanced/sso-providers/zitadel'} title={'ZITADEL'} />
|
|
47
44
|
</Cards>
|
|
45
|
+
|
|
48
46
|
Click on the links to view the corresponding platform's configuration documentation.
|
|
49
47
|
|
|
50
48
|
## Advanced Configuration
|
|
@@ -48,7 +48,7 @@ S3_BUCKET=lobechat
|
|
|
48
48
|
# Request endpoint of the bucket (note that the path in this link includes the bucket name, which must be removed, or use the link provided on the page for applying S3 API token)
|
|
49
49
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
50
50
|
# Access domain of the bucket
|
|
51
|
-
|
|
51
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
<Callout type={'warning'}>`S3_ENDPOINT` must have its path removed, otherwise uploaded files cannot be accessed.</Callout>
|
|
@@ -138,7 +138,7 @@ S3_BUCKET=lobechat
|
|
|
138
138
|
# Bucket Request Endpoint
|
|
139
139
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
140
140
|
# Public Access Domain for the Bucket
|
|
141
|
-
|
|
141
|
+
S3_PUBLIC_DOMAIN=https://s3-dev.your-domain.com
|
|
142
142
|
|
|
143
143
|
# Bucket Region, such as us-west-1. Generally not required, but some service providers may need it.
|
|
144
144
|
# S3_REGION=us-west-1
|
|
@@ -49,7 +49,7 @@ S3_BUCKET=lobechat
|
|
|
49
49
|
# 存储桶的请求端点(注意此处链接的路径带存储桶名称,必须删除该路径,或使用申请 S3 API token 页面所提供的链接)
|
|
50
50
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
51
51
|
# 存储桶对外的访问域名
|
|
52
|
-
|
|
52
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
<Callout type={'warning'}>`S3_ENDPOINT`必须删除其路径,否则会无法访问所上传文件</Callout>
|
|
@@ -139,7 +139,7 @@ S3_BUCKET=lobechat
|
|
|
139
139
|
# 存储桶的请求端点
|
|
140
140
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
141
141
|
# 存储桶对外的访问域名
|
|
142
|
-
|
|
142
|
+
S3_PUBLIC_DOMAIN=https://s3-dev.your-domain.com
|
|
143
143
|
|
|
144
144
|
# 桶的区域,如 us-west-1,一般来说不需要添加,但某些服务商则需要配置
|
|
145
145
|
# S3_REGION=us-west-1
|
|
@@ -18,6 +18,45 @@ The best practice in this area is to use a file storage service (S3) to store im
|
|
|
18
18
|
In this documentation, S3 refers to a compatible S3 storage solution, which supports the Amazon S3 API for object storage systems. Common examples include Cloudflare R2, Alibaba Cloud OSS, and self-deployable Minio, all of which support the S3 compatible API.
|
|
19
19
|
</Callout>
|
|
20
20
|
|
|
21
|
+
## Core Environment Variables
|
|
22
|
+
|
|
23
|
+
<Steps>
|
|
24
|
+
### `S3_ACCESS_KEY_ID` and `S3_SECRET_ACCESS_KEY`
|
|
25
|
+
|
|
26
|
+
These are the two keys required by all S3 compatible storage services to access the S3 storage service, not detailed here.
|
|
27
|
+
|
|
28
|
+
### `S3_ENDPOINT`
|
|
29
|
+
|
|
30
|
+
The request endpoint of the storage bucket. Note that this link should not contain the name of the storage bucket.
|
|
31
|
+
|
|
32
|
+
<Callout type={'warning'}>`S3_ENDPOINT` must remove the suffix path, otherwise the uploaded files will not be accessible</Callout>
|
|
33
|
+
|
|
34
|
+
For example, for Cloudflare:
|
|
35
|
+
|
|
36
|
+
```shell
|
|
37
|
+
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `S3_BUCKET` and `S3_REGION`
|
|
41
|
+
|
|
42
|
+
The name and region of the storage bucket. `S3_BUCKET` is required to specify the name of the storage bucket. `S3_REGION` is optional and is used to specify the region of the storage bucket. Generally, it does not need to be added, but some service providers may require configuration.
|
|
43
|
+
|
|
44
|
+
### `S3_SET_ACL`
|
|
45
|
+
|
|
46
|
+
Whether to set the ACL to `public-read` when uploading files. This option is enabled by default. If the service provider does not support setting individual ACLs for files (i.e., all files inherit the ACL of the storage bucket), enabling this option may cause request errors. Set `S3_SET_ACL` to `0` to disable it.
|
|
47
|
+
|
|
48
|
+
### `S3_PUBLIC_DOMAIN`
|
|
49
|
+
|
|
50
|
+
The public access domain of the storage bucket, used to access files in the storage bucket. This address needs to be **publicly readable**. The reason is that when OpenAI's gpt-4o and other vision models recognize images, OpenAI will try to download this image link on their servers. Therefore, this link must be publicly accessible. If it is a private link, OpenAI will not be able to access the image and thus will not be able to recognize the image content properly.
|
|
51
|
+
|
|
52
|
+
<Callout type={'warning'}>
|
|
53
|
+
Additionally, since this access domain is often a separate URL, it needs to be configured to allow cross-origin access to the site. Otherwise, cross-origin issues will occur in the browser.
|
|
54
|
+
</Callout>
|
|
55
|
+
|
|
56
|
+
</Steps>
|
|
57
|
+
|
|
58
|
+
## S3 Configuration Guide
|
|
59
|
+
|
|
21
60
|
Currently, the S3 configuration tutorials included in the documentation are:
|
|
22
61
|
|
|
23
62
|
<Cards>
|
|
@@ -46,7 +46,7 @@ S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
|
46
46
|
|
|
47
47
|
是否在上传文件时设置 ACL 为 `public-read`。该选项默认启用。如果服务商不支持为文件设置单独的 ACL(即所有文件继承存储桶的 ACL),启用此选项可能会导致请求错误,将 `S3_SET_ACL` 设置为 `0` 即可关闭。
|
|
48
48
|
|
|
49
|
-
### `
|
|
49
|
+
### `S3_PUBLIC_DOMAIN`
|
|
50
50
|
|
|
51
51
|
存储桶对外的访问域名,用于访问存储桶中的文件,这个地址需要**允许互联网可读**。 原因是 OpenAI 的 gpt-4o 等视觉模型识别图片时,OpenAI 会尝试在他们的服务器中下载这个图片链接,因此这个链接必须是公开可访问的,如果是私有的链接,OpenAI 将无法访问到这个图片,进而无法正常识别到图片内容。
|
|
52
52
|
|
|
@@ -32,26 +32,35 @@ Here is the process for deploying the LobeChat server database version on a Linu
|
|
|
32
32
|
|
|
33
33
|
### Create a Postgres Database Instance
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Please create a Postgres database instance with the PGVector plugin according to your needs, for example:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
|
-
docker
|
|
38
|
+
docker network create pg
|
|
39
|
+
|
|
40
|
+
docker run --name my-postgres --network pg -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d pgvector/pgvector:pg16
|
|
39
41
|
```
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
The above command will create a PG instance named `my-postgres` on the network `pg`, where `pgvector/pgvector:pg16` is a Postgres 16 image with the pgvector plugin installed by default.
|
|
44
|
+
|
|
45
|
+
<Callout type="info">
|
|
46
|
+
The pgvector plugin provides vector search capabilities for Postgres, which is an important component for LobeChat to implement RAG.
|
|
43
47
|
</Callout>
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
<Callout type="warning">
|
|
50
|
+
The above command does not specify a persistent storage location for the pg instance, so it is only for testing/demonstration purposes. Please configure persistent storage for production environments.
|
|
51
|
+
</Callout>
|
|
46
52
|
|
|
47
53
|
### Create a file named `lobe-chat.env` to store environment variables:
|
|
48
54
|
|
|
49
55
|
```shell
|
|
50
|
-
#
|
|
56
|
+
# Website domain
|
|
57
|
+
APP_URL=https://your-prod-domain.com
|
|
58
|
+
|
|
59
|
+
# DB required environment variables
|
|
51
60
|
KEY_VAULTS_SECRET=jgwsK28dspyVQoIf8/M3IIHl1h6LYYceSYNXeLpy6uk=
|
|
52
61
|
DATABASE_URL=postgres://postgres:mysecretpassword@my-postgres:5432/postgres
|
|
53
62
|
|
|
54
|
-
# NEXT_AUTH related
|
|
63
|
+
# NEXT_AUTH related, can use auth0, Azure AD, GitHub, Authentik, zitadel, etc. If you have other access requirements, feel free to submit a PR
|
|
55
64
|
NEXT_AUTH_SECRET=3904039cd41ea1bdf6c93db0db96e250
|
|
56
65
|
NEXT_AUTH_SSO_PROVIDERS=auth0
|
|
57
66
|
NEXTAUTH_URL=https://your-prod-domain.com/api/auth
|
|
@@ -64,7 +73,7 @@ S3_ACCESS_KEY_ID=xxxxxxxxxx
|
|
|
64
73
|
S3_SECRET_ACCESS_KEY=xxxxxxxxxx
|
|
65
74
|
S3_ENDPOINT=https://xxxxxxxxxx.r2.cloudflarestorage.com
|
|
66
75
|
S3_BUCKET=lobechat
|
|
67
|
-
|
|
76
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
68
77
|
```
|
|
69
78
|
|
|
70
79
|
### Start the lobe-chat-database Docker image
|
|
@@ -103,20 +112,21 @@ The script command you need to execute is:
|
|
|
103
112
|
|
|
104
113
|
```shell
|
|
105
114
|
$ docker run -it -d --name lobe-chat-database -p 3210:3210 \
|
|
106
|
-
-e DATABASE_URL=postgres://postgres:mysecretpassword@host.docker.internal:5432/postgres \
|
|
107
|
-
-e KEY_VAULTS_SECRET=jgwsK28dspyVQoIf8/M3IIHl1h6LYYceSYNXeLpy6uk= \
|
|
108
|
-
-e NEXT_AUTH_SECRET=3904039cd41ea1bdf6c93db0db96e250 \
|
|
109
|
-
-e NEXT_AUTH_SSO_PROVIDERS=auth0 \
|
|
110
|
-
-e AUTH0_CLIENT_ID=xxxxxx \
|
|
111
|
-
-e AUTH0_CLIENT_SECRET=cSX_xxxxx \
|
|
112
|
-
-e AUTH0_ISSUER=https://lobe-chat-demo.us.auth0.com \
|
|
113
|
-
-e
|
|
114
|
-
-e
|
|
115
|
-
-e
|
|
116
|
-
-e
|
|
117
|
-
-e
|
|
118
|
-
-e
|
|
119
|
-
|
|
115
|
+
-e DATABASE_URL=postgres://postgres:mysecretpassword@host.docker.internal:5432/postgres \
|
|
116
|
+
-e KEY_VAULTS_SECRET=jgwsK28dspyVQoIf8/M3IIHl1h6LYYceSYNXeLpy6uk= \
|
|
117
|
+
-e NEXT_AUTH_SECRET=3904039cd41ea1bdf6c93db0db96e250 \
|
|
118
|
+
-e NEXT_AUTH_SSO_PROVIDERS=auth0 \
|
|
119
|
+
-e AUTH0_CLIENT_ID=xxxxxx \
|
|
120
|
+
-e AUTH0_CLIENT_SECRET=cSX_xxxxx \
|
|
121
|
+
-e AUTH0_ISSUER=https://lobe-chat-demo.us.auth0.com \
|
|
122
|
+
-e APP_URL=http://localhost:3210 \
|
|
123
|
+
-e NEXTAUTH_URL=http://localhost:3210/api/auth \
|
|
124
|
+
-e S3_ACCESS_KEY_ID=xxxxxxxxxx \
|
|
125
|
+
-e S3_SECRET_ACCESS_KEY=xxxxxxxxxx \
|
|
126
|
+
-e S3_ENDPOINT=https://xxxxxxxxxx.r2.cloudflarestorage.com \
|
|
127
|
+
-e S3_BUCKET=lobechat \
|
|
128
|
+
-e S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com \
|
|
129
|
+
lobehub/lobe-chat-database
|
|
120
130
|
```
|
|
121
131
|
|
|
122
132
|
<Callout type="tip">
|
|
@@ -75,7 +75,7 @@ S3_ACCESS_KEY_ID=xxxxxxxxxx
|
|
|
75
75
|
S3_SECRET_ACCESS_KEY=xxxxxxxxxx
|
|
76
76
|
S3_ENDPOINT=https://xxxxxxxxxx.r2.cloudflarestorage.com
|
|
77
77
|
S3_BUCKET=lobechat
|
|
78
|
-
|
|
78
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
### 启动 lobe-chat-database docker 镜像
|
|
@@ -130,7 +130,7 @@ $ docker run -it -d --name lobe-chat-database -p 3210:3210 \
|
|
|
130
130
|
-e S3_SECRET_ACCESS_KEY=xxxxxxxxxx \
|
|
131
131
|
-e S3_ENDPOINT=https://xxxxxxxxxx.r2.cloudflarestorage.com \
|
|
132
132
|
-e S3_BUCKET=lobechat \
|
|
133
|
-
-e
|
|
133
|
+
-e S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com \
|
|
134
134
|
lobehub/lobe-chat-database
|
|
135
135
|
```
|
|
136
136
|
|
|
@@ -250,7 +250,7 @@ S3_BUCKET=lobechat
|
|
|
250
250
|
# Storage bucket request endpoint (note that the path in this link includes the bucket name, which must be removed, or use the link provided on the S3 API token application page)
|
|
251
251
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
252
252
|
# Public access domain for the storage bucket
|
|
253
|
-
|
|
253
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
254
254
|
```
|
|
255
255
|
|
|
256
256
|
<Callout type={'warning'}>
|
|
@@ -312,7 +312,7 @@ S3_BUCKET=lobechat
|
|
|
312
312
|
# Bucket request endpoint
|
|
313
313
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
314
314
|
# Public domain for bucket access
|
|
315
|
-
|
|
315
|
+
S3_PUBLIC_DOMAIN=https://s3-dev.your-domain.com
|
|
316
316
|
|
|
317
317
|
# Bucket region, such as us-west-1, generally not required, but some providers may need to configure
|
|
318
318
|
# S3_REGION=us-west-1
|
|
@@ -384,7 +384,7 @@ src={'https://github.com/lobehub/lobe-chat/assets/28616219/da84edc3-46f7-4e2b-a0
|
|
|
384
384
|
<Image
|
|
385
385
|
alt={'Login successful state'}
|
|
386
386
|
src={'https://github.com/lobehub/lobe-chat/assets/28616219/9cb5150d-6e1e-4c59-9a18-4e418dce1a5d'}/>
|
|
387
|
-
|
|
387
|
+
|
|
388
388
|
</Steps>
|
|
389
389
|
|
|
390
390
|
## Appendix
|
|
@@ -416,7 +416,7 @@ S3_BUCKET=lobechat
|
|
|
416
416
|
# Bucket request endpoint
|
|
417
417
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
418
418
|
# Public access domain for the bucket
|
|
419
|
-
|
|
419
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
420
420
|
# Bucket region, such as us-west-1, generally not needed to add, but some service providers may require configuration
|
|
421
421
|
# S3_REGION=us-west-1
|
|
422
422
|
```
|
|
@@ -18,8 +18,8 @@ tags:
|
|
|
18
18
|
|
|
19
19
|
<Callout type={'warning'}>
|
|
20
20
|
进行后续操作前,请务必确认以下事项:
|
|
21
|
-
- 导出所有数据,部署服务端数据库后,原有用户数据无法自动迁移,只能提前备份后进行手动导入!
|
|
22
|
-
- 环境变量中的`ACCESS_CODE`未设置或已清除!
|
|
21
|
+
- 导出所有数据,部署服务端数据库后,原有用户数据无法自动迁移,只能提前备份后进行手动导入!
|
|
22
|
+
- 环境变量中的`ACCESS_CODE`未设置或已清除!
|
|
23
23
|
- 配置服务端数据库所需要的环境变量时,需全部填入后再进行部署,否则可能遭遇数据库迁移问题!
|
|
24
24
|
</Callout>
|
|
25
25
|
|
|
@@ -46,7 +46,7 @@ tags:
|
|
|
46
46
|
|
|
47
47
|
<Callout type={'warning'}>
|
|
48
48
|
请确认您的供应商所提供的 `Postgres` 类型,若为 `Node Postgres`,请切换到 `Node Postgres` Tab 。
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
</Callout>
|
|
51
51
|
|
|
52
52
|
Serverless Postgres 需要填写的变量如下:
|
|
@@ -233,7 +233,7 @@ S3_BUCKET=lobechat
|
|
|
233
233
|
# 存储桶的请求端点(注意此处链接的路径带存储桶名称,必须删除该路径,或使用申请 S3 API token 页面所提供的链接)
|
|
234
234
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
235
235
|
# 存储桶对外的访问域名
|
|
236
|
-
|
|
236
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
237
237
|
```
|
|
238
238
|
|
|
239
239
|
<Callout type={'warning'}>`S3_ENDPOINT`必须删除其路径,否则会无法访问所上传文件</Callout>
|
|
@@ -291,7 +291,7 @@ S3_BUCKET=lobechat
|
|
|
291
291
|
# 存储桶的请求端点
|
|
292
292
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
293
293
|
# 存储桶对外的访问域名
|
|
294
|
-
|
|
294
|
+
S3_PUBLIC_DOMAIN=https://s3-dev.your-domain.com
|
|
295
295
|
|
|
296
296
|
# 桶的区域,如 us-west-1,一般来说不需要添加,但某些服务商则需要配置
|
|
297
297
|
# S3_REGION=us-west-1
|
|
@@ -397,7 +397,7 @@ S3_BUCKET=lobechat
|
|
|
397
397
|
# 存储桶的请求端点
|
|
398
398
|
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
399
399
|
# 存储桶对外的访问域名
|
|
400
|
-
|
|
400
|
+
S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
|
|
401
401
|
# 桶的区域,如 us-west-1,一般来说不需要添加,但某些服务商则需要配置
|
|
402
402
|
# S3_REGION=us-west-1
|
|
403
403
|
```
|
|
@@ -36,7 +36,9 @@ Before deployment, make sure you have a Postgres database instance ready. You ca
|
|
|
36
36
|
- `A.` Use Serverless Postgres instances like Vercel/Neon;
|
|
37
37
|
- `B.` Use self-deployed Postgres instances like Docker/Railway/Zeabur, collectively referred to as Node Postgres instances;
|
|
38
38
|
|
|
39
|
-
There is a slight difference in the way they are configured in terms of environment variables
|
|
39
|
+
<Callout>There is a slight difference in the way they are configured in terms of environment variables.</Callout>
|
|
40
|
+
|
|
41
|
+
Since we support file-based conversations/knowledge base conversations, we need to install the `pgvector` plugin for Postgres. This plugin provides vector search capabilities and is a key component for LobeChat to implement RAG.
|
|
40
42
|
|
|
41
43
|
<Steps>
|
|
42
44
|
### `NEXT_PUBLIC_SERVICE_MODE`
|
|
@@ -49,6 +51,12 @@ For server-side database deployment scenarios, you need to set `NEXT_PUBLIC_SERV
|
|
|
49
51
|
In the official `lobe-chat-database` Docker image, this environment variable is already set to `server` by default. Therefore, if you deploy using the Docker image, you do not need to configure this environment variable again.
|
|
50
52
|
</Callout>
|
|
51
53
|
|
|
54
|
+
<Callout type={'tip'}>
|
|
55
|
+
Since environment variables starting with `NEXT_PUBLIC` take effect in the front-end code, they cannot be modified through container runtime injection. (Refer to the `next.js` documentation [Configuring: Environment Variables | Next.js (nextjs.org)](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables)). This is why we chose to create a separate DB version image.
|
|
56
|
+
|
|
57
|
+
If you need to modify variables with the `NEXT_PUBLIC` prefix in a Docker deployment, you must build the image yourself and inject your own `NEXT_PUBLIC` prefixed environment variables during the build.
|
|
58
|
+
</Callout>
|
|
59
|
+
|
|
52
60
|
### `DATABASE_URL`
|
|
53
61
|
|
|
54
62
|
The core of configuring the database is to add the `DATABASE_URL` environment variable and fill in the Postgres database connection URL you have prepared. The typical format of the database connection URL is `postgres://username:password@host:port/database`.
|
|
@@ -87,7 +95,7 @@ In the server-side database mode, we need an authentication service to distingui
|
|
|
87
95
|
|
|
88
96
|
### Clerk
|
|
89
97
|
|
|
90
|
-
[Clerk](https://clerk.com?utm_source=lobehub
|
|
98
|
+
[Clerk](https://clerk.com?utm_source=lobehub&utm_medium=docs) is an authentication SaaS service that provides out-of-the-box authentication capabilities with high productization, low integration costs, and a great user experience. For those who offer SaaS products, Clerk is a good choice. Our official [LobeChat Cloud](https://lobechat.com) uses Clerk as the authentication service.
|
|
91
99
|
|
|
92
100
|
The integration of Clerk is relatively simple, requiring only the configuration of the `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY`, `CLERK_SECRET_KEY`, and `CLERK_WEBHOOK_SECRET` environment variables, which can be obtained from the Clerk console.
|
|
93
101
|
|
|
@@ -123,40 +131,6 @@ The best practice in this area is to use a file storage service (S3) to store im
|
|
|
123
131
|
In this documentation, S3 refers to a compatible S3 storage solution, which supports the Amazon S3 API-compatible object storage system. Common examples include Cloudflare R2, Alibaba Cloud OSS, and self-deployable Minio, all of which support the S3-compatible API.
|
|
124
132
|
</Callout>
|
|
125
133
|
|
|
126
|
-
<Steps>
|
|
127
|
-
### `S3_ACCESS_KEY_ID` and `S3_SECRET_ACCESS_KEY`
|
|
128
|
-
|
|
129
|
-
These are the two keys required by all S3-compatible storage services to access the S3 storage service, without going into detail.
|
|
130
|
-
|
|
131
|
-
### `S3_ENDPOINT`
|
|
132
|
-
|
|
133
|
-
The request endpoint of the bucket, note that the link here should not include the bucket's name.
|
|
134
|
-
|
|
135
|
-
<Callout type={'warning'}>`S3_ENDPOINT` must remove the suffix path, otherwise the uploaded files will not be accessible.</Callout>
|
|
136
|
-
|
|
137
|
-
For example, for Cloudflare:
|
|
138
|
-
|
|
139
|
-
```shell
|
|
140
|
-
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### `S3_BUCKET` and `S3_REGION`
|
|
144
|
-
|
|
145
|
-
The name and region of the bucket. `S3_BUCKET` is mandatory for specifying the bucket's name. `S3_REGION` is optional for specifying the bucket's region, generally not required to add, but some service providers may need to configure it.
|
|
146
|
-
|
|
147
|
-
### `S3_SET_ACL`
|
|
148
|
-
Whether to set the ACL to `public-read` when uploading files. This option is enabled by default. If the service provider does not support setting individual ACLs for files (i.e., all files inherit the bucket's ACL), enabling this option may result in a request error. You can disable it by setting `S3_SET_ACL` to `0`.
|
|
149
|
-
|
|
150
|
-
### `NEXT_PUBLIC_S3_DOMAIN`
|
|
151
|
-
|
|
152
|
-
The public access domain of the bucket, used to access files in the bucket. This address needs to be **internet-readable**. The reason is that when OpenAI's GPT-4o and other visual models recognize images, OpenAI will try to download the image link on their servers. Therefore, this link must be publicly accessible. If it is a private link, OpenAI will not be able to access the image and will not be able to recognize the image content properly.
|
|
153
|
-
|
|
154
|
-
<Callout type={'warning'}>
|
|
155
|
-
In addition, since this access domain is often an independent URL, it needs to be configured to allow cross-origin access to the site, otherwise cross-origin issues will occur in the browser.
|
|
156
|
-
</Callout>
|
|
157
|
-
|
|
158
|
-
</Steps>
|
|
159
|
-
|
|
160
134
|
For detailed configuration guidelines on S3, please refer to [S3 Object Storage](/en/docs/self-hosting/advanced/s3) for more information.
|
|
161
135
|
|
|
162
136
|
## Getting Started with Deployment
|
|
@@ -164,4 +138,3 @@ For detailed configuration guidelines on S3, please refer to [S3 Object Storage]
|
|
|
164
138
|
The above is a detailed explanation of configuring LobeChat with a server-side database. You can configure it according to your actual situation and then choose a deployment platform that suits you to start deployment:
|
|
165
139
|
|
|
166
140
|
<PlatformCards urlPrefix={'server-database'} />
|
|
167
|
-
|
package/locales/ar/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "التفاصيل: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "وضع النشر الحالي لا يدعم تحميل ملفات غير الصور. إذا كنت بحاجة إلى تحميل تنسيق {{ext}}، يرجى التبديل إلى نشر قاعدة بيانات الخادم أو استخدام خدمة LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "يرجى التأكد من أن اتصال الشبكة لديك يعمل بشكل صحيح، والتحقق من إعدادات تكوين خدمة تخزين الملفات عبر النطاق.",
|
|
120
|
+
"title": "فشل تحميل الملف، يرجى التحقق من الاتصال بالشبكة أو المحاولة لاحقًا",
|
|
121
|
+
"unknownError": "سبب الخطأ: {{reason}}",
|
|
122
|
+
"uploadFailed": "فشل تحميل الملف"
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/bg-BG/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Подробности: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "Текущият режим на разполагане не поддържа качване на файлове, различни от изображения. За да качите формат {{ext}}, моля, превключете на разполагане с база данни на сървъра или използвайте услугата LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Моля, уверете се, че вашата мрежа работи нормално и проверете дали конфигурацията за крос-домейн на услугата за съхранение на файлове е правилна.",
|
|
120
|
+
"title": "Неуспешно качване на файл, моля проверете интернет връзката или опитайте по-късно",
|
|
121
|
+
"unknownError": "Причина за грешка: {{reason}}",
|
|
122
|
+
"uploadFailed": "Неуспешно качване на файла."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/de-DE/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Details: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "Der aktuelle Bereitstellungsmodus unterstützt das Hochladen von Nicht-Bilddateien nicht. Um Dateien im {{ext}}-Format hochzuladen, wechseln Sie bitte zum Serverdatenbank-Bereitstellungsmodus oder verwenden Sie den LobeChat Cloud-Dienst.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Bitte überprüfen Sie, ob Ihre Internetverbindung stabil ist, und prüfen Sie die Cross-Origin-Konfiguration des Dateispeicherdienstes.",
|
|
120
|
+
"title": "Dateiupload fehlgeschlagen. Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es später erneut.",
|
|
121
|
+
"unknownError": "Fehlerursache: {{reason}}",
|
|
122
|
+
"uploadFailed": "Der Datei-Upload ist fehlgeschlagen."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/en-US/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Details: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "The current deployment mode does not support uploading non-image files. To upload files in {{ext}} format, please switch to server database deployment or use LobeChat Cloud service.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Please check your network connection and ensure that the file storage service's cross-origin configuration is correct.",
|
|
120
|
+
"title": "File upload failed. Please check your network connection or try again later",
|
|
121
|
+
"unknownError": "Error reason: {{reason}}",
|
|
122
|
+
"uploadFailed": "File upload failed."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/es-ES/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Detalles: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "El modo de implementación actual no admite la carga de archivos que no sean imágenes. Si desea cargar un archivo en formato {{ext}}, cambie a la implementación de base de datos en servidor o utilice el servicio LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Por favor, verifica que tu red esté funcionando correctamente y comprueba si la configuración de CORS del servicio de almacenamiento de archivos es correcta.",
|
|
120
|
+
"title": "Error al subir el archivo, por favor verifica la conexión a internet o inténtalo de nuevo más tarde",
|
|
121
|
+
"unknownError": "Razón del error: {{reason}}",
|
|
122
|
+
"uploadFailed": "La carga del archivo ha fallado."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/fr-FR/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Détails : {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "Le mode de déploiement actuel ne prend pas en charge le téléchargement de fichiers non image. Pour télécharger un format {{ext}}, veuillez passer à un déploiement de base de données côté serveur ou utiliser le service LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Veuillez vérifier si votre réseau fonctionne correctement et assurez-vous que la configuration CORS du service de stockage de fichiers est correcte.",
|
|
120
|
+
"title": "Échec de l'envoi du fichier, veuillez vérifier votre connexion réseau ou réessayer plus tard",
|
|
121
|
+
"unknownError": "Raison de l'erreur : {{reason}}",
|
|
122
|
+
"uploadFailed": "Échec du téléchargement du fichier."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/it-IT/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Dettagli: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "L'attuale modalità di distribuzione non supporta il caricamento di file non immagine. Se desideri caricare un formato {{ext}}, ti preghiamo di passare alla distribuzione del database sul server o di utilizzare il servizio LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Si prega di verificare che la connessione di rete sia stabile e controllare se la configurazione CORS del servizio di archiviazione file è corretta.",
|
|
120
|
+
"title": "Caricamento del file fallito, controlla la connessione di rete o riprova più tardi",
|
|
121
|
+
"unknownError": "Motivo dell'errore: {{reason}}",
|
|
122
|
+
"uploadFailed": "Caricamento del file non riuscito."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/ja-JP/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "詳細: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "現在のデプロイモードでは、画像以外のファイルのアップロードはサポートされていません。{{ext}} 形式のファイルをアップロードするには、サーバーデータベースデプロイに切り替えるか、LobeChat Cloud サービスを使用してください。",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "ネットワークが正常であることを確認し、ファイルストレージサービスのクロスオリジン設定が正しいかどうかを確認してください。",
|
|
120
|
+
"title": "ファイルのアップロードに失敗しました。ネットワーク接続を確認するか、後でもう一度お試しください",
|
|
121
|
+
"unknownError": "エラーの原因: {{reason}}",
|
|
122
|
+
"uploadFailed": "ファイルのアップロードに失敗しました。"
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/ko-KR/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "상세 내용: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "현재 배포 모드에서는 이미지 파일이 아닌 파일 업로드를 지원하지 않습니다. {{ext}} 형식을 업로드하려면 서버 데이터베이스 배포로 전환하거나 LobeChat Cloud 서비스를 사용하세요.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "네트워크가 정상인지 확인하고 파일 저장 서비스의 교차 출처 구성도 올바른지 확인하세요.",
|
|
120
|
+
"title": "파일 업로드 실패, 네트워크 연결을 확인하거나 나중에 다시 시도해주세요",
|
|
121
|
+
"unknownError": "오류 원인: {{reason}}",
|
|
122
|
+
"uploadFailed": "파일 업로드에 실패했습니다."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/nl-NL/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Details: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "De huidige implementatiemodus ondersteunt het uploaden van niet-afbeeldingsbestanden niet. Als u bestanden in {{ext}}-formaat wilt uploaden, schakelt u over naar de serverdatabase-implementatie of gebruikt u de LobeChat Cloud-service.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Controleer of je netwerk goed werkt en of de cross-origin configuratie van de bestandsopslagservice correct is.",
|
|
120
|
+
"title": "Bestand uploaden mislukt, controleer uw internetverbinding of probeer het later opnieuw",
|
|
121
|
+
"unknownError": "Foutreden: {{reason}}",
|
|
122
|
+
"uploadFailed": "Bestand uploaden is mislukt."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/pl-PL/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Szczegóły: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "Aktualny tryb wdrożenia nie obsługuje przesyłania plików, które nie są obrazami. Aby przesłać pliki w formacie {{ext}}, przełącz się na wdrożenie bazy danych na serwerze lub skorzystaj z usługi LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Proszę upewnić się, że Twoja sieć działa poprawnie oraz sprawdzić, czy konfiguracja CORS dla usługi przechowywania plików jest prawidłowa.",
|
|
120
|
+
"title": "Nie udało się przesłać pliku. Sprawdź połączenie sieciowe lub spróbuj ponownie później",
|
|
121
|
+
"unknownError": "Przyczyna błędu: {{reason}}",
|
|
122
|
+
"uploadFailed": "Wysyłanie pliku nie powiodło się."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/pt-BR/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Detalhes: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "O modo de implantação atual não suporta o upload de arquivos que não sejam imagens. Para fazer o upload de arquivos no formato {{ext}}, por favor, mude para a implantação do banco de dados no servidor ou utilize o serviço LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Por favor, verifique se sua rede está funcionando corretamente e se a configuração de CORS do serviço de armazenamento de arquivos está correta.",
|
|
120
|
+
"title": "Falha ao enviar o arquivo, verifique a conexão de rede ou tente novamente mais tarde",
|
|
121
|
+
"unknownError": "Erro: {{reason}}",
|
|
122
|
+
"uploadFailed": "Falha ao fazer o upload do arquivo."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/ru-RU/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Подробности: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "Текущий режим развертывания не поддерживает загрузку файлов, отличных от изображений. Если вы хотите загрузить файл формата {{ext}}, пожалуйста, переключитесь на развертывание с серверной базой данных или используйте LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Пожалуйста, убедитесь, что ваше соединение с сетью работает нормально, и проверьте правильность конфигурации кросс-доменных запросов для службы хранения файлов.",
|
|
120
|
+
"title": "Ошибка загрузки файла. Проверьте подключение к сети или попробуйте позже",
|
|
121
|
+
"unknownError": "Причина ошибки: {{reason}}",
|
|
122
|
+
"uploadFailed": "Ошибка загрузки файла"
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/tr-TR/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Detay: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "Mevcut dağıtım modu, yalnızca resim dosyalarının yüklenmesini desteklemektedir. {{ext}} formatında bir dosya yüklemek istiyorsanız, lütfen sunucu veritabanı dağıtımına geçin veya LobeChat Cloud hizmetini kullanın.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Lütfen ağ bağlantınızın düzgün çalıştığından emin olun ve dosya depolama hizmetinin çapraz alan yapılandırmasının doğru olup olmadığını kontrol edin.",
|
|
120
|
+
"title": "Dosya yükleme başarısız, lütfen ağ bağlantınızı kontrol edin veya daha sonra tekrar deneyin",
|
|
121
|
+
"unknownError": "Hata nedeni: {{reason}}",
|
|
122
|
+
"uploadFailed": "Dosya yüklemesi başarısız oldu."
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/vi-VN/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "Chi tiết: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "Chế độ triển khai hiện tại không hỗ trợ tải lên các tệp không phải hình ảnh. Nếu bạn cần tải lên định dạng {{ext}}, vui lòng chuyển sang triển khai cơ sở dữ liệu trên máy chủ hoặc sử dụng dịch vụ LobeChat Cloud.",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "Vui lòng kiểm tra xem mạng của bạn có hoạt động bình thường không và kiểm tra cấu hình chia sẻ tệp giữa các miền có đúng không",
|
|
120
|
+
"title": "Tải lên tệp thất bại, vui lòng kiểm tra kết nối mạng hoặc thử lại sau",
|
|
121
|
+
"unknownError": "Lỗi: {{reason}}",
|
|
122
|
+
"uploadFailed": "Tải tệp lên không thành công"
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/zh-CN/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "详情: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "当前部署模式不支持上传非图片文件,如需上传 {{ext}} 格式,请切换到服务端数据库部署或使用 LobeChat Cloud 服务",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "请确认你的网络是否正常,并检查文件存储服务跨域配置是否正确",
|
|
120
|
+
"title": "文件上传失败,请检查网络连接或稍后再试",
|
|
121
|
+
"unknownError": "错误原因: {{reason}}",
|
|
122
|
+
"uploadFailed": "文件上传失败"
|
|
120
123
|
}
|
|
121
124
|
}
|
package/locales/zh-TW/error.json
CHANGED
|
@@ -116,6 +116,9 @@
|
|
|
116
116
|
"upload": {
|
|
117
117
|
"desc": "詳情: {{detail}}",
|
|
118
118
|
"fileOnlySupportInServerMode": "當前部署模式不支持上傳非圖片文件,如需上傳 {{ext}} 格式,請切換到伺服器端資料庫部署或使用 LobeChat Cloud 服務",
|
|
119
|
-
"
|
|
119
|
+
"networkError": "請確認你的網路是否正常,並檢查檔案儲存服務的跨域配置是否正確",
|
|
120
|
+
"title": "檔案上傳失敗,請檢查網路連線或稍後再試",
|
|
121
|
+
"unknownError": "錯誤原因: {{reason}}",
|
|
122
|
+
"uploadFailed": "檔案上傳失敗"
|
|
120
123
|
}
|
|
121
124
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.6",
|
|
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",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"@vercel/speed-insights": "^1.0.12",
|
|
136
136
|
"ahooks": "^3.8.0",
|
|
137
137
|
"ai": "^3.2.16",
|
|
138
|
-
"antd": "5.20.
|
|
138
|
+
"antd": "^5.20.2",
|
|
139
139
|
"antd-style": "^3.6.2",
|
|
140
140
|
"brotli-wasm": "^3.0.1",
|
|
141
141
|
"chroma-js": "^2.4.2",
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { act, renderHook } from '@testing-library/react';
|
|
2
|
+
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { getContainer, useDragUpload } from './useDragUpload';
|
|
5
|
+
|
|
6
|
+
describe('useDragUpload', () => {
|
|
7
|
+
let mockOnUploadFiles: Mock;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockOnUploadFiles = vi.fn();
|
|
11
|
+
vi.useFakeTimers();
|
|
12
|
+
document.body.innerHTML = '';
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
vi.useRealTimers();
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should initialize and cleanup correctly', () => {
|
|
21
|
+
const { result, unmount } = renderHook(() => useDragUpload(mockOnUploadFiles));
|
|
22
|
+
|
|
23
|
+
expect(result.current).toBe(false);
|
|
24
|
+
expect(document.getElementById('dragging-root')).not.toBeNull();
|
|
25
|
+
|
|
26
|
+
unmount();
|
|
27
|
+
|
|
28
|
+
expect(document.getElementById('dragging-root')).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should handle drag events correctly', () => {
|
|
32
|
+
const { result } = renderHook(() => useDragUpload(mockOnUploadFiles));
|
|
33
|
+
|
|
34
|
+
act(() => {
|
|
35
|
+
window.dispatchEvent(new Event('dragenter'));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(result.current).toBe(false);
|
|
39
|
+
|
|
40
|
+
act(() => {
|
|
41
|
+
const dragEnterEvent = new Event('dragenter') as DragEvent;
|
|
42
|
+
Object.defineProperty(dragEnterEvent, 'dataTransfer', {
|
|
43
|
+
value: {
|
|
44
|
+
items: [{}],
|
|
45
|
+
types: ['Files'],
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
window.dispatchEvent(dragEnterEvent);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
expect(result.current).toBe(true);
|
|
52
|
+
|
|
53
|
+
act(() => {
|
|
54
|
+
const dragLeaveEvent = new Event('dragleave') as DragEvent;
|
|
55
|
+
Object.defineProperty(dragLeaveEvent, 'dataTransfer', {
|
|
56
|
+
value: {
|
|
57
|
+
items: [{}],
|
|
58
|
+
types: ['Files'],
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
window.dispatchEvent(dragLeaveEvent);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(result.current).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should handle file drop', async () => {
|
|
68
|
+
renderHook(() => useDragUpload(mockOnUploadFiles));
|
|
69
|
+
|
|
70
|
+
const mockFile = new File([''], 'test.txt', { type: 'text/plain' });
|
|
71
|
+
const dropEvent = new Event('drop') as DragEvent;
|
|
72
|
+
Object.defineProperty(dropEvent, 'dataTransfer', {
|
|
73
|
+
value: {
|
|
74
|
+
items: [
|
|
75
|
+
{
|
|
76
|
+
kind: 'file',
|
|
77
|
+
getAsFile: () => mockFile,
|
|
78
|
+
webkitGetAsEntry: () => ({
|
|
79
|
+
isFile: true,
|
|
80
|
+
file: (cb: (file: File) => void) => cb(mockFile),
|
|
81
|
+
}),
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
types: ['Files'],
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await act(async () => {
|
|
89
|
+
window.dispatchEvent(dropEvent);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(mockOnUploadFiles).toHaveBeenCalledWith([mockFile]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should handle paste event', async () => {
|
|
96
|
+
renderHook(() => useDragUpload(mockOnUploadFiles));
|
|
97
|
+
|
|
98
|
+
const mockFile = new File([''], 'test.txt', { type: 'text/plain' });
|
|
99
|
+
const pasteEvent = new Event('paste') as ClipboardEvent;
|
|
100
|
+
Object.defineProperty(pasteEvent, 'clipboardData', {
|
|
101
|
+
value: {
|
|
102
|
+
items: [
|
|
103
|
+
{
|
|
104
|
+
kind: 'file',
|
|
105
|
+
getAsFile: () => mockFile,
|
|
106
|
+
webkitGetAsEntry: () => null,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
await act(async () => {
|
|
113
|
+
window.dispatchEvent(pasteEvent);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(mockOnUploadFiles).toHaveBeenCalledWith([mockFile]);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('getContainer', () => {
|
|
121
|
+
it('should return the dragging root element', () => {
|
|
122
|
+
const rootElement = document.createElement('div');
|
|
123
|
+
rootElement.id = 'dragging-root';
|
|
124
|
+
document.body.appendChild(rootElement);
|
|
125
|
+
|
|
126
|
+
const container = getContainer();
|
|
127
|
+
expect(container).not.toBeNull();
|
|
128
|
+
expect(container?.id).toBe('dragging-root');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -40,6 +40,15 @@ const getFileListFromDataTransferItems = async (items: DataTransferItem[]) => {
|
|
|
40
40
|
const entry = item.webkitGetAsEntry();
|
|
41
41
|
if (entry) {
|
|
42
42
|
filePromises.push(processEntry(entry));
|
|
43
|
+
} else {
|
|
44
|
+
const file = item.getAsFile();
|
|
45
|
+
|
|
46
|
+
if (file)
|
|
47
|
+
filePromises.push(
|
|
48
|
+
new Promise((resolve) => {
|
|
49
|
+
resolve([file]);
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
43
52
|
}
|
|
44
53
|
}
|
|
45
54
|
}
|
package/src/config/file.ts
CHANGED
|
@@ -4,8 +4,19 @@ import { z } from 'zod';
|
|
|
4
4
|
const DEFAULT_S3_FILE_PATH = 'files';
|
|
5
5
|
|
|
6
6
|
export const getFileConfig = () => {
|
|
7
|
+
if (!!process.env.NEXT_PUBLIC_S3_DOMAIN) {
|
|
8
|
+
console.warn(
|
|
9
|
+
'⚠️ `NEXT_PUBLIC_S3_DOMAIN` will be de deprecated in the next major version, please replace it with `S3_PUBLIC_DOMAIN` in your env',
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const S3_PUBLIC_DOMAIN = process.env.S3_PUBLIC_DOMAIN || process.env.NEXT_PUBLIC_S3_DOMAIN;
|
|
14
|
+
|
|
7
15
|
return createEnv({
|
|
8
16
|
client: {
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated
|
|
19
|
+
*/
|
|
9
20
|
NEXT_PUBLIC_S3_DOMAIN: z.string().url().optional(),
|
|
10
21
|
NEXT_PUBLIC_S3_FILE_PATH: z.string().optional(),
|
|
11
22
|
},
|
|
@@ -18,7 +29,9 @@ export const getFileConfig = () => {
|
|
|
18
29
|
|
|
19
30
|
S3_ACCESS_KEY_ID: process.env.S3_ACCESS_KEY_ID,
|
|
20
31
|
S3_BUCKET: process.env.S3_BUCKET,
|
|
32
|
+
S3_ENABLE_PATH_STYLE: process.env.S3_ENABLE_PATH_STYLE === '1',
|
|
21
33
|
S3_ENDPOINT: process.env.S3_ENDPOINT,
|
|
34
|
+
S3_PUBLIC_DOMAIN,
|
|
22
35
|
S3_REGION: process.env.S3_REGION,
|
|
23
36
|
S3_SECRET_ACCESS_KEY: process.env.S3_SECRET_ACCESS_KEY,
|
|
24
37
|
S3_SET_ACL: process.env.S3_SET_ACL !== '0',
|
|
@@ -30,8 +43,10 @@ export const getFileConfig = () => {
|
|
|
30
43
|
// S3
|
|
31
44
|
S3_ACCESS_KEY_ID: z.string().optional(),
|
|
32
45
|
S3_BUCKET: z.string().optional(),
|
|
33
|
-
|
|
46
|
+
S3_ENABLE_PATH_STYLE: z.boolean(),
|
|
34
47
|
|
|
48
|
+
S3_ENDPOINT: z.string().url().optional(),
|
|
49
|
+
S3_PUBLIC_DOMAIN: z.string().url().optional(),
|
|
35
50
|
S3_REGION: z.string().optional(),
|
|
36
51
|
S3_SECRET_ACCESS_KEY: z.string().optional(),
|
|
37
52
|
S3_SET_ACL: z.boolean(),
|
|
@@ -142,6 +142,9 @@ export default {
|
|
|
142
142
|
desc: '详情: {{detail}}',
|
|
143
143
|
fileOnlySupportInServerMode:
|
|
144
144
|
'当前部署模式不支持上传非图片文件,如需上传 {{ext}} 格式,请切换到服务端数据库部署或使用 LobeChat Cloud 服务',
|
|
145
|
+
networkError: '请确认你的网络是否正常,并检查文件存储服务跨域配置是否正确',
|
|
145
146
|
title: '文件上传失败,请检查网络连接或稍后再试',
|
|
147
|
+
unknownError: '错误原因: {{reason}}',
|
|
148
|
+
uploadFailed: '文件上传失败',
|
|
146
149
|
},
|
|
147
150
|
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { TRPCError } from '@trpc/server';
|
|
2
|
-
import urlJoin from 'url-join';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
|
|
5
|
-
import { fileEnv } from '@/config/file';
|
|
6
4
|
import { AsyncTaskModel } from '@/database/server/models/asyncTask';
|
|
7
5
|
import { ChunkModel } from '@/database/server/models/chunk';
|
|
8
6
|
import { FileModel } from '@/database/server/models/file';
|
|
@@ -137,7 +135,7 @@ export const fileRouter = router({
|
|
|
137
135
|
embeddingError: embeddingTask?.error ?? null,
|
|
138
136
|
embeddingStatus: embeddingTask?.status as AsyncTaskStatus,
|
|
139
137
|
finishEmbedding: embeddingTask?.status === AsyncTaskStatus.Success,
|
|
140
|
-
url:
|
|
138
|
+
url: getFullFileUrl(item.url!),
|
|
141
139
|
};
|
|
142
140
|
});
|
|
143
141
|
}),
|
|
@@ -21,6 +21,10 @@ export class ServerService implements IFileService {
|
|
|
21
21
|
return lambdaClient.file.createFile.mutate({ ...params, knowledgeBaseId } as CreateFileParams);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated
|
|
26
|
+
* @param id
|
|
27
|
+
*/
|
|
24
28
|
async getFile(id: string): Promise<FilePreview> {
|
|
25
29
|
if (!fileEnv.NEXT_PUBLIC_S3_DOMAIN) {
|
|
26
30
|
throw new Error('fileEnv.NEXT_PUBLIC_S3_DOMAIN is not set while enable server upload');
|
package/src/services/upload.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { FileMetadata, UploadFileParams } from '@/types/files';
|
|
|
5
5
|
import { FileUploadState, FileUploadStatus } from '@/types/files/upload';
|
|
6
6
|
import { uuid } from '@/utils/uuid';
|
|
7
7
|
|
|
8
|
+
export const UPLOAD_NETWORK_ERROR = 'NetWorkError';
|
|
9
|
+
|
|
8
10
|
class UploadService {
|
|
9
11
|
uploadWithProgress = async (
|
|
10
12
|
file: File,
|
|
@@ -13,7 +15,6 @@ class UploadService {
|
|
|
13
15
|
const xhr = new XMLHttpRequest();
|
|
14
16
|
|
|
15
17
|
const { preSignUrl, ...result } = await this.getSignedUploadUrl(file);
|
|
16
|
-
|
|
17
18
|
let startTime = Date.now();
|
|
18
19
|
xhr.upload.addEventListener('progress', (event) => {
|
|
19
20
|
if (event.lengthComputable) {
|
|
@@ -49,7 +50,10 @@ class UploadService {
|
|
|
49
50
|
reject(xhr.statusText);
|
|
50
51
|
}
|
|
51
52
|
});
|
|
52
|
-
xhr.addEventListener('error', () =>
|
|
53
|
+
xhr.addEventListener('error', () => {
|
|
54
|
+
if (xhr.status === 0) reject(UPLOAD_NETWORK_ERROR);
|
|
55
|
+
else reject(xhr.statusText);
|
|
56
|
+
});
|
|
53
57
|
xhr.send(data);
|
|
54
58
|
});
|
|
55
59
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { t } from 'i18next';
|
|
1
2
|
import { produce } from 'immer';
|
|
2
3
|
import useSWR, { SWRResponse } from 'swr';
|
|
3
4
|
import { StateCreator } from 'zustand/vanilla';
|
|
4
5
|
|
|
6
|
+
import { notification } from '@/components/AntdStaticMethods';
|
|
5
7
|
import { FILE_UPLOAD_BLACKLIST } from '@/const/file';
|
|
6
8
|
import { fileService } from '@/services/file';
|
|
7
9
|
import { ServerService } from '@/services/file/server';
|
|
8
10
|
import { ragService } from '@/services/rag';
|
|
11
|
+
import { UPLOAD_NETWORK_ERROR } from '@/services/upload';
|
|
9
12
|
import { userService } from '@/services/user';
|
|
10
13
|
import { useAgentStore } from '@/store/agent';
|
|
11
14
|
import {
|
|
@@ -128,10 +131,30 @@ export const createFileSlice: StateCreator<
|
|
|
128
131
|
|
|
129
132
|
// upload files and process it
|
|
130
133
|
const pools = files.map(async (file) => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
let fileResult: { id: string; url: string } | undefined;
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
fileResult = await get().uploadWithProgress({
|
|
138
|
+
file,
|
|
139
|
+
onStatusUpdate: dispatchChatUploadFileList,
|
|
140
|
+
});
|
|
141
|
+
} catch (error) {
|
|
142
|
+
// skip `UNAUTHORIZED` error
|
|
143
|
+
if ((error as any)?.message !== 'UNAUTHORIZED')
|
|
144
|
+
notification.error({
|
|
145
|
+
description:
|
|
146
|
+
// it may be a network error or the cors error
|
|
147
|
+
error === UPLOAD_NETWORK_ERROR
|
|
148
|
+
? t('upload.networkError', { ns: 'error' })
|
|
149
|
+
: // or the error from the server
|
|
150
|
+
typeof error === 'string'
|
|
151
|
+
? error
|
|
152
|
+
: t('upload.unknownError', { ns: 'error', reason: (error as Error).message }),
|
|
153
|
+
message: t('upload.uploadFailed', { ns: 'error' }),
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
dispatchChatUploadFileList({ id: file.name, type: 'removeFile' });
|
|
157
|
+
}
|
|
135
158
|
|
|
136
159
|
if (!fileResult) return;
|
|
137
160
|
|