@lobehub/chat 1.19.31 โ 1.19.33
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 +58 -0
- package/next.config.mjs +5 -7
- package/package.json +3 -2
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.test.tsx +1 -0
- package/src/app/sw.ts +26 -0
- package/src/config/modelProviders/google.ts +53 -62
- package/src/config/modelProviders/taichu.ts +5 -2
- package/src/features/FileViewer/Renderer/Image/index.tsx +1 -0
- package/src/features/PWAInstall/Install.tsx +80 -0
- package/src/features/PWAInstall/index.tsx +6 -61
- package/src/libs/agent-runtime/minimax/index.test.ts +4 -4
- package/src/libs/agent-runtime/minimax/index.ts +16 -6
- package/src/libs/agent-runtime/utils/streams/minimax.test.ts +24 -0
- package/src/libs/agent-runtime/utils/streams/minimax.ts +15 -0
- package/src/server/services/discover/index.ts +1 -1
- package/src/services/message/server.ts +1 -1
- package/src/services/session/server.ts +2 -2
- package/src/store/chat/slices/plugin/action.ts +3 -1
- package/tsconfig.json +3 -3
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,64 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.19.33](https://github.com/lobehub/lobe-chat/compare/v1.19.32...v1.19.33)
|
6
|
+
|
7
|
+
<sup>Released on **2024-09-25**</sup>
|
8
|
+
|
9
|
+
#### ๐ Bug Fixes
|
10
|
+
|
11
|
+
- **misc**: MiniMax output long content interrupted by non-existent error.
|
12
|
+
|
13
|
+
#### ๐ Styles
|
14
|
+
|
15
|
+
- **misc**: Update google provider model info.
|
16
|
+
|
17
|
+
<br/>
|
18
|
+
|
19
|
+
<details>
|
20
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
21
|
+
|
22
|
+
#### What's fixed
|
23
|
+
|
24
|
+
- **misc**: MiniMax output long content interrupted by non-existent error, closes [#4088](https://github.com/lobehub/lobe-chat/issues/4088) ([4f6e20d](https://github.com/lobehub/lobe-chat/commit/4f6e20d))
|
25
|
+
|
26
|
+
#### Styles
|
27
|
+
|
28
|
+
- **misc**: Update google provider model info, closes [#4129](https://github.com/lobehub/lobe-chat/issues/4129) ([b1442b9](https://github.com/lobehub/lobe-chat/commit/b1442b9))
|
29
|
+
|
30
|
+
</details>
|
31
|
+
|
32
|
+
<div align="right">
|
33
|
+
|
34
|
+
[](#readme-top)
|
35
|
+
|
36
|
+
</div>
|
37
|
+
|
38
|
+
### [Version 1.19.32](https://github.com/lobehub/lobe-chat/compare/v1.19.31...v1.19.32)
|
39
|
+
|
40
|
+
<sup>Released on **2024-09-25**</sup>
|
41
|
+
|
42
|
+
#### ๐ Styles
|
43
|
+
|
44
|
+
- **misc**: Add function call for `taichu_llm`.
|
45
|
+
|
46
|
+
<br/>
|
47
|
+
|
48
|
+
<details>
|
49
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
50
|
+
|
51
|
+
#### Styles
|
52
|
+
|
53
|
+
- **misc**: Add function call for `taichu_llm`, closes [#4119](https://github.com/lobehub/lobe-chat/issues/4119) ([8f629d8](https://github.com/lobehub/lobe-chat/commit/8f629d8))
|
54
|
+
|
55
|
+
</details>
|
56
|
+
|
57
|
+
<div align="right">
|
58
|
+
|
59
|
+
[](#readme-top)
|
60
|
+
|
61
|
+
</div>
|
62
|
+
|
5
63
|
### [Version 1.19.31](https://github.com/lobehub/lobe-chat/compare/v1.19.30...v1.19.31)
|
6
64
|
|
7
65
|
<sup>Released on **2024-09-24**</sup>
|
package/next.config.mjs
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import nextPWA from '@ducanh2912/next-pwa';
|
2
1
|
import analyzer from '@next/bundle-analyzer';
|
3
2
|
import { withSentryConfig } from '@sentry/nextjs';
|
3
|
+
import withSerwistInit from '@serwist/next';
|
4
4
|
|
5
5
|
const isProd = process.env.NODE_ENV === 'production';
|
6
6
|
const buildWithDocker = process.env.DOCKER === 'true';
|
@@ -192,12 +192,10 @@ const noWrapper = (config) => config;
|
|
192
192
|
const withBundleAnalyzer = process.env.ANALYZE === 'true' ? analyzer() : noWrapper;
|
193
193
|
|
194
194
|
const withPWA = isProd
|
195
|
-
?
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
skipWaiting: true,
|
200
|
-
},
|
195
|
+
? withSerwistInit({
|
196
|
+
register: false,
|
197
|
+
swDest: 'public/sw.js',
|
198
|
+
swSrc: 'src/app/sw.ts',
|
201
199
|
})
|
202
200
|
: noWrapper;
|
203
201
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.19.
|
3
|
+
"version": "1.19.33",
|
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",
|
@@ -127,6 +127,7 @@
|
|
127
127
|
"@next/third-parties": "^14.2.6",
|
128
128
|
"@react-spring/web": "^9.7.3",
|
129
129
|
"@sentry/nextjs": "^7.119.0",
|
130
|
+
"@serwist/next": "^9.0.8",
|
130
131
|
"@t3-oss/env-nextjs": "^0.11.0",
|
131
132
|
"@tanstack/react-query": "^5.52.1",
|
132
133
|
"@trpc/client": "next",
|
@@ -232,7 +233,6 @@
|
|
232
233
|
},
|
233
234
|
"devDependencies": {
|
234
235
|
"@commitlint/cli": "^19.4.0",
|
235
|
-
"@ducanh2912/next-pwa": "^10.2.8",
|
236
236
|
"@edge-runtime/vm": "^4.0.2",
|
237
237
|
"@lobehub/i18n-cli": "^1.19.1",
|
238
238
|
"@lobehub/lint": "^1.24.4",
|
@@ -288,6 +288,7 @@
|
|
288
288
|
"remark-cli": "^11.0.0",
|
289
289
|
"remark-parse": "^10.0.2",
|
290
290
|
"semantic-release": "^21.1.2",
|
291
|
+
"serwist": "^9.0.8",
|
291
292
|
"stylelint": "^15.11.0",
|
292
293
|
"supports-color": "8",
|
293
294
|
"tsx": "^4.17.0",
|
package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.test.tsx
CHANGED
@@ -150,6 +150,7 @@ describe('<InputArea />', () => {
|
|
150
150
|
const beforeUnloadHandler = vi.fn();
|
151
151
|
|
152
152
|
addEventListenerSpy.mockImplementation((event, handler) => {
|
153
|
+
// @ts-ignore
|
153
154
|
if (event === 'beforeunload') {
|
154
155
|
beforeUnloadHandler.mockImplementation(handler as any);
|
155
156
|
}
|
package/src/app/sw.ts
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
import { defaultCache } from '@serwist/next/worker';
|
2
|
+
import type { PrecacheEntry, SerwistGlobalConfig } from 'serwist';
|
3
|
+
import { Serwist } from 'serwist';
|
4
|
+
|
5
|
+
// This declares the value of `injectionPoint` to TypeScript.
|
6
|
+
// `injectionPoint` is the string that will be replaced by the
|
7
|
+
// actual precache manifest. By default, this string is set to
|
8
|
+
// `"self.__SW_MANIFEST"`.
|
9
|
+
declare global {
|
10
|
+
interface WorkerGlobalScope extends SerwistGlobalConfig {
|
11
|
+
__SW_MANIFEST: (PrecacheEntry | string)[] | undefined;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
// eslint-disable-next-line no-undef
|
16
|
+
declare const self: ServiceWorkerGlobalScope;
|
17
|
+
|
18
|
+
const serwist = new Serwist({
|
19
|
+
clientsClaim: true,
|
20
|
+
navigationPreload: true,
|
21
|
+
precacheEntries: self.__SW_MANIFEST,
|
22
|
+
runtimeCaching: defaultCache,
|
23
|
+
skipWaiting: true,
|
24
|
+
});
|
25
|
+
|
26
|
+
serwist.addEventListeners();
|
@@ -16,78 +16,69 @@ const Google: ModelProviderCard = {
|
|
16
16
|
input: 0.075,
|
17
17
|
output: 0.3,
|
18
18
|
},
|
19
|
-
tokens:
|
19
|
+
tokens: 1_000_000 + 8192,
|
20
20
|
vision: true,
|
21
21
|
},
|
22
22
|
{
|
23
|
-
description: 'Gemini 1.5 Flash
|
24
|
-
displayName: 'Gemini 1.5 Flash
|
23
|
+
description: 'Gemini 1.5 Flash 002 ๆฏไธๆฌพ้ซๆ็ๅคๆจกๆๆจกๅ๏ผๆฏๆๅนฟๆณๅบ็จ็ๆฉๅฑใ',
|
24
|
+
displayName: 'Gemini 1.5 Flash 002',
|
25
|
+
enabled: true,
|
25
26
|
functionCall: true,
|
26
|
-
id: 'gemini-1.5-flash-
|
27
|
+
id: 'gemini-1.5-flash-002',
|
27
28
|
maxOutput: 8192,
|
28
29
|
pricing: {
|
29
30
|
cachedInput: 0.018_75,
|
30
31
|
input: 0.075,
|
31
32
|
output: 0.3,
|
32
33
|
},
|
33
|
-
releasedAt: '2024-
|
34
|
-
tokens:
|
35
|
-
vision: true,
|
36
|
-
},
|
37
|
-
{
|
38
|
-
description: 'Gemini 1.5 Flash 8B 0827 ไธไธบๅค็ๅคง่งๆจกไปปๅกๅบๆฏ่ฎพ่ฎก๏ผๆไพๆ ไธไผฆๆฏ็ๅค็้ๅบฆใ',
|
39
|
-
displayName: 'Gemini 1.5 Flash 8B 0827',
|
40
|
-
functionCall: true,
|
41
|
-
id: 'gemini-1.5-flash-8b-exp-0827',
|
42
|
-
maxOutput: 8192,
|
43
|
-
releasedAt: '2024-08-27',
|
44
|
-
tokens: 1_048_576 + 8192,
|
34
|
+
releasedAt: '2024-09-25',
|
35
|
+
tokens: 1_000_000 + 8192,
|
45
36
|
vision: true,
|
46
37
|
},
|
47
38
|
{
|
48
|
-
description:
|
49
|
-
|
50
|
-
displayName: 'Gemini 1.5 Flash 8B 0924',
|
51
|
-
enabled: true,
|
39
|
+
description: 'Gemini 1.5 Flash 001 ๆฏไธๆฌพ้ซๆ็ๅคๆจกๆๆจกๅ๏ผๆฏๆๅนฟๆณๅบ็จ็ๆฉๅฑใ',
|
40
|
+
displayName: 'Gemini 1.5 Flash 001',
|
52
41
|
functionCall: true,
|
53
|
-
id: 'gemini-1.5-flash-
|
42
|
+
id: 'gemini-1.5-flash-001',
|
54
43
|
maxOutput: 8192,
|
55
44
|
pricing: {
|
56
45
|
cachedInput: 0.018_75,
|
57
46
|
input: 0.075,
|
58
47
|
output: 0.3,
|
59
48
|
},
|
60
|
-
|
61
|
-
tokens: 1_048_576 + 8192,
|
49
|
+
tokens: 1_000_000 + 8192,
|
62
50
|
vision: true,
|
63
51
|
},
|
64
52
|
{
|
65
|
-
description: 'Gemini 1.5 Flash
|
66
|
-
displayName: 'Gemini 1.5 Flash
|
53
|
+
description: 'Gemini 1.5 Flash 0827 ๆไพไบไผๅๅ็ๅคๆจกๆๅค็่ฝๅ๏ผ้็จๅค็งๅคๆไปปๅกๅบๆฏใ',
|
54
|
+
displayName: 'Gemini 1.5 Flash 0827',
|
67
55
|
functionCall: true,
|
68
|
-
id: 'gemini-1.5-flash-
|
56
|
+
id: 'gemini-1.5-flash-exp-0827',
|
69
57
|
maxOutput: 8192,
|
70
58
|
pricing: {
|
71
59
|
cachedInput: 0.018_75,
|
72
60
|
input: 0.075,
|
73
61
|
output: 0.3,
|
74
62
|
},
|
75
|
-
|
63
|
+
releasedAt: '2024-08-27',
|
64
|
+
tokens: 1_000_000 + 8192,
|
76
65
|
vision: true,
|
77
66
|
},
|
67
|
+
|
78
68
|
{
|
79
|
-
description:
|
80
|
-
|
69
|
+
description:
|
70
|
+
'Gemini 1.5 Flash 8B 0924 ๆฏๆๆฐ็ๅฎ้ชๆงๆจกๅ๏ผๅจๆๆฌๅๅคๆจกๆ็จไพไธญ้ฝๆๆพ่็ๆง่ฝๆๅใ',
|
71
|
+
displayName: 'Gemini 1.5 Flash 8B 0924',
|
81
72
|
functionCall: true,
|
82
|
-
id: 'gemini-1.5-flash-
|
73
|
+
id: 'gemini-1.5-flash-8b-exp-0924',
|
83
74
|
maxOutput: 8192,
|
84
75
|
pricing: {
|
85
76
|
cachedInput: 0.018_75,
|
86
77
|
input: 0.075,
|
87
78
|
output: 0.3,
|
88
79
|
},
|
89
|
-
releasedAt: '2024-09-
|
90
|
-
tokens:
|
80
|
+
releasedAt: '2024-09-24',
|
81
|
+
tokens: 1_000_000 + 8192,
|
91
82
|
vision: true,
|
92
83
|
},
|
93
84
|
{
|
@@ -104,69 +95,69 @@ const Google: ModelProviderCard = {
|
|
104
95
|
output: 10.5,
|
105
96
|
},
|
106
97
|
releasedAt: '2024-02-15',
|
107
|
-
tokens:
|
98
|
+
tokens: 2_000_000 + 8192,
|
108
99
|
vision: true,
|
109
100
|
},
|
110
101
|
{
|
111
|
-
description:
|
112
|
-
|
102
|
+
description:
|
103
|
+
'Gemini 1.5 Pro 002 ๆฏๆๆฐ็็ไบงๅฐฑ็ปชๆจกๅ๏ผๆไพๆด้ซ่ดจ้็่พๅบ๏ผ็นๅซๅจๆฐๅญฆใ้ฟไธไธๆๅ่ง่งไปปๅกๆน้ขๆๆพ่ๆๅใ',
|
104
|
+
displayName: 'Gemini 1.5 Pro 002',
|
105
|
+
enabled: true,
|
113
106
|
functionCall: true,
|
114
|
-
id: 'gemini-1.5-pro-
|
107
|
+
id: 'gemini-1.5-pro-002',
|
115
108
|
maxOutput: 8192,
|
116
109
|
pricing: {
|
117
|
-
cachedInput: 0.
|
118
|
-
input:
|
119
|
-
output:
|
110
|
+
cachedInput: 0.315,
|
111
|
+
input: 1.25,
|
112
|
+
output: 2.5,
|
120
113
|
},
|
121
|
-
releasedAt: '2024-
|
122
|
-
tokens:
|
114
|
+
releasedAt: '2024-09-24',
|
115
|
+
tokens: 2_000_000 + 8192,
|
123
116
|
vision: true,
|
124
117
|
},
|
125
118
|
{
|
126
|
-
description: 'Gemini 1.5 Pro
|
127
|
-
displayName: 'Gemini 1.5 Pro
|
119
|
+
description: 'Gemini 1.5 Pro 001 ๆฏๅฏๆฉๅฑ็ๅคๆจกๆAI่งฃๅณๆนๆก๏ผๆฏๆๅนฟๆณ็ๅคๆไปปๅกใ',
|
120
|
+
displayName: 'Gemini 1.5 Pro 001',
|
128
121
|
functionCall: true,
|
129
|
-
id: 'gemini-1.5-pro-
|
122
|
+
id: 'gemini-1.5-pro-001',
|
130
123
|
maxOutput: 8192,
|
131
124
|
pricing: {
|
132
125
|
cachedInput: 0.875,
|
133
126
|
input: 3.5,
|
134
127
|
output: 10.5,
|
135
128
|
},
|
136
|
-
releasedAt: '2024-
|
137
|
-
tokens:
|
129
|
+
releasedAt: '2024-02-15',
|
130
|
+
tokens: 2_000_000 + 8192,
|
138
131
|
vision: true,
|
139
132
|
},
|
140
133
|
{
|
141
|
-
description: 'Gemini 1.5 Pro
|
142
|
-
displayName: 'Gemini 1.5 Pro
|
134
|
+
description: 'Gemini 1.5 Pro 0827 ็ปๅๆๆฐไผๅๆๆฏ๏ผๅธฆๆฅๆด้ซๆ็ๅคๆจกๆๆฐๆฎๅค็่ฝๅใ',
|
135
|
+
displayName: 'Gemini 1.5 Pro 0827',
|
143
136
|
functionCall: true,
|
144
|
-
id: 'gemini-1.5-pro-
|
137
|
+
id: 'gemini-1.5-pro-exp-0827',
|
145
138
|
maxOutput: 8192,
|
146
139
|
pricing: {
|
147
140
|
cachedInput: 0.875,
|
148
141
|
input: 3.5,
|
149
142
|
output: 10.5,
|
150
143
|
},
|
151
|
-
releasedAt: '2024-
|
152
|
-
tokens:
|
144
|
+
releasedAt: '2024-08-27',
|
145
|
+
tokens: 2_000_000 + 8192,
|
153
146
|
vision: true,
|
154
147
|
},
|
155
148
|
{
|
156
|
-
description:
|
157
|
-
|
158
|
-
displayName: 'Gemini 1.5 Pro 002',
|
159
|
-
enabled: true,
|
149
|
+
description: 'Gemini 1.5 Pro 0801 ๆไพๅบ่ฒ็ๅคๆจกๆๅค็่ฝๅ๏ผไธบๅบ็จๅผๅๅธฆๆฅๆดๅคง็ตๆดปๆงใ',
|
150
|
+
displayName: 'Gemini 1.5 Pro 0801',
|
160
151
|
functionCall: true,
|
161
|
-
id: 'gemini-1.5-pro-
|
152
|
+
id: 'gemini-1.5-pro-exp-0801',
|
162
153
|
maxOutput: 8192,
|
163
154
|
pricing: {
|
164
|
-
cachedInput: 0.
|
165
|
-
input:
|
166
|
-
output:
|
155
|
+
cachedInput: 0.875,
|
156
|
+
input: 3.5,
|
157
|
+
output: 10.5,
|
167
158
|
},
|
168
|
-
releasedAt: '2024-
|
169
|
-
tokens:
|
159
|
+
releasedAt: '2024-08-01',
|
160
|
+
tokens: 2_000_000 + 8192,
|
170
161
|
vision: true,
|
171
162
|
},
|
172
163
|
{
|
@@ -210,7 +201,7 @@ const Google: ModelProviderCard = {
|
|
210
201
|
],
|
211
202
|
checkModel: 'gemini-1.5-flash-latest',
|
212
203
|
description:
|
213
|
-
'Google ็ Gemini ็ณปๅๆฏๅ
ถๆๅ
่ฟใ้็จ็
|
204
|
+
'Google ็ Gemini ็ณปๅๆฏๅ
ถๆๅ
่ฟใ้็จ็ AIๆจกๅ๏ผ็ฑ Google DeepMind ๆ้ ๏ผไธไธบๅคๆจกๆ่ฎพ่ฎก๏ผๆฏๆๆๆฌใไปฃ็ ใๅพๅใ้ณ้ขๅ่ง้ข็ๆ ็ผ็่งฃไธๅค็ใ้็จไบไปๆฐๆฎไธญๅฟๅฐ็งปๅจ่ฎพๅค็ๅค็ง็ฏๅข๏ผๆๅคงๆๅไบAIๆจกๅ็ๆ็ไธๅบ็จๅนฟๆณๆงใ',
|
214
205
|
id: 'google',
|
215
206
|
modelsUrl: 'https://ai.google.dev/gemini-api/docs/models/gemini',
|
216
207
|
name: 'Google',
|
@@ -8,11 +8,13 @@ const Taichu: ModelProviderCard = {
|
|
8
8
|
'Taichu 2.0 ๅบไบๆตท้้ซ่ดจๆฐๆฎ่ฎญ็ป๏ผๅ
ทๆๆดๅผบ็ๆๆฌ็่งฃใๅ
ๅฎนๅไฝใๅฏน่ฏ้ฎ็ญ็ญ่ฝๅ',
|
9
9
|
displayName: 'Taichu 2.0',
|
10
10
|
enabled: true,
|
11
|
-
functionCall:
|
11
|
+
functionCall: true,
|
12
12
|
id: 'taichu_llm',
|
13
13
|
tokens: 32_768,
|
14
14
|
},
|
15
|
-
|
15
|
+
/*
|
16
|
+
// TODO: Not support for now
|
17
|
+
{
|
16
18
|
description:
|
17
19
|
'Taichu 2.0V ่ๅไบๅพๅ็่งฃใ็ฅ่ฏ่ฟ็งปใ้ป่พๅฝๅ ็ญ่ฝๅ๏ผๅจๅพๆ้ฎ็ญ้ขๅ่กจ็ฐ็ชๅบ',
|
18
20
|
displayName: 'Taichu 2.0V',
|
@@ -20,6 +22,7 @@ const Taichu: ModelProviderCard = {
|
|
20
22
|
tokens: 4096,
|
21
23
|
vision: true,
|
22
24
|
},
|
25
|
+
*/
|
23
26
|
],
|
24
27
|
checkModel: 'taichu_llm',
|
25
28
|
description:
|
@@ -0,0 +1,80 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import dynamic from 'next/dynamic';
|
4
|
+
import { memo, useEffect, useLayoutEffect } from 'react';
|
5
|
+
import { useTranslation } from 'react-i18next';
|
6
|
+
|
7
|
+
import { BRANDING_NAME } from '@/const/branding';
|
8
|
+
import { PWA_INSTALL_ID } from '@/const/layoutTokens';
|
9
|
+
import { usePWAInstall } from '@/hooks/usePWAInstall';
|
10
|
+
import { useGlobalStore } from '@/store/global';
|
11
|
+
import { systemStatusSelectors } from '@/store/global/selectors';
|
12
|
+
import { useUserStore } from '@/store/user';
|
13
|
+
|
14
|
+
// @ts-ignore
|
15
|
+
const PWA: any = dynamic(() => import('@khmyznikov/pwa-install/dist/pwa-install.react.js'), {
|
16
|
+
ssr: false,
|
17
|
+
});
|
18
|
+
|
19
|
+
const PWAInstall = memo(() => {
|
20
|
+
const { t } = useTranslation('metadata');
|
21
|
+
|
22
|
+
const { install, canInstall } = usePWAInstall();
|
23
|
+
|
24
|
+
const isShowPWAGuide = useUserStore((s) => s.isShowPWAGuide);
|
25
|
+
const [hidePWAInstaller, updateSystemStatus] = useGlobalStore((s) => [
|
26
|
+
systemStatusSelectors.hidePWAInstaller(s),
|
27
|
+
s.updateSystemStatus,
|
28
|
+
]);
|
29
|
+
|
30
|
+
// we need to make the pwa installer hidden by default
|
31
|
+
useLayoutEffect(() => {
|
32
|
+
sessionStorage.setItem('pwa-hide-install', 'true');
|
33
|
+
}, []);
|
34
|
+
|
35
|
+
const pwaInstall =
|
36
|
+
// eslint-disable-next-line unicorn/prefer-query-selector
|
37
|
+
typeof window === 'undefined' ? undefined : document.getElementById(PWA_INSTALL_ID);
|
38
|
+
|
39
|
+
// add an event listener to control the user close installer action
|
40
|
+
useEffect(() => {
|
41
|
+
if (!pwaInstall) return;
|
42
|
+
|
43
|
+
const handler = (e: Event) => {
|
44
|
+
const event = e as CustomEvent;
|
45
|
+
|
46
|
+
// it means user hide installer
|
47
|
+
if (event.detail.message === 'dismissed') {
|
48
|
+
updateSystemStatus({ hidePWAInstaller: true });
|
49
|
+
}
|
50
|
+
};
|
51
|
+
|
52
|
+
pwaInstall.addEventListener('pwa-user-choice-result-event', handler);
|
53
|
+
return () => {
|
54
|
+
pwaInstall.removeEventListener('pwa-user-choice-result-event', handler);
|
55
|
+
};
|
56
|
+
}, [pwaInstall]);
|
57
|
+
|
58
|
+
// trigger the PWA guide on demand
|
59
|
+
useEffect(() => {
|
60
|
+
if (!canInstall || hidePWAInstaller) return;
|
61
|
+
|
62
|
+
// trigger the pwa installer and register the service worker
|
63
|
+
if (isShowPWAGuide) {
|
64
|
+
install();
|
65
|
+
if ('serviceWorker' in navigator && window.serwist !== undefined) {
|
66
|
+
window.serwist.register();
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}, [canInstall, hidePWAInstaller, isShowPWAGuide]);
|
70
|
+
|
71
|
+
return (
|
72
|
+
<PWA
|
73
|
+
description={t('chat.description', { appName: BRANDING_NAME })}
|
74
|
+
id={PWA_INSTALL_ID}
|
75
|
+
manifest-url={'/manifest.webmanifest'}
|
76
|
+
/>
|
77
|
+
);
|
78
|
+
});
|
79
|
+
|
80
|
+
export default PWAInstall;
|
@@ -1,79 +1,24 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
3
|
import dynamic from 'next/dynamic';
|
4
|
-
import { memo
|
5
|
-
import { useTranslation } from 'react-i18next';
|
4
|
+
import { memo } from 'react';
|
6
5
|
|
7
|
-
import { BRANDING_NAME } from '@/const/branding';
|
8
|
-
import { PWA_INSTALL_ID } from '@/const/layoutTokens';
|
9
|
-
import { usePWAInstall } from '@/hooks/usePWAInstall';
|
10
6
|
import { usePlatform } from '@/hooks/usePlatform';
|
11
|
-
import { useGlobalStore } from '@/store/global';
|
12
|
-
import { systemStatusSelectors } from '@/store/global/selectors';
|
13
7
|
import { useUserStore } from '@/store/user';
|
14
8
|
|
15
|
-
|
16
|
-
const PWA: any = dynamic(() => import('@khmyznikov/pwa-install/dist/pwa-install.react.js'), {
|
9
|
+
const Install: any = dynamic(() => import('./Install'), {
|
17
10
|
ssr: false,
|
18
11
|
});
|
19
12
|
|
20
13
|
const PWAInstall = memo(() => {
|
21
|
-
const { t } = useTranslation('metadata');
|
22
14
|
const { isPWA } = usePlatform();
|
23
|
-
|
24
|
-
const { install, canInstall } = usePWAInstall();
|
25
|
-
|
26
15
|
const isShowPWAGuide = useUserStore((s) => s.isShowPWAGuide);
|
27
|
-
const [hidePWAInstaller, updateSystemStatus] = useGlobalStore((s) => [
|
28
|
-
systemStatusSelectors.hidePWAInstaller(s),
|
29
|
-
s.updateSystemStatus,
|
30
|
-
]);
|
31
|
-
|
32
|
-
// we need to make the pwa installer hidden by default
|
33
|
-
useLayoutEffect(() => {
|
34
|
-
sessionStorage.setItem('pwa-hide-install', 'true');
|
35
|
-
}, []);
|
36
|
-
|
37
|
-
const pwaInstall =
|
38
|
-
// eslint-disable-next-line unicorn/prefer-query-selector
|
39
|
-
typeof window === 'undefined' ? undefined : document.getElementById(PWA_INSTALL_ID);
|
40
|
-
|
41
|
-
// add an event listener to control the user close installer action
|
42
|
-
useEffect(() => {
|
43
|
-
if (!pwaInstall) return;
|
44
|
-
|
45
|
-
const handler = (e: Event) => {
|
46
|
-
const event = e as CustomEvent;
|
47
|
-
|
48
|
-
// it means user hide installer
|
49
|
-
if (event.detail.message === 'dismissed') {
|
50
|
-
updateSystemStatus({ hidePWAInstaller: true });
|
51
|
-
}
|
52
|
-
};
|
53
|
-
|
54
|
-
pwaInstall.addEventListener('pwa-user-choice-result-event', handler);
|
55
|
-
return () => {
|
56
|
-
pwaInstall.removeEventListener('pwa-user-choice-result-event', handler);
|
57
|
-
};
|
58
|
-
}, [pwaInstall]);
|
59
|
-
|
60
|
-
// trigger the PWA guide on demand
|
61
|
-
useEffect(() => {
|
62
|
-
if (!canInstall || hidePWAInstaller) return;
|
63
16
|
|
64
|
-
|
65
|
-
install();
|
66
|
-
}
|
67
|
-
}, [canInstall, hidePWAInstaller, isShowPWAGuide]);
|
17
|
+
if (isPWA || !isShowPWAGuide) return null;
|
68
18
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
description={t('chat.description', { appName: BRANDING_NAME })}
|
73
|
-
id={PWA_INSTALL_ID}
|
74
|
-
manifest-url={'/manifest.webmanifest'}
|
75
|
-
/>
|
76
|
-
);
|
19
|
+
// only when the user is suitable for the pwa install and not install the pwa
|
20
|
+
// then show the installation guide
|
21
|
+
return <Install />;
|
77
22
|
});
|
78
23
|
|
79
24
|
export default PWAInstall;
|
@@ -253,10 +253,10 @@ describe('LobeMinimaxAI', () => {
|
|
253
253
|
});
|
254
254
|
});
|
255
255
|
|
256
|
-
it('should include max tokens when model is abab6.
|
256
|
+
it('should include max tokens when model is abab6.5t-chat', () => {
|
257
257
|
const payload: ChatStreamPayload = {
|
258
258
|
messages: [{ content: 'Hello', role: 'user' }],
|
259
|
-
model: 'abab6.
|
259
|
+
model: 'abab6.5t-chat',
|
260
260
|
temperature: 0,
|
261
261
|
top_p: 0,
|
262
262
|
};
|
@@ -265,9 +265,9 @@ describe('LobeMinimaxAI', () => {
|
|
265
265
|
|
266
266
|
expect(result).toEqual({
|
267
267
|
messages: [{ content: 'Hello', role: 'user' }],
|
268
|
-
model: 'abab6.
|
268
|
+
model: 'abab6.5t-chat',
|
269
269
|
stream: true,
|
270
|
-
max_tokens:
|
270
|
+
max_tokens: 4096,
|
271
271
|
});
|
272
272
|
});
|
273
273
|
});
|
@@ -127,9 +127,14 @@ export class LobeMinimaxAI implements LobeRuntimeAI {
|
|
127
127
|
// https://www.minimaxi.com/document/guides/chat-model/V2
|
128
128
|
private getMaxTokens(model: string): number | undefined {
|
129
129
|
switch (model) {
|
130
|
-
case 'abab6.
|
130
|
+
case 'abab6.5t-chat':
|
131
|
+
case 'abab6.5g-chat':
|
132
|
+
case 'abab5.5s-chat':
|
133
|
+
case 'abab5.5-chat':{
|
134
|
+
return 4096;
|
135
|
+
}
|
131
136
|
case 'abab6.5s-chat': {
|
132
|
-
return
|
137
|
+
return 8192;
|
133
138
|
}
|
134
139
|
}
|
135
140
|
}
|
@@ -139,12 +144,17 @@ export class LobeMinimaxAI implements LobeRuntimeAI {
|
|
139
144
|
|
140
145
|
return {
|
141
146
|
...params,
|
142
|
-
|
147
|
+
frequency_penalty: undefined,
|
148
|
+
max_tokens:
|
149
|
+
payload.max_tokens !== undefined
|
150
|
+
? payload.max_tokens
|
151
|
+
: this.getMaxTokens(payload.model),
|
152
|
+
presence_penalty: undefined,
|
143
153
|
stream: true,
|
144
154
|
temperature:
|
145
|
-
|
146
|
-
|
147
|
-
|
155
|
+
temperature === undefined || temperature <= 0
|
156
|
+
? undefined
|
157
|
+
: temperature / 2,
|
148
158
|
|
149
159
|
tools: params.tools?.map((tool) => ({
|
150
160
|
function: {
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
2
|
+
import { processDoubleData } from './minimax'; // ๅ่ฎพๆไปถๅไธบ minimax.ts
|
3
|
+
|
4
|
+
describe('processDoubleData', () => {
|
5
|
+
it('should remove the second "data: {"id": and everything after it when matchCount is 2', () => {
|
6
|
+
const chunkValue = `data: {"id":"first"} some other text
|
7
|
+
|
8
|
+
data: {"id":"second"} more text`;
|
9
|
+
const result = processDoubleData(chunkValue);
|
10
|
+
expect(result).toBe('data: {"id":"first"} some other text');
|
11
|
+
});
|
12
|
+
|
13
|
+
it('should not modify chunkValue when matchCount is not 2', () => {
|
14
|
+
const chunkValue = `data: {"id":"first"} some other text`;
|
15
|
+
const result = processDoubleData(chunkValue);
|
16
|
+
expect(result).toBe(chunkValue);
|
17
|
+
});
|
18
|
+
|
19
|
+
it('should not modify chunkValue when matchCount is more than 2', () => {
|
20
|
+
const chunkValue = `data: {"id":"first"} some other text data: {"id":"second"} more text data: {"id":"third"} even more text`;
|
21
|
+
const result = processDoubleData(chunkValue);
|
22
|
+
expect(result).toBe(chunkValue);
|
23
|
+
});
|
24
|
+
});
|
@@ -4,6 +4,19 @@ import { ChatStreamCallbacks } from '../../types';
|
|
4
4
|
import { transformOpenAIStream } from './openai';
|
5
5
|
import { createCallbacksTransformer, createSSEProtocolTransformer } from './protocol';
|
6
6
|
|
7
|
+
export const processDoubleData = (chunkValue: string): string => {
|
8
|
+
const dataPattern = /data: {"id":"/g;
|
9
|
+
const matchCount = (chunkValue.match(dataPattern) || []).length;
|
10
|
+
let modifiedChunkValue = chunkValue;
|
11
|
+
if (matchCount === 2) {
|
12
|
+
const secondDataIdIndex = chunkValue.indexOf('data: {"id":', chunkValue.indexOf('data: {"id":') + 1);
|
13
|
+
if (secondDataIdIndex !== -1) {
|
14
|
+
modifiedChunkValue = chunkValue.slice(0, secondDataIdIndex).trim();
|
15
|
+
}
|
16
|
+
}
|
17
|
+
return modifiedChunkValue;
|
18
|
+
};
|
19
|
+
|
7
20
|
const unit8ArrayToJSONChunk = (unit8Array: Uint8Array): OpenAI.ChatCompletionChunk => {
|
8
21
|
const decoder = new TextDecoder();
|
9
22
|
|
@@ -12,6 +25,8 @@ const unit8ArrayToJSONChunk = (unit8Array: Uint8Array): OpenAI.ChatCompletionChu
|
|
12
25
|
// chunkValue example:
|
13
26
|
// data: {"id":"028a65377137d57aaceeffddf48ae99f","choices":[{"finish_reason":"tool_calls","index":0,"delta":{"role":"assistant","tool_calls":[{"id":"call_function_7371372822","type":"function","function":{"name":"realtime-weather____fetchCurrentWeather","arguments":"{\"city\": [\"ๆญๅท\", \"ๅไบฌ\"]}"}}]}}],"created":155511,"model":"abab6.5s-chat","object":"chat.completion.chunk"}
|
14
27
|
|
28
|
+
chunkValue = processDoubleData(chunkValue);
|
29
|
+
|
15
30
|
// so we need to remove `data:` prefix and then parse it as JSON
|
16
31
|
if (chunkValue.startsWith('data:')) {
|
17
32
|
chunkValue = chunkValue.slice(5).trim();
|
@@ -212,7 +212,7 @@ export class DiscoverService {
|
|
212
212
|
// Providers
|
213
213
|
|
214
214
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
215
|
-
getProviderList = async (
|
215
|
+
getProviderList = async (_locale: Locales): Promise<DiscoverProviderItem[]> => {
|
216
216
|
const list = DEFAULT_MODEL_PROVIDER_LIST.filter((item) => item.chatModels.length > 0);
|
217
217
|
return list.map((item) => {
|
218
218
|
const provider = {
|
@@ -79,7 +79,7 @@ export class ServerService implements IMessageService {
|
|
79
79
|
return lambdaClient.message.updatePluginState.mutate({ id, value });
|
80
80
|
}
|
81
81
|
|
82
|
-
bindMessagesToTopic(
|
82
|
+
bindMessagesToTopic(_topicId: string, _messageIds: string[]): Promise<any> {
|
83
83
|
throw new Error('Method not implemented.');
|
84
84
|
}
|
85
85
|
|
@@ -91,7 +91,7 @@ export class ServerService implements ISessionService {
|
|
91
91
|
return lambdaClient.session.updateSessionChatConfig.mutate({ id, value }, { signal });
|
92
92
|
}
|
93
93
|
|
94
|
-
getSessionsByType(
|
94
|
+
getSessionsByType(_type: 'agent' | 'group' | 'all' = 'all'): Promise<LobeSessions> {
|
95
95
|
// TODO: need be fixed
|
96
96
|
// @ts-ignore
|
97
97
|
return lambdaClient.session.getSessions.query({});
|
@@ -121,7 +121,7 @@ export class ServerService implements ISessionService {
|
|
121
121
|
return lambdaClient.sessionGroup.getSessionGroup.query();
|
122
122
|
}
|
123
123
|
|
124
|
-
batchCreateSessionGroups(
|
124
|
+
batchCreateSessionGroups(_groups: SessionGroups): Promise<BatchTaskResult> {
|
125
125
|
return Promise.resolve({ added: 0, ids: [], skips: [], success: true });
|
126
126
|
}
|
127
127
|
|
package/tsconfig.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"$schema": "https://json.schemastore.org/tsconfig",
|
3
3
|
"compilerOptions": {
|
4
4
|
"target": "ESNext",
|
5
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
5
|
+
"lib": ["dom", "dom.iterable", "esnext", "webworker"],
|
6
6
|
"allowJs": true,
|
7
7
|
"skipLibCheck": true,
|
8
8
|
"strict": true,
|
@@ -16,7 +16,7 @@
|
|
16
16
|
"jsx": "preserve",
|
17
17
|
"incremental": true,
|
18
18
|
"baseUrl": ".",
|
19
|
-
"types": ["vitest/globals"],
|
19
|
+
"types": ["vitest/globals", "@serwist/next/typings"],
|
20
20
|
"paths": {
|
21
21
|
"@/*": ["./src/*"],
|
22
22
|
"~test-utils": ["./tests/utils.tsx"]
|
@@ -27,7 +27,7 @@
|
|
27
27
|
}
|
28
28
|
]
|
29
29
|
},
|
30
|
-
"exclude": ["node_modules"],
|
30
|
+
"exclude": ["node_modules", "public/sw.js"],
|
31
31
|
"include": [
|
32
32
|
"next-env.d.ts",
|
33
33
|
"vitest.config.ts",
|