@lobehub/chat 1.12.4 → 1.12.5
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/CHANGELOG.md +25 -0
- package/docs/self-hosting/advanced/auth.mdx +8 -10
- package/docs/self-hosting/advanced/s3.mdx +39 -0
- package/docs/self-hosting/server-database/docker.mdx +31 -21
- 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/locales/default/error.ts +3 -0
- package/src/services/upload.ts +6 -2
- package/src/store/file/slices/chat/action.ts +27 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.12.5](https://github.com/lobehub/lobe-chat/compare/v1.12.4...v1.12.5)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-08-22**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fix clipboard copy issue and improve upload cors feedback.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **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))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
### [Version 1.12.4](https://github.com/lobehub/lobe-chat/compare/v1.12.3...v1.12.4)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2024-08-22**</sup>
|
|
@@ -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
|
|
@@ -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
|
+
### `NEXT_PUBLIC_S3_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>
|
|
@@ -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
|
|
@@ -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 NEXT_PUBLIC_S3_DOMAIN=https://s3-for-lobechat.your-domain.com \
|
|
129
|
+
lobehub/lobe-chat-database
|
|
120
130
|
```
|
|
121
131
|
|
|
122
132
|
<Callout type="tip">
|
|
@@ -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.5",
|
|
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
|
}
|
|
@@ -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
|
};
|
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
|
|