@lobehub/chat 1.36.46 → 1.37.1
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/README.ja-JP.md +8 -8
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/changelog/v1.json +18 -0
- package/next.config.mjs +4 -1
- package/package.json +5 -3
- package/scripts/migrateClientDB/compile-migrations.ts +14 -0
- package/src/app/(main)/(mobile)/me/(home)/layout.tsx +2 -0
- package/src/app/(main)/chat/_layout/Desktop/index.tsx +3 -2
- package/src/app/(main)/chat/_layout/Mobile.tsx +5 -3
- package/src/app/(main)/chat/features/Migration/DBReader.ts +290 -0
- package/src/app/(main)/chat/features/Migration/UpgradeButton.tsx +4 -8
- package/src/app/(main)/chat/features/Migration/index.tsx +26 -15
- package/src/app/(main)/settings/_layout/Desktop/index.tsx +2 -0
- package/src/app/loading/Client/Content.tsx +11 -1
- package/src/app/loading/Client/Error.tsx +27 -0
- package/src/app/loading/stage.ts +8 -0
- package/src/components/FullscreenLoading/index.tsx +4 -3
- package/src/const/version.ts +1 -0
- package/src/database/client/db.test.ts +172 -0
- package/src/database/client/db.ts +246 -0
- package/src/database/client/migrations.json +289 -0
- package/src/features/InitClientDB/EnableModal.tsx +111 -0
- package/src/features/InitClientDB/ErrorResult.tsx +125 -0
- package/src/features/InitClientDB/InitIndicator.tsx +124 -0
- package/src/features/InitClientDB/PGliteSVG.tsx +22 -0
- package/src/features/InitClientDB/index.tsx +37 -0
- package/src/hooks/useCheckPluginsIsInstalled.ts +2 -2
- package/src/hooks/useFetchInstalledPlugins.ts +2 -2
- package/src/hooks/useFetchMessages.ts +2 -2
- package/src/hooks/useFetchSessions.ts +2 -2
- package/src/hooks/useFetchThreads.ts +2 -2
- package/src/hooks/useFetchTopics.ts +2 -2
- package/src/layout/GlobalProvider/StoreInitialization.tsx +2 -2
- package/src/services/baseClientService/index.ts +9 -0
- package/src/services/debug.ts +32 -34
- package/src/services/file/{client.test.ts → _deprecated.test.ts} +1 -1
- package/src/services/file/index.ts +6 -2
- package/src/services/file/pglite.test.ts +198 -0
- package/src/services/file/pglite.ts +84 -0
- package/src/services/file/type.ts +4 -3
- package/src/services/github.ts +17 -0
- package/src/services/import/index.ts +6 -2
- package/src/services/import/pglite.test.ts +997 -0
- package/src/services/import/pglite.ts +34 -0
- package/src/services/message/{client.test.ts → _deprecated.test.ts} +1 -1
- package/src/services/message/{client.ts → _deprecated.ts} +2 -0
- package/src/services/message/index.ts +6 -2
- package/src/services/message/pglite.test.ts +430 -0
- package/src/services/message/pglite.ts +118 -0
- package/src/services/message/server.ts +9 -9
- package/src/services/message/type.ts +3 -4
- package/src/services/plugin/{client.test.ts → _deprecated.test.ts} +1 -1
- package/src/services/plugin/index.ts +6 -2
- package/src/services/plugin/pglite.test.ts +175 -0
- package/src/services/plugin/pglite.ts +51 -0
- package/src/services/session/{client.test.ts → _deprecated.test.ts} +1 -1
- package/src/services/session/{client.ts → _deprecated.ts} +1 -1
- package/src/services/session/index.ts +6 -2
- package/src/services/session/pglite.test.ts +411 -0
- package/src/services/session/pglite.ts +184 -0
- package/src/services/session/type.ts +14 -1
- package/src/services/topic/client.test.ts +1 -1
- package/src/services/topic/index.ts +6 -3
- package/src/services/topic/pglite.test.ts +212 -0
- package/src/services/topic/pglite.ts +85 -0
- package/src/services/user/{client.test.ts → _deprecated.test.ts} +1 -2
- package/src/services/user/index.ts +8 -2
- package/src/services/user/pglite.test.ts +98 -0
- package/src/services/user/pglite.ts +92 -0
- package/src/store/chat/slices/builtinTool/action.test.ts +4 -5
- package/src/store/global/actions/clientDb.ts +51 -0
- package/src/store/global/initialState.ts +13 -0
- package/src/store/global/selectors.ts +24 -3
- package/src/store/global/store.ts +3 -1
- package/src/store/session/slices/sessionGroup/reducer.test.ts +6 -6
- package/src/store/user/slices/common/action.test.ts +1 -1
- package/src/store/user/slices/common/action.ts +2 -4
- package/src/types/clientDB.ts +29 -0
- package/src/types/importer.ts +17 -5
- package/src/types/meta.ts +0 -9
- package/src/types/session/sessionGroup.ts +3 -3
- package/src/services/message/index.test.ts +0 -48
- /package/src/services/file/{client.ts → _deprecated.ts} +0 -0
- /package/src/services/import/{client.ts → _deprecated.ts} +0 -0
- /package/src/services/plugin/{client.ts → _deprecated.ts} +0 -0
- /package/src/services/topic/{client.ts → _deprecated.ts} +0 -0
- /package/src/services/user/{client.ts → _deprecated.ts} +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { MessageItem } from '@/database/schemas';
|
2
2
|
import {
|
3
3
|
ChatMessage,
|
4
4
|
ChatMessageError,
|
@@ -11,7 +11,7 @@ import {
|
|
11
11
|
|
12
12
|
export interface IMessageService {
|
13
13
|
createMessage(data: CreateMessageParams): Promise<string>;
|
14
|
-
batchCreateMessages(messages:
|
14
|
+
batchCreateMessages(messages: MessageItem[]): Promise<any>;
|
15
15
|
|
16
16
|
getMessages(sessionId: string, topicId?: string): Promise<ChatMessage[]>;
|
17
17
|
getAllMessages(): Promise<ChatMessage[]>;
|
@@ -20,11 +20,10 @@ export interface IMessageService {
|
|
20
20
|
countTodayMessages(): Promise<number>;
|
21
21
|
|
22
22
|
updateMessageError(id: string, error: ChatMessageError): Promise<any>;
|
23
|
-
updateMessage(id: string, message: Partial<
|
23
|
+
updateMessage(id: string, message: Partial<MessageItem>): Promise<any>;
|
24
24
|
updateMessageTTS(id: string, tts: Partial<ChatTTS> | false): Promise<any>;
|
25
25
|
updateMessageTranslate(id: string, translate: Partial<ChatTranslate> | false): Promise<any>;
|
26
26
|
updateMessagePluginState(id: string, value: Record<string, any>): Promise<any>;
|
27
|
-
bindMessagesToTopic(topicId: string, messageIds: string[]): Promise<any>;
|
28
27
|
|
29
28
|
removeMessage(id: string): Promise<any>;
|
30
29
|
removeMessages(ids: string[]): Promise<any>;
|
@@ -6,7 +6,7 @@ import { DB_Plugin } from '@/database/_deprecated/schemas/plugin';
|
|
6
6
|
import { LobeTool } from '@/types/tool';
|
7
7
|
import { LobeToolCustomPlugin } from '@/types/tool/plugin';
|
8
8
|
|
9
|
-
import { ClientService } from './
|
9
|
+
import { ClientService } from './_deprecated';
|
10
10
|
import { InstallPluginParams } from './type';
|
11
11
|
|
12
12
|
const pluginService = new ClientService();
|
@@ -1,5 +1,9 @@
|
|
1
|
-
import { ClientService } from './
|
1
|
+
import { ClientService as DeprecatedService } from './_deprecated';
|
2
|
+
import { ClientService } from './pglite';
|
2
3
|
import { ServerService } from './server';
|
3
4
|
|
5
|
+
const clientService =
|
6
|
+
process.env.NEXT_PUBLIC_CLIENT_DB === 'pglite' ? new ClientService() : new DeprecatedService();
|
7
|
+
|
4
8
|
export const pluginService =
|
5
|
-
process.env.NEXT_PUBLIC_SERVICE_MODE === 'server' ? new ServerService() :
|
9
|
+
process.env.NEXT_PUBLIC_SERVICE_MODE === 'server' ? new ServerService() : clientService;
|
@@ -0,0 +1,175 @@
|
|
1
|
+
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
|
2
|
+
import { eq } from 'drizzle-orm';
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
4
|
+
|
5
|
+
import { clientDB, initializeDB } from '@/database/client/db';
|
6
|
+
import { installedPlugins, users } from '@/database/schemas';
|
7
|
+
import { LobeTool } from '@/types/tool';
|
8
|
+
import { LobeToolCustomPlugin } from '@/types/tool/plugin';
|
9
|
+
|
10
|
+
import { ClientService } from './pglite';
|
11
|
+
import { InstallPluginParams } from './type';
|
12
|
+
|
13
|
+
// Mocking modules and functions
|
14
|
+
|
15
|
+
const userId = 'message-db';
|
16
|
+
const pluginService = new ClientService(userId);
|
17
|
+
|
18
|
+
// Mock data
|
19
|
+
beforeEach(async () => {
|
20
|
+
await initializeDB();
|
21
|
+
|
22
|
+
// 在每个测试用例之前,重置表数据
|
23
|
+
await clientDB.transaction(async (trx) => {
|
24
|
+
await trx.delete(users);
|
25
|
+
await trx.insert(users).values([{ id: userId }, { id: '456' }]);
|
26
|
+
});
|
27
|
+
});
|
28
|
+
|
29
|
+
describe('PluginService', () => {
|
30
|
+
describe('installPlugin', () => {
|
31
|
+
it('should install a plugin', async () => {
|
32
|
+
// Arrange
|
33
|
+
const fakePlugin = {
|
34
|
+
identifier: 'test-plugin-d',
|
35
|
+
manifest: { name: 'TestPlugin', version: '1.0.0' } as unknown as LobeChatPluginManifest,
|
36
|
+
type: 'plugin',
|
37
|
+
} as InstallPluginParams;
|
38
|
+
|
39
|
+
// Act
|
40
|
+
await pluginService.installPlugin(fakePlugin);
|
41
|
+
|
42
|
+
// Assert
|
43
|
+
const result = await clientDB.query.installedPlugins.findFirst({
|
44
|
+
where: eq(installedPlugins.identifier, fakePlugin.identifier),
|
45
|
+
});
|
46
|
+
expect(result).toMatchObject(fakePlugin);
|
47
|
+
});
|
48
|
+
});
|
49
|
+
|
50
|
+
describe('getInstalledPlugins', () => {
|
51
|
+
it('should return a list of installed plugins', async () => {
|
52
|
+
// Arrange
|
53
|
+
const fakePlugins = [{ identifier: 'test-plugin', type: 'plugin' }] as LobeTool[];
|
54
|
+
await clientDB
|
55
|
+
.insert(installedPlugins)
|
56
|
+
.values([{ identifier: 'test-plugin', type: 'plugin', userId }]);
|
57
|
+
// Act
|
58
|
+
const data = await pluginService.getInstalledPlugins();
|
59
|
+
|
60
|
+
// Assert
|
61
|
+
expect(data).toMatchObject(fakePlugins);
|
62
|
+
});
|
63
|
+
});
|
64
|
+
|
65
|
+
describe('uninstallPlugin', () => {
|
66
|
+
it('should uninstall a plugin', async () => {
|
67
|
+
// Arrange
|
68
|
+
const identifier = 'test-plugin';
|
69
|
+
await clientDB.insert(installedPlugins).values([{ identifier, type: 'plugin', userId }]);
|
70
|
+
|
71
|
+
// Act
|
72
|
+
await pluginService.uninstallPlugin(identifier);
|
73
|
+
|
74
|
+
// Assert
|
75
|
+
const result = await clientDB.query.installedPlugins.findFirst({
|
76
|
+
where: eq(installedPlugins.identifier, identifier),
|
77
|
+
});
|
78
|
+
expect(result).toBe(undefined);
|
79
|
+
});
|
80
|
+
});
|
81
|
+
|
82
|
+
describe('createCustomPlugin', () => {
|
83
|
+
it('should create a custom plugin', async () => {
|
84
|
+
// Arrange
|
85
|
+
const customPlugin = {
|
86
|
+
identifier: 'custom-plugin-x',
|
87
|
+
manifest: {},
|
88
|
+
type: 'customPlugin',
|
89
|
+
} as LobeToolCustomPlugin;
|
90
|
+
|
91
|
+
// Act
|
92
|
+
await pluginService.createCustomPlugin(customPlugin);
|
93
|
+
|
94
|
+
// Assert
|
95
|
+
const result = await clientDB.query.installedPlugins.findFirst({
|
96
|
+
where: eq(installedPlugins.identifier, customPlugin.identifier),
|
97
|
+
});
|
98
|
+
expect(result).toMatchObject(customPlugin);
|
99
|
+
});
|
100
|
+
});
|
101
|
+
|
102
|
+
describe('updatePlugin', () => {
|
103
|
+
it('should update a plugin', async () => {
|
104
|
+
// Arrange
|
105
|
+
const identifier = 'plugin-id';
|
106
|
+
const value = { customParams: { ab: '1' } } as unknown as LobeToolCustomPlugin;
|
107
|
+
await clientDB.insert(installedPlugins).values([{ identifier, type: 'plugin', userId }]);
|
108
|
+
|
109
|
+
// Act
|
110
|
+
await pluginService.updatePlugin(identifier, value);
|
111
|
+
|
112
|
+
// Assert
|
113
|
+
const result = await clientDB.query.installedPlugins.findFirst({
|
114
|
+
where: eq(installedPlugins.identifier, identifier),
|
115
|
+
});
|
116
|
+
expect(result).toMatchObject(value);
|
117
|
+
});
|
118
|
+
});
|
119
|
+
|
120
|
+
describe('updatePluginManifest', () => {
|
121
|
+
it('should update a plugin manifest', async () => {
|
122
|
+
// Arrange
|
123
|
+
const identifier = 'plugin-id';
|
124
|
+
const manifest = { name: 'NewPluginManifest' } as unknown as LobeChatPluginManifest;
|
125
|
+
await clientDB.insert(installedPlugins).values([{ identifier, type: 'plugin', userId }]);
|
126
|
+
|
127
|
+
// Act
|
128
|
+
await pluginService.updatePluginManifest(identifier, manifest);
|
129
|
+
|
130
|
+
// Assert
|
131
|
+
const result = await clientDB.query.installedPlugins.findFirst({
|
132
|
+
where: eq(installedPlugins.identifier, identifier),
|
133
|
+
});
|
134
|
+
expect(result).toMatchObject({ manifest });
|
135
|
+
});
|
136
|
+
});
|
137
|
+
|
138
|
+
describe('removeAllPlugins', () => {
|
139
|
+
it('should remove all plugins', async () => {
|
140
|
+
// Arrange
|
141
|
+
await clientDB.insert(installedPlugins).values([
|
142
|
+
{ identifier: '123', type: 'plugin', userId },
|
143
|
+
{ identifier: '234', type: 'plugin', userId },
|
144
|
+
]);
|
145
|
+
|
146
|
+
// Act
|
147
|
+
await pluginService.removeAllPlugins();
|
148
|
+
|
149
|
+
// Assert
|
150
|
+
const result = await clientDB.query.installedPlugins.findMany({
|
151
|
+
where: eq(installedPlugins.userId, userId),
|
152
|
+
});
|
153
|
+
expect(result.length).toEqual(0);
|
154
|
+
});
|
155
|
+
});
|
156
|
+
|
157
|
+
describe('updatePluginSettings', () => {
|
158
|
+
it('should update plugin settings', async () => {
|
159
|
+
// Arrange
|
160
|
+
const id = 'plugin-id';
|
161
|
+
const settings = { color: 'blue' };
|
162
|
+
await clientDB.insert(installedPlugins).values([{ identifier: id, type: 'plugin', userId }]);
|
163
|
+
|
164
|
+
// Act
|
165
|
+
await pluginService.updatePluginSettings(id, settings);
|
166
|
+
|
167
|
+
// Assert
|
168
|
+
const result = await clientDB.query.installedPlugins.findFirst({
|
169
|
+
where: eq(installedPlugins.identifier, id),
|
170
|
+
});
|
171
|
+
|
172
|
+
expect(result).toMatchObject({ settings });
|
173
|
+
});
|
174
|
+
});
|
175
|
+
});
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
|
2
|
+
|
3
|
+
import { clientDB } from '@/database/client/db';
|
4
|
+
import { PluginModel } from '@/database/server/models/plugin';
|
5
|
+
import { BaseClientService } from '@/services/baseClientService';
|
6
|
+
import { LobeTool } from '@/types/tool';
|
7
|
+
import { LobeToolCustomPlugin } from '@/types/tool/plugin';
|
8
|
+
|
9
|
+
import { IPluginService, InstallPluginParams } from './type';
|
10
|
+
|
11
|
+
export class ClientService extends BaseClientService implements IPluginService {
|
12
|
+
private get pluginModel(): PluginModel {
|
13
|
+
return new PluginModel(clientDB as any, this.userId);
|
14
|
+
}
|
15
|
+
|
16
|
+
installPlugin = async (plugin: InstallPluginParams) => {
|
17
|
+
await this.pluginModel.create(plugin);
|
18
|
+
return;
|
19
|
+
};
|
20
|
+
|
21
|
+
getInstalledPlugins = () => {
|
22
|
+
return this.pluginModel.query() as Promise<LobeTool[]>;
|
23
|
+
};
|
24
|
+
|
25
|
+
async uninstallPlugin(identifier: string) {
|
26
|
+
await this.pluginModel.delete(identifier);
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
|
30
|
+
async createCustomPlugin(customPlugin: LobeToolCustomPlugin) {
|
31
|
+
await this.pluginModel.create({ ...customPlugin, type: 'customPlugin' });
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
|
35
|
+
async updatePlugin(id: string, value: LobeToolCustomPlugin) {
|
36
|
+
await this.pluginModel.update(id, value);
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
async updatePluginManifest(id: string, manifest: LobeChatPluginManifest) {
|
40
|
+
await this.pluginModel.update(id, { manifest });
|
41
|
+
}
|
42
|
+
|
43
|
+
async removeAllPlugins() {
|
44
|
+
await this.pluginModel.deleteAll();
|
45
|
+
}
|
46
|
+
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
48
|
+
async updatePluginSettings(id: string, settings: any, _?: AbortSignal) {
|
49
|
+
await this.pluginModel.update(id, { settings });
|
50
|
+
}
|
51
|
+
}
|
@@ -5,7 +5,7 @@ import { SessionGroupModel } from '@/database/_deprecated/models/sessionGroup';
|
|
5
5
|
import { LobeAgentConfig } from '@/types/agent';
|
6
6
|
import { LobeAgentSession, LobeSessionType, SessionGroups } from '@/types/session';
|
7
7
|
|
8
|
-
import { ClientService } from './
|
8
|
+
import { ClientService } from './_deprecated';
|
9
9
|
|
10
10
|
const sessionService = new ClientService();
|
11
11
|
|
@@ -166,7 +166,7 @@ export class ClientService implements ISessionService {
|
|
166
166
|
}
|
167
167
|
|
168
168
|
async updateSessionGroup(id: string, data: Partial<SessionGroupItem>) {
|
169
|
-
return SessionGroupModel.update(id, data);
|
169
|
+
return SessionGroupModel.update(id, data as any);
|
170
170
|
}
|
171
171
|
|
172
172
|
async updateSessionGroupOrder(sortMap: { id: string; sort: number }[]) {
|
@@ -1,5 +1,9 @@
|
|
1
|
-
import { ClientService } from './
|
1
|
+
import { ClientService as DeprecatedService } from './_deprecated';
|
2
|
+
import { ClientService } from './pglite';
|
2
3
|
import { ServerService } from './server';
|
3
4
|
|
5
|
+
const clientService =
|
6
|
+
process.env.NEXT_PUBLIC_CLIENT_DB === 'pglite' ? new ClientService() : new DeprecatedService();
|
7
|
+
|
4
8
|
export const sessionService =
|
5
|
-
process.env.NEXT_PUBLIC_SERVICE_MODE === 'server' ? new ServerService() :
|
9
|
+
process.env.NEXT_PUBLIC_SERVICE_MODE === 'server' ? new ServerService() : clientService;
|