@lobehub/chat 0.162.25 → 0.164.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.
Files changed (84) hide show
  1. package/.github/workflows/release.yml +21 -2
  2. package/.github/workflows/sync.yml +1 -1
  3. package/.github/workflows/test.yml +35 -4
  4. package/CHANGELOG.md +63 -0
  5. package/LICENSE +38 -21
  6. package/codecov.yml +11 -0
  7. package/drizzle.config.ts +29 -0
  8. package/next.config.mjs +3 -0
  9. package/package.json +24 -4
  10. package/scripts/migrateServerDB/index.ts +30 -0
  11. package/src/app/(main)/(mobile)/me/(home)/features/useCategory.tsx +2 -1
  12. package/src/app/(main)/chat/@session/features/SessionListContent/List/Item/Actions.tsx +95 -88
  13. package/src/app/(main)/chat/settings/features/HeaderContent.tsx +37 -31
  14. package/src/app/api/webhooks/clerk/__tests__/fixtures/createUser.json +73 -0
  15. package/src/app/api/webhooks/clerk/route.ts +159 -0
  16. package/src/app/api/webhooks/clerk/validateRequest.ts +22 -0
  17. package/src/app/trpc/edge/[trpc]/route.ts +1 -1
  18. package/src/app/trpc/lambda/[trpc]/route.ts +26 -0
  19. package/src/config/auth.ts +2 -0
  20. package/src/config/db.ts +13 -1
  21. package/src/database/server/core/db.ts +44 -0
  22. package/src/database/server/core/dbForTest.ts +45 -0
  23. package/src/database/server/index.ts +1 -0
  24. package/src/database/server/migrations/0000_init.sql +439 -0
  25. package/src/database/server/migrations/0001_add_client_id.sql +9 -0
  26. package/src/database/server/migrations/0002_amusing_puma.sql +9 -0
  27. package/src/database/server/migrations/meta/0000_snapshot.json +1583 -0
  28. package/src/database/server/migrations/meta/0001_snapshot.json +1636 -0
  29. package/src/database/server/migrations/meta/0002_snapshot.json +1630 -0
  30. package/src/database/server/migrations/meta/_journal.json +27 -0
  31. package/src/database/server/models/__tests__/file.test.ts +140 -0
  32. package/src/database/server/models/__tests__/message.test.ts +847 -0
  33. package/src/database/server/models/__tests__/plugin.test.ts +172 -0
  34. package/src/database/server/models/__tests__/session.test.ts +595 -0
  35. package/src/database/server/models/__tests__/topic.test.ts +623 -0
  36. package/src/database/server/models/__tests__/user.test.ts +173 -0
  37. package/src/database/server/models/_template.ts +44 -0
  38. package/src/database/server/models/file.ts +51 -0
  39. package/src/database/server/models/message.ts +378 -0
  40. package/src/database/server/models/plugin.ts +63 -0
  41. package/src/database/server/models/session.ts +290 -0
  42. package/src/database/server/models/sessionGroup.ts +69 -0
  43. package/src/database/server/models/topic.ts +265 -0
  44. package/src/database/server/models/user.ts +138 -0
  45. package/src/database/server/modules/DataImporter/__tests__/fixtures/messages.json +1101 -0
  46. package/src/database/server/modules/DataImporter/__tests__/index.test.ts +954 -0
  47. package/src/database/server/modules/DataImporter/index.ts +333 -0
  48. package/src/database/server/schemas/_id.ts +15 -0
  49. package/src/database/server/schemas/lobechat.ts +601 -0
  50. package/src/database/server/utils/idGenerator.test.ts +39 -0
  51. package/src/database/server/utils/idGenerator.ts +26 -0
  52. package/src/features/User/UserPanel/useMenu.tsx +43 -37
  53. package/src/libs/trpc/client.ts +52 -3
  54. package/src/server/files/s3.ts +21 -1
  55. package/src/server/keyVaultsEncrypt/index.test.ts +62 -0
  56. package/src/server/keyVaultsEncrypt/index.ts +93 -0
  57. package/src/server/mock.ts +1 -1
  58. package/src/server/routers/{index.ts → edge/index.ts} +3 -3
  59. package/src/server/routers/lambda/file.ts +49 -0
  60. package/src/server/routers/lambda/importer.ts +54 -0
  61. package/src/server/routers/lambda/index.ts +28 -0
  62. package/src/server/routers/lambda/message.ts +165 -0
  63. package/src/server/routers/lambda/plugin.ts +100 -0
  64. package/src/server/routers/lambda/session.ts +194 -0
  65. package/src/server/routers/lambda/sessionGroup.ts +77 -0
  66. package/src/server/routers/lambda/topic.ts +134 -0
  67. package/src/server/routers/lambda/user.ts +57 -0
  68. package/src/services/file/index.ts +4 -7
  69. package/src/services/file/server.ts +45 -0
  70. package/src/services/import/index.ts +4 -1
  71. package/src/services/import/server.ts +115 -0
  72. package/src/services/message/index.ts +4 -8
  73. package/src/services/message/server.ts +93 -0
  74. package/src/services/plugin/index.ts +4 -9
  75. package/src/services/plugin/server.ts +46 -0
  76. package/src/services/session/index.ts +4 -8
  77. package/src/services/session/server.ts +148 -0
  78. package/src/services/topic/index.ts +4 -9
  79. package/src/services/topic/server.ts +68 -0
  80. package/src/services/user/index.ts +4 -9
  81. package/src/services/user/server.ts +28 -0
  82. package/tests/setup-db.ts +7 -0
  83. package/vitest.config.ts +2 -1
  84. package/vitest.server.config.ts +23 -0
@@ -8,6 +8,17 @@ jobs:
8
8
  release:
9
9
  name: Release
10
10
  runs-on: ubuntu-latest
11
+
12
+ services:
13
+ postgres:
14
+ image: postgres:16
15
+ env:
16
+ POSTGRES_PASSWORD: postgres
17
+ options: >-
18
+ --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
19
+ ports:
20
+ - 5432:5432
21
+
11
22
  steps:
12
23
  - uses: actions/checkout@v4
13
24
 
@@ -22,8 +33,16 @@ jobs:
22
33
  - name: Lint
23
34
  run: bun run lint
24
35
 
25
- - name: Test
26
- run: bun run test
36
+ - name: Test Server Coverage
37
+ run: bun run test-server:coverage
38
+ env:
39
+ DATABASE_TEST_URL: postgresql://postgres:postgres@localhost:5432/postgres
40
+ DATABASE_DRIVER: node
41
+ NEXT_PUBLIC_SERVICE_MODE: server
42
+ KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
43
+
44
+ - name: Test App Coverage
45
+ run: bun run test-app:coverage
27
46
 
28
47
  - name: Release
29
48
  run: bun run release
@@ -7,7 +7,7 @@ permissions:
7
7
 
8
8
  on:
9
9
  schedule:
10
- - cron: '0 * * * *' # every hour
10
+ - cron: '0 */6 * * *' # every 6 hours
11
11
  workflow_dispatch:
12
12
 
13
13
  jobs:
@@ -1,9 +1,23 @@
1
1
  name: Test CI
2
+
2
3
  on: [push, pull_request]
4
+
3
5
  jobs:
4
6
  test:
5
7
  runs-on: ubuntu-latest
6
8
 
9
+ services:
10
+ postgres:
11
+ image: postgres:16
12
+ env:
13
+ POSTGRES_PASSWORD: postgres
14
+ options: >-
15
+ --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
16
+
17
+
18
+ ports:
19
+ - 5432:5432
20
+
7
21
  steps:
8
22
  - uses: actions/checkout@v4
9
23
 
@@ -18,10 +32,27 @@ jobs:
18
32
  - name: Lint
19
33
  run: bun run lint
20
34
 
21
- - name: Test and coverage
22
- run: bun run test:coverage
35
+ - name: Test Server Coverage
36
+ run: bun run test-server:coverage
37
+ env:
38
+ DATABASE_TEST_URL: postgresql://postgres:postgres@localhost:5432/postgres
39
+ DATABASE_DRIVER: node
40
+ NEXT_PUBLIC_SERVICE_MODE: server
41
+ KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
42
+
43
+ - name: Upload Server coverage to Codecov
44
+ uses: codecov/codecov-action@v4
45
+ with:
46
+ token: ${{ secrets.CODECOV_TOKEN }}
47
+ files: ./coverage/server/lcov.info
48
+ flags: server
49
+
50
+ - name: Test App Coverage
51
+ run: bun run test-app:coverage
23
52
 
24
- - name: Upload coverage to Codecov
53
+ - name: Upload App Coverage to Codecov
25
54
  uses: codecov/codecov-action@v4
26
55
  with:
27
- token: ${{ secrets.CODECOV_TOKEN }} # required
56
+ token: ${{ secrets.CODECOV_TOKEN }}
57
+ files: ./coverage/app/lcov.info
58
+ flags: app
package/CHANGELOG.md CHANGED
@@ -2,6 +2,69 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 0.164.0](https://github.com/lobehub/lobe-chat/compare/v0.163.0...v0.164.0)
6
+
7
+ <sup>Released on **2024-06-17**</sup>
8
+
9
+ #### ✨ Features
10
+
11
+ - **misc**: Release LobeChat 1.0.
12
+
13
+ #### 🔧 Chores
14
+
15
+ - **misc**: Bump version.
16
+
17
+ <br/>
18
+
19
+ <details>
20
+ <summary><kbd>Improvements and Fixes</kbd></summary>
21
+
22
+ #### What's improved
23
+
24
+ - **misc**: Release LobeChat 1.0, closes [#2897](https://github.com/lobehub/lobe-chat/issues/2897) ([97bb377](https://github.com/lobehub/lobe-chat/commit/97bb377))
25
+
26
+ #### Chores
27
+
28
+ - **misc**: Bump version, closes [#2896](https://github.com/lobehub/lobe-chat/issues/2896) ([6e2d03b](https://github.com/lobehub/lobe-chat/commit/6e2d03b))
29
+
30
+ </details>
31
+
32
+ #### 💥 BREAKING CHANGES
33
+
34
+ - **misc**: Update LICENSE to Apache 2.0
35
+ - **misc**: update to 1.0.0
36
+
37
+ <div align="right">
38
+
39
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
40
+
41
+ </div>
42
+
43
+ ## [Version 0.163.0](https://github.com/lobehub/lobe-chat/compare/v0.162.25...v0.163.0)
44
+
45
+ <sup>Released on **2024-06-17**</sup>
46
+
47
+ #### ✨ Features
48
+
49
+ - **misc**: Support server db mode with Postgres / Drizzle ORM / tRPC.
50
+
51
+ <br/>
52
+
53
+ <details>
54
+ <summary><kbd>Improvements and Fixes</kbd></summary>
55
+
56
+ #### What's improved
57
+
58
+ - **misc**: Support server db mode with Postgres / Drizzle ORM / tRPC, closes [#2556](https://github.com/lobehub/lobe-chat/issues/2556) ([b26afbf](https://github.com/lobehub/lobe-chat/commit/b26afbf))
59
+
60
+ </details>
61
+
62
+ <div align="right">
63
+
64
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
65
+
66
+ </div>
67
+
5
68
  ### [Version 0.162.25](https://github.com/lobehub/lobe-chat/compare/v0.162.24...v0.162.25)
6
69
 
7
70
  <sup>Released on **2024-06-16**</sup>
package/LICENSE CHANGED
@@ -1,21 +1,38 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 - current LobeHub
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ Apache License Version 2.0
2
+
3
+ Copyright (c) 2024/06/17 - current LobeHub LLC. All rights reserved.
4
+
5
+ ----------
6
+
7
+ From 1.0, LobeChat is licensed under the Apache License 2.0, with the following additional conditions:
8
+
9
+ 1. The commercial usage of LobeChat:
10
+
11
+ a. LobeChat may be utilized commercially, including as a frontend and backend service without modifying the source code.
12
+
13
+ b. a commercial license must be obtained from the producer if you want to develop and distribute a derivative work based on LobeChat.
14
+
15
+ Please contact hello@lobehub.com by email to inquire about licensing matters.
16
+
17
+
18
+ 2. As a contributor, you should agree that:
19
+
20
+ a. The producer can adjust the open-source agreement to be more strict or relaxed as deemed necessary.
21
+
22
+ b. Your contributed code may be used for commercial purposes, including but not limited to its cloud edition.
23
+
24
+ Apart from the specific conditions mentioned above, all other rights and restrictions follow the Apache License 2.0. Detailed information about the Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0.
25
+
26
+ ----------
27
+
28
+ Licensed under the Apache License, Version 2.0 (the "License");
29
+ you may not use this file except in compliance with the License.
30
+ You may obtain a copy of the License at
31
+
32
+ http://www.apache.org/licenses/LICENSE-2.0
33
+
34
+ Unless required by applicable law or agreed to in writing, software
35
+ distributed under the License is distributed on an "AS IS" BASIS,
36
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37
+ See the License for the specific language governing permissions and
38
+ limitations under the License.
package/codecov.yml ADDED
@@ -0,0 +1,11 @@
1
+ coverage:
2
+ status:
3
+ project:
4
+ default: off
5
+ server:
6
+ flags:
7
+ - server
8
+ app:
9
+ flags:
10
+ - app
11
+ patch: off
@@ -0,0 +1,29 @@
1
+ import * as dotenv from 'dotenv';
2
+ import type { Config } from 'drizzle-kit';
3
+
4
+ // Read the .env file if it exists, or a file specified by the
5
+
6
+ // dotenv_config_path parameter that's passed to Node.js
7
+
8
+ dotenv.config();
9
+
10
+ let connectionString = process.env.DATABASE_URL;
11
+
12
+ if (process.env.NODE_ENV === 'test') {
13
+ console.log('current ENV:', process.env.NODE_ENV);
14
+ connectionString = process.env.DATABASE_TEST_URL;
15
+ }
16
+
17
+ if (!connectionString)
18
+ throw new Error('`DATABASE_URL` or `DATABASE_TEST_URL` not found in environment');
19
+
20
+ export default {
21
+ dbCredentials: {
22
+ url: connectionString,
23
+ },
24
+ dialect: 'postgresql',
25
+ out: './src/database/server/migrations',
26
+
27
+ schema: './src/database/server/schemas/lobechat.ts',
28
+ strict: true,
29
+ } satisfies Config;
package/next.config.mjs CHANGED
@@ -60,6 +60,9 @@ const nextConfig = {
60
60
  },
61
61
  });
62
62
 
63
+ // https://github.com/pinojs/pino/issues/688#issuecomment-637763276
64
+ config.externals.push('pino-pretty');
65
+
63
66
  return config;
64
67
  },
65
68
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.162.25",
3
+ "version": "0.164.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",
@@ -27,10 +27,17 @@
27
27
  "sideEffects": false,
28
28
  "scripts": {
29
29
  "build": "next build",
30
- "postbuild": "npm run build-sitemap",
30
+ "postbuild": "npm run build-sitemap && npm run build-migrate-db",
31
+ "build-migrate-db": "bun run db:migrate",
31
32
  "build-sitemap": "next-sitemap --config next-sitemap.config.mjs",
32
33
  "build:analyze": "ANALYZE=true next build",
33
34
  "build:docker": "DOCKER=true next build && npm run build-sitemap",
35
+ "db:generate": "drizzle-kit generate -- dotenv_config_path='.env'",
36
+ "db:migrate": "MIGRATION_DB=1 tsx scripts/migrateServerDB/index.ts",
37
+ "db:push": "drizzle-kit push -- dotenv_config_path='.env'",
38
+ "db:push-test": "NODE_ENV=test drizzle-kit push -- dotenv_config_path='.env'",
39
+ "db:studio": "drizzle-kit studio",
40
+ "db:z-pull": "drizzle-kit introspect -- dotenv_config_path='.env'",
34
41
  "dev": "next dev -p 3010",
35
42
  "dev:clerk-proxy": "ngrok http http://localhost:3011",
36
43
  "docs:i18n": "lobe-i18n md && npm run workflow:docs && npm run lint:mdx",
@@ -48,8 +55,11 @@
48
55
  "release": "semantic-release",
49
56
  "start": "next start",
50
57
  "stylelint": "stylelint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
51
- "test": "vitest",
52
- "test:coverage": "vitest run --coverage",
58
+ "test": "npm run test-app && npm run test-server",
59
+ "test-app": "vitest run --config vitest.config.ts",
60
+ "test-app:coverage": "vitest run --config vitest.config.ts --coverage",
61
+ "test-server": "vitest run --config vitest.server.config.ts",
62
+ "test-server:coverage": "vitest run --config vitest.server.config.ts --coverage",
53
63
  "test:update": "vitest -u",
54
64
  "type-check": "tsc --noEmit",
55
65
  "workflow:docs": "tsx scripts/docsWorkflow/index.ts",
@@ -101,6 +111,7 @@
101
111
  "@lobehub/tts": "^1.24.1",
102
112
  "@lobehub/ui": "^1.141.2",
103
113
  "@microsoft/fetch-event-source": "^2.0.1",
114
+ "@neondatabase/serverless": "^0.9.3",
104
115
  "@next/third-parties": "^14.2.3",
105
116
  "@sentry/nextjs": "^7.116.0",
106
117
  "@t3-oss/env-nextjs": "^0.10.1",
@@ -119,6 +130,8 @@
119
130
  "debug": "^4.3.4",
120
131
  "dexie": "^3.2.7",
121
132
  "diff": "^5.2.0",
133
+ "drizzle-orm": "^0.30.10",
134
+ "drizzle-zod": "^0.5.1",
122
135
  "fast-deep-equal": "^3.1.3",
123
136
  "gpt-tokenizer": "^2.1.2",
124
137
  "i18next": "^23.11.5",
@@ -141,6 +154,7 @@
141
154
  "nuqs": "^1.17.4",
142
155
  "ollama": "^0.5.1",
143
156
  "openai": "^4.47.1",
157
+ "pg": "^8.11.5",
144
158
  "pino": "^9.1.0",
145
159
  "polished": "^4.3.1",
146
160
  "posthog-js": "^1.135.2",
@@ -163,6 +177,7 @@
163
177
  "semver": "^7.6.2",
164
178
  "sharp": "^0.33.4",
165
179
  "superjson": "^2.2.1",
180
+ "svix": "^1.24.0",
166
181
  "swr": "^2.2.5",
167
182
  "systemjs": "^6.15.1",
168
183
  "ts-md5": "^1.3.1",
@@ -171,6 +186,7 @@
171
186
  "use-merge-value": "^1.2.0",
172
187
  "utility-types": "^3.11.0",
173
188
  "uuid": "^10.0.0",
189
+ "ws": "^8.17.0",
174
190
  "y-protocols": "^1.0.6",
175
191
  "y-webrtc": "^10.3.0",
176
192
  "yaml": "^2.4.2",
@@ -200,6 +216,7 @@
200
216
  "@types/lodash-es": "^4.17.12",
201
217
  "@types/node": "^20.12.12",
202
218
  "@types/numeral": "^2.0.5",
219
+ "@types/pg": "^8.11.6",
203
220
  "@types/react": "^18.3.3",
204
221
  "@types/react-dom": "^18.3.0",
205
222
  "@types/rtl-detect": "^1.0.3",
@@ -207,12 +224,15 @@
207
224
  "@types/systemjs": "^6.13.5",
208
225
  "@types/ua-parser-js": "^0.7.39",
209
226
  "@types/uuid": "^9.0.8",
227
+ "@types/ws": "^8.5.10",
210
228
  "@umijs/lint": "^4.2.5",
211
229
  "@vitest/coverage-v8": "~1.2.2",
212
230
  "ajv-keywords": "^5.1.0",
213
231
  "commitlint": "^19.3.0",
214
232
  "consola": "^3.2.3",
233
+ "dotenv": "^16.4.5",
215
234
  "dpdm": "^3.14.0",
235
+ "drizzle-kit": "^0.21.1",
216
236
  "eslint": "^8.57.0",
217
237
  "eslint-plugin-mdx": "^2.3.4",
218
238
  "fake-indexeddb": "^6.0.0",
@@ -0,0 +1,30 @@
1
+ import * as dotenv from 'dotenv';
2
+ import * as migrator from 'drizzle-orm/neon-serverless/migrator';
3
+ import { join } from 'node:path';
4
+
5
+ import { serverDB } from '../../src/database/server/core/db';
6
+
7
+ // Read the `.env` file if it exists, or a file specified by the
8
+ // dotenv_config_path parameter that's passed to Node.js
9
+ dotenv.config();
10
+
11
+ const runMigrations = async () => {
12
+ await migrator.migrate(serverDB, {
13
+ migrationsFolder: join(__dirname, '../../src/database/server/migrations'),
14
+ });
15
+ console.log('✅ database migration pass.');
16
+ // eslint-disable-next-line unicorn/no-process-exit
17
+ process.exit(0);
18
+ };
19
+
20
+ let connectionString = process.env.DATABASE_URL;
21
+
22
+ // only migrate database if the connection string is available
23
+ if (connectionString) {
24
+ // eslint-disable-next-line unicorn/prefer-top-level-await
25
+ runMigrations().catch((err) => {
26
+ console.error('❌ Database migrate failed:', err);
27
+ // eslint-disable-next-line unicorn/no-process-exit
28
+ process.exit(1);
29
+ });
30
+ }
@@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';
6
6
  import { CellProps } from '@/components/Cell';
7
7
  import { enableAuth } from '@/const/auth';
8
8
  import { DISCORD, DOCUMENTS, FEEDBACK } from '@/const/url';
9
+ import { isServerMode } from '@/const/version';
9
10
  import { usePWAInstall } from '@/hooks/usePWAInstall';
10
11
  import { useUserStore } from '@/store/user';
11
12
  import { authSelectors } from '@/store/user/slices/auth/selectors';
@@ -109,7 +110,7 @@ export const useCategory = () => {
109
110
 
110
111
  /* ↑ cloud slot ↑ */
111
112
  ...(canInstall ? pwa : []),
112
- ...(isLogin ? data : []),
113
+ ...(isLogin && !isServerMode ? data : []),
113
114
  ...helps,
114
115
  ].filter(Boolean) as CellProps[];
115
116
 
@@ -1,6 +1,7 @@
1
1
  import { ActionIcon, Icon } from '@lobehub/ui';
2
- import { App, Dropdown, type MenuProps } from 'antd';
2
+ import { App, Dropdown } from 'antd';
3
3
  import { createStyles } from 'antd-style';
4
+ import { ItemType } from 'antd/es/menu/interface';
4
5
  import isEqual from 'fast-deep-equal';
5
6
  import {
6
7
  Check,
@@ -16,6 +17,7 @@ import {
16
17
  import { memo, useMemo } from 'react';
17
18
  import { useTranslation } from 'react-i18next';
18
19
 
20
+ import { isServerMode } from '@/const/version';
19
21
  import { configService } from '@/services/config';
20
22
  import { useSessionStore } from '@/store/session';
21
23
  import { sessionHelpers } from '@/store/session/helpers';
@@ -58,108 +60,113 @@ const Actions = memo<ActionProps>(({ group, id, openCreateGroupModal, setOpen })
58
60
  const isDefault = group === SessionDefaultGroup.Default;
59
61
  // const hasDivider = !isDefault || Object.keys(sessionByGroup).length > 0;
60
62
 
61
- const items: MenuProps['items'] = useMemo(
62
- () => [
63
- {
64
- icon: <Icon icon={pin ? PinOff : Pin} />,
65
- key: 'pin',
66
- label: t(pin ? 'pinOff' : 'pin'),
67
- onClick: () => {
68
- pinSession(id, !pin);
69
- },
70
- },
71
- {
72
- icon: <Icon icon={LucideCopy} />,
73
- key: 'duplicate',
74
- label: t('duplicate', { ns: 'common' }),
75
- onClick: ({ domEvent }) => {
76
- domEvent.stopPropagation();
77
-
78
- duplicateSession(id);
79
- },
80
- },
81
- {
82
- type: 'divider',
83
- },
84
- {
85
- children: [
86
- ...sessionCustomGroups.map(({ id: groupId, name }) => ({
87
- icon: group === groupId ? <Icon icon={Check} /> : <div />,
88
- key: groupId,
89
- label: name,
63
+ const items = useMemo(
64
+ () =>
65
+ (
66
+ [
67
+ {
68
+ icon: <Icon icon={pin ? PinOff : Pin} />,
69
+ key: 'pin',
70
+ label: t(pin ? 'pinOff' : 'pin'),
90
71
  onClick: () => {
91
- updateSessionGroup(id, groupId);
72
+ pinSession(id, !pin);
92
73
  },
93
- })),
74
+ },
94
75
  {
95
- icon: isDefault ? <Icon icon={Check} /> : <div />,
96
- key: 'defaultList',
97
- label: t('defaultList'),
98
- onClick: () => {
99
- updateSessionGroup(id, SessionDefaultGroup.Default);
76
+ icon: <Icon icon={LucideCopy} />,
77
+ key: 'duplicate',
78
+ label: t('duplicate', { ns: 'common' }),
79
+ onClick: ({ domEvent }) => {
80
+ domEvent.stopPropagation();
81
+
82
+ duplicateSession(id);
100
83
  },
101
84
  },
102
85
  {
103
86
  type: 'divider',
104
87
  },
105
88
  {
106
- icon: <Icon icon={LucidePlus} />,
107
- key: 'createGroup',
108
- label: <div>{t('sessionGroup.createGroup')}</div>,
109
- onClick: ({ domEvent }) => {
110
- domEvent.stopPropagation();
111
- openCreateGroupModal();
112
- },
89
+ children: [
90
+ ...sessionCustomGroups.map(({ id: groupId, name }) => ({
91
+ icon: group === groupId ? <Icon icon={Check} /> : <div />,
92
+ key: groupId,
93
+ label: name,
94
+ onClick: () => {
95
+ updateSessionGroup(id, groupId);
96
+ },
97
+ })),
98
+ {
99
+ icon: isDefault ? <Icon icon={Check} /> : <div />,
100
+ key: 'defaultList',
101
+ label: t('defaultList'),
102
+ onClick: () => {
103
+ updateSessionGroup(id, SessionDefaultGroup.Default);
104
+ },
105
+ },
106
+ {
107
+ type: 'divider',
108
+ },
109
+ {
110
+ icon: <Icon icon={LucidePlus} />,
111
+ key: 'createGroup',
112
+ label: <div>{t('sessionGroup.createGroup')}</div>,
113
+ onClick: ({ domEvent }) => {
114
+ domEvent.stopPropagation();
115
+ openCreateGroupModal();
116
+ },
117
+ },
118
+ ],
119
+ icon: <Icon icon={ListTree} />,
120
+ key: 'moveGroup',
121
+ label: t('sessionGroup.moveGroup'),
113
122
  },
114
- ],
115
- icon: <Icon icon={ListTree} />,
116
- key: 'moveGroup',
117
- label: t('sessionGroup.moveGroup'),
118
- },
119
- {
120
- type: 'divider',
121
- },
122
- {
123
- children: [
124
123
  {
125
- key: 'agent',
126
- label: t('exportType.agent', { ns: 'common' }),
127
- onClick: () => {
128
- configService.exportSingleAgent(id);
129
- },
124
+ type: 'divider',
130
125
  },
126
+ isServerMode
127
+ ? undefined
128
+ : {
129
+ children: [
130
+ {
131
+ key: 'agent',
132
+ label: t('exportType.agent', { ns: 'common' }),
133
+ onClick: () => {
134
+ configService.exportSingleAgent(id);
135
+ },
136
+ },
137
+ {
138
+ key: 'agentWithMessage',
139
+ label: t('exportType.agentWithMessage', { ns: 'common' }),
140
+ onClick: () => {
141
+ configService.exportSingleSession(id);
142
+ },
143
+ },
144
+ ],
145
+ icon: <Icon icon={HardDriveDownload} />,
146
+ key: 'export',
147
+ label: t('export', { ns: 'common' }),
148
+ },
131
149
  {
132
- key: 'agentWithMessage',
133
- label: t('exportType.agentWithMessage', { ns: 'common' }),
134
- onClick: () => {
135
- configService.exportSingleSession(id);
150
+ danger: true,
151
+ icon: <Icon icon={Trash} />,
152
+ key: 'delete',
153
+ label: t('delete', { ns: 'common' }),
154
+ onClick: ({ domEvent }) => {
155
+ domEvent.stopPropagation();
156
+ modal.confirm({
157
+ centered: true,
158
+ okButtonProps: { danger: true },
159
+ onOk: async () => {
160
+ await removeSession(id);
161
+ message.success(t('confirmRemoveSessionSuccess'));
162
+ },
163
+ rootClassName: styles.modalRoot,
164
+ title: t('confirmRemoveSessionItemAlert'),
165
+ });
136
166
  },
137
167
  },
138
- ],
139
- icon: <Icon icon={HardDriveDownload} />,
140
- key: 'export',
141
- label: t('export', { ns: 'common' }),
142
- },
143
- {
144
- danger: true,
145
- icon: <Icon icon={Trash} />,
146
- key: 'delete',
147
- label: t('delete', { ns: 'common' }),
148
- onClick: ({ domEvent }) => {
149
- domEvent.stopPropagation();
150
- modal.confirm({
151
- centered: true,
152
- okButtonProps: { danger: true },
153
- onOk: async () => {
154
- await removeSession(id);
155
- message.success(t('confirmRemoveSessionSuccess'));
156
- },
157
- rootClassName: styles.modalRoot,
158
- title: t('confirmRemoveSessionItemAlert'),
159
- });
160
- },
161
- },
162
- ],
168
+ ] as ItemType[]
169
+ ).filter(Boolean),
163
170
  [id, pin],
164
171
  );
165
172