@lobehub/chat 0.147.12 → 0.147.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/package.json +1 -1
- package/src/config/modelProviders/google.ts +2 -1
- package/src/features/PluginDevModal/UrlManifestForm.tsx +2 -2
- package/src/services/__tests__/__snapshots__/{plugin.test.ts.snap → tool.test.ts.snap} +2 -2
- package/src/services/__tests__/chat.test.ts +0 -1
- package/src/services/__tests__/{plugin.test.ts → tool.test.ts} +13 -160
- package/src/services/{__tests__/file.test.ts → file/client.test.ts} +3 -1
- package/src/services/{file.ts → file/client.ts} +2 -4
- package/src/services/file/index.ts +3 -0
- package/src/services/{__tests__/message.test.ts → message/client.test.ts} +5 -9
- package/src/services/{message.ts → message/client.ts} +0 -2
- package/src/services/message/index.ts +4 -0
- package/src/services/plugin/client.test.ts +162 -0
- package/src/services/plugin/client.ts +44 -0
- package/src/services/plugin/index.ts +5 -0
- package/src/services/{__tests__/session.test.ts → session/client.test.ts} +3 -1
- package/src/services/{session.ts → session/client.ts} +1 -3
- package/src/services/session/index.ts +3 -0
- package/src/services/{plugin.ts → tool.ts} +2 -41
- package/src/services/{__tests__/topic.test.ts → topic/client.test.ts} +2 -1
- package/src/services/{topic.ts → topic/client.ts} +1 -3
- package/src/services/topic/index.ts +3 -0
- package/src/services/trace.ts +2 -4
- package/src/services/{user.ts → user/client.ts} +1 -3
- package/src/services/user/index.ts +5 -0
- package/src/store/tool/slices/customPlugin/action.test.ts +7 -1
- package/src/store/tool/slices/customPlugin/action.ts +2 -1
- package/src/store/tool/slices/store/action.test.ts +16 -10
- package/src/store/tool/slices/store/action.ts +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.147.14](https://github.com/lobehub/lobe-chat/compare/v0.147.13...v0.147.14)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-04-14**</sup>
|
|
8
|
+
|
|
9
|
+
#### 💄 Styles
|
|
10
|
+
|
|
11
|
+
- **misc**: Enable `gemini-1.5-pro-latest` model by default.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Styles
|
|
19
|
+
|
|
20
|
+
- **misc**: Enable `gemini-1.5-pro-latest` model by default, closes [#2034](https://github.com/lobehub/lobe-chat/issues/2034) ([e8c65a9](https://github.com/lobehub/lobe-chat/commit/e8c65a9))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.147.13](https://github.com/lobehub/lobe-chat/compare/v0.147.12...v0.147.13)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2024-04-14**</sup>
|
|
33
|
+
|
|
34
|
+
#### ♻ Code Refactoring
|
|
35
|
+
|
|
36
|
+
- **misc**: Refactor the service with browser db invoke.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### Code refactoring
|
|
44
|
+
|
|
45
|
+
- **misc**: Refactor the service with browser db invoke, closes [#2038](https://github.com/lobehub/lobe-chat/issues/2038) ([43a2791](https://github.com/lobehub/lobe-chat/commit/43a2791))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
### [Version 0.147.12](https://github.com/lobehub/lobe-chat/compare/v0.147.11...v0.147.12)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2024-04-14**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.147.
|
|
3
|
+
"version": "0.147.14",
|
|
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",
|
|
@@ -26,7 +26,6 @@ const Google: ModelProviderCard = {
|
|
|
26
26
|
{
|
|
27
27
|
description: 'The best image understanding model to handle a broad range of applications',
|
|
28
28
|
displayName: 'Gemini 1.0 Pro Vision',
|
|
29
|
-
enabled: true,
|
|
30
29
|
id: 'gemini-1.0-pro-vision-latest',
|
|
31
30
|
maxOutput: 4096,
|
|
32
31
|
tokens: 16_384,
|
|
@@ -35,6 +34,7 @@ const Google: ModelProviderCard = {
|
|
|
35
34
|
{
|
|
36
35
|
description: 'The best image understanding model to handle a broad range of applications',
|
|
37
36
|
displayName: 'Gemini 1.0 Pro Vision',
|
|
37
|
+
enabled: true,
|
|
38
38
|
id: 'gemini-pro-vision',
|
|
39
39
|
maxOutput: 4096,
|
|
40
40
|
tokens: 16_384,
|
|
@@ -59,6 +59,7 @@ const Google: ModelProviderCard = {
|
|
|
59
59
|
{
|
|
60
60
|
description: 'Mid-size multimodal model that supports up to 1 million tokens',
|
|
61
61
|
displayName: 'Gemini 1.5 Pro',
|
|
62
|
+
enabled: true,
|
|
62
63
|
id: 'gemini-1.5-pro-latest',
|
|
63
64
|
maxOutput: 8192,
|
|
64
65
|
tokens: 1_056_768,
|
|
@@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
9
|
import ManifestPreviewer from '@/components/ManifestPreviewer';
|
|
10
|
-
import {
|
|
10
|
+
import { toolService } from '@/services/tool';
|
|
11
11
|
import { useToolStore } from '@/store/tool';
|
|
12
12
|
import { pluginSelectors } from '@/store/tool/selectors';
|
|
13
13
|
import { PluginInstallError } from '@/types/tool/plugin';
|
|
@@ -77,7 +77,7 @@ const UrlManifestForm = memo<{ form: FormInstance; isEditMode: boolean }>(
|
|
|
77
77
|
|
|
78
78
|
try {
|
|
79
79
|
const useProxy = form.getFieldValue(proxyKey);
|
|
80
|
-
const data = await
|
|
80
|
+
const data = await toolService.getPluginManifest(value, useProxy);
|
|
81
81
|
setManifest(data);
|
|
82
82
|
|
|
83
83
|
form.setFieldsValue({ identifier: data.identifier, manifest: data });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`
|
|
3
|
+
exports[`ToolService > can parse the OpenAI plugin 1`] = `
|
|
4
4
|
{
|
|
5
5
|
"api": [],
|
|
6
6
|
"homepage": "https://products.wolframalpha.com/api/commercial-termsofuse",
|
|
@@ -78,7 +78,7 @@ getWolframCloudResults guidelines:
|
|
|
78
78
|
}
|
|
79
79
|
`;
|
|
80
80
|
|
|
81
|
-
exports[`
|
|
81
|
+
exports[`ToolService > getPluginManifest > support OpenAPI manifest > should get plugin manifest 1`] = `
|
|
82
82
|
{
|
|
83
83
|
"$schema": "../node_modules/@lobehub/chat-plugin-sdk/schema.json",
|
|
84
84
|
"api": [
|
|
@@ -9,7 +9,6 @@ import { DalleManifest } from '@/tools/dalle';
|
|
|
9
9
|
import { ChatMessage } from '@/types/message';
|
|
10
10
|
import { ChatStreamPayload } from '@/types/openai/chat';
|
|
11
11
|
import { LobeTool } from '@/types/tool';
|
|
12
|
-
import { FetchSSEOptions, fetchSSE } from '@/utils/fetch';
|
|
13
12
|
|
|
14
13
|
import { chatService } from '../chat';
|
|
15
14
|
|
|
@@ -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/client/models/plugin';
|
|
5
|
-
import { DB_Plugin } from '@/database/client/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 {
|
|
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/client/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('
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
264
|
+
const manifest = toolService['convertOpenAIManifestToLobeManifest'](OpenAIPlugin as any);
|
|
412
265
|
|
|
413
266
|
expect(manifest).toMatchSnapshot();
|
|
414
267
|
});
|
|
@@ -3,7 +3,9 @@ import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
3
3
|
import { FileModel } from '@/database/client/models/file';
|
|
4
4
|
import { DB_File } from '@/database/client/schemas/files';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { FileService } from './client';
|
|
7
|
+
|
|
8
|
+
const fileService = new FileService();
|
|
7
9
|
|
|
8
10
|
// Mocks for the FileModel
|
|
9
11
|
vi.mock('@/database/client/models/file', () => ({
|
|
@@ -3,9 +3,9 @@ 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 '
|
|
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,15 +1,11 @@
|
|
|
1
1
|
import { Mock, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { CreateMessageParams, MessageModel } from '@/database/client/models/message';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
ChatTranslate,
|
|
10
|
-
} from '@/types/message';
|
|
11
|
-
|
|
12
|
-
import { messageService } from '../message';
|
|
4
|
+
import { ChatMessage, ChatMessageError, ChatPluginPayload } from '@/types/message';
|
|
5
|
+
|
|
6
|
+
import { MessageService } from './client';
|
|
7
|
+
|
|
8
|
+
const messageService = new MessageService();
|
|
13
9
|
|
|
14
10
|
// Mock the MessageModel
|
|
15
11
|
vi.mock('@/database/client/models/message', () => {
|
|
@@ -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
|
+
});
|
|
@@ -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
|
+
}
|
|
@@ -5,7 +5,9 @@ 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 {
|
|
8
|
+
import { SessionService } from './client';
|
|
9
|
+
|
|
10
|
+
const sessionService = new SessionService();
|
|
9
11
|
|
|
10
12
|
// Mock the SessionModel
|
|
11
13
|
vi.mock('@/database/client/models/session', () => {
|
|
@@ -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();
|
|
@@ -4,20 +4,12 @@ import {
|
|
|
4
4
|
pluginManifestSchema,
|
|
5
5
|
} from '@lobehub/chat-plugin-sdk';
|
|
6
6
|
|
|
7
|
-
import { PluginModel } from '@/database/client/models/plugin';
|
|
8
7
|
import { globalHelpers } from '@/store/global/helpers';
|
|
9
8
|
import { OpenAIPluginManifest } from '@/types/openai/plugin';
|
|
10
|
-
import { LobeTool } from '@/types/tool';
|
|
11
|
-
import { LobeToolCustomPlugin } from '@/types/tool/plugin';
|
|
12
9
|
|
|
13
10
|
import { API_ENDPOINTS } from './_url';
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
identifier: string;
|
|
17
|
-
manifest: LobeChatPluginManifest;
|
|
18
|
-
type: 'plugin' | 'customPlugin';
|
|
19
|
-
}
|
|
20
|
-
class PluginService {
|
|
12
|
+
class ToolService {
|
|
21
13
|
private _fetchJSON = async <T = any>(url: string, proxy = false): Promise<T> => {
|
|
22
14
|
// 2. 发送请求
|
|
23
15
|
let res: Response;
|
|
@@ -107,37 +99,6 @@ class PluginService {
|
|
|
107
99
|
return data;
|
|
108
100
|
};
|
|
109
101
|
|
|
110
|
-
installPlugin = async (plugin: InstallPluginParams) => {
|
|
111
|
-
return PluginModel.create(plugin);
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
getInstalledPlugins = () => {
|
|
115
|
-
return PluginModel.getList() as Promise<LobeTool[]>;
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
uninstallPlugin(identifier: string) {
|
|
119
|
-
return PluginModel.delete(identifier);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async createCustomPlugin(customPlugin: LobeToolCustomPlugin) {
|
|
123
|
-
return PluginModel.create({ ...customPlugin, type: 'customPlugin' });
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async updatePlugin(id: string, value: LobeToolCustomPlugin) {
|
|
127
|
-
return PluginModel.update(id, value);
|
|
128
|
-
}
|
|
129
|
-
async updatePluginManifest(id: string, manifest: LobeChatPluginManifest) {
|
|
130
|
-
return PluginModel.update(id, { manifest });
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async removeAllPlugins() {
|
|
134
|
-
return PluginModel.clear();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async updatePluginSettings(id: string, settings: any) {
|
|
138
|
-
return PluginModel.update(id, { settings });
|
|
139
|
-
}
|
|
140
|
-
|
|
141
102
|
private convertOpenAIManifestToLobeManifest = (
|
|
142
103
|
data: OpenAIPluginManifest,
|
|
143
104
|
): LobeChatPluginManifest => {
|
|
@@ -180,4 +141,4 @@ class PluginService {
|
|
|
180
141
|
};
|
|
181
142
|
}
|
|
182
143
|
|
|
183
|
-
export const
|
|
144
|
+
export const toolService = new ToolService();
|
|
@@ -3,8 +3,9 @@ import { Mock, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
3
3
|
import { CreateTopicParams, TopicModel } from '@/database/client/models/topic';
|
|
4
4
|
import { ChatTopic } from '@/types/topic';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { TopicService } from './client';
|
|
7
7
|
|
|
8
|
+
const topicService = new TopicService();
|
|
8
9
|
// Mock the TopicModel
|
|
9
10
|
vi.mock('@/database/client/models/topic', () => {
|
|
10
11
|
return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CreateTopicParams, QueryTopicParams, TopicModel } from '@/database/client/models/topic';
|
|
2
2
|
import { ChatTopic } from '@/types/topic';
|
|
3
3
|
|
|
4
|
-
class TopicService {
|
|
4
|
+
export class TopicService {
|
|
5
5
|
async createTopic(params: CreateTopicParams): Promise<string> {
|
|
6
6
|
const item = await TopicModel.create(params);
|
|
7
7
|
|
|
@@ -56,5 +56,3 @@ class TopicService {
|
|
|
56
56
|
return TopicModel.duplicateTopic(id, newTitle);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
export const topicService = new TopicService();
|
package/src/services/trace.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { API_ENDPOINTS } from '@/services/_url';
|
|
2
2
|
import { useGlobalStore } from '@/store/global';
|
|
3
|
-
import { preferenceSelectors } from '@/store/global/
|
|
3
|
+
import { preferenceSelectors } from '@/store/global/selectors';
|
|
4
4
|
import { TraceEventBasePayload, TraceEventPayloads } from '@/types/trace';
|
|
5
5
|
|
|
6
6
|
class TraceService {
|
|
@@ -8,9 +8,7 @@ class TraceService {
|
|
|
8
8
|
try {
|
|
9
9
|
return fetch(API_ENDPOINTS.trace, {
|
|
10
10
|
body: JSON.stringify(data),
|
|
11
|
-
headers: {
|
|
12
|
-
'Content-Type': 'application/json',
|
|
13
|
-
},
|
|
11
|
+
headers: { 'Content-Type': 'application/json' },
|
|
14
12
|
method: 'POST',
|
|
15
13
|
});
|
|
16
14
|
} catch (e) {
|
|
@@ -9,7 +9,7 @@ export interface UserConfig {
|
|
|
9
9
|
uuid: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
class UserService {
|
|
12
|
+
export class UserService {
|
|
13
13
|
getUserConfig = async () => {
|
|
14
14
|
const user = await UserModel.getUser();
|
|
15
15
|
return user as unknown as UserConfig;
|
|
@@ -27,5 +27,3 @@ class UserService {
|
|
|
27
27
|
return UserModel.updateAvatar(avatar);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
export const userService = new UserService();
|
|
@@ -12,13 +12,19 @@ beforeEach(() => {
|
|
|
12
12
|
});
|
|
13
13
|
vi.mock('@/services/plugin', () => ({
|
|
14
14
|
pluginService: {
|
|
15
|
-
getPluginManifest: vi.fn(),
|
|
16
15
|
updatePlugin: vi.fn(),
|
|
17
16
|
createCustomPlugin: vi.fn(),
|
|
18
17
|
uninstallPlugin: vi.fn(),
|
|
19
18
|
updatePluginManifest: vi.fn(),
|
|
20
19
|
},
|
|
21
20
|
}));
|
|
21
|
+
|
|
22
|
+
vi.mock('@/services/tool', () => ({
|
|
23
|
+
toolService: {
|
|
24
|
+
getPluginManifest: vi.fn(),
|
|
25
|
+
},
|
|
26
|
+
}));
|
|
27
|
+
|
|
22
28
|
describe('useToolStore:customPlugin', () => {
|
|
23
29
|
describe('deleteCustomPlugin', () => {
|
|
24
30
|
it('should delete custom plugin and related settings', async () => {
|
|
@@ -4,6 +4,7 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
4
4
|
|
|
5
5
|
import { notification } from '@/components/AntdStaticMethods';
|
|
6
6
|
import { pluginService } from '@/services/plugin';
|
|
7
|
+
import { toolService } from '@/services/tool';
|
|
7
8
|
import { pluginHelpers } from '@/store/tool/helpers';
|
|
8
9
|
import { LobeToolCustomPlugin, PluginInstallError } from '@/types/tool/plugin';
|
|
9
10
|
import { setNamespace } from '@/utils/storeDebug';
|
|
@@ -41,7 +42,7 @@ export const createCustomPluginSlice: StateCreator<
|
|
|
41
42
|
const { refreshPlugins, updateInstallLoadingState } = get();
|
|
42
43
|
try {
|
|
43
44
|
updateInstallLoadingState(id, true);
|
|
44
|
-
const manifest = await
|
|
45
|
+
const manifest = await toolService.getPluginManifest(
|
|
45
46
|
plugin.customParams?.manifestUrl,
|
|
46
47
|
plugin.customParams?.useProxy,
|
|
47
48
|
);
|
|
@@ -5,6 +5,7 @@ import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
5
5
|
|
|
6
6
|
import { notification } from '@/components/AntdStaticMethods';
|
|
7
7
|
import { pluginService } from '@/services/plugin';
|
|
8
|
+
import { toolService } from '@/services/tool';
|
|
8
9
|
|
|
9
10
|
import { useToolStore } from '../../store';
|
|
10
11
|
|
|
@@ -17,13 +18,18 @@ vi.mock('@/components/AntdStaticMethods', () => ({
|
|
|
17
18
|
// Mock the pluginService.getPluginList method
|
|
18
19
|
vi.mock('@/services/plugin', () => ({
|
|
19
20
|
pluginService: {
|
|
20
|
-
getPluginManifest: vi.fn(),
|
|
21
|
-
getPluginList: vi.fn(),
|
|
22
21
|
uninstallPlugin: vi.fn(),
|
|
23
22
|
installPlugin: vi.fn(),
|
|
24
23
|
},
|
|
25
24
|
}));
|
|
26
25
|
|
|
26
|
+
vi.mock('@/services/tool', () => ({
|
|
27
|
+
toolService: {
|
|
28
|
+
getPluginManifest: vi.fn(),
|
|
29
|
+
getPluginList: vi.fn(),
|
|
30
|
+
},
|
|
31
|
+
}));
|
|
32
|
+
|
|
27
33
|
// Mock i18next
|
|
28
34
|
vi.mock('i18next', () => ({
|
|
29
35
|
t: vi.fn((key) => key),
|
|
@@ -97,7 +103,7 @@ describe('useToolStore:pluginStore', () => {
|
|
|
97
103
|
it('should load plugin list and update state', async () => {
|
|
98
104
|
// Given
|
|
99
105
|
const pluginListMock = { plugins: [{ identifier: 'plugin1' }, { identifier: 'plugin2' }] };
|
|
100
|
-
(
|
|
106
|
+
(toolService.getPluginList as Mock).mockResolvedValue(pluginListMock);
|
|
101
107
|
|
|
102
108
|
// When
|
|
103
109
|
let pluginList;
|
|
@@ -106,7 +112,7 @@ describe('useToolStore:pluginStore', () => {
|
|
|
106
112
|
});
|
|
107
113
|
|
|
108
114
|
// Then
|
|
109
|
-
expect(
|
|
115
|
+
expect(toolService.getPluginList).toHaveBeenCalled();
|
|
110
116
|
expect(pluginList).toEqual(pluginListMock);
|
|
111
117
|
expect(useToolStore.getState().pluginStoreList).toEqual(pluginListMock.plugins);
|
|
112
118
|
});
|
|
@@ -114,7 +120,7 @@ describe('useToolStore:pluginStore', () => {
|
|
|
114
120
|
it('should handle errors when loading plugin list', async () => {
|
|
115
121
|
// Given
|
|
116
122
|
const error = new Error('Failed to load plugin list');
|
|
117
|
-
(
|
|
123
|
+
(toolService.getPluginList as Mock).mockRejectedValue(error);
|
|
118
124
|
|
|
119
125
|
// When
|
|
120
126
|
let pluginList;
|
|
@@ -128,7 +134,7 @@ describe('useToolStore:pluginStore', () => {
|
|
|
128
134
|
}
|
|
129
135
|
|
|
130
136
|
// Then
|
|
131
|
-
expect(
|
|
137
|
+
expect(toolService.getPluginList).toHaveBeenCalled();
|
|
132
138
|
expect(errorOccurred).toBe(true);
|
|
133
139
|
expect(pluginList).toBeUndefined();
|
|
134
140
|
// Ensure the state is not updated with an undefined value
|
|
@@ -224,14 +230,14 @@ describe('useToolStore:pluginStore', () => {
|
|
|
224
230
|
},
|
|
225
231
|
version: '1',
|
|
226
232
|
};
|
|
227
|
-
(
|
|
233
|
+
(toolService.getPluginManifest as Mock).mockResolvedValue(pluginManifestMock);
|
|
228
234
|
|
|
229
235
|
await act(async () => {
|
|
230
236
|
await useToolStore.getState().installPlugin(pluginIdentifier);
|
|
231
237
|
});
|
|
232
238
|
|
|
233
239
|
// Then
|
|
234
|
-
expect(
|
|
240
|
+
expect(toolService.getPluginManifest).toHaveBeenCalled();
|
|
235
241
|
expect(notification.error).not.toHaveBeenCalled();
|
|
236
242
|
expect(updateInstallLoadingStateMock).toHaveBeenCalledTimes(2);
|
|
237
243
|
expect(pluginService.installPlugin).toHaveBeenCalledWith({
|
|
@@ -253,7 +259,7 @@ describe('useToolStore:pluginStore', () => {
|
|
|
253
259
|
const error = new TypeError('noManifest');
|
|
254
260
|
|
|
255
261
|
// Mock necessary modules and functions
|
|
256
|
-
(
|
|
262
|
+
(toolService.getPluginManifest as Mock).mockRejectedValue(error);
|
|
257
263
|
|
|
258
264
|
useToolStore.setState({
|
|
259
265
|
pluginStoreList: [
|
|
@@ -297,7 +303,7 @@ describe('useToolStore:pluginStore', () => {
|
|
|
297
303
|
|
|
298
304
|
const plugins = ['plugin1', 'plugin2'];
|
|
299
305
|
|
|
300
|
-
(
|
|
306
|
+
(toolService.getPluginManifest as Mock).mockResolvedValue(pluginManifestMock);
|
|
301
307
|
|
|
302
308
|
// When
|
|
303
309
|
await act(async () => {
|
|
@@ -6,6 +6,7 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
6
6
|
|
|
7
7
|
import { notification } from '@/components/AntdStaticMethods';
|
|
8
8
|
import { pluginService } from '@/services/plugin';
|
|
9
|
+
import { toolService } from '@/services/tool';
|
|
9
10
|
import { pluginStoreSelectors } from '@/store/tool/selectors';
|
|
10
11
|
import { LobeTool } from '@/types/tool';
|
|
11
12
|
import { PluginInstallError } from '@/types/tool/plugin';
|
|
@@ -43,7 +44,7 @@ export const createPluginStoreSlice: StateCreator<
|
|
|
43
44
|
const { updateInstallLoadingState, refreshPlugins } = get();
|
|
44
45
|
try {
|
|
45
46
|
updateInstallLoadingState(name, true);
|
|
46
|
-
const data = await
|
|
47
|
+
const data = await toolService.getPluginManifest(plugin.manifest);
|
|
47
48
|
updateInstallLoadingState(name, undefined);
|
|
48
49
|
|
|
49
50
|
// 4. 存储 manifest 信息
|
|
@@ -66,7 +67,7 @@ export const createPluginStoreSlice: StateCreator<
|
|
|
66
67
|
await Promise.all(plugins.map((identifier) => installPlugin(identifier)));
|
|
67
68
|
},
|
|
68
69
|
loadPluginStore: async () => {
|
|
69
|
-
const pluginMarketIndex = await
|
|
70
|
+
const pluginMarketIndex = await toolService.getPluginList();
|
|
70
71
|
|
|
71
72
|
set({ pluginStoreList: pluginMarketIndex.plugins }, false, n('loadPluginList'));
|
|
72
73
|
|