@lobehub/chat 0.147.16 → 0.147.17
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 +25 -0
- package/contributing/Basic/Feature-Development.md +7 -7
- package/contributing/Basic/Feature-Development.zh-CN.md +7 -7
- package/next.config.mjs +61 -13
- package/package.json +2 -1
- package/sentry.client.config.ts +30 -0
- package/sentry.edge.config.ts +17 -0
- package/sentry.server.config.ts +19 -0
- package/src/app/home/Redirect.tsx +2 -2
- package/src/database/client/models/__tests__/session.test.ts +1 -3
- package/src/database/client/models/session.ts +4 -4
- package/src/services/config.ts +4 -4
- package/src/services/file/client.test.ts +2 -2
- package/src/services/file/client.ts +35 -33
- package/src/services/file/index.ts +8 -2
- package/src/services/file/type.ts +11 -0
- package/src/services/message/client.test.ts +6 -32
- package/src/services/message/client.ts +24 -37
- package/src/services/message/index.test.ts +48 -0
- package/src/services/message/index.ts +22 -2
- package/src/services/message/type.ts +33 -0
- package/src/services/plugin/client.test.ts +2 -2
- package/src/services/plugin/client.ts +1 -1
- package/src/services/plugin/index.ts +9 -3
- package/src/services/session/client.test.ts +37 -44
- package/src/services/session/client.ts +30 -22
- package/src/services/session/index.ts +9 -2
- package/src/services/session/type.ts +44 -0
- package/src/services/topic/client.test.ts +18 -22
- package/src/services/topic/client.ts +31 -23
- package/src/services/topic/index.ts +10 -2
- package/src/services/topic/type.ts +32 -0
- package/src/services/user/client.ts +1 -1
- package/src/services/user/index.ts +10 -2
- package/src/store/chat/slices/message/action.test.ts +12 -12
- package/src/store/chat/slices/message/action.ts +4 -4
- package/src/store/chat/slices/plugin/action.test.ts +5 -6
- package/src/store/chat/slices/plugin/action.ts +1 -1
- package/src/store/chat/slices/topic/action.test.ts +11 -6
- package/src/store/chat/slices/topic/action.ts +7 -5
- package/src/store/session/slices/agent/action.test.ts +175 -0
- package/src/store/session/slices/agent/action.ts +1 -1
- package/src/store/session/slices/session/action.test.ts +14 -15
- package/src/store/session/slices/session/action.ts +4 -4
- package/src/store/session/slices/sessionGroup/action.test.ts +6 -4
- package/src/store/session/slices/sessionGroup/action.ts +3 -3
|
@@ -2,42 +2,29 @@ import { MessageModel } from '@/database/client/models/message';
|
|
|
2
2
|
import { DB_Message } from '@/database/client/schemas/message';
|
|
3
3
|
import { ChatMessage, ChatMessageError, ChatPluginPayload } from '@/types/message';
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
}
|
|
5
|
+
import { CreateMessageParams, IMessageService } from './type';
|
|
13
6
|
|
|
14
|
-
export class
|
|
15
|
-
async
|
|
7
|
+
export class ClientService implements IMessageService {
|
|
8
|
+
async createMessage(data: CreateMessageParams) {
|
|
16
9
|
const { id } = await MessageModel.create(data);
|
|
17
10
|
|
|
18
11
|
return id;
|
|
19
12
|
}
|
|
20
13
|
|
|
21
|
-
async
|
|
14
|
+
async batchCreateMessages(messages: ChatMessage[]) {
|
|
22
15
|
return MessageModel.batchCreate(messages);
|
|
23
16
|
}
|
|
24
17
|
|
|
25
|
-
async hasMessages() {
|
|
26
|
-
const number = await MessageModel.count();
|
|
27
|
-
return number > 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async messageCountToCheckTrace() {
|
|
31
|
-
const number = await MessageModel.count();
|
|
32
|
-
return number >= 4;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
18
|
async getMessages(sessionId: string, topicId?: string): Promise<ChatMessage[]> {
|
|
36
19
|
return MessageModel.query({ sessionId, topicId });
|
|
37
20
|
}
|
|
38
21
|
|
|
39
|
-
async
|
|
40
|
-
return MessageModel.
|
|
22
|
+
async getAllMessages() {
|
|
23
|
+
return MessageModel.queryAll();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async countMessages() {
|
|
27
|
+
return MessageModel.count();
|
|
41
28
|
}
|
|
42
29
|
|
|
43
30
|
async getAllMessagesInSession(sessionId: string) {
|
|
@@ -48,18 +35,6 @@ export class MessageService {
|
|
|
48
35
|
return MessageModel.update(id, { error });
|
|
49
36
|
}
|
|
50
37
|
|
|
51
|
-
async removeMessages(assistantId: string, topicId?: string) {
|
|
52
|
-
return MessageModel.batchDelete(assistantId, topicId);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async clearAllMessage() {
|
|
56
|
-
return MessageModel.clearTable();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async bindMessagesToTopic(topicId: string, messageIds: string[]) {
|
|
60
|
-
return MessageModel.batchUpdate(messageIds, { topicId });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
38
|
async updateMessage(id: string, message: Partial<DB_Message>) {
|
|
64
39
|
return MessageModel.update(id, message);
|
|
65
40
|
}
|
|
@@ -72,7 +47,19 @@ export class MessageService {
|
|
|
72
47
|
return MessageModel.updatePluginState(id, key, value);
|
|
73
48
|
}
|
|
74
49
|
|
|
75
|
-
async
|
|
76
|
-
return MessageModel.
|
|
50
|
+
async bindMessagesToTopic(topicId: string, messageIds: string[]) {
|
|
51
|
+
return MessageModel.batchUpdate(messageIds, { topicId });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async removeMessage(id: string) {
|
|
55
|
+
return MessageModel.delete(id);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async removeMessages(assistantId: string, topicId?: string) {
|
|
59
|
+
return MessageModel.batchDelete(assistantId, topicId);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async removeAllMessages() {
|
|
63
|
+
return MessageModel.clearTable();
|
|
77
64
|
}
|
|
78
65
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Mock, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { CreateMessageParams, MessageModel } from '@/database/client/models/message';
|
|
4
|
+
import { ChatMessage, ChatMessageError, ChatPluginPayload } from '@/types/message';
|
|
5
|
+
|
|
6
|
+
import { messageService } from './index';
|
|
7
|
+
|
|
8
|
+
// Mock the MessageModel
|
|
9
|
+
vi.mock('@/database/client/models/message', () => {
|
|
10
|
+
return {
|
|
11
|
+
MessageModel: {
|
|
12
|
+
count: vi.fn(),
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('MessageService', () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
// Reset all mocks before running each test case
|
|
20
|
+
vi.resetAllMocks();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('hasMessages', () => {
|
|
24
|
+
it('should return true if there are messages', async () => {
|
|
25
|
+
// Setup
|
|
26
|
+
(MessageModel.count as Mock).mockResolvedValue(1);
|
|
27
|
+
|
|
28
|
+
// Execute
|
|
29
|
+
const hasMessages = await messageService.hasMessages();
|
|
30
|
+
|
|
31
|
+
// Assert
|
|
32
|
+
expect(MessageModel.count).toHaveBeenCalled();
|
|
33
|
+
expect(hasMessages).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should return false if there are no messages', async () => {
|
|
37
|
+
// Setup
|
|
38
|
+
(MessageModel.count as Mock).mockResolvedValue(0);
|
|
39
|
+
|
|
40
|
+
// Execute
|
|
41
|
+
const hasMessages = await messageService.hasMessages();
|
|
42
|
+
|
|
43
|
+
// Assert
|
|
44
|
+
expect(MessageModel.count).toHaveBeenCalled();
|
|
45
|
+
expect(hasMessages).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
// import { getClientConfig } from '@/config/client';
|
|
2
|
+
// import { ServerService } from './server';
|
|
3
|
+
// import { ClientService } from './client';
|
|
4
|
+
//
|
|
5
|
+
// const { ENABLED_SERVER_SERVICE } = getClientConfig();
|
|
6
|
+
//
|
|
7
|
+
// export const messageService = ENABLED_SERVER_SERVICE ? new ServerService() : new ClientService();
|
|
8
|
+
import { ClientService } from './client';
|
|
9
|
+
|
|
10
|
+
export type { CreateMessageParams } from './type';
|
|
11
|
+
|
|
12
|
+
class MessageService extends ClientService {
|
|
13
|
+
async hasMessages() {
|
|
14
|
+
const number = await this.countMessages();
|
|
15
|
+
return number > 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async messageCountToCheckTrace() {
|
|
19
|
+
const number = await this.countMessages();
|
|
20
|
+
return number >= 4;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
2
23
|
|
|
3
24
|
export const messageService = new MessageService();
|
|
4
|
-
export type { CreateMessageParams } from './client';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DB_Message } from '@/database/client/schemas/message';
|
|
2
|
+
import { ChatMessage, ChatMessageError, ChatPluginPayload } from '@/types/message';
|
|
3
|
+
|
|
4
|
+
/* eslint-disable typescript-sort-keys/interface */
|
|
5
|
+
|
|
6
|
+
export interface CreateMessageParams
|
|
7
|
+
extends Partial<Omit<ChatMessage, 'content' | 'role'>>,
|
|
8
|
+
Pick<ChatMessage, 'content' | 'role'> {
|
|
9
|
+
fromModel?: string;
|
|
10
|
+
fromProvider?: string;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
traceId?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface IMessageService {
|
|
16
|
+
createMessage(data: CreateMessageParams): Promise<string>;
|
|
17
|
+
batchCreateMessages(messages: ChatMessage[]): Promise<any>;
|
|
18
|
+
|
|
19
|
+
getMessages(sessionId: string, topicId?: string): Promise<ChatMessage[]>;
|
|
20
|
+
getAllMessages(): Promise<ChatMessage[]>;
|
|
21
|
+
getAllMessagesInSession(sessionId: string): Promise<ChatMessage[]>;
|
|
22
|
+
countMessages(): Promise<number>;
|
|
23
|
+
|
|
24
|
+
updateMessageError(id: string, error: ChatMessageError): Promise<any>;
|
|
25
|
+
updateMessage(id: string, message: Partial<DB_Message>): Promise<any>;
|
|
26
|
+
updateMessagePlugin(id: string, plugin: ChatPluginPayload): Promise<any>;
|
|
27
|
+
updateMessagePluginState(id: string, key: string, value: any): Promise<any>;
|
|
28
|
+
bindMessagesToTopic(topicId: string, messageIds: string[]): Promise<any>;
|
|
29
|
+
|
|
30
|
+
removeMessage(id: string): Promise<any>;
|
|
31
|
+
removeMessages(assistantId: string, topicId?: string): Promise<any>;
|
|
32
|
+
removeAllMessages(): Promise<any>;
|
|
33
|
+
}
|
|
@@ -6,9 +6,9 @@ import { DB_Plugin } from '@/database/client/schemas/plugin';
|
|
|
6
6
|
import { LobeTool } from '@/types/tool';
|
|
7
7
|
import { LobeToolCustomPlugin } from '@/types/tool/plugin';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { ClientService, InstallPluginParams } from './client';
|
|
10
10
|
|
|
11
|
-
const pluginService = new
|
|
11
|
+
const pluginService = new ClientService();
|
|
12
12
|
|
|
13
13
|
// Mocking modules and functions
|
|
14
14
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
// import { getClientConfig } from '@/config/client';
|
|
2
|
+
import { ClientService } from './client';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
// import { ServerService } from './server';
|
|
5
|
+
//
|
|
6
|
+
// export type { InstallPluginParams } from './client';
|
|
7
|
+
//
|
|
8
|
+
// const { ENABLED_SERVER_SERVICE } = getClientConfig();
|
|
4
9
|
|
|
5
|
-
export const pluginService = new
|
|
10
|
+
// export const pluginService = ENABLED_SERVER_SERVICE ? new ServerService() : new ClientService();
|
|
11
|
+
export const pluginService = new ClientService();
|
|
@@ -5,9 +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 { ClientService } from './client';
|
|
9
9
|
|
|
10
|
-
const sessionService = new
|
|
10
|
+
const sessionService = new ClientService();
|
|
11
11
|
|
|
12
12
|
// Mock the SessionModel
|
|
13
13
|
vi.mock('@/database/client/models/session', () => {
|
|
@@ -18,6 +18,7 @@ vi.mock('@/database/client/models/session', () => {
|
|
|
18
18
|
delete: vi.fn(),
|
|
19
19
|
clearTable: vi.fn(),
|
|
20
20
|
update: vi.fn(),
|
|
21
|
+
count: vi.fn(),
|
|
21
22
|
batchCreate: vi.fn(),
|
|
22
23
|
isEmpty: vi.fn(),
|
|
23
24
|
queryByKeyword: vi.fn(),
|
|
@@ -63,7 +64,7 @@ describe('SessionService', () => {
|
|
|
63
64
|
vi.resetAllMocks();
|
|
64
65
|
});
|
|
65
66
|
|
|
66
|
-
describe('
|
|
67
|
+
describe('createSession', () => {
|
|
67
68
|
it('should create a new session and return its id', async () => {
|
|
68
69
|
// Setup
|
|
69
70
|
const sessionType = LobeSessionType.Agent;
|
|
@@ -71,7 +72,7 @@ describe('SessionService', () => {
|
|
|
71
72
|
(SessionModel.create as Mock).mockResolvedValue(mockSession);
|
|
72
73
|
|
|
73
74
|
// Execute
|
|
74
|
-
const sessionId = await sessionService.
|
|
75
|
+
const sessionId = await sessionService.createSession(sessionType, defaultValue);
|
|
75
76
|
|
|
76
77
|
// Assert
|
|
77
78
|
expect(SessionModel.create).toHaveBeenCalledWith(sessionType, defaultValue);
|
|
@@ -85,7 +86,7 @@ describe('SessionService', () => {
|
|
|
85
86
|
(SessionModel.create as Mock).mockResolvedValue(null);
|
|
86
87
|
|
|
87
88
|
// Execute & Assert
|
|
88
|
-
await expect(sessionService.
|
|
89
|
+
await expect(sessionService.createSession(sessionType, defaultValue)).rejects.toThrow(
|
|
89
90
|
'session create Error',
|
|
90
91
|
);
|
|
91
92
|
});
|
|
@@ -105,21 +106,19 @@ describe('SessionService', () => {
|
|
|
105
106
|
});
|
|
106
107
|
});
|
|
107
108
|
|
|
108
|
-
describe('
|
|
109
|
+
describe('getSessionsByType', () => {
|
|
109
110
|
it('should retrieve sessions with their group ids', async () => {
|
|
110
111
|
// Setup
|
|
111
112
|
(SessionModel.query as Mock).mockResolvedValue(mockSessions);
|
|
112
113
|
|
|
113
114
|
// Execute
|
|
114
|
-
const sessions = await sessionService.
|
|
115
|
+
const sessions = await sessionService.getSessionsByType();
|
|
115
116
|
|
|
116
117
|
// Assert
|
|
117
118
|
expect(SessionModel.query).toHaveBeenCalled();
|
|
118
119
|
expect(sessions).toBe(mockSessions);
|
|
119
120
|
});
|
|
120
|
-
});
|
|
121
121
|
|
|
122
|
-
describe('getAllAgents', () => {
|
|
123
122
|
it('should retrieve all agent sessions', async () => {
|
|
124
123
|
// Setup
|
|
125
124
|
// Assuming that SessionModel.query has been modified to accept filters
|
|
@@ -127,7 +126,7 @@ describe('SessionService', () => {
|
|
|
127
126
|
(SessionModel.query as Mock).mockResolvedValue(agentSessions);
|
|
128
127
|
|
|
129
128
|
// Execute
|
|
130
|
-
const result = await sessionService.
|
|
129
|
+
const result = await sessionService.getSessionsByType('agent');
|
|
131
130
|
|
|
132
131
|
// Assert
|
|
133
132
|
// Assuming that SessionModel.query would be called with a filter for agents
|
|
@@ -164,34 +163,43 @@ describe('SessionService', () => {
|
|
|
164
163
|
});
|
|
165
164
|
});
|
|
166
165
|
|
|
167
|
-
describe('
|
|
166
|
+
describe('updateSession', () => {
|
|
168
167
|
it('should update the group of a session', async () => {
|
|
169
168
|
// Setup
|
|
170
169
|
const groupId = 'new-group';
|
|
171
170
|
(SessionModel.update as Mock).mockResolvedValue({ ...mockSession, group: groupId });
|
|
172
171
|
|
|
173
172
|
// Execute
|
|
174
|
-
const result = await sessionService.
|
|
173
|
+
const result = await sessionService.updateSession(mockSessionId, { group: groupId });
|
|
175
174
|
|
|
176
175
|
// Assert
|
|
177
176
|
expect(SessionModel.update).toHaveBeenCalledWith(mockSessionId, { group: groupId });
|
|
178
177
|
expect(result).toEqual({ ...mockSession, group: groupId });
|
|
179
178
|
});
|
|
180
|
-
});
|
|
181
179
|
|
|
182
|
-
describe('updateSessionMeta', () => {
|
|
183
180
|
it('should update the meta of a session', async () => {
|
|
184
181
|
// Setup
|
|
185
182
|
const newMeta = { description: 'Updated description' };
|
|
186
183
|
(SessionModel.update as Mock).mockResolvedValue({ ...mockSession, meta: newMeta });
|
|
187
184
|
|
|
188
185
|
// Execute
|
|
189
|
-
const result = await sessionService.
|
|
186
|
+
const result = await sessionService.updateSession(mockSessionId, { meta: newMeta });
|
|
190
187
|
|
|
191
188
|
// Assert
|
|
192
189
|
expect(SessionModel.update).toHaveBeenCalledWith(mockSessionId, { meta: newMeta });
|
|
193
190
|
expect(result).toEqual({ ...mockSession, meta: newMeta });
|
|
194
191
|
});
|
|
192
|
+
|
|
193
|
+
it('should update the pinned status of a session', async () => {
|
|
194
|
+
// Setup
|
|
195
|
+
const pinned = true;
|
|
196
|
+
|
|
197
|
+
// Execute
|
|
198
|
+
await sessionService.updateSession(mockSessionId, { pinned });
|
|
199
|
+
|
|
200
|
+
// Assert
|
|
201
|
+
expect(SessionModel.update).toHaveBeenCalledWith(mockSessionId, { pinned: 1 });
|
|
202
|
+
});
|
|
195
203
|
});
|
|
196
204
|
|
|
197
205
|
describe('updateSessionConfig', () => {
|
|
@@ -209,29 +217,29 @@ describe('SessionService', () => {
|
|
|
209
217
|
});
|
|
210
218
|
});
|
|
211
219
|
|
|
212
|
-
describe('
|
|
220
|
+
describe('countSessions', () => {
|
|
213
221
|
it('should return false if no sessions exist', async () => {
|
|
214
222
|
// Setup
|
|
215
|
-
(SessionModel.
|
|
223
|
+
(SessionModel.count as Mock).mockResolvedValue(0);
|
|
216
224
|
|
|
217
225
|
// Execute
|
|
218
|
-
const result = await sessionService.
|
|
226
|
+
const result = await sessionService.countSessions();
|
|
219
227
|
|
|
220
228
|
// Assert
|
|
221
|
-
expect(SessionModel.
|
|
222
|
-
expect(result).toBe(
|
|
229
|
+
expect(SessionModel.count).toHaveBeenCalled();
|
|
230
|
+
expect(result).toBe(0);
|
|
223
231
|
});
|
|
224
232
|
|
|
225
233
|
it('should return true if sessions exist', async () => {
|
|
226
234
|
// Setup
|
|
227
|
-
(SessionModel.
|
|
235
|
+
(SessionModel.count as Mock).mockResolvedValue(1);
|
|
228
236
|
|
|
229
237
|
// Execute
|
|
230
|
-
const result = await sessionService.
|
|
238
|
+
const result = await sessionService.countSessions();
|
|
231
239
|
|
|
232
240
|
// Assert
|
|
233
|
-
expect(SessionModel.
|
|
234
|
-
expect(result).toBe(
|
|
241
|
+
expect(SessionModel.count).toHaveBeenCalled();
|
|
242
|
+
expect(result).toBe(1);
|
|
235
243
|
});
|
|
236
244
|
});
|
|
237
245
|
|
|
@@ -250,7 +258,7 @@ describe('SessionService', () => {
|
|
|
250
258
|
});
|
|
251
259
|
});
|
|
252
260
|
|
|
253
|
-
describe('
|
|
261
|
+
describe('cloneSession', () => {
|
|
254
262
|
it('should duplicate a session and return its id', async () => {
|
|
255
263
|
// Setup
|
|
256
264
|
const newTitle = 'Duplicated Session';
|
|
@@ -260,7 +268,7 @@ describe('SessionService', () => {
|
|
|
260
268
|
});
|
|
261
269
|
|
|
262
270
|
// Execute
|
|
263
|
-
const duplicatedSessionId = await sessionService.
|
|
271
|
+
const duplicatedSessionId = await sessionService.cloneSession(mockSessionId, newTitle);
|
|
264
272
|
|
|
265
273
|
// Assert
|
|
266
274
|
expect(SessionModel.duplicate).toHaveBeenCalledWith(mockSessionId, newTitle);
|
|
@@ -268,13 +276,13 @@ describe('SessionService', () => {
|
|
|
268
276
|
});
|
|
269
277
|
});
|
|
270
278
|
|
|
271
|
-
describe('
|
|
279
|
+
describe('getGroupedSessions', () => {
|
|
272
280
|
it('should retrieve sessions with their group', async () => {
|
|
273
281
|
// Setup
|
|
274
282
|
(SessionModel.queryWithGroups as Mock).mockResolvedValue(mockSessions);
|
|
275
283
|
|
|
276
284
|
// Execute
|
|
277
|
-
const sessionsWithGroup = await sessionService.
|
|
285
|
+
const sessionsWithGroup = await sessionService.getGroupedSessions();
|
|
278
286
|
|
|
279
287
|
// Assert
|
|
280
288
|
expect(SessionModel.queryWithGroups).toHaveBeenCalled();
|
|
@@ -282,21 +290,6 @@ describe('SessionService', () => {
|
|
|
282
290
|
});
|
|
283
291
|
});
|
|
284
292
|
|
|
285
|
-
describe('updateSessionPinned', () => {
|
|
286
|
-
it('should update the pinned status of a session', async () => {
|
|
287
|
-
// Setup
|
|
288
|
-
const pinned = true;
|
|
289
|
-
(SessionModel.updatePinned as Mock).mockResolvedValue({ ...mockSession, pinned });
|
|
290
|
-
|
|
291
|
-
// Execute
|
|
292
|
-
const result = await sessionService.updateSessionPinned(mockSessionId, pinned);
|
|
293
|
-
|
|
294
|
-
// Assert
|
|
295
|
-
expect(SessionModel.updatePinned).toHaveBeenCalledWith(mockSessionId, pinned);
|
|
296
|
-
expect(result).toEqual({ ...mockSession, pinned });
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
293
|
// SessionGroup related tests
|
|
301
294
|
describe('createSessionGroup', () => {
|
|
302
295
|
it('should create a new session group and return its id', async () => {
|
|
@@ -358,7 +351,7 @@ describe('SessionService', () => {
|
|
|
358
351
|
(SessionGroupModel.clear as Mock).mockResolvedValue(true);
|
|
359
352
|
|
|
360
353
|
// Execute
|
|
361
|
-
const result = await sessionService.
|
|
354
|
+
const result = await sessionService.removeSessionGroups();
|
|
362
355
|
|
|
363
356
|
// Assert
|
|
364
357
|
expect(SessionGroupModel.clear).toHaveBeenCalled();
|
|
@@ -3,19 +3,19 @@ import { DeepPartial } from 'utility-types';
|
|
|
3
3
|
import { SessionModel } from '@/database/client/models/session';
|
|
4
4
|
import { SessionGroupModel } from '@/database/client/models/sessionGroup';
|
|
5
5
|
import { LobeAgentConfig } from '@/types/agent';
|
|
6
|
-
import { MetaData } from '@/types/meta';
|
|
7
6
|
import {
|
|
8
7
|
ChatSessionList,
|
|
9
8
|
LobeAgentSession,
|
|
10
9
|
LobeSessionType,
|
|
11
10
|
LobeSessions,
|
|
12
|
-
SessionGroupId,
|
|
13
11
|
SessionGroupItem,
|
|
14
12
|
SessionGroups,
|
|
15
13
|
} from '@/types/session';
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
import { ISessionService } from './type';
|
|
16
|
+
|
|
17
|
+
export class ClientService implements ISessionService {
|
|
18
|
+
async createSession(
|
|
19
19
|
type: LobeSessionType,
|
|
20
20
|
defaultValue: Partial<LobeAgentSession>,
|
|
21
21
|
): Promise<string> {
|
|
@@ -30,18 +30,30 @@ export class SessionService {
|
|
|
30
30
|
return SessionModel.batchCreate(importSessions);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
async
|
|
33
|
+
async cloneSession(id: string, newTitle: string): Promise<string | undefined> {
|
|
34
34
|
const res = await SessionModel.duplicate(id, newTitle);
|
|
35
35
|
|
|
36
36
|
if (res) return res?.id;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
async
|
|
40
|
-
return SessionModel.
|
|
39
|
+
async getGroupedSessions(): Promise<ChatSessionList> {
|
|
40
|
+
return SessionModel.queryWithGroups();
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
async
|
|
44
|
-
|
|
43
|
+
async getSessionsByType(type: 'agent' | 'group' | 'all' = 'all'): Promise<LobeSessions> {
|
|
44
|
+
switch (type) {
|
|
45
|
+
// TODO: add a filter to get only agents or agents
|
|
46
|
+
case 'group': {
|
|
47
|
+
return SessionModel.query();
|
|
48
|
+
}
|
|
49
|
+
case 'agent': {
|
|
50
|
+
return SessionModel.query();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
case 'all': {
|
|
54
|
+
return SessionModel.query();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
45
57
|
}
|
|
46
58
|
|
|
47
59
|
async getAllAgents(): Promise<LobeSessions> {
|
|
@@ -49,24 +61,20 @@ export class SessionService {
|
|
|
49
61
|
return await SessionModel.query();
|
|
50
62
|
}
|
|
51
63
|
|
|
52
|
-
async
|
|
53
|
-
|
|
54
|
-
return !isEmpty;
|
|
64
|
+
async countSessions() {
|
|
65
|
+
return SessionModel.count();
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
async searchSessions(keyword: string) {
|
|
58
69
|
return SessionModel.queryByKeyword(keyword);
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
async
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
async updateSessionMeta(activeId: string, meta: Partial<MetaData>) {
|
|
69
|
-
return SessionModel.update(activeId, { meta });
|
|
72
|
+
async updateSession(
|
|
73
|
+
id: string,
|
|
74
|
+
data: Partial<Pick<LobeAgentSession, 'group' | 'meta' | 'pinned'>>,
|
|
75
|
+
) {
|
|
76
|
+
const pinned = typeof data.pinned === 'boolean' ? (data.pinned ? 1 : 0) : undefined;
|
|
77
|
+
return SessionModel.update(id, { ...data, pinned });
|
|
70
78
|
}
|
|
71
79
|
|
|
72
80
|
async updateSessionConfig(activeId: string, config: DeepPartial<LobeAgentConfig>) {
|
|
@@ -114,7 +122,7 @@ export class SessionService {
|
|
|
114
122
|
return SessionGroupModel.query();
|
|
115
123
|
}
|
|
116
124
|
|
|
117
|
-
async
|
|
125
|
+
async removeSessionGroups() {
|
|
118
126
|
return SessionGroupModel.clear();
|
|
119
127
|
}
|
|
120
128
|
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
// import { getClientConfig } from '@/config/client';
|
|
2
|
+
//
|
|
3
|
+
import { ClientService } from './client';
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
// import { ServerService } from './server';
|
|
6
|
+
|
|
7
|
+
// const { ENABLED_SERVER_SERVICE } = getClientConfig();
|
|
8
|
+
|
|
9
|
+
// export const sessionService = ENABLED_SERVER_SERVICE ? new ServerService() : new ClientService();
|
|
10
|
+
export const sessionService = new ClientService();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* eslint-disable typescript-sort-keys/interface */
|
|
2
|
+
import { DeepPartial } from 'utility-types';
|
|
3
|
+
|
|
4
|
+
import { LobeAgentConfig } from '@/types/agent';
|
|
5
|
+
import {
|
|
6
|
+
ChatSessionList,
|
|
7
|
+
LobeAgentSession,
|
|
8
|
+
LobeSessionType,
|
|
9
|
+
LobeSessions,
|
|
10
|
+
SessionGroupItem,
|
|
11
|
+
SessionGroups,
|
|
12
|
+
} from '@/types/session';
|
|
13
|
+
|
|
14
|
+
export interface ISessionService {
|
|
15
|
+
createSession(type: LobeSessionType, defaultValue: Partial<LobeAgentSession>): Promise<string>;
|
|
16
|
+
batchCreateSessions(importSessions: LobeSessions): Promise<any>;
|
|
17
|
+
cloneSession(id: string, newTitle: string): Promise<string | undefined>;
|
|
18
|
+
|
|
19
|
+
getGroupedSessions(): Promise<ChatSessionList>;
|
|
20
|
+
getSessionsByType(type: 'agent' | 'group' | 'all'): Promise<LobeSessions>;
|
|
21
|
+
countSessions(): Promise<number>;
|
|
22
|
+
searchSessions(keyword: string): Promise<LobeSessions>;
|
|
23
|
+
|
|
24
|
+
updateSession(id: string, data: Partial<Pick<LobeAgentSession, 'group' | 'meta'>>): Promise<any>;
|
|
25
|
+
updateSessionConfig(id: string, config: DeepPartial<LobeAgentConfig>): Promise<any>;
|
|
26
|
+
|
|
27
|
+
removeSession(id: string): Promise<any>;
|
|
28
|
+
removeAllSessions(): Promise<any>;
|
|
29
|
+
|
|
30
|
+
// ************************************** //
|
|
31
|
+
// *********** SessionGroup *********** //
|
|
32
|
+
// ************************************** //
|
|
33
|
+
|
|
34
|
+
createSessionGroup(name: string, sort?: number): Promise<string>;
|
|
35
|
+
batchCreateSessionGroups(groups: SessionGroups): Promise<any>;
|
|
36
|
+
|
|
37
|
+
getSessionGroups(): Promise<SessionGroupItem[]>;
|
|
38
|
+
|
|
39
|
+
updateSessionGroup(id: string, data: Partial<SessionGroupItem>): Promise<any>;
|
|
40
|
+
updateSessionGroupOrder(sortMap: { id: string; sort: number }[]): Promise<any>;
|
|
41
|
+
|
|
42
|
+
removeSessionGroup(id: string, removeChildren?: boolean): Promise<any>;
|
|
43
|
+
removeSessionGroups(): Promise<any>;
|
|
44
|
+
}
|