@lobehub/chat 1.37.2 → 1.39.0

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,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 1.39.0](https://github.com/lobehub/lobe-chat/compare/v1.38.0...v1.39.0)
6
+
7
+ <sup>Released on **2024-12-23**</sup>
8
+
9
+ #### ✨ Features
10
+
11
+ - **misc**: Upgrade to next15 and react19.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's improved
19
+
20
+ - **misc**: Upgrade to next15 and react19, closes [#4450](https://github.com/lobehub/lobe-chat/issues/4450) ([07d7417](https://github.com/lobehub/lobe-chat/commit/07d7417))
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
+
30
+ ## [Version 1.38.0](https://github.com/lobehub/lobe-chat/compare/v1.37.2...v1.38.0)
31
+
32
+ <sup>Released on **2024-12-23**</sup>
33
+
34
+ #### ✨ Features
35
+
36
+ - **misc**: Support thread in client pglite.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's improved
44
+
45
+ - **misc**: Support thread in client pglite, closes [#5150](https://github.com/lobehub/lobe-chat/issues/5150) ([848b29f](https://github.com/lobehub/lobe-chat/commit/848b29f))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.37.2](https://github.com/lobehub/lobe-chat/compare/v1.37.1...v1.37.2)
6
56
 
7
57
  <sup>Released on **2024-12-22**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "features": [
5
+ "Upgrade to next15 and react19."
6
+ ]
7
+ },
8
+ "date": "2024-12-23",
9
+ "version": "1.39.0"
10
+ },
11
+ {
12
+ "children": {
13
+ "features": [
14
+ "Support thread in client pglite."
15
+ ]
16
+ },
17
+ "date": "2024-12-23",
18
+ "version": "1.38.0"
19
+ },
2
20
  {
3
21
  "children": {
4
22
  "improvements": [
@@ -1,6 +1,7 @@
1
1
  import analyzer from '@next/bundle-analyzer';
2
2
  import { withSentryConfig } from '@sentry/nextjs';
3
3
  import withSerwistInit from '@serwist/next';
4
+ import type { NextConfig } from 'next';
4
5
  import ReactComponentName from 'react-scan/react-component-name/webpack';
5
6
 
6
7
  const isProd = process.env.NODE_ENV === 'production';
@@ -13,8 +14,7 @@ const API_PROXY_ENDPOINT = process.env.API_PROXY_ENDPOINT || '';
13
14
 
14
15
  const basePath = process.env.NEXT_PUBLIC_BASE_PATH;
15
16
 
16
- /** @type {import('next').NextConfig} */
17
- const nextConfig = {
17
+ const nextConfig: NextConfig = {
18
18
  basePath,
19
19
  compress: isProd,
20
20
  experimental: {
@@ -27,7 +27,6 @@ const nextConfig = {
27
27
  'gpt-tokenizer',
28
28
  'chroma-js',
29
29
  ],
30
- serverComponentsExternalPackages: ['@electric-sql/pglite'],
31
30
  webVitalsAttribution: ['CLS', 'LCP'],
32
31
  },
33
32
 
@@ -107,7 +106,6 @@ const nextConfig = {
107
106
  },
108
107
  ];
109
108
  },
110
-
111
109
  output: buildWithDocker ? 'standalone' : undefined,
112
110
  reactStrictMode: true,
113
111
  redirects: async () => [
@@ -169,13 +167,14 @@ const nextConfig = {
169
167
  source: '/welcome',
170
168
  },
171
169
  ],
172
-
173
170
  rewrites: async () => [
174
171
  // due to google api not work correct in some countries
175
172
  // we need a proxy to bypass the restriction
176
173
  { destination: `${API_PROXY_ENDPOINT}/api/chat/google`, source: '/api/chat/google' },
177
174
  ],
178
175
 
176
+ serverExternalPackages: ['@electric-sql/pglite'],
177
+
179
178
  webpack(config) {
180
179
  config.experiments = {
181
180
  asyncWebAssembly: true,
@@ -206,7 +205,7 @@ const nextConfig = {
206
205
  },
207
206
  };
208
207
 
209
- const noWrapper = (config) => config;
208
+ const noWrapper = (config: NextConfig) => config;
210
209
 
211
210
  const withBundleAnalyzer = process.env.ANALYZE === 'true' ? analyzer() : noWrapper;
212
211
 
@@ -221,7 +220,7 @@ const withPWA = isProd
221
220
  const hasSentry = !!process.env.NEXT_PUBLIC_SENTRY_DSN;
222
221
  const withSentry =
223
222
  isProd && hasSentry
224
- ? (c) =>
223
+ ? (c: NextConfig) =>
225
224
  withSentryConfig(
226
225
  c,
227
226
  {
@@ -262,4 +261,4 @@ const withSentry =
262
261
  )
263
262
  : noWrapper;
264
263
 
265
- export default withBundleAnalyzer(withPWA(withSentry(nextConfig)));
264
+ export default withBundleAnalyzer(withPWA(withSentry(nextConfig) as NextConfig));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.37.2",
3
+ "version": "1.39.0",
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",
@@ -39,7 +39,7 @@
39
39
  "db:push-test": "NODE_ENV=test drizzle-kit push",
40
40
  "db:studio": "drizzle-kit studio",
41
41
  "db:z-pull": "drizzle-kit introspect",
42
- "dev": "next dev -p 3010",
42
+ "dev": "next dev --turbo -p 3010",
43
43
  "docs:i18n": "lobe-i18n md && npm run lint:mdx",
44
44
  "docs:seo": "lobe-seo && npm run lint:mdx",
45
45
  "i18n": "npm run workflow:i18n && lobe-i18n",
@@ -104,7 +104,7 @@
104
104
  "dependencies": {
105
105
  "@ant-design/icons": "^5.5.1",
106
106
  "@ant-design/pro-components": "^2.7.18",
107
- "@anthropic-ai/sdk": "^0.32.0",
107
+ "@anthropic-ai/sdk": "^0.33.0",
108
108
  "@auth/core": "^0.37.0",
109
109
  "@aws-sdk/client-bedrock-runtime": "^3.675.0",
110
110
  "@aws-sdk/client-s3": "^3.675.0",
@@ -130,7 +130,7 @@
130
130
  "@lobehub/tts": "^1.25.1",
131
131
  "@lobehub/ui": "^1.153.13",
132
132
  "@neondatabase/serverless": "^0.10.1",
133
- "@next/third-parties": "^14.2.15",
133
+ "@next/third-parties": "^15.0.0",
134
134
  "@react-spring/web": "^9.7.5",
135
135
  "@sentry/nextjs": "^7.119.2",
136
136
  "@serwist/next": "^9.0.9",
@@ -145,7 +145,7 @@
145
145
  "@vercel/speed-insights": "^1.0.12",
146
146
  "ahooks": "^3.8.1",
147
147
  "ai": "^3.4.16",
148
- "antd": "^5.21.4",
148
+ "antd": "^5.22.6",
149
149
  "antd-style": "^3.7.1",
150
150
  "brotli-wasm": "^3.0.1",
151
151
  "chroma-js": "^2.6.0",
@@ -175,7 +175,7 @@
175
175
  "mammoth": "^1.8.0",
176
176
  "modern-screenshot": "^4.4.39",
177
177
  "nanoid": "^5.0.7",
178
- "next": "14.2.8",
178
+ "next": "^15.1.2",
179
179
  "next-auth": "beta",
180
180
  "next-mdx-remote": "^4.4.1",
181
181
  "nextjs-toploader": "^3.7.15",
@@ -195,9 +195,9 @@
195
195
  "pwa-install-handler": "^2.6.1",
196
196
  "query-string": "^9.1.1",
197
197
  "random-words": "^2.0.1",
198
- "react": "^18.3.1",
198
+ "react": "^19.0.0",
199
199
  "react-confetti": "^6.1.0",
200
- "react-dom": "^18.3.1",
200
+ "react-dom": "^19.0.0",
201
201
  "react-fast-marquee": "^1.6.5",
202
202
  "react-hotkeys-hook": "^4.5.1",
203
203
  "react-i18next": "14.0.2",
@@ -244,8 +244,8 @@
244
244
  "@lobehub/i18n-cli": "^1.20.0",
245
245
  "@lobehub/lint": "^1.24.4",
246
246
  "@lobehub/seo-cli": "^1.4.2",
247
- "@next/bundle-analyzer": "^14.2.15",
248
- "@next/eslint-plugin-next": "^14.2.15",
247
+ "@next/bundle-analyzer": "^15.0.0",
248
+ "@next/eslint-plugin-next": "^15.0.0",
249
249
  "@peculiar/webcrypto": "^1.5.0",
250
250
  "@semantic-release/exec": "^6.0.3",
251
251
  "@testing-library/jest-dom": "^6.6.2",
@@ -8,6 +8,8 @@ export const CURRENT_VERSION = pkg.version;
8
8
  export const isServerMode = getServerDBConfig().NEXT_PUBLIC_ENABLED_SERVER_SERVICE;
9
9
  export const isUsePgliteDB = process.env.NEXT_PUBLIC_CLIENT_DB === 'pglite';
10
10
 
11
+ export const isDeprecatedEdition = !isServerMode && !isUsePgliteDB;
12
+
11
13
  // @ts-ignore
12
14
  export const isCustomBranding = BRANDING_NAME !== 'LobeChat';
13
15
  // @ts-ignore
@@ -3,7 +3,7 @@ import { Copy, Edit, ListRestart, RotateCcw, Split, Trash } from 'lucide-react';
3
3
  import { useMemo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
- import { isServerMode } from '@/const/version';
6
+ import { isDeprecatedEdition } from '@/const/version';
7
7
 
8
8
  interface ChatListActionsBar {
9
9
  branching: ActionIconGroupItems;
@@ -23,10 +23,10 @@ export const useChatListActionsBar = ({
23
23
  return useMemo(
24
24
  () => ({
25
25
  branching: {
26
- disable: !isServerMode,
26
+ disable: isDeprecatedEdition,
27
27
  icon: Split,
28
28
  key: 'branching',
29
- label: isServerMode
29
+ label: !isDeprecatedEdition
30
30
  ? t('branching', { defaultValue: 'Create Sub Topic' })
31
31
  : t('branchingDisable'),
32
32
  },
@@ -0,0 +1,20 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import { unstableSetRender } from "antd";
5
+ import { createRoot } from "react-dom/client";
6
+
7
+ const AntdV5MonkeyPatch = () => {
8
+ useEffect(() => {
9
+ unstableSetRender((node, container) => {
10
+ const root = createRoot(container);
11
+ root.render(node);
12
+ return async () => {
13
+ root.unmount();
14
+ };
15
+ });
16
+ }, []);
17
+ return null;
18
+ };
19
+
20
+ export default AntdV5MonkeyPatch;
@@ -17,6 +17,7 @@ import { ServerConfigStoreProvider } from '@/store/serverConfig';
17
17
  import { getAntdLocale } from '@/utils/locale';
18
18
  import { isMobileDevice } from '@/utils/server/responsive';
19
19
 
20
+ import AntdV5MonkeyPatch from './AntdV5MonkeyPatch';
20
21
  import AppTheme from './AppTheme';
21
22
  import Debug from './Debug';
22
23
  import Locale from './Locale';
@@ -91,6 +92,7 @@ const GlobalLayout = async ({ children }: PropsWithChildren) => {
91
92
  <DebugUI />
92
93
  <Debug />
93
94
  </AppTheme>
95
+ <AntdV5MonkeyPatch />
94
96
  </Locale>
95
97
  </StyleRegistry>
96
98
  );
@@ -33,7 +33,7 @@ export default {
33
33
  blog: '产品博客',
34
34
  branching: '创建子话题',
35
35
  branchingDisable:
36
- '「子话题」功能仅服务端版本可用,如需该功能,请切换到服务端部署模式或使用 LobeChat Cloud',
36
+ '「子话题」功能在当前模式下不可用,如需该功能,请切换到 Postgres/Pglite DB 模式或使用 LobeChat Cloud',
37
37
  cancel: '取消',
38
38
  changelog: '更新日志',
39
39
  clientDB: {
@@ -0,0 +1,57 @@
1
+ import { INBOX_SESSION_ID } from '@/const/session';
2
+ import { clientDB } from '@/database/client/db';
3
+ import { MessageModel } from '@/database/server/models/message';
4
+ import { ThreadModel } from '@/database/server/models/thread';
5
+ import { BaseClientService } from '@/services/baseClientService';
6
+ import { CreateMessageParams } from '@/types/message';
7
+ import { CreateThreadParams, ThreadItem } from '@/types/topic';
8
+
9
+ import { IThreadService } from './type';
10
+
11
+ interface CreateThreadWithMessageParams extends CreateThreadParams {
12
+ message: CreateMessageParams;
13
+ }
14
+ export class ClientService extends BaseClientService implements IThreadService {
15
+ private get threadModel(): ThreadModel {
16
+ return new ThreadModel(clientDB as any, this.userId);
17
+ }
18
+ private get messageModel(): MessageModel {
19
+ return new MessageModel(clientDB as any, this.userId);
20
+ }
21
+
22
+ getThreads = async (topicId: string): Promise<ThreadItem[]> => {
23
+ return this.threadModel.queryByTopicId(topicId);
24
+ };
25
+
26
+ createThreadWithMessage = async (
27
+ input: CreateThreadWithMessageParams,
28
+ ): Promise<{ messageId: string; threadId: string }> => {
29
+ const thread = await this.threadModel.create({
30
+ parentThreadId: input.parentThreadId,
31
+ sourceMessageId: input.sourceMessageId,
32
+ title: input.message.content.slice(0, 20),
33
+ topicId: input.topicId,
34
+ type: input.type,
35
+ });
36
+
37
+ const message = await this.messageModel.create({
38
+ ...input.message,
39
+ sessionId: this.toDbSessionId(input.message.sessionId) as string,
40
+ threadId: thread?.id,
41
+ });
42
+
43
+ return { messageId: message?.id, threadId: thread?.id };
44
+ };
45
+
46
+ updateThread(id: string, data: Partial<ThreadItem>): Promise<any> {
47
+ return this.threadModel.update(id, data);
48
+ }
49
+
50
+ removeThread(id: string): Promise<any> {
51
+ return this.threadModel.delete(id);
52
+ }
53
+
54
+ private toDbSessionId(sessionId: string | undefined) {
55
+ return sessionId === INBOX_SESSION_ID ? null : sessionId;
56
+ }
57
+ }
@@ -0,0 +1,5 @@
1
+ import { ClientService } from './client';
2
+ import { ServerService } from './server';
3
+
4
+ export const threadService =
5
+ process.env.NEXT_PUBLIC_SERVICE_MODE === 'server' ? new ServerService() : new ClientService();
@@ -3,10 +3,12 @@ import { lambdaClient } from '@/libs/trpc/client';
3
3
  import { CreateMessageParams } from '@/types/message';
4
4
  import { CreateThreadParams, ThreadItem } from '@/types/topic';
5
5
 
6
+ import { IThreadService } from './type';
7
+
6
8
  interface CreateThreadWithMessageParams extends CreateThreadParams {
7
9
  message: CreateMessageParams;
8
10
  }
9
- export class ThreadService {
11
+ export class ServerService implements IThreadService {
10
12
  getThreads = (topicId: string): Promise<ThreadItem[]> => {
11
13
  return lambdaClient.thread.getThreads.query({ topicId });
12
14
  };
@@ -21,34 +23,15 @@ export class ThreadService {
21
23
  });
22
24
  }
23
25
 
24
- // createThread(params: CreateThreadParams): Promise<string> {
25
- // return lambdaClient.thread.createThread.mutate(params);
26
- // }
27
-
28
26
  updateThread(id: string, data: Partial<ThreadItem>): Promise<any> {
29
27
  return lambdaClient.thread.updateThread.mutate({ id, value: data });
30
28
  }
31
29
 
32
- //
33
30
  removeThread(id: string): Promise<any> {
34
31
  return lambdaClient.thread.removeThread.mutate({ id });
35
32
  }
36
- //
37
- // removeThreads(sessionId: string): Promise<any> {
38
- // return lambdaClient.thread.batchDeleteBySessionId.mutate({ id: this.toDbSessionId(sessionId) });
39
- // }
40
- //
41
- // batchRemoveThreads(topics: string[]): Promise<any> {
42
- // return lambdaClient.thread.batchDelete.mutate({ ids: topics });
43
- // }
44
- //
45
- // removeAllThread(): Promise<any> {
46
- // return lambdaClient.thread.removeAllThreads.mutate();
47
- // }
48
33
 
49
34
  private toDbSessionId(sessionId: string | undefined) {
50
35
  return sessionId === INBOX_SESSION_ID ? null : sessionId;
51
36
  }
52
37
  }
53
-
54
- export const threadService = new ThreadService();
@@ -0,0 +1,20 @@
1
+ /* eslint-disable typescript-sort-keys/interface */
2
+ import { CreateMessageParams } from '@/types/message';
3
+ import { CreateThreadParams, ThreadItem } from '@/types/topic';
4
+
5
+ interface CreateThreadWithMessageParams extends CreateThreadParams {
6
+ message: CreateMessageParams;
7
+ }
8
+
9
+ export interface IThreadService {
10
+ getThreads(topicId: string): Promise<ThreadItem[]>;
11
+
12
+ createThreadWithMessage({
13
+ message,
14
+ ...params
15
+ }: CreateThreadWithMessageParams): Promise<{ messageId: string; threadId: string }>;
16
+
17
+ updateThread(id: string, data: Partial<ThreadItem>): Promise<any>;
18
+ //
19
+ removeThread(id: string): Promise<any>;
20
+ }
@@ -6,7 +6,7 @@ import { StateCreator } from 'zustand/vanilla';
6
6
 
7
7
  import { chainSummaryTitle } from '@/chains/summaryTitle';
8
8
  import { LOADING_FLAT, THREAD_DRAFT_ID } from '@/const/message';
9
- import { isServerMode } from '@/const/version';
9
+ import { isDeprecatedEdition } from '@/const/version';
10
10
  import { useClientDataSWR } from '@/libs/swr';
11
11
  import { chatService } from '@/services/chat';
12
12
  import { threadService } from '@/services/thread';
@@ -211,7 +211,7 @@ export const chatThreadMessage: StateCreator<
211
211
 
212
212
  useFetchThreads: (enable, topicId) =>
213
213
  useClientDataSWR<ThreadItem[]>(
214
- enable && !!topicId && isServerMode ? [SWR_USE_FETCH_THREADS, topicId] : null,
214
+ enable && !!topicId && !isDeprecatedEdition ? [SWR_USE_FETCH_THREADS, topicId] : null,
215
215
  async ([, topicId]: [string, string]) => threadService.getThreads(topicId),
216
216
  {
217
217
  suspense: true,