@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 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
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#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
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#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
- ? nextPWA({
196
- dest: 'public',
197
- register: true,
198
- workboxOptions: {
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.31",
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",
@@ -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: 1_048_576 + 8192,
19
+ tokens: 1_000_000 + 8192,
20
20
  vision: true,
21
21
  },
22
22
  {
23
- description: 'Gemini 1.5 Flash 0827 ๆไพ›ไบ†ไผ˜ๅŒ–ๅŽ็š„ๅคšๆจกๆ€ๅค„็†่ƒฝๅŠ›๏ผŒ้€‚็”จๅคš็งๅคๆ‚ไปปๅŠกๅœบๆ™ฏใ€‚',
24
- displayName: 'Gemini 1.5 Flash 0827',
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-exp-0827',
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-08-27',
34
- tokens: 1_048_576 + 8192,
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
- 'Gemini 1.5 Flash 8B 0924 ๆ˜ฏๆœ€ๆ–ฐ็š„ๅฎž้ชŒๆ€งๆจกๅž‹๏ผŒๅœจๆ–‡ๆœฌๅ’Œๅคšๆจกๆ€็”จไพ‹ไธญ้ƒฝๆœ‰ๆ˜พ่‘—็š„ๆ€ง่ƒฝๆๅ‡ใ€‚',
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-8b-exp-0924',
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
- releasedAt: '2024-09-24',
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 001 ๆ˜ฏไธ€ๆฌพ้ซ˜ๆ•ˆ็š„ๅคšๆจกๆ€ๆจกๅž‹๏ผŒๆ”ฏๆŒๅนฟๆณ›ๅบ”็”จ็š„ๆ‰ฉๅฑ•ใ€‚',
66
- displayName: 'Gemini 1.5 Flash 001',
53
+ description: 'Gemini 1.5 Flash 0827 ๆไพ›ไบ†ไผ˜ๅŒ–ๅŽ็š„ๅคšๆจกๆ€ๅค„็†่ƒฝๅŠ›๏ผŒ้€‚็”จๅคš็งๅคๆ‚ไปปๅŠกๅœบๆ™ฏใ€‚',
54
+ displayName: 'Gemini 1.5 Flash 0827',
67
55
  functionCall: true,
68
- id: 'gemini-1.5-flash-001',
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
- tokens: 1_048_576 + 8192,
63
+ releasedAt: '2024-08-27',
64
+ tokens: 1_000_000 + 8192,
76
65
  vision: true,
77
66
  },
67
+
78
68
  {
79
- description: 'Gemini 1.5 Flash 002 ๆ˜ฏไธ€ๆฌพ้ซ˜ๆ•ˆ็š„ๅคšๆจกๆ€ๆจกๅž‹๏ผŒๆ”ฏๆŒๅนฟๆณ›ๅบ”็”จ็š„ๆ‰ฉๅฑ•ใ€‚',
80
- displayName: 'Gemini 1.5 Flash 002',
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-002',
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-25',
90
- tokens: 1_048_576 + 8192,
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: 2_097_152 + 8192,
98
+ tokens: 2_000_000 + 8192,
108
99
  vision: true,
109
100
  },
110
101
  {
111
- description: 'Gemini 1.5 Pro 0827 ็ป“ๅˆๆœ€ๆ–ฐไผ˜ๅŒ–ๆŠ€ๆœฏ๏ผŒๅธฆๆฅๆ›ด้ซ˜ๆ•ˆ็š„ๅคšๆจกๆ€ๆ•ฐๆฎๅค„็†่ƒฝๅŠ›ใ€‚',
112
- displayName: 'Gemini 1.5 Pro 0827',
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-exp-0827',
107
+ id: 'gemini-1.5-pro-002',
115
108
  maxOutput: 8192,
116
109
  pricing: {
117
- cachedInput: 0.875,
118
- input: 3.5,
119
- output: 10.5,
110
+ cachedInput: 0.315,
111
+ input: 1.25,
112
+ output: 2.5,
120
113
  },
121
- releasedAt: '2024-08-27',
122
- tokens: 2_097_152 + 8192,
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 0801 ๆไพ›ๅ‡บ่‰ฒ็š„ๅคšๆจกๆ€ๅค„็†่ƒฝๅŠ›๏ผŒไธบๅบ”็”จๅผ€ๅ‘ๅธฆๆฅๆ›ดๅคง็ตๆดปๆ€งใ€‚',
127
- displayName: 'Gemini 1.5 Pro 0801',
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-exp-0801',
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-08-01',
137
- tokens: 2_097_152 + 8192,
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 001 ๆ˜ฏๅฏๆ‰ฉๅฑ•็š„ๅคšๆจกๆ€AI่งฃๅ†ณๆ–นๆกˆ๏ผŒๆ”ฏๆŒๅนฟๆณ›็š„ๅคๆ‚ไปปๅŠกใ€‚',
142
- displayName: 'Gemini 1.5 Pro 001',
134
+ description: 'Gemini 1.5 Pro 0827 ็ป“ๅˆๆœ€ๆ–ฐไผ˜ๅŒ–ๆŠ€ๆœฏ๏ผŒๅธฆๆฅๆ›ด้ซ˜ๆ•ˆ็š„ๅคšๆจกๆ€ๆ•ฐๆฎๅค„็†่ƒฝๅŠ›ใ€‚',
135
+ displayName: 'Gemini 1.5 Pro 0827',
143
136
  functionCall: true,
144
- id: 'gemini-1.5-pro-001',
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-02-15',
152
- tokens: 2_097_152 + 8192,
144
+ releasedAt: '2024-08-27',
145
+ tokens: 2_000_000 + 8192,
153
146
  vision: true,
154
147
  },
155
148
  {
156
- description:
157
- 'Gemini 1.5 Pro 002 ๆ˜ฏๆœ€ๆ–ฐ็š„็”Ÿไบงๅฐฑ็ปชๆจกๅž‹๏ผŒๆไพ›ๆ›ด้ซ˜่ดจ้‡็š„่พ“ๅ‡บ๏ผŒ็‰นๅˆซๅœจๆ•ฐๅญฆใ€้•ฟไธŠไธ‹ๆ–‡ๅ’Œ่ง†่ง‰ไปปๅŠกๆ–น้ขๆœ‰ๆ˜พ่‘—ๆๅ‡ใ€‚',
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-002',
152
+ id: 'gemini-1.5-pro-exp-0801',
162
153
  maxOutput: 8192,
163
154
  pricing: {
164
- cachedInput: 0.315,
165
- input: 1.25,
166
- output: 2.5,
155
+ cachedInput: 0.875,
156
+ input: 3.5,
157
+ output: 10.5,
167
158
  },
168
- releasedAt: '2024-09-24',
169
- tokens: 2_097_152 + 8192,
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 ็ณปๅˆ—ๆ˜ฏๅ…ถๆœ€ๅ…ˆ่ฟ›ใ€้€š็”จ็š„ A Iๆจกๅž‹๏ผŒ็”ฑ Google DeepMind ๆ‰“้€ ๏ผŒไธ“ไธบๅคšๆจกๆ€่ฎพ่ฎก๏ผŒๆ”ฏๆŒๆ–‡ๆœฌใ€ไปฃ็ ใ€ๅ›พๅƒใ€้Ÿณ้ข‘ๅ’Œ่ง†้ข‘็š„ๆ— ็ผ็†่งฃไธŽๅค„็†ใ€‚้€‚็”จไบŽไปŽๆ•ฐๆฎไธญๅฟƒๅˆฐ็งปๅŠจ่ฎพๅค‡็š„ๅคš็ง็Žฏๅขƒ๏ผŒๆžๅคงๆๅ‡ไบ†AIๆจกๅž‹็š„ๆ•ˆ็އไธŽๅบ”็”จๅนฟๆณ›ๆ€งใ€‚',
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: false,
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:
@@ -6,6 +6,7 @@ const ImageRenderer: DocRenderer = ({ mainState: { currentDocument } }) => {
6
6
 
7
7
  return (
8
8
  <Center height={'100%'} width={'100%'}>
9
+ {/* eslint-disable-next-line @next/next/no-img-element */}
9
10
  <img
10
11
  alt={fileName}
11
12
  height={'100%'}
@@ -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, useEffect, useLayoutEffect } from 'react';
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
- // @ts-ignore
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
- if (isShowPWAGuide) {
65
- install();
66
- }
67
- }, [canInstall, hidePWAInstaller, isShowPWAGuide]);
17
+ if (isPWA || !isShowPWAGuide) return null;
68
18
 
69
- if (isPWA) return null;
70
- return (
71
- <PWA
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.5-chat', () => {
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.5-chat',
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.5-chat',
268
+ model: 'abab6.5t-chat',
269
269
  stream: true,
270
- max_tokens: 2048,
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.5-chat':
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 2048;
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
- max_tokens: this.getMaxTokens(payload.model),
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
- temperature === undefined || temperature <= 0
146
- ? undefined
147
- : temperature / 2,
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 (locale: Locales): Promise<DiscoverProviderItem[]> => {
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(topicId: string, messageIds: string[]): Promise<any> {
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(type: 'agent' | 'group' | 'all' = 'all'): Promise<LobeSessions> {
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(groups: SessionGroups): Promise<BatchTaskResult> {
124
+ batchCreateSessionGroups(_groups: SessionGroups): Promise<BatchTaskResult> {
125
125
  return Promise.resolve({ added: 0, ids: [], skips: [], success: true });
126
126
  }
127
127
 
@@ -141,7 +141,9 @@ export const chatPlugin: StateCreator<
141
141
 
142
142
  try {
143
143
  content = JSON.parse(data);
144
- } catch {}
144
+ } catch {
145
+ /* empty block */
146
+ }
145
147
 
146
148
  if (!content) return;
147
149
 
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",