@lobehub/chat 1.19.31 → 1.19.32

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,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.19.32](https://github.com/lobehub/lobe-chat/compare/v1.19.31...v1.19.32)
6
+
7
+ <sup>Released on **2024-09-25**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Add function call for `taichu_llm`.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **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))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.19.31](https://github.com/lobehub/lobe-chat/compare/v1.19.30...v1.19.31)
6
31
 
7
32
  <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.32",
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();
@@ -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;
@@ -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",