@lobehub/lobehub 2.0.0-next.17 → 2.0.0-next.19

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.
Files changed (46) hide show
  1. package/.env.desktop +1 -2
  2. package/.env.example +0 -3
  3. package/.env.example.development +0 -2
  4. package/.github/workflows/e2e.yml +14 -0
  5. package/.github/workflows/release.yml +0 -1
  6. package/.github/workflows/test.yml +0 -1
  7. package/CHANGELOG.md +58 -0
  8. package/Dockerfile +1 -3
  9. package/changelog/v1.json +18 -0
  10. package/locales/ar/oauth.json +1 -0
  11. package/locales/bg-BG/oauth.json +1 -0
  12. package/locales/de-DE/oauth.json +1 -0
  13. package/locales/en-US/oauth.json +1 -0
  14. package/locales/es-ES/oauth.json +1 -0
  15. package/locales/fa-IR/oauth.json +1 -0
  16. package/locales/fr-FR/oauth.json +1 -0
  17. package/locales/it-IT/oauth.json +1 -0
  18. package/locales/ja-JP/oauth.json +1 -0
  19. package/locales/ko-KR/oauth.json +1 -0
  20. package/locales/nl-NL/oauth.json +1 -0
  21. package/locales/pl-PL/oauth.json +1 -0
  22. package/locales/pt-BR/oauth.json +1 -0
  23. package/locales/ru-RU/oauth.json +1 -0
  24. package/locales/tr-TR/oauth.json +1 -0
  25. package/locales/vi-VN/oauth.json +1 -0
  26. package/locales/zh-CN/oauth.json +1 -0
  27. package/locales/zh-TW/oauth.json +1 -0
  28. package/package.json +2 -2
  29. package/packages/database/src/core/web-server.ts +2 -1
  30. package/packages/memory-extract/package.json +1 -1
  31. package/packages/types/src/message/ui/params.ts +98 -4
  32. package/packages/types/src/user/index.ts +13 -1
  33. package/packages/types/src/user/settings/index.ts +22 -0
  34. package/scripts/migrateServerDB/errorHint.js +1 -7
  35. package/src/app/[variants]/(main)/_layout/Desktop/SideBar/TopActions.tsx +1 -4
  36. package/src/app/[variants]/oauth/consent/[uid]/Consent/BuiltinConsent.tsx +57 -0
  37. package/src/app/[variants]/oauth/consent/[uid]/{Consent.tsx → Consent/index.tsx} +9 -1
  38. package/src/app/[variants]/oauth/consent/[uid]/Login.tsx +9 -1
  39. package/src/config/db.ts +0 -5
  40. package/src/libs/next-auth/auth.config.ts +2 -5
  41. package/src/locales/default/oauth.ts +1 -0
  42. package/src/server/routers/lambda/__tests__/integration/message.integration.test.ts +0 -41
  43. package/src/server/routers/lambda/message.ts +4 -11
  44. package/src/server/routers/lambda/user.ts +24 -25
  45. package/src/services/message/server.ts +0 -4
  46. package/src/services/message/type.ts +0 -2
package/.env.desktop CHANGED
@@ -4,6 +4,5 @@ FEATURE_FLAGS=-check_updates,+pin_list
4
4
  KEY_VAULTS_SECRET=oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE=
5
5
  DATABASE_URL=postgresql://postgres@localhost:5432/postgres
6
6
  SEARCH_PROVIDERS=search1api
7
- NEXT_PUBLIC_SERVICE_MODE='server'
8
7
  NEXT_PUBLIC_IS_DESKTOP_APP=1
9
- NEXT_PUBLIC_ENABLE_NEXT_AUTH=0
8
+ NEXT_PUBLIC_ENABLE_NEXT_AUTH=0
package/.env.example CHANGED
@@ -273,9 +273,6 @@ OPENAI_API_KEY=sk-xxxxxxxxx
273
273
  ########## Server Database #############
274
274
  ########################################
275
275
 
276
- # Specify the service mode as server if you want to use the server database
277
- # NEXT_PUBLIC_SERVICE_MODE=server
278
-
279
276
  # Postgres database URL
280
277
  # DATABASE_URL=postgres://username:password@host:port/database
281
278
 
@@ -8,8 +8,6 @@ UNSAFE_SECRET="ww+0igxjGRAAR/eTNFQ55VmhQB5KE5trFZseuntThJs="
8
8
  UNSAFE_PASSWORD="CHANGE_THIS_PASSWORD_IN_PRODUCTION"
9
9
 
10
10
  # Core Server Configuration
11
- # Service mode - set to 'server' for server-side deployment
12
- NEXT_PUBLIC_SERVICE_MODE=server
13
11
 
14
12
  # Service Ports Configuration
15
13
  LOBE_PORT=3010
@@ -14,6 +14,17 @@ jobs:
14
14
  e2e:
15
15
  name: Test Web App
16
16
  runs-on: ubuntu-latest
17
+ services:
18
+ postgres:
19
+ image: paradedb/paradedb:latest
20
+ env:
21
+ POSTGRES_PASSWORD: postgres
22
+ options: >-
23
+ --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
24
+
25
+ ports:
26
+ - 5432:5432
27
+
17
28
  timeout-minutes: 25
18
29
  steps:
19
30
  - name: Checkout
@@ -33,6 +44,9 @@ jobs:
33
44
  - name: Run E2E tests
34
45
  env:
35
46
  PORT: 3010
47
+ DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
48
+ DATABASE_DRIVER: node
49
+ KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
36
50
  run: bun run e2e
37
51
 
38
52
  - name: Upload Cucumber HTML report (on failure)
@@ -54,7 +54,6 @@ jobs:
54
54
  env:
55
55
  DATABASE_TEST_URL: postgresql://postgres:postgres@localhost:5432/postgres
56
56
  DATABASE_DRIVER: node
57
- NEXT_PUBLIC_SERVICE_MODE: server
58
57
  KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
59
58
  S3_PUBLIC_DOMAIN: https://example.com
60
59
  APP_URL: https://home.com
@@ -165,7 +165,6 @@ jobs:
165
165
  env:
166
166
  DATABASE_TEST_URL: postgresql://postgres:postgres@localhost:5432/postgres
167
167
  DATABASE_DRIVER: node
168
- NEXT_PUBLIC_SERVICE_MODE: server
169
168
  KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
170
169
  S3_PUBLIC_DOMAIN: https://example.com
171
170
  APP_URL: https://home.com
package/CHANGELOG.md CHANGED
@@ -2,6 +2,64 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.19](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.18...v2.0.0-next.19)
6
+
7
+ <sup>Released on **2025-11-03**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Remove `NEXT_PUBLIC_SERVICE_MODE` env and use server by default.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Remove `NEXT_PUBLIC_SERVICE_MODE` env and use server by default, closes [#10017](https://github.com/lobehub/lobe-chat/issues/10017) ([f2ab2fc](https://github.com/lobehub/lobe-chat/commit/f2ab2fc))
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 2.0.0-next.18](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.17...v2.0.0-next.18)
31
+
32
+ <sup>Released on **2025-11-03**</sup>
33
+
34
+ #### ♻ Code Refactoring
35
+
36
+ - **misc**: Refactor trpc request to use zod schema.
37
+
38
+ #### 💄 Styles
39
+
40
+ - **misc**: Improve built-in client OIDC user flow.
41
+
42
+ <br/>
43
+
44
+ <details>
45
+ <summary><kbd>Improvements and Fixes</kbd></summary>
46
+
47
+ #### Code refactoring
48
+
49
+ - **misc**: Refactor trpc request to use zod schema, closes [#10016](https://github.com/lobehub/lobe-chat/issues/10016) ([1a84f2c](https://github.com/lobehub/lobe-chat/commit/1a84f2c))
50
+
51
+ #### Styles
52
+
53
+ - **misc**: Improve built-in client OIDC user flow, closes [#10020](https://github.com/lobehub/lobe-chat/issues/10020) ([80202ed](https://github.com/lobehub/lobe-chat/commit/80202ed))
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 2.0.0-next.17](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.16...v2.0.0-next.17)
6
64
 
7
65
  <sup>Released on **2025-11-03**</sup>
package/Dockerfile CHANGED
@@ -37,7 +37,6 @@ FROM base AS builder
37
37
 
38
38
  ARG USE_CN_MIRROR
39
39
  ARG NEXT_PUBLIC_BASE_PATH
40
- ARG NEXT_PUBLIC_SERVICE_MODE
41
40
  ARG NEXT_PUBLIC_ENABLE_NEXT_AUTH
42
41
  ARG NEXT_PUBLIC_ENABLE_CLERK_AUTH
43
42
  ARG NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
@@ -53,8 +52,7 @@ ARG FEATURE_FLAGS
53
52
  ENV NEXT_PUBLIC_BASE_PATH="${NEXT_PUBLIC_BASE_PATH}" \
54
53
  FEATURE_FLAGS="${FEATURE_FLAGS}"
55
54
 
56
- ENV NEXT_PUBLIC_SERVICE_MODE="${NEXT_PUBLIC_SERVICE_MODE:-server}" \
57
- NEXT_PUBLIC_ENABLE_NEXT_AUTH="${NEXT_PUBLIC_ENABLE_NEXT_AUTH:-1}" \
55
+ ENV NEXT_PUBLIC_ENABLE_NEXT_AUTH="${NEXT_PUBLIC_ENABLE_NEXT_AUTH:-1}" \
58
56
  NEXT_PUBLIC_ENABLE_CLERK_AUTH="${NEXT_PUBLIC_ENABLE_CLERK_AUTH:-0}" \
59
57
  NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="${NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY}" \
60
58
  CLERK_WEBHOOK_SECRET="whsec_xxx" \
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Remove NEXT_PUBLIC_SERVICE_MODE env and use server by default."
6
+ ]
7
+ },
8
+ "date": "2025-11-03",
9
+ "version": "2.0.0-next.19"
10
+ },
11
+ {
12
+ "children": {
13
+ "improvements": [
14
+ "Improve built-in client OIDC user flow."
15
+ ]
16
+ },
17
+ "date": "2025-11-03",
18
+ "version": "2.0.0-next.18"
19
+ },
2
20
  {
3
21
  "children": {
4
22
  "fixes": [
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "طلب الأذونات التالية:",
20
20
  "redirectUri": "سيتم إعادة التوجيه إلى بعد نجاح التفويض",
21
+ "redirecting": "تم التفويض بنجاح، جارٍ إعادة التوجيه...",
21
22
  "scope": {
22
23
  "email": "الوصول إلى عنوان بريدك الإلكتروني",
23
24
  "offline_access": "السماح للتطبيق بالوصول إلى بياناتك",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Искаме следните разрешения:",
20
20
  "redirectUri": "Ще бъдете пренасочени след успешното разрешение",
21
+ "redirecting": "Успешно упълномощено, пренасочване...",
21
22
  "scope": {
22
23
  "email": "Достъп до вашия имейл адрес",
23
24
  "offline_access": "Позволете на клиента да получи достъп до вашите данни",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Anforderung der folgenden Berechtigungen:",
20
20
  "redirectUri": "Nach erfolgreicher Autorisierung werden Sie umgeleitet zu",
21
+ "redirecting": "Autorisierung erfolgreich, Weiterleitung...",
21
22
  "scope": {
22
23
  "email": "Zugriff auf Ihre E-Mail-Adresse",
23
24
  "offline_access": "Erlauben Sie dem Client, auf Ihre Daten zuzugreifen",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Requesting the following permissions:",
20
20
  "redirectUri": "You will be redirected to after successful authorization",
21
+ "redirecting": "Authorization successful, redirecting...",
21
22
  "scope": {
22
23
  "email": "Access your email address",
23
24
  "offline_access": "Allow the client to access your data",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Solicitar los siguientes permisos:",
20
20
  "redirectUri": "Se redirigirá a después de la autorización exitosa",
21
+ "redirecting": "Autorización exitosa, redirigiendo...",
21
22
  "scope": {
22
23
  "email": "Acceder a su dirección de correo electrónico",
23
24
  "offline_access": "Permitir que el cliente acceda a sus datos",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "درخواست مجوزهای زیر:",
20
20
  "redirectUri": "پس از موفقیت در مجوز، به آدرس زیر هدایت می‌شوید",
21
+ "redirecting": "دسترسی با موفقیت انجام شد، در حال انتقال...",
21
22
  "scope": {
22
23
  "email": "دسترسی به آدرس ایمیل شما",
23
24
  "offline_access": "اجازه دسترسی به داده‌های شما توسط کلاینت",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Demander les autorisations suivantes :",
20
20
  "redirectUri": "Vous serez redirigé vers après une autorisation réussie",
21
+ "redirecting": "Autorisation réussie, redirection en cours...",
21
22
  "scope": {
22
23
  "email": "Accéder à votre adresse e-mail",
23
24
  "offline_access": "Autoriser le client à accéder à vos données",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Richiesta delle seguenti autorizzazioni:",
20
20
  "redirectUri": "Verrai reindirizzato a dopo un'autorizzazione riuscita",
21
+ "redirecting": "Autorizzazione completata, reindirizzamento in corso...",
21
22
  "scope": {
22
23
  "email": "Accesso al tuo indirizzo email",
23
24
  "offline_access": "Consenti all'accesso del client ai tuoi dati",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "以下の権限をリクエストします:",
20
20
  "redirectUri": "承認が成功した後、次の場所にリダイレクトされます",
21
+ "redirecting": "認証に成功しました。リダイレクト中です...",
21
22
  "scope": {
22
23
  "email": "あなたのメールアドレスにアクセス",
23
24
  "offline_access": "クライアントがあなたのデータにアクセスすることを許可",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "다음 권한을 요청합니다:",
20
20
  "redirectUri": "인증이 완료되면 다음으로 리디렉션됩니다:",
21
+ "redirecting": "인증이 완료되었습니다. 이동 중...",
21
22
  "scope": {
22
23
  "email": "귀하의 이메일 주소에 접근",
23
24
  "offline_access": "클라이언트가 귀하의 데이터에 접근할 수 있도록 허용",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Vraag om de volgende toestemmingen:",
20
20
  "redirectUri": "U wordt omgeleid naar na succesvolle autorisatie",
21
+ "redirecting": "Autorisatie geslaagd, doorverwijzen...",
21
22
  "scope": {
22
23
  "email": "Toegang tot uw e-mailadres",
23
24
  "offline_access": "Toestaan dat de client toegang heeft tot uw gegevens",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Proszę o następujące uprawnienia:",
20
20
  "redirectUri": "Zostaniesz przekierowany po pomyślnym autoryzowaniu",
21
+ "redirecting": "Autoryzacja zakończona pomyślnie, przekierowywanie...",
21
22
  "scope": {
22
23
  "email": "Dostęp do Twojego adresu e-mail",
23
24
  "offline_access": "Zezwól klientowi na dostęp do Twoich danych",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Solicitar as seguintes permissões:",
20
20
  "redirectUri": "Você será redirecionado após a autorização bem-sucedida",
21
+ "redirecting": "Autorização bem-sucedida, redirecionando...",
21
22
  "scope": {
22
23
  "email": "Acessar seu endereço de e-mail",
23
24
  "offline_access": "Permitir que o cliente acesse seus dados",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Запросить следующие разрешения:",
20
20
  "redirectUri": "После успешного авторизации будет выполнен редирект на",
21
+ "redirecting": "Авторизация прошла успешно, перенаправление...",
21
22
  "scope": {
22
23
  "email": "Доступ к вашему адресу электронной почты",
23
24
  "offline_access": "Разрешить клиенту доступ к вашим данным",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Aşağıdaki izinleri talep et:",
20
20
  "redirectUri": "İzin verildikten sonra şu adrese yönlendirileceksiniz",
21
+ "redirecting": "Yetkilendirme başarılı, yönlendiriliyor...",
21
22
  "scope": {
22
23
  "email": "E-posta adresinize erişim",
23
24
  "offline_access": "Müşterinin verilerinize erişmesine izin ver",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "Yêu cầu các quyền sau:",
20
20
  "redirectUri": "Sẽ được chuyển hướng đến sau khi ủy quyền thành công",
21
+ "redirecting": "Ủy quyền thành công, đang chuyển hướng...",
21
22
  "scope": {
22
23
  "email": "Truy cập địa chỉ email của bạn",
23
24
  "offline_access": "Cho phép ứng dụng truy cập dữ liệu của bạn",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "请求以下权限:",
20
20
  "redirectUri": "授权成功后将重定向到",
21
+ "redirecting": "授权成功,跳转中...",
21
22
  "scope": {
22
23
  "email": "访问您的电子邮件地址",
23
24
  "offline_access": "允许客户端访问您的数据",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "permissionsTitle": "請求以下權限:",
20
20
  "redirectUri": "授權成功後將重定向到",
21
+ "redirecting": "授權成功,正在跳轉...",
21
22
  "scope": {
22
23
  "email": "訪問您的電子郵件地址",
23
24
  "offline_access": "允許客戶端訪問您的資料",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.17",
3
+ "version": "2.0.0-next.19",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent 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",
@@ -38,7 +38,7 @@
38
38
  "build:analyze": "NODE_OPTIONS=--max-old-space-size=6144 ANALYZE=true next build --webpack",
39
39
  "build:docker": "npm run prebuild && NODE_OPTIONS=--max-old-space-size=6144 DOCKER=true next build --webpack && npm run build-sitemap",
40
40
  "prebuild:electron": "cross-env NEXT_PUBLIC_IS_DESKTOP_APP=1 tsx scripts/prebuild.mts",
41
- "build:electron": "cross-env NODE_OPTIONS=--max-old-space-size=6144 NEXT_PUBLIC_IS_DESKTOP_APP=1 NEXT_PUBLIC_SERVICE_MODE=server next build --webpack",
41
+ "build:electron": "cross-env NODE_OPTIONS=--max-old-space-size=6144 NEXT_PUBLIC_IS_DESKTOP_APP=1 next build --webpack",
42
42
  "clean:node_modules": "bash -lc 'set -e; echo \"Removing all node_modules...\"; rm -rf node_modules; pnpm -r exec rm -rf node_modules; rm -rf apps/desktop/node_modules; echo \"All node_modules removed.\"'",
43
43
  "db:generate": "drizzle-kit generate && npm run db:generate-client && npm run workflow:dbml",
44
44
  "db:generate-client": "tsx ./scripts/migrateClientDB/compile-migrations.ts",
@@ -10,7 +10,8 @@ import * as schema from '../schemas';
10
10
  import { LobeChatDatabase } from '../type';
11
11
 
12
12
  export const getDBInstance = (): LobeChatDatabase => {
13
- if (!(process.env.NEXT_PUBLIC_SERVICE_MODE === 'server')) return {} as any;
13
+ // In test environment, return a mock instance to avoid initialization errors
14
+ if (process.env.NODE_ENV === 'test') return {} as LobeChatDatabase;
14
15
 
15
16
  if (!serverDBEnv.KEY_VAULTS_SECRET) {
16
17
  throw new Error(
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "@lobechat/model-runtime": "workspace:*",
11
11
  "@lobechat/prompts": "workspace:*",
12
- "dotenv": "^16.4.7",
12
+ "dotenv": "^17.2.3",
13
13
  "ora": "^8.2.0"
14
14
  },
15
15
  "devDependencies": {
@@ -1,9 +1,14 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix , typescript-sort-keys/interface */
2
+ import { z } from 'zod';
3
+
2
4
  import { UploadFileItem } from '../../files';
3
5
  import { MessageSemanticSearchChunk } from '../../rag';
4
- import { ChatMessageError } from '../common/base';
6
+ import { ChatMessageError, ChatMessageErrorSchema } from '../common/base';
5
7
  import { ChatPluginPayload } from '../common/tools';
6
- import { UIChatMessage, UIMessageRoleType } from './chat';
8
+ import { UIChatMessage } from './chat';
9
+ import { SemanticSearchChunkSchema } from './rag';
10
+
11
+ export type CreateMessageRoleType = 'user' | 'assistant' | 'tool' | 'supervisor';
7
12
 
8
13
  export interface CreateMessageParams
9
14
  extends Partial<Omit<UIChatMessage, 'content' | 'role' | 'topicId' | 'chunksList'>> {
@@ -14,7 +19,7 @@ export interface CreateMessageParams
14
19
  fromModel?: string;
15
20
  fromProvider?: string;
16
21
  groupId?: string;
17
- role: UIMessageRoleType;
22
+ role: CreateMessageRoleType;
18
23
  sessionId: string;
19
24
  targetId?: string | null;
20
25
  threadId?: string | null;
@@ -28,7 +33,7 @@ export interface CreateMessageParams
28
33
  */
29
34
  export interface CreateNewMessageParams {
30
35
  // ========== Required fields ==========
31
- role: UIMessageRoleType;
36
+ role: CreateMessageRoleType;
32
37
  content: string;
33
38
  sessionId: string;
34
39
 
@@ -103,3 +108,92 @@ export interface SendGroupMessageParams {
103
108
  */
104
109
  targetMemberId?: string | null;
105
110
  }
111
+
112
+ // ========== Zod Schemas ========== //
113
+
114
+ const UIMessageRoleTypeSchema = z.enum(['user', 'assistant', 'tool', 'supervisor']);
115
+
116
+ const ChatPluginPayloadSchema = z.object({
117
+ apiName: z.string(),
118
+ arguments: z.string(),
119
+ identifier: z.string(),
120
+ type: z.string(),
121
+ });
122
+
123
+ export const CreateMessageParamsSchema = z
124
+ .object({
125
+ content: z.string(),
126
+ role: UIMessageRoleTypeSchema,
127
+ sessionId: z.string().nullable().optional(),
128
+ error: ChatMessageErrorSchema.nullable().optional(),
129
+ fileChunks: z.array(SemanticSearchChunkSchema).optional(),
130
+ files: z.array(z.string()).optional(),
131
+ fromModel: z.string().optional(),
132
+ fromProvider: z.string().optional(),
133
+ groupId: z.string().optional(),
134
+ targetId: z.string().nullable().optional(),
135
+ threadId: z.string().nullable().optional(),
136
+ topicId: z.string().optional(),
137
+ traceId: z.string().optional(),
138
+ // Allow additional fields from UIChatMessage (many can be null)
139
+ agentId: z.string().optional(),
140
+ children: z.any().optional(),
141
+ chunksList: z.any().optional(),
142
+ createdAt: z.number().optional(),
143
+ extra: z.any().optional(),
144
+ favorite: z.boolean().optional(),
145
+ fileList: z.any().optional(),
146
+ id: z.string().optional(),
147
+ imageList: z.any().optional(),
148
+ meta: z.any().optional(),
149
+ metadata: z.any().nullable().optional(),
150
+ model: z.string().nullable().optional(),
151
+ observationId: z.string().optional(),
152
+ parentId: z.string().optional(),
153
+ performance: z.any().optional(),
154
+ plugin: z.any().optional(),
155
+ pluginError: z.any().optional(),
156
+ pluginState: z.any().optional(),
157
+ provider: z.string().nullable().optional(),
158
+ quotaId: z.string().optional(),
159
+ ragQuery: z.string().nullable().optional(),
160
+ ragQueryId: z.string().nullable().optional(),
161
+ reasoning: z.any().optional(),
162
+ search: z.any().optional(),
163
+ tool_call_id: z.string().optional(),
164
+ toolCalls: z.any().optional(),
165
+ tools: z.any().optional(),
166
+ translate: z.any().optional(),
167
+ tts: z.any().optional(),
168
+ updatedAt: z.number().optional(),
169
+ })
170
+ .passthrough();
171
+
172
+ export const CreateNewMessageParamsSchema = z
173
+ .object({
174
+ // Required fields
175
+ role: UIMessageRoleTypeSchema,
176
+ content: z.string(),
177
+ sessionId: z.string().nullable().optional(),
178
+ // Tool related
179
+ tool_call_id: z.string().optional(),
180
+ plugin: ChatPluginPayloadSchema.optional(),
181
+ // Grouping
182
+ parentId: z.string().optional(),
183
+ groupId: z.string().optional(),
184
+ // Context
185
+ topicId: z.string().optional(),
186
+ threadId: z.string().nullable().optional(),
187
+ targetId: z.string().nullable().optional(),
188
+ // Model info
189
+ model: z.string().nullable().optional(),
190
+ provider: z.string().nullable().optional(),
191
+ // Content
192
+ files: z.array(z.string()).optional(),
193
+ // Error handling
194
+ error: ChatMessageErrorSchema.nullable().optional(),
195
+ // Metadata
196
+ traceId: z.string().optional(),
197
+ fileChunks: z.array(SemanticSearchChunkSchema).optional(),
198
+ })
199
+ .passthrough();
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
 
4
4
  import { Plans } from '../subscription';
5
5
  import { TopicDisplayMode } from '../topic';
6
- import { UserSettings } from '../user/settings';
6
+ import { UserSettings } from './settings';
7
7
 
8
8
  export interface LobeUser {
9
9
  avatar?: string;
@@ -74,3 +74,15 @@ export const NextAuthAccountSchame = z.object({
74
74
  provider: z.string(),
75
75
  providerAccountId: z.string(),
76
76
  });
77
+
78
+ export const UserPreferenceSchema = z
79
+ .object({
80
+ disableInputMarkdownRender: z.boolean().optional(),
81
+ enableGroupChat: z.boolean().optional(),
82
+ guide: UserGuideSchema.optional(),
83
+ hideSyncAlert: z.boolean().optional(),
84
+ telemetry: z.boolean().nullable(),
85
+ topicDisplayMode: z.nativeEnum(TopicDisplayMode).optional(),
86
+ useCmdEnterToSend: z.boolean().optional(),
87
+ })
88
+ .partial();
@@ -1,3 +1,5 @@
1
+ import { z } from 'zod';
2
+
1
3
  import type { LobeAgentSettings } from '../../session';
2
4
  import { UserGeneralConfig } from './general';
3
5
  import { UserHotkeyConfig } from './hotkey';
@@ -18,6 +20,7 @@ export * from './keyVaults';
18
20
  export * from './modelProvider';
19
21
  export * from './sync';
20
22
  export * from './systemAgent';
23
+ export * from './tool';
21
24
  export * from './tts';
22
25
 
23
26
  /**
@@ -34,3 +37,22 @@ export interface UserSettings {
34
37
  tool: UserToolConfig;
35
38
  tts: UserTTSConfig;
36
39
  }
40
+
41
+ /**
42
+ * Zod schema for partial UserSettings updates
43
+ * Uses passthrough to allow any nested settings fields
44
+ */
45
+ export const UserSettingsSchema = z
46
+ .object({
47
+ defaultAgent: z.any().optional(),
48
+ general: z.any().optional(),
49
+ hotkey: z.any().optional(),
50
+ image: z.any().optional(),
51
+ keyVaults: z.any().optional(),
52
+ languageModel: z.any().optional(),
53
+ systemAgent: z.any().optional(),
54
+ tool: z.any().optional(),
55
+ tts: z.any().optional(),
56
+ })
57
+ .passthrough()
58
+ .partial();
@@ -15,13 +15,7 @@ if you have any other question, please open issue here: https://github.com/lobeh
15
15
  const DB_FAIL_INIT_HINT = `------------------------------------------------------------------------------------------
16
16
  ⚠️ Database migrate failed due to not find the db instance.
17
17
 
18
- 1) You might not switch to server db mode, please set the env blow and try again:
19
-
20
- \`\`\`
21
- NEXT_PUBLIC_SERVICE_MODE=server
22
- \`\`\`
23
-
24
- 2) if you are using docker postgres image, you may need to set DATABASE_DRIVER to node
18
+ if you are using docker postgres image, you may need to set DATABASE_DRIVER to node
25
19
 
26
20
  \`\`\`
27
21
  DATABASE_DRIVER=node
@@ -32,9 +32,6 @@ const TopActions = memo<TopActionProps>(({ tab, isPinned }) => {
32
32
  useServerConfigStore(featureFlagsSelectors);
33
33
  const hotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.NavigateToChat));
34
34
 
35
- // Check if server mode is enabled
36
- const isServerMode = process.env.NEXT_PUBLIC_SERVICE_MODE === 'server';
37
-
38
35
  const isChatActive = tab === SidebarTabKey.Chat && !isPinned;
39
36
  const isFilesActive = tab === SidebarTabKey.Files;
40
37
  const isDiscoverActive = tab === SidebarTabKey.Discover;
@@ -69,7 +66,7 @@ const TopActions = memo<TopActionProps>(({ tab, isPinned }) => {
69
66
  tooltipProps={{ placement: 'right' }}
70
67
  />
71
68
  </Link>
72
- {enableKnowledgeBase && isServerMode && (
69
+ {enableKnowledgeBase && (
73
70
  <Link aria-label={t('tab.knowledgeBase')} href={'/knowledge'}>
74
71
  <ActionIcon
75
72
  active={isFilesActive}
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+
3
+ import { Icon } from '@lobehub/ui';
4
+ import { Card, Result } from 'antd';
5
+ import { useTheme } from 'antd-style';
6
+ import { LoaderCircle } from 'lucide-react';
7
+ import { memo, useEffect, useRef } from 'react';
8
+ import { useTranslation } from 'react-i18next';
9
+ import { Center } from 'react-layout-kit';
10
+
11
+ interface BuiltinConsentProps {
12
+ uid: string;
13
+ }
14
+
15
+ const BuiltinConsent = memo<BuiltinConsentProps>(({ uid }) => {
16
+ const { t } = useTranslation('oauth');
17
+ const formRef = useRef<HTMLFormElement>(null);
18
+
19
+ useEffect(() => {
20
+ // Auto-submit on mount
21
+ formRef.current?.submit();
22
+ }, []);
23
+
24
+ const theme = useTheme();
25
+ return (
26
+ <>
27
+ <Center height="100vh">
28
+ <Card
29
+ style={{
30
+ alignItems: 'center',
31
+ display: 'flex',
32
+ justifyContent: 'center',
33
+ minHeight: 280,
34
+ minWidth: 500,
35
+ width: '100%',
36
+ }}
37
+ >
38
+ <Result
39
+ icon={<Icon icon={LoaderCircle} spin style={{ color: theme.colorText }} />}
40
+ status="success"
41
+ style={{ padding: 0 }}
42
+ subTitle={t('consent.redirecting')}
43
+ title=""
44
+ />
45
+ </Card>
46
+ </Center>
47
+ <form action="/oidc/consent" method="post" ref={formRef} style={{ display: 'none' }}>
48
+ <input name="uid" type="hidden" value={uid} />
49
+ <input name="consent" type="hidden" value="accept" />
50
+ </form>
51
+ </>
52
+ );
53
+ });
54
+
55
+ BuiltinConsent.displayName = 'BuiltinConsent';
56
+
57
+ export default BuiltinConsent;
@@ -7,7 +7,8 @@ import { memo, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { Center, Flexbox } from 'react-layout-kit';
9
9
 
10
- import OAuthApplicationLogo from './components/OAuthApplicationLogo';
10
+ import OAuthApplicationLogo from '../components/OAuthApplicationLogo';
11
+ import BuiltinConsent from './BuiltinConsent';
11
12
 
12
13
  interface ClientProps {
13
14
  clientId: string;
@@ -117,6 +118,8 @@ function getScopeDescription(scope: string, t: any): string {
117
118
  return t(`consent.scope.${scope.replace(':', '-')}`, scope);
118
119
  }
119
120
 
121
+ const BUILTIN_CLIENTS = new Set(['lobehub-desktop', 'lobehub-mobile', 'lobehub-market']);
122
+
120
123
  const ConsentClient = memo<ClientProps>(({ uid, clientId, scopes, clientMetadata }) => {
121
124
  const { styles } = useStyles();
122
125
  const { t } = useTranslation('oauth');
@@ -124,6 +127,11 @@ const ConsentClient = memo<ClientProps>(({ uid, clientId, scopes, clientMetadata
124
127
  const [isLoading, setIsLoading] = useState(false);
125
128
 
126
129
  const clientDisplayName = clientMetadata?.clientName || clientId;
130
+
131
+ if (BUILTIN_CLIENTS.has(clientId)) {
132
+ return <BuiltinConsent uid={clientId} />;
133
+ }
134
+
127
135
  return (
128
136
  <Center className={styles.container} gap={16}>
129
137
  <Flexbox gap={40}>
@@ -59,6 +59,8 @@ const LoginConfirmClient = memo<LoginConfirmProps>(({ uid, clientMetadata }) =>
59
59
  const avatar = useUserStore(userProfileSelectors.userAvatar);
60
60
  const nickName = useUserStore(userProfileSelectors.nickName);
61
61
 
62
+ const [isLoading, setIsLoading] = React.useState(false);
63
+
62
64
  const titleText = t('login.title', { clientName: clientDisplayName });
63
65
  const descriptionText = t('login.description', { clientName: clientDisplayName });
64
66
  const buttonText = t('login.button'); // Or "Continue"
@@ -99,7 +101,12 @@ const LoginConfirmClient = memo<LoginConfirmProps>(({ uid, clientMetadata }) =>
99
101
 
100
102
  <Flexbox gap={16}>
101
103
  {/* Form points to the endpoint handling login confirmation */}
102
- <form action="/oidc/consent" method="post" style={{ width: '100%' }}>
104
+ <form
105
+ action="/oidc/consent"
106
+ method="post"
107
+ onSubmit={() => setIsLoading(true)}
108
+ style={{ width: '100%' }}
109
+ >
103
110
  {/* Adjust action URL */}
104
111
  <input name="uid" type="hidden" value={uid} />
105
112
  <input name="choice" type="hidden" value={'accept'} />
@@ -108,6 +115,7 @@ const LoginConfirmClient = memo<LoginConfirmProps>(({ uid, clientMetadata }) =>
108
115
  className={styles.authButton}
109
116
  disabled={!isUserStateInit}
110
117
  htmlType="submit"
118
+ loading={isLoading}
111
119
  name="consent"
112
120
  size="large"
113
121
  type="primary"
package/src/config/db.ts CHANGED
@@ -3,9 +3,6 @@ import { z } from 'zod';
3
3
 
4
4
  export const getServerDBConfig = () => {
5
5
  return createEnv({
6
- client: {
7
- NEXT_PUBLIC_ENABLED_SERVER_SERVICE: z.boolean(),
8
- },
9
6
  runtimeEnv: {
10
7
  DATABASE_DRIVER: process.env.DATABASE_DRIVER || 'neon',
11
8
  DATABASE_TEST_URL: process.env.DATABASE_TEST_URL,
@@ -13,8 +10,6 @@ export const getServerDBConfig = () => {
13
10
 
14
11
  KEY_VAULTS_SECRET: process.env.KEY_VAULTS_SECRET,
15
12
 
16
- NEXT_PUBLIC_ENABLED_SERVER_SERVICE: process.env.NEXT_PUBLIC_SERVICE_MODE === 'server',
17
-
18
13
  REMOVE_GLOBAL_FILE: process.env.DISABLE_REMOVE_GLOBAL_FILE !== '0',
19
14
  },
20
15
  server: {
@@ -1,6 +1,5 @@
1
1
  import type { NextAuthConfig } from 'next-auth';
2
2
 
3
- import { getServerDBConfig } from '@/config/db';
4
3
  import { getAuthConfig } from '@/envs/auth';
5
4
 
6
5
  import { LobeNextAuthDbAdapter } from './adapter';
@@ -14,8 +13,6 @@ const {
14
13
  NEXT_PUBLIC_ENABLE_NEXT_AUTH,
15
14
  } = getAuthConfig();
16
15
 
17
- const { NEXT_PUBLIC_ENABLED_SERVER_SERVICE } = getServerDBConfig();
18
-
19
16
  export const initSSOProviders = () => {
20
17
  return NEXT_PUBLIC_ENABLE_NEXT_AUTH
21
18
  ? NEXT_AUTH_SSO_PROVIDERS.split(/[,,]/).map((provider) => {
@@ -30,7 +27,7 @@ export const initSSOProviders = () => {
30
27
 
31
28
  // Notice this is only an object, not a full Auth.js instance
32
29
  export default {
33
- adapter: NEXT_PUBLIC_ENABLED_SERVER_SERVICE ? LobeNextAuthDbAdapter() : undefined,
30
+ adapter: NEXT_PUBLIC_ENABLE_NEXT_AUTH ? LobeNextAuthDbAdapter() : undefined,
34
31
  callbacks: {
35
32
  // Note: Data processing order of callback: authorize --> jwt --> session
36
33
  async jwt({ token, user }) {
@@ -61,7 +58,7 @@ export default {
61
58
  secret: NEXT_AUTH_SECRET ?? process.env.AUTH_SECRET,
62
59
  session: {
63
60
  // Force use JWT if server service is disabled
64
- strategy: NEXT_PUBLIC_ENABLED_SERVER_SERVICE ? NEXT_AUTH_SSO_SESSION_STRATEGY : 'jwt',
61
+ strategy: NEXT_AUTH_SSO_SESSION_STRATEGY,
65
62
  },
66
63
  trustHost: process.env?.AUTH_TRUST_HOST ? process.env.AUTH_TRUST_HOST === 'true' : true,
67
64
  } satisfies NextAuthConfig;
@@ -19,6 +19,7 @@ const oauth = {
19
19
  },
20
20
  permissionsTitle: '请求以下权限:',
21
21
  redirectUri: '授权成功后将重定向到',
22
+ redirecting: '授权成功,跳转中...',
22
23
  scope: {
23
24
  'email': '访问您的电子邮件地址',
24
25
  'offline_access': '允许客户端访问您的数据',
@@ -318,47 +318,6 @@ describe('Message Router Integration Tests', () => {
318
318
  });
319
319
  });
320
320
 
321
- describe('batchCreateMessages', () => {
322
- it('should create multiple messages in batch', async () => {
323
- const caller = messageRouter.createCaller(createTestContext(userId));
324
-
325
- const messagesToCreate = [
326
- {
327
- content: 'Batch message 1',
328
- role: 'user' as const,
329
- sessionId: testSessionId,
330
- },
331
- {
332
- content: 'Batch message 2',
333
- role: 'assistant' as const,
334
- sessionId: testSessionId,
335
- },
336
- {
337
- content: 'Batch message 3',
338
- role: 'user' as const,
339
- sessionId: testSessionId,
340
- topicId: testTopicId,
341
- },
342
- ];
343
-
344
- const result = await caller.batchCreateMessages(messagesToCreate);
345
-
346
- expect(result.success).toBe(true);
347
- // Note: rowCount might be undefined in PGlite, so we skip this check
348
- // expect(result.added).toBe(3);
349
-
350
- // 验证数据库中的消息
351
- const dbMessages = await serverDB
352
- .select()
353
- .from(messages)
354
- .where(eq(messages.sessionId, testSessionId));
355
-
356
- expect(dbMessages.length).toBeGreaterThanOrEqual(3);
357
- const topicMessage = dbMessages.find((m) => m.content === 'Batch message 3');
358
- expect(topicMessage?.topicId).toBe(testTopicId);
359
- });
360
- });
361
-
362
321
  describe('removeMessages', () => {
363
322
  it('should remove multiple messages', async () => {
364
323
  const caller = messageRouter.createCaller(createTestContext(userId));
@@ -1,5 +1,6 @@
1
1
  import {
2
- BatchTaskResult,
2
+ CreateMessageParamsSchema,
3
+ CreateNewMessageParamsSchema,
3
4
  UIChatMessage,
4
5
  UpdateMessageParamsSchema,
5
6
  UpdateMessageRAGParamsSchema,
@@ -27,14 +28,6 @@ const messageProcedure = authedProcedure.use(serverDatabase).use(async (opts) =>
27
28
  });
28
29
 
29
30
  export const messageRouter = router({
30
- batchCreateMessages: messageProcedure
31
- .input(z.array(z.any()))
32
- .mutation(async ({ input, ctx }): Promise<BatchTaskResult> => {
33
- const data = await ctx.messageModel.batchCreate(input);
34
-
35
- return { added: data.rowCount as number, ids: [], skips: [], success: true };
36
- }),
37
-
38
31
  count: messageProcedure
39
32
  .input(
40
33
  z
@@ -64,7 +57,7 @@ export const messageRouter = router({
64
57
  }),
65
58
 
66
59
  createMessage: messageProcedure
67
- .input(z.object({}).passthrough().partial())
60
+ .input(CreateMessageParamsSchema)
68
61
  .mutation(async ({ input, ctx }) => {
69
62
  const data = await ctx.messageModel.create(input as any);
70
63
 
@@ -72,7 +65,7 @@ export const messageRouter = router({
72
65
  }),
73
66
 
74
67
  createNewMessage: messageProcedure
75
- .input(z.object({}).passthrough().partial())
68
+ .input(CreateNewMessageParamsSchema)
76
69
  .mutation(async ({ input, ctx }) => {
77
70
  return ctx.messageModel.createNewMessage(input as any, {
78
71
  postProcessUrl: (path) => ctx.fileService.getFullFileUrl(path),
@@ -1,9 +1,17 @@
1
1
  import { UserJSON } from '@clerk/backend';
2
+ import { enableClerk, isDesktop } from '@lobechat/const';
3
+ import {
4
+ NextAuthAccountSchame,
5
+ UserGuideSchema,
6
+ UserInitializationState,
7
+ UserPreference,
8
+ UserPreferenceSchema,
9
+ UserSettings,
10
+ UserSettingsSchema,
11
+ } from '@lobechat/types';
2
12
  import { v4 as uuidv4 } from 'uuid';
3
13
  import { z } from 'zod';
4
14
 
5
- import { enableClerk } from '@/const/auth';
6
- import { isDesktop } from '@/const/version';
7
15
  import { MessageModel } from '@/database/models/message';
8
16
  import { SessionModel } from '@/database/models/session';
9
17
  import { UserModel, UserNotFoundError } from '@/database/models/user';
@@ -16,13 +24,6 @@ import { S3 } from '@/server/modules/S3';
16
24
  import { FileService } from '@/server/services/file';
17
25
  import { NextAuthUserService } from '@/server/services/nextAuthUser';
18
26
  import { UserService } from '@/server/services/user';
19
- import {
20
- NextAuthAccountSchame,
21
- UserGuideSchema,
22
- UserInitializationState,
23
- UserPreference,
24
- } from '@/types/user';
25
- import { UserSettings } from '@/types/user/settings';
26
27
 
27
28
  const userProcedure = authedProcedure.use(serverDatabase).use(async ({ ctx, next }) => {
28
29
  return next({
@@ -199,30 +200,28 @@ export const userRouter = router({
199
200
  return ctx.userModel.updateGuide(input);
200
201
  }),
201
202
 
202
- updatePreference: userProcedure.input(z.any()).mutation(async ({ ctx, input }) => {
203
+ updatePreference: userProcedure.input(UserPreferenceSchema).mutation(async ({ ctx, input }) => {
203
204
  return ctx.userModel.updatePreference(input);
204
205
  }),
205
206
 
206
- updateSettings: userProcedure
207
- .input(z.object({}).passthrough())
208
- .mutation(async ({ ctx, input }) => {
209
- const { keyVaults, ...res } = input as Partial<UserSettings>;
207
+ updateSettings: userProcedure.input(UserSettingsSchema).mutation(async ({ ctx, input }) => {
208
+ const { keyVaults, ...res } = input as Partial<UserSettings>;
210
209
 
211
- // Encrypt keyVaults
212
- let encryptedKeyVaults: string | null = null;
210
+ // Encrypt keyVaults
211
+ let encryptedKeyVaults: string | null = null;
213
212
 
214
- if (keyVaults) {
215
- // TODO: better to add a validation
216
- const data = JSON.stringify(keyVaults);
217
- const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
213
+ if (keyVaults) {
214
+ // TODO: better to add a validation
215
+ const data = JSON.stringify(keyVaults);
216
+ const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
218
217
 
219
- encryptedKeyVaults = await gateKeeper.encrypt(data);
220
- }
218
+ encryptedKeyVaults = await gateKeeper.encrypt(data);
219
+ }
221
220
 
222
- const nextValue = { ...res, keyVaults: encryptedKeyVaults };
221
+ const nextValue = { ...res, keyVaults: encryptedKeyVaults };
223
222
 
224
- return ctx.userModel.updateSetting(nextValue);
225
- }),
223
+ return ctx.userModel.updateSetting(nextValue);
224
+ }),
226
225
  });
227
226
 
228
227
  export type UserRouter = typeof userRouter;
@@ -21,10 +21,6 @@ export class ServerService implements IMessageService {
21
21
  });
22
22
  };
23
23
 
24
- batchCreateMessages: IMessageService['batchCreateMessages'] = async (messages) => {
25
- return lambdaClient.message.batchCreateMessages.mutate(messages);
26
- };
27
-
28
24
  getMessages: IMessageService['getMessages'] = async (sessionId, topicId, groupId) => {
29
25
  const data = await lambdaClient.message.getMessages.query({
30
26
  groupId,
@@ -5,7 +5,6 @@ import {
5
5
  ChatTranslate,
6
6
  CreateMessageParams,
7
7
  CreateMessageResult,
8
- DBMessageItem,
9
8
  ModelRankItem,
10
9
  UIChatMessage,
11
10
  UpdateMessageParams,
@@ -19,7 +18,6 @@ import type { HeatmapsProps } from '@lobehub/charts';
19
18
  export interface IMessageService {
20
19
  createMessage(data: CreateMessageParams): Promise<string>;
21
20
  createNewMessage(data: CreateMessageParams): Promise<CreateMessageResult>;
22
- batchCreateMessages(messages: DBMessageItem[]): Promise<any>;
23
21
 
24
22
  getMessages(sessionId: string, topicId?: string, groupId?: string): Promise<UIChatMessage[]>;
25
23
  getGroupMessages(groupId: string, topicId?: string): Promise<UIChatMessage[]>;