@lobehub/chat 0.147.11 → 0.147.13

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 (71) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/contributing/Basic/Feature-Development.md +2 -2
  3. package/contributing/Basic/Feature-Development.zh-CN.md +2 -2
  4. package/package.json +1 -1
  5. package/src/database/{core → client/core}/__tests__/db-upgrade.test.ts +2 -2
  6. package/src/database/{core → client/core}/__tests__/db.test.ts +5 -6
  7. package/src/database/{core → client/core}/db.ts +18 -18
  8. package/src/database/{core → client/core}/index.ts +1 -1
  9. package/src/database/{core → client/core}/migrations/migrateSettingsToUser/index.ts +1 -1
  10. package/src/database/{core → client/core}/model.ts +7 -7
  11. package/src/database/{core → client/core}/sync.ts +3 -3
  12. package/src/database/{models → client/models}/__DEBUG.ts +3 -3
  13. package/src/database/{models → client/models}/__tests__/file.test.ts +3 -4
  14. package/src/database/{models → client/models}/__tests__/session.test.ts +3 -3
  15. package/src/database/{models → client/models}/__tests__/sessionGroup.test.ts +1 -1
  16. package/src/database/{models → client/models}/__tests__/topic.test.ts +4 -4
  17. package/src/database/{models → client/models}/file.ts +1 -1
  18. package/src/database/{models → client/models}/message.ts +3 -3
  19. package/src/database/{models → client/models}/plugin.ts +1 -1
  20. package/src/database/{models → client/models}/session.ts +3 -3
  21. package/src/database/{models → client/models}/sessionGroup.ts +2 -2
  22. package/src/database/{models → client/models}/topic.ts +4 -4
  23. package/src/database/{models → client/models}/user.ts +1 -1
  24. package/src/database/{schemas → client/schemas}/user.ts +1 -1
  25. package/src/features/PluginDevModal/UrlManifestForm.tsx +2 -2
  26. package/src/services/__tests__/__snapshots__/{plugin.test.ts.snap → tool.test.ts.snap} +2 -2
  27. package/src/services/__tests__/chat.test.ts +0 -1
  28. package/src/services/__tests__/{plugin.test.ts → tool.test.ts} +13 -160
  29. package/src/services/debug.ts +1 -1
  30. package/src/services/{file.ts → file/client.ts} +4 -6
  31. package/src/services/{__tests__ → file}/file.test.ts +6 -4
  32. package/src/services/file/index.ts +3 -0
  33. package/src/services/global.ts +1 -1
  34. package/src/services/{__tests__/message.test.ts → message/client.test.ts} +6 -10
  35. package/src/services/{message.ts → message/client.ts} +11 -4
  36. package/src/services/message/index.ts +4 -0
  37. package/src/services/plugin/client.ts +44 -0
  38. package/src/services/plugin/index.ts +5 -0
  39. package/src/services/plugin/plugin.test.ts +162 -0
  40. package/src/services/{session.ts → session/client.ts} +3 -5
  41. package/src/services/session/index.ts +3 -0
  42. package/src/services/{__tests__ → session}/session.test.ts +7 -5
  43. package/src/services/{plugin.ts → tool.ts} +2 -41
  44. package/src/services/{topic.ts → topic/client.ts} +2 -4
  45. package/src/services/topic/index.ts +3 -0
  46. package/src/services/{__tests__ → topic}/topic.test.ts +4 -3
  47. package/src/services/{user.ts → user/client.ts} +2 -4
  48. package/src/services/user/index.ts +5 -0
  49. package/src/store/chat/slices/message/action.ts +1 -2
  50. package/src/store/chat/slices/plugin/action.ts +1 -2
  51. package/src/store/tool/slices/customPlugin/action.test.ts +7 -1
  52. package/src/store/tool/slices/customPlugin/action.ts +2 -1
  53. package/src/store/tool/slices/store/action.test.ts +16 -10
  54. package/src/store/tool/slices/store/action.ts +3 -2
  55. package/src/types/sync.ts +1 -1
  56. /package/src/database/{core → client/core}/__tests__/model.test.ts +0 -0
  57. /package/src/database/{core → client/core}/migrations/migrateSettingsToUser/fixtures/input.json +0 -0
  58. /package/src/database/{core → client/core}/migrations/migrateSettingsToUser/fixtures/output.json +0 -0
  59. /package/src/database/{core → client/core}/migrations/migrateSettingsToUser/index.test.ts +0 -0
  60. /package/src/database/{core → client/core}/migrations/migrateSettingsToUser/type.ts +0 -0
  61. /package/src/database/{core → client/core}/schemas.ts +0 -0
  62. /package/src/database/{core → client/core}/types/db.ts +0 -0
  63. /package/src/database/{models → client/models}/__tests__/message.test.ts +0 -0
  64. /package/src/database/{models → client/models}/__tests__/plugin.test.ts +0 -0
  65. /package/src/database/{models → client/models}/__tests__/user.test.ts +0 -0
  66. /package/src/database/{schemas → client/schemas}/files.ts +0 -0
  67. /package/src/database/{schemas → client/schemas}/message.ts +0 -0
  68. /package/src/database/{schemas → client/schemas}/plugin.ts +0 -0
  69. /package/src/database/{schemas → client/schemas}/session.ts +0 -0
  70. /package/src/database/{schemas → client/schemas}/sessionGroup.ts +0 -0
  71. /package/src/database/{schemas → client/schemas}/topic.ts +0 -0
@@ -1,13 +1,8 @@
1
- import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
2
1
  import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
3
2
 
4
- import { PluginModel } from '@/database/models/plugin';
5
- import { DB_Plugin } from '@/database/schemas/plugin';
6
3
  import { globalHelpers } from '@/store/global/helpers';
7
- import { LobeTool } from '@/types/tool';
8
- import { LobeToolCustomPlugin } from '@/types/tool/plugin';
9
4
 
10
- import { InstallPluginParams, pluginService } from '../plugin';
5
+ import { toolService } from '../tool';
11
6
  import openAPIV3 from './openai/OpenAPI_V3.json';
12
7
  import OpenAIPlugin from './openai/plugin.json';
13
8
 
@@ -18,21 +13,12 @@ vi.mock('@/store/global/helpers', () => ({
18
13
  getCurrentLanguage: vi.fn(),
19
14
  },
20
15
  }));
21
- vi.mock('@/database/models/plugin', () => ({
22
- PluginModel: {
23
- getList: vi.fn(),
24
- create: vi.fn(),
25
- delete: vi.fn(),
26
- update: vi.fn(),
27
- clear: vi.fn(),
28
- },
29
- }));
30
16
 
31
17
  beforeEach(() => {
32
18
  vi.resetAllMocks();
33
19
  });
34
20
 
35
- describe('PluginService', () => {
21
+ describe('ToolService', () => {
36
22
  describe('getPluginList', () => {
37
23
  it('should fetch and return the plugin list', async () => {
38
24
  // Arrange
@@ -45,7 +31,7 @@ describe('PluginService', () => {
45
31
  ) as any;
46
32
 
47
33
  // Act
48
- const pluginList = await pluginService.getPluginList();
34
+ const pluginList = await toolService.getPluginList();
49
35
 
50
36
  // Assert
51
37
  expect(globalHelpers.getCurrentLanguage).toHaveBeenCalled();
@@ -60,7 +46,7 @@ describe('PluginService', () => {
60
46
  global.fetch = vi.fn(() => Promise.reject(new Error('Network error')));
61
47
 
62
48
  // Act & Assert
63
- await expect(pluginService.getPluginList()).rejects.toThrow('Network error');
49
+ await expect(toolService.getPluginList()).rejects.toThrow('Network error');
64
50
  });
65
51
  });
66
52
 
@@ -112,7 +98,7 @@ describe('PluginService', () => {
112
98
  }),
113
99
  ) as any;
114
100
 
115
- const manifest = await pluginService.getPluginManifest(manifestUrl);
101
+ const manifest = await toolService.getPluginManifest(manifestUrl);
116
102
 
117
103
  expect(fetch).toHaveBeenCalledWith(manifestUrl);
118
104
  expect(manifest).toEqual(fakeManifest);
@@ -120,7 +106,7 @@ describe('PluginService', () => {
120
106
 
121
107
  it('should return error on noManifest', async () => {
122
108
  try {
123
- await pluginService.getPluginManifest();
109
+ await toolService.getPluginManifest();
124
110
  } catch (e) {
125
111
  expect(e).toEqual(new TypeError('noManifest'));
126
112
  }
@@ -138,7 +124,7 @@ describe('PluginService', () => {
138
124
  ) as any;
139
125
 
140
126
  try {
141
- await pluginService.getPluginManifest(manifestUrl);
127
+ await toolService.getPluginManifest(manifestUrl);
142
128
  } catch (e) {
143
129
  expect(e).toEqual(new TypeError('manifestInvalid'));
144
130
  }
@@ -149,7 +135,7 @@ describe('PluginService', () => {
149
135
  global.fetch = vi.fn(() => Promise.reject(new Error('Network error')));
150
136
 
151
137
  try {
152
- await pluginService.getPluginManifest(manifestUrl);
138
+ await toolService.getPluginManifest(manifestUrl);
153
139
  } catch (e) {
154
140
  expect(e).toEqual(new TypeError('fetchError'));
155
141
  }
@@ -170,7 +156,7 @@ describe('PluginService', () => {
170
156
  ) as any;
171
157
 
172
158
  try {
173
- await pluginService.getPluginManifest(manifestUrl);
159
+ await toolService.getPluginManifest(manifestUrl);
174
160
  } catch (e) {
175
161
  expect(e).toEqual(new TypeError('urlError'));
176
162
  }
@@ -188,7 +174,7 @@ describe('PluginService', () => {
188
174
  ) as any;
189
175
 
190
176
  try {
191
- await pluginService.getPluginManifest(manifestUrl);
177
+ await toolService.getPluginManifest(manifestUrl);
192
178
  } catch (e) {
193
179
  expect(e).toEqual(new TypeError('fetchError'));
194
180
  }
@@ -228,7 +214,7 @@ describe('PluginService', () => {
228
214
  }),
229
215
  ) as any;
230
216
 
231
- const manifest = await pluginService.getPluginManifest(manifestUrl);
217
+ const manifest = await toolService.getPluginManifest(manifestUrl);
232
218
 
233
219
  expect(manifest).toMatchSnapshot();
234
220
  });
@@ -266,7 +252,7 @@ describe('PluginService', () => {
266
252
  ) as any;
267
253
 
268
254
  try {
269
- await pluginService.getPluginManifest(manifestUrl);
255
+ await toolService.getPluginManifest(manifestUrl);
270
256
  } catch (e) {
271
257
  expect(e).toEqual(new TypeError('openAPIInvalid'));
272
258
  }
@@ -274,141 +260,8 @@ describe('PluginService', () => {
274
260
  });
275
261
  });
276
262
 
277
- describe('installPlugin', () => {
278
- it('should install a plugin', async () => {
279
- // Arrange
280
- const fakePlugin = {
281
- identifier: 'test-plugin',
282
- manifest: { name: 'TestPlugin', version: '1.0.0' } as unknown as LobeChatPluginManifest,
283
- type: 'plugin',
284
- } as InstallPluginParams;
285
- vi.mocked(PluginModel.create).mockResolvedValue(fakePlugin);
286
-
287
- // Act
288
- const installedPlugin = await pluginService.installPlugin(fakePlugin);
289
-
290
- // Assert
291
- expect(PluginModel.create).toHaveBeenCalledWith(fakePlugin);
292
- expect(installedPlugin).toEqual(fakePlugin);
293
- });
294
- });
295
-
296
- describe('getInstalledPlugins', () => {
297
- it('should return a list of installed plugins', async () => {
298
- // Arrange
299
- const fakePlugins = [{ identifier: 'test-plugin', type: 'plugin' }] as LobeTool[];
300
- vi.mocked(PluginModel.getList).mockResolvedValue(fakePlugins as DB_Plugin[]);
301
-
302
- // Act
303
- const installedPlugins = await pluginService.getInstalledPlugins();
304
-
305
- // Assert
306
- expect(PluginModel.getList).toHaveBeenCalled();
307
- expect(installedPlugins).toEqual(fakePlugins);
308
- });
309
- });
310
-
311
- describe('uninstallPlugin', () => {
312
- it('should uninstall a plugin', async () => {
313
- // Arrange
314
- const identifier = 'test-plugin';
315
- vi.mocked(PluginModel.delete).mockResolvedValue();
316
-
317
- // Act
318
- const result = await pluginService.uninstallPlugin(identifier);
319
-
320
- // Assert
321
- expect(PluginModel.delete).toHaveBeenCalledWith(identifier);
322
- expect(result).toBe(undefined);
323
- });
324
- });
325
-
326
- describe('createCustomPlugin', () => {
327
- it('should create a custom plugin', async () => {
328
- // Arrange
329
- const customPlugin = {
330
- identifier: 'custom-plugin',
331
- manifest: {},
332
- type: 'customPlugin',
333
- } as LobeToolCustomPlugin;
334
- vi.mocked(PluginModel.create).mockResolvedValue(customPlugin);
335
-
336
- // Act
337
- const result = await pluginService.createCustomPlugin(customPlugin);
338
-
339
- // Assert
340
- expect(PluginModel.create).toHaveBeenCalledWith({
341
- ...customPlugin,
342
- type: 'customPlugin',
343
- });
344
- expect(result).toEqual(customPlugin);
345
- });
346
- });
347
-
348
- describe('updatePlugin', () => {
349
- it('should update a plugin', async () => {
350
- // Arrange
351
- const id = 'plugin-id';
352
- const value = { settings: { ab: '1' } } as unknown as LobeToolCustomPlugin;
353
- vi.mocked(PluginModel.update).mockResolvedValue(1);
354
-
355
- // Act
356
- const result = await pluginService.updatePlugin(id, value);
357
-
358
- // Assert
359
- expect(PluginModel.update).toHaveBeenCalledWith(id, value);
360
- expect(result).toEqual(1);
361
- });
362
- });
363
-
364
- describe('updatePluginManifest', () => {
365
- it('should update a plugin manifest', async () => {
366
- // Arrange
367
- const id = 'plugin-id';
368
- const manifest = { name: 'NewPluginManifest' } as unknown as LobeChatPluginManifest;
369
- vi.mocked(PluginModel.update).mockResolvedValue(1);
370
-
371
- // Act
372
- const result = await pluginService.updatePluginManifest(id, manifest);
373
-
374
- // Assert
375
- expect(PluginModel.update).toHaveBeenCalledWith(id, { manifest });
376
- expect(result).toEqual(1);
377
- });
378
- });
379
-
380
- describe('removeAllPlugins', () => {
381
- it('should remove all plugins', async () => {
382
- // Arrange
383
- vi.mocked(PluginModel.clear).mockResolvedValue(undefined);
384
-
385
- // Act
386
- const result = await pluginService.removeAllPlugins();
387
-
388
- // Assert
389
- expect(PluginModel.clear).toHaveBeenCalled();
390
- expect(result).toBe(undefined);
391
- });
392
- });
393
-
394
- describe('updatePluginSettings', () => {
395
- it('should update plugin settings', async () => {
396
- // Arrange
397
- const id = 'plugin-id';
398
- const settings = { color: 'blue' };
399
- vi.mocked(PluginModel.update).mockResolvedValue(1);
400
-
401
- // Act
402
- const result = await pluginService.updatePluginSettings(id, settings);
403
-
404
- // Assert
405
- expect(PluginModel.update).toHaveBeenCalledWith(id, { settings });
406
- expect(result).toEqual(1);
407
- });
408
- });
409
-
410
263
  it('can parse the OpenAI plugin', async () => {
411
- const manifest = pluginService['convertOpenAIManifestToLobeManifest'](OpenAIPlugin as any);
264
+ const manifest = toolService['convertOpenAIManifestToLobeManifest'](OpenAIPlugin as any);
412
265
 
413
266
  expect(manifest).toMatchSnapshot();
414
267
  });
@@ -1,4 +1,4 @@
1
- import { DEBUG_MODEL } from '@/database/models/__DEBUG';
1
+ import { DEBUG_MODEL } from '@/database/client/models/__DEBUG';
2
2
 
3
3
  class DebugService {
4
4
  async insertLargeDataToDB() {
@@ -1,11 +1,11 @@
1
- import { FileModel } from '@/database/models/file';
2
- import { DB_File } from '@/database/schemas/files';
1
+ import { FileModel } from '@/database/client/models/file';
2
+ import { DB_File } from '@/database/client/schemas/files';
3
3
  import { FilePreview } from '@/types/files';
4
4
  import compressImage from '@/utils/compressImage';
5
5
 
6
- import { API_ENDPOINTS } from './_url';
6
+ import { API_ENDPOINTS } from '../_url';
7
7
 
8
- class FileService {
8
+ export class FileService {
9
9
  private isImage(fileType: string) {
10
10
  const imageRegex = /^image\//;
11
11
  return imageRegex.test(fileType);
@@ -84,5 +84,3 @@ class FileService {
84
84
  };
85
85
  }
86
86
  }
87
-
88
- export const fileService = new FileService();
@@ -1,12 +1,14 @@
1
1
  import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
2
2
 
3
- import { FileModel } from '@/database/models/file';
4
- import { DB_File } from '@/database/schemas/files';
3
+ import { FileModel } from '@/database/client/models/file';
4
+ import { DB_File } from '@/database/client/schemas/files';
5
5
 
6
- import { fileService } from '../file';
6
+ import { FileService } from './client';
7
+
8
+ const fileService = new FileService();
7
9
 
8
10
  // Mocks for the FileModel
9
- vi.mock('@/database/models/file', () => ({
11
+ vi.mock('@/database/client/models/file', () => ({
10
12
  FileModel: {
11
13
  create: vi.fn(),
12
14
  delete: vi.fn(),
@@ -0,0 +1,3 @@
1
+ import { FileService } from './client';
2
+
3
+ export const fileService = new FileService();
@@ -1,4 +1,4 @@
1
- import { dataSync } from '@/database/core';
1
+ import { dataSync } from '@/database/client/core';
2
2
  import { GlobalServerConfig } from '@/types/serverConfig';
3
3
  import { StartDataSyncParams } from '@/types/sync';
4
4
 
@@ -1,18 +1,14 @@
1
1
  import { Mock, describe, expect, it, vi } from 'vitest';
2
2
 
3
- import { CreateMessageParams, MessageModel } from '@/database/models/message';
4
- import {
5
- ChatMessage,
6
- ChatMessageError,
7
- ChatPluginPayload,
8
- ChatTTS,
9
- ChatTranslate,
10
- } from '@/types/message';
3
+ import { CreateMessageParams, MessageModel } from '@/database/client/models/message';
4
+ import { ChatMessage, ChatMessageError, ChatPluginPayload } from '@/types/message';
11
5
 
12
- import { messageService } from '../message';
6
+ import { MessageService } from './client';
7
+
8
+ const messageService = new MessageService();
13
9
 
14
10
  // Mock the MessageModel
15
- vi.mock('@/database/models/message', () => {
11
+ vi.mock('@/database/client/models/message', () => {
16
12
  return {
17
13
  MessageModel: {
18
14
  create: vi.fn(),
@@ -1,7 +1,16 @@
1
- import { CreateMessageParams, MessageModel } from '@/database/models/message';
2
- import { DB_Message } from '@/database/schemas/message';
1
+ import { MessageModel } from '@/database/client/models/message';
2
+ import { DB_Message } from '@/database/client/schemas/message';
3
3
  import { ChatMessage, ChatMessageError, ChatPluginPayload } from '@/types/message';
4
4
 
5
+ export interface CreateMessageParams
6
+ extends Partial<Omit<ChatMessage, 'content' | 'role'>>,
7
+ Pick<ChatMessage, 'content' | 'role'> {
8
+ fromModel?: string;
9
+ fromProvider?: string;
10
+ sessionId: string;
11
+ traceId?: string;
12
+ }
13
+
5
14
  export class MessageService {
6
15
  async create(data: CreateMessageParams) {
7
16
  const { id } = await MessageModel.create(data);
@@ -67,5 +76,3 @@ export class MessageService {
67
76
  return MessageModel.queryAll();
68
77
  }
69
78
  }
70
-
71
- export const messageService = new MessageService();
@@ -0,0 +1,4 @@
1
+ import { MessageService } from './client';
2
+
3
+ export const messageService = new MessageService();
4
+ export type { CreateMessageParams } from './client';
@@ -0,0 +1,44 @@
1
+ import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
2
+
3
+ import { PluginModel } from '@/database/client/models/plugin';
4
+ import { LobeTool } from '@/types/tool';
5
+ import { LobeToolCustomPlugin } from '@/types/tool/plugin';
6
+
7
+ export interface InstallPluginParams {
8
+ identifier: string;
9
+ manifest: LobeChatPluginManifest;
10
+ type: 'plugin' | 'customPlugin';
11
+ }
12
+
13
+ export class PluginService {
14
+ installPlugin = async (plugin: InstallPluginParams) => {
15
+ return PluginModel.create(plugin);
16
+ };
17
+
18
+ getInstalledPlugins = () => {
19
+ return PluginModel.getList() as Promise<LobeTool[]>;
20
+ };
21
+
22
+ uninstallPlugin(identifier: string) {
23
+ return PluginModel.delete(identifier);
24
+ }
25
+
26
+ async createCustomPlugin(customPlugin: LobeToolCustomPlugin) {
27
+ return PluginModel.create({ ...customPlugin, type: 'customPlugin' });
28
+ }
29
+
30
+ async updatePlugin(id: string, value: LobeToolCustomPlugin) {
31
+ return PluginModel.update(id, value);
32
+ }
33
+ async updatePluginManifest(id: string, manifest: LobeChatPluginManifest) {
34
+ return PluginModel.update(id, { manifest });
35
+ }
36
+
37
+ async removeAllPlugins() {
38
+ return PluginModel.clear();
39
+ }
40
+
41
+ async updatePluginSettings(id: string, settings: any) {
42
+ return PluginModel.update(id, { settings });
43
+ }
44
+ }
@@ -0,0 +1,5 @@
1
+ import { PluginService } from './client';
2
+
3
+ export type { InstallPluginParams } from './client';
4
+
5
+ export const pluginService = new PluginService();
@@ -0,0 +1,162 @@
1
+ import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
3
+
4
+ import { PluginModel } from '@/database/client/models/plugin';
5
+ import { DB_Plugin } from '@/database/client/schemas/plugin';
6
+ import { LobeTool } from '@/types/tool';
7
+ import { LobeToolCustomPlugin } from '@/types/tool/plugin';
8
+
9
+ import { InstallPluginParams, PluginService } from './client';
10
+
11
+ const pluginService = new PluginService();
12
+
13
+ // Mocking modules and functions
14
+
15
+ vi.mock('@/database/client/models/plugin', () => ({
16
+ PluginModel: {
17
+ getList: vi.fn(),
18
+ create: vi.fn(),
19
+ delete: vi.fn(),
20
+ update: vi.fn(),
21
+ clear: vi.fn(),
22
+ },
23
+ }));
24
+
25
+ beforeEach(() => {
26
+ vi.resetAllMocks();
27
+ });
28
+
29
+ describe('PluginService', () => {
30
+ describe('installPlugin', () => {
31
+ it('should install a plugin', async () => {
32
+ // Arrange
33
+ const fakePlugin = {
34
+ identifier: 'test-plugin',
35
+ manifest: { name: 'TestPlugin', version: '1.0.0' } as unknown as LobeChatPluginManifest,
36
+ type: 'plugin',
37
+ } as InstallPluginParams;
38
+ vi.mocked(PluginModel.create).mockResolvedValue(fakePlugin);
39
+
40
+ // Act
41
+ const installedPlugin = await pluginService.installPlugin(fakePlugin);
42
+
43
+ // Assert
44
+ expect(PluginModel.create).toHaveBeenCalledWith(fakePlugin);
45
+ expect(installedPlugin).toEqual(fakePlugin);
46
+ });
47
+ });
48
+
49
+ describe('getInstalledPlugins', () => {
50
+ it('should return a list of installed plugins', async () => {
51
+ // Arrange
52
+ const fakePlugins = [{ identifier: 'test-plugin', type: 'plugin' }] as LobeTool[];
53
+ vi.mocked(PluginModel.getList).mockResolvedValue(fakePlugins as DB_Plugin[]);
54
+
55
+ // Act
56
+ const installedPlugins = await pluginService.getInstalledPlugins();
57
+
58
+ // Assert
59
+ expect(PluginModel.getList).toHaveBeenCalled();
60
+ expect(installedPlugins).toEqual(fakePlugins);
61
+ });
62
+ });
63
+
64
+ describe('uninstallPlugin', () => {
65
+ it('should uninstall a plugin', async () => {
66
+ // Arrange
67
+ const identifier = 'test-plugin';
68
+ vi.mocked(PluginModel.delete).mockResolvedValue();
69
+
70
+ // Act
71
+ const result = await pluginService.uninstallPlugin(identifier);
72
+
73
+ // Assert
74
+ expect(PluginModel.delete).toHaveBeenCalledWith(identifier);
75
+ expect(result).toBe(undefined);
76
+ });
77
+ });
78
+
79
+ describe('createCustomPlugin', () => {
80
+ it('should create a custom plugin', async () => {
81
+ // Arrange
82
+ const customPlugin = {
83
+ identifier: 'custom-plugin',
84
+ manifest: {},
85
+ type: 'customPlugin',
86
+ } as LobeToolCustomPlugin;
87
+ vi.mocked(PluginModel.create).mockResolvedValue(customPlugin);
88
+
89
+ // Act
90
+ const result = await pluginService.createCustomPlugin(customPlugin);
91
+
92
+ // Assert
93
+ expect(PluginModel.create).toHaveBeenCalledWith({
94
+ ...customPlugin,
95
+ type: 'customPlugin',
96
+ });
97
+ expect(result).toEqual(customPlugin);
98
+ });
99
+ });
100
+
101
+ describe('updatePlugin', () => {
102
+ it('should update a plugin', async () => {
103
+ // Arrange
104
+ const id = 'plugin-id';
105
+ const value = { settings: { ab: '1' } } as unknown as LobeToolCustomPlugin;
106
+ vi.mocked(PluginModel.update).mockResolvedValue(1);
107
+
108
+ // Act
109
+ const result = await pluginService.updatePlugin(id, value);
110
+
111
+ // Assert
112
+ expect(PluginModel.update).toHaveBeenCalledWith(id, value);
113
+ expect(result).toEqual(1);
114
+ });
115
+ });
116
+
117
+ describe('updatePluginManifest', () => {
118
+ it('should update a plugin manifest', async () => {
119
+ // Arrange
120
+ const id = 'plugin-id';
121
+ const manifest = { name: 'NewPluginManifest' } as unknown as LobeChatPluginManifest;
122
+ vi.mocked(PluginModel.update).mockResolvedValue(1);
123
+
124
+ // Act
125
+ const result = await pluginService.updatePluginManifest(id, manifest);
126
+
127
+ // Assert
128
+ expect(PluginModel.update).toHaveBeenCalledWith(id, { manifest });
129
+ expect(result).toEqual(1);
130
+ });
131
+ });
132
+
133
+ describe('removeAllPlugins', () => {
134
+ it('should remove all plugins', async () => {
135
+ // Arrange
136
+ vi.mocked(PluginModel.clear).mockResolvedValue(undefined);
137
+
138
+ // Act
139
+ const result = await pluginService.removeAllPlugins();
140
+
141
+ // Assert
142
+ expect(PluginModel.clear).toHaveBeenCalled();
143
+ expect(result).toBe(undefined);
144
+ });
145
+ });
146
+
147
+ describe('updatePluginSettings', () => {
148
+ it('should update plugin settings', async () => {
149
+ // Arrange
150
+ const id = 'plugin-id';
151
+ const settings = { color: 'blue' };
152
+ vi.mocked(PluginModel.update).mockResolvedValue(1);
153
+
154
+ // Act
155
+ const result = await pluginService.updatePluginSettings(id, settings);
156
+
157
+ // Assert
158
+ expect(PluginModel.update).toHaveBeenCalledWith(id, { settings });
159
+ expect(result).toEqual(1);
160
+ });
161
+ });
162
+ });
@@ -1,7 +1,7 @@
1
1
  import { DeepPartial } from 'utility-types';
2
2
 
3
- import { SessionModel } from '@/database/models/session';
4
- import { SessionGroupModel } from '@/database/models/sessionGroup';
3
+ import { SessionModel } from '@/database/client/models/session';
4
+ import { SessionGroupModel } from '@/database/client/models/sessionGroup';
5
5
  import { LobeAgentConfig } from '@/types/agent';
6
6
  import { MetaData } from '@/types/meta';
7
7
  import {
@@ -14,7 +14,7 @@ import {
14
14
  SessionGroups,
15
15
  } from '@/types/session';
16
16
 
17
- class SessionService {
17
+ export class SessionService {
18
18
  async createNewSession(
19
19
  type: LobeSessionType,
20
20
  defaultValue: Partial<LobeAgentSession>,
@@ -118,5 +118,3 @@ class SessionService {
118
118
  return SessionGroupModel.clear();
119
119
  }
120
120
  }
121
-
122
- export const sessionService = new SessionService();
@@ -0,0 +1,3 @@
1
+ import { SessionService } from './client';
2
+
3
+ export const sessionService = new SessionService();
@@ -1,14 +1,16 @@
1
1
  import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
2
2
 
3
- import { SessionModel } from '@/database/models/session';
4
- import { SessionGroupModel } from '@/database/models/sessionGroup';
3
+ import { SessionModel } from '@/database/client/models/session';
4
+ import { SessionGroupModel } from '@/database/client/models/sessionGroup';
5
5
  import { LobeAgentConfig } from '@/types/agent';
6
6
  import { LobeAgentSession, LobeSessionType, SessionGroups } from '@/types/session';
7
7
 
8
- import { sessionService } from '../session';
8
+ import { SessionService } from './client';
9
+
10
+ const sessionService = new SessionService();
9
11
 
10
12
  // Mock the SessionModel
11
- vi.mock('@/database/models/session', () => {
13
+ vi.mock('@/database/client/models/session', () => {
12
14
  return {
13
15
  SessionModel: {
14
16
  create: vi.fn(),
@@ -29,7 +31,7 @@ vi.mock('@/database/models/session', () => {
29
31
  });
30
32
 
31
33
  // Mock the SessionGroupModel
32
- vi.mock('@/database/models/sessionGroup', () => {
34
+ vi.mock('@/database/client/models/sessionGroup', () => {
33
35
  return {
34
36
  SessionGroupModel: {
35
37
  create: vi.fn(),