@lobehub/lobehub 2.0.0-next.13 → 2.0.0-next.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 +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +1 -1
- package/packages/const/src/version.ts +3 -3
- package/packages/database/src/repositories/dataImporter/deprecated/__tests__/index.test.ts +2 -1
- package/packages/database/src/repositories/dataImporter/deprecated/index.ts +7 -1
- package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +9 -0
- package/src/app/[variants]/(main)/(mobile)/me/(home)/layout.tsx +0 -2
- package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/Actions.tsx +3 -28
- package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +0 -2
- package/src/app/[variants]/(main)/chat/_layout/Mobile.tsx +1 -5
- package/src/app/[variants]/(main)/chat/settings/features/HeaderContent.tsx +2 -62
- package/src/app/[variants]/(main)/image/page.tsx +0 -2
- package/src/app/[variants]/(main)/profile/_layout/Desktop/index.tsx +23 -24
- package/src/app/[variants]/(main)/profile/_layout/Mobile/index.tsx +5 -9
- package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +0 -2
- package/src/app/[variants]/(main)/settings/_layout/Mobile/index.tsx +0 -2
- package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +1 -1
- package/src/app/[variants]/loading/index.tsx +1 -10
- package/src/components/Link.tsx +12 -0
- package/src/envs/app.ts +5 -8
- package/src/features/DataImporter/index.tsx +15 -60
- package/src/features/DevPanel/PostgresViewer/usePgTable.ts +3 -2
- package/src/hooks/useInterceptingRoutes.test.ts +21 -3
- package/src/libs/trpc/client/index.ts +0 -1
- package/src/libs/trpc/client/lambda.ts +8 -5
- package/src/server/routers/desktop/mcp.ts +1 -3
- package/src/server/routers/lambda/config/index.test.ts +2 -2
- package/src/server/routers/tools/mcp.ts +2 -3
- package/src/server/routers/tools/search.test.ts +1 -7
- package/src/server/routers/tools/search.ts +1 -4
- package/src/services/__tests__/tool.test.ts +0 -3
- package/src/services/aiModel/index.test.ts +0 -3
- package/src/services/aiModel/index.ts +1 -7
- package/src/services/aiProvider/index.test.ts +0 -3
- package/src/services/aiProvider/index.ts +1 -7
- package/src/services/chatGroup/index.ts +1 -10
- package/src/services/config.ts +1 -65
- package/src/services/export/index.ts +1 -4
- package/src/services/file/index.ts +1 -11
- package/src/services/import/index.ts +1 -7
- package/src/services/message/index.ts +1 -11
- package/src/services/plugin/index.ts +1 -11
- package/src/services/session/index.ts +1 -11
- package/src/services/tableViewer/client.ts +12 -15
- package/src/services/thread/index.ts +1 -7
- package/src/services/topic/index.ts +1 -11
- package/src/services/user/index.ts +1 -13
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +0 -241
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +26 -1
- package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +3 -1
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +1 -138
- package/src/store/user/slices/common/action.test.ts +1 -4
- package/src/app/(backend)/trpc/edge/[trpc]/route.ts +0 -26
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +0 -48
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Header.tsx +0 -33
- package/src/app/[variants]/(main)/(mobile)/me/data/layout.tsx +0 -13
- package/src/app/[variants]/(main)/(mobile)/me/data/loading.tsx +0 -5
- package/src/app/[variants]/(main)/(mobile)/me/data/page.tsx +0 -29
- package/src/app/[variants]/(main)/chat/features/Migration/DBReader.ts +0 -290
- package/src/app/[variants]/(main)/chat/features/Migration/ExportConfigButton.tsx +0 -35
- package/src/app/[variants]/(main)/chat/features/Migration/Failed.tsx +0 -120
- package/src/app/[variants]/(main)/chat/features/Migration/Modal.tsx +0 -81
- package/src/app/[variants]/(main)/chat/features/Migration/Start.tsx +0 -108
- package/src/app/[variants]/(main)/chat/features/Migration/UpgradeButton.tsx +0 -71
- package/src/app/[variants]/(main)/chat/features/Migration/const.ts +0 -15
- package/src/app/[variants]/(main)/chat/features/Migration/index.tsx +0 -50
- package/src/app/[variants]/loading/Client/Content.tsx +0 -48
- package/src/app/[variants]/loading/Client/Error.tsx +0 -27
- package/src/app/[variants]/loading/Client/Redirect.tsx +0 -47
- package/src/app/[variants]/loading/Client/index.tsx +0 -22
- package/src/components/InnerLink.tsx +0 -20
- package/src/database/_deprecated/core/__tests__/db-upgrade.test.ts +0 -42
- package/src/database/_deprecated/core/__tests__/db.test.ts +0 -79
- package/src/database/_deprecated/core/__tests__/model.test.ts +0 -55
- package/src/database/_deprecated/core/db.ts +0 -246
- package/src/database/_deprecated/core/index.ts +0 -2
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/input.json +0 -55
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/output.json +0 -60
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.test.ts +0 -14
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.ts +0 -22
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/type.ts +0 -105
- package/src/database/_deprecated/core/model.ts +0 -218
- package/src/database/_deprecated/core/schemas.ts +0 -88
- package/src/database/_deprecated/core/types/db.ts +0 -15
- package/src/database/_deprecated/models/__DEBUG.ts +0 -124
- package/src/database/_deprecated/models/__tests__/file.test.ts +0 -83
- package/src/database/_deprecated/models/__tests__/message.test.ts +0 -426
- package/src/database/_deprecated/models/__tests__/plugin.test.ts +0 -81
- package/src/database/_deprecated/models/__tests__/session.test.ts +0 -253
- package/src/database/_deprecated/models/__tests__/sessionGroup.test.ts +0 -220
- package/src/database/_deprecated/models/__tests__/topic.test.ts +0 -523
- package/src/database/_deprecated/models/__tests__/user.test.ts +0 -82
- package/src/database/_deprecated/models/file.ts +0 -51
- package/src/database/_deprecated/models/message.ts +0 -277
- package/src/database/_deprecated/models/plugin.ts +0 -62
- package/src/database/_deprecated/models/session.ts +0 -271
- package/src/database/_deprecated/models/sessionGroup.ts +0 -93
- package/src/database/_deprecated/models/topic.ts +0 -250
- package/src/database/_deprecated/models/user.ts +0 -69
- package/src/database/_deprecated/schemas/files.ts +0 -39
- package/src/database/_deprecated/schemas/message.ts +0 -50
- package/src/database/_deprecated/schemas/plugin.ts +0 -12
- package/src/database/_deprecated/schemas/session.ts +0 -54
- package/src/database/_deprecated/schemas/sessionGroup.ts +0 -8
- package/src/database/_deprecated/schemas/topic.ts +0 -12
- package/src/database/_deprecated/schemas/user.ts +0 -40
- package/src/features/DataImporter/_deprecated.ts +0 -43
- package/src/features/InitClientDB/EnableModal.tsx +0 -118
- package/src/features/InitClientDB/ErrorResult.tsx +0 -143
- package/src/features/InitClientDB/InitIndicator.tsx +0 -124
- package/src/features/InitClientDB/PGliteIcon.tsx +0 -28
- package/src/features/InitClientDB/features/DatabaseRepair/Backup.tsx +0 -75
- package/src/features/InitClientDB/features/DatabaseRepair/Diagnosis.tsx +0 -98
- package/src/features/InitClientDB/features/DatabaseRepair/Repair.tsx +0 -218
- package/src/features/InitClientDB/features/DatabaseRepair/index.tsx +0 -91
- package/src/features/InitClientDB/index.tsx +0 -37
- package/src/libs/trpc/client/edge.ts +0 -26
- package/src/libs/trpc/edge/context.ts +0 -71
- package/src/libs/trpc/edge/index.ts +0 -45
- package/src/libs/trpc/edge/init.ts +0 -26
- package/src/libs/trpc/edge/middleware/jwtPayload.test.ts +0 -75
- package/src/libs/trpc/edge/middleware/jwtPayload.ts +0 -14
- package/src/migrations/FromV0ToV1.ts +0 -10
- package/src/migrations/FromV1ToV2/fixtures/input-v1-session.json +0 -191
- package/src/migrations/FromV1ToV2/fixtures/output-v2.json +0 -202
- package/src/migrations/FromV1ToV2/index.ts +0 -82
- package/src/migrations/FromV1ToV2/migrations.test.ts +0 -224
- package/src/migrations/FromV1ToV2/types/v1.ts +0 -78
- package/src/migrations/FromV1ToV2/types/v2.ts +0 -52
- package/src/migrations/FromV2ToV3/fixtures/input-v2-session.json +0 -72
- package/src/migrations/FromV2ToV3/fixtures/output-v3-from-v1.json +0 -203
- package/src/migrations/FromV2ToV3/fixtures/output-v3.json +0 -74
- package/src/migrations/FromV2ToV3/index.ts +0 -30
- package/src/migrations/FromV2ToV3/migrations.test.ts +0 -42
- package/src/migrations/FromV2ToV3/types/v3.ts +0 -27
- package/src/migrations/FromV3ToV4/fixtures/azure-input-v3.json +0 -79
- package/src/migrations/FromV3ToV4/fixtures/azure-output-v4.json +0 -75
- package/src/migrations/FromV3ToV4/fixtures/ollama-input-v3.json +0 -85
- package/src/migrations/FromV3ToV4/fixtures/ollama-output-v4.json +0 -86
- package/src/migrations/FromV3ToV4/fixtures/openai-input-v3.json +0 -77
- package/src/migrations/FromV3ToV4/fixtures/openai-output-v4.json +0 -77
- package/src/migrations/FromV3ToV4/fixtures/openrouter-input-v3.json +0 -82
- package/src/migrations/FromV3ToV4/fixtures/openrouter-output-v4.json +0 -85
- package/src/migrations/FromV3ToV4/fixtures/output-v4-from-v1.json +0 -203
- package/src/migrations/FromV3ToV4/index.ts +0 -102
- package/src/migrations/FromV3ToV4/migrations.test.ts +0 -195
- package/src/migrations/FromV3ToV4/types/v3.ts +0 -52
- package/src/migrations/FromV3ToV4/types/v4.ts +0 -37
- package/src/migrations/FromV4ToV5/fixtures/from-v1-to-v5-output.json +0 -245
- package/src/migrations/FromV4ToV5/fixtures/function-input-v4.json +0 -96
- package/src/migrations/FromV4ToV5/fixtures/function-output-v5.json +0 -120
- package/src/migrations/FromV4ToV5/index.ts +0 -58
- package/src/migrations/FromV4ToV5/migrations.test.ts +0 -49
- package/src/migrations/FromV4ToV5/types/v4.ts +0 -21
- package/src/migrations/FromV4ToV5/types/v5.ts +0 -27
- package/src/migrations/FromV5ToV6/fixtures/from-v1-to-v6-output.json +0 -247
- package/src/migrations/FromV5ToV6/fixtures/session-input-v5.json +0 -81
- package/src/migrations/FromV5ToV6/fixtures/session-output-v6.json +0 -85
- package/src/migrations/FromV5ToV6/index.ts +0 -61
- package/src/migrations/FromV5ToV6/migrations.test.ts +0 -50
- package/src/migrations/FromV5ToV6/types/v5.ts +0 -48
- package/src/migrations/FromV5ToV6/types/v6.ts +0 -63
- package/src/migrations/FromV6ToV7/fixtures/output-v7-from-v1.json +0 -203
- package/src/migrations/FromV6ToV7/fixtures/provider-input-v6.json +0 -103
- package/src/migrations/FromV6ToV7/fixtures/provider-output-v7.json +0 -118
- package/src/migrations/FromV6ToV7/index.ts +0 -101
- package/src/migrations/FromV6ToV7/migrations.test.ts +0 -64
- package/src/migrations/FromV6ToV7/types/v6.ts +0 -61
- package/src/migrations/FromV6ToV7/types/v7.ts +0 -69
- package/src/migrations/VersionController.test.ts +0 -88
- package/src/migrations/VersionController.ts +0 -67
- package/src/migrations/index.ts +0 -61
- package/src/server/routers/edge/appStatus.ts +0 -3
- package/src/server/routers/edge/index.ts +0 -14
- package/src/server/routers/edge/upload.ts +0 -16
- package/src/services/aiModel/client.ts +0 -70
- package/src/services/aiProvider/client.ts +0 -58
- package/src/services/baseClientService/index.ts +0 -9
- package/src/services/chatGroup/client.ts +0 -63
- package/src/services/export/_deprecated.ts +0 -155
- package/src/services/export/client.ts +0 -15
- package/src/services/file/_deprecated.test.ts +0 -119
- package/src/services/file/_deprecated.ts +0 -80
- package/src/services/file/client.test.ts +0 -199
- package/src/services/file/client.ts +0 -85
- package/src/services/import/_deprecated.ts +0 -115
- package/src/services/import/client.test.ts +0 -1015
- package/src/services/import/client.ts +0 -64
- package/src/services/message/_deprecated.test.ts +0 -398
- package/src/services/message/_deprecated.ts +0 -168
- package/src/services/message/client.test.ts +0 -410
- package/src/services/message/client.ts +0 -192
- package/src/services/plugin/_deprecated.test.ts +0 -162
- package/src/services/plugin/_deprecated.ts +0 -42
- package/src/services/plugin/client.test.ts +0 -177
- package/src/services/plugin/client.ts +0 -46
- package/src/services/session/_deprecated.test.ts +0 -440
- package/src/services/session/_deprecated.ts +0 -190
- package/src/services/session/client.test.ts +0 -413
- package/src/services/session/client.ts +0 -193
- package/src/services/thread/client.ts +0 -51
- package/src/services/topic/_deprecated.test.ts +0 -245
- package/src/services/topic/_deprecated.ts +0 -75
- package/src/services/topic/client.ts +0 -89
- package/src/services/topic/pglite.test.ts +0 -212
- package/src/services/user/_deprecated.test.ts +0 -101
- package/src/services/user/_deprecated.ts +0 -70
- package/src/services/user/client.test.ts +0 -111
- package/src/services/user/client.ts +0 -104
|
@@ -1,413 +0,0 @@
|
|
|
1
|
-
import { eq, not } from 'drizzle-orm';
|
|
2
|
-
import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
|
|
4
|
-
import { INBOX_SESSION_ID } from '@/const/session';
|
|
5
|
-
import { clientDB, initializeDB } from '@/database/client/db';
|
|
6
|
-
import {
|
|
7
|
-
NewSession,
|
|
8
|
-
SessionItem,
|
|
9
|
-
agents,
|
|
10
|
-
agentsToSessions,
|
|
11
|
-
sessionGroups,
|
|
12
|
-
sessions,
|
|
13
|
-
users,
|
|
14
|
-
} from '@/database/schemas';
|
|
15
|
-
import { LobeAgentChatConfig, LobeAgentConfig } from '@/types/agent';
|
|
16
|
-
import { LobeAgentSession, LobeSessionType, SessionGroups } from '@/types/session';
|
|
17
|
-
|
|
18
|
-
import { ClientService } from './client';
|
|
19
|
-
|
|
20
|
-
const userId = 'message-db';
|
|
21
|
-
const sessionService = new ClientService(userId);
|
|
22
|
-
|
|
23
|
-
const mockSessionId = 'mock-session-id';
|
|
24
|
-
const mockAgentId = 'agent-id';
|
|
25
|
-
|
|
26
|
-
// Mock data
|
|
27
|
-
beforeEach(async () => {
|
|
28
|
-
await initializeDB();
|
|
29
|
-
|
|
30
|
-
// 在每个测试用例之前,清空表
|
|
31
|
-
await clientDB.transaction(async (trx) => {
|
|
32
|
-
await trx.insert(users).values([{ id: userId }, { id: '456' }]);
|
|
33
|
-
await trx.insert(sessions).values([{ id: mockSessionId, userId }]);
|
|
34
|
-
await trx.insert(agents).values([{ id: mockAgentId, userId }]);
|
|
35
|
-
await trx
|
|
36
|
-
.insert(agentsToSessions)
|
|
37
|
-
.values([{ agentId: mockAgentId, sessionId: mockSessionId, userId }]);
|
|
38
|
-
await trx.insert(sessionGroups).values([
|
|
39
|
-
{ id: 'group-1', name: 'group-A', sort: 2, userId },
|
|
40
|
-
{ id: 'group-2', name: 'group-B', sort: 1, userId },
|
|
41
|
-
{ id: 'group-4', name: 'group-C', sort: 1, userId: '456' },
|
|
42
|
-
]);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
afterEach(async () => {
|
|
47
|
-
// 在每个测试用例之后,清空表
|
|
48
|
-
await clientDB.delete(users);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('SessionService', () => {
|
|
52
|
-
const mockSession = {
|
|
53
|
-
id: mockSessionId,
|
|
54
|
-
type: 'agent',
|
|
55
|
-
meta: { title: 'Mock Session' },
|
|
56
|
-
} as LobeAgentSession;
|
|
57
|
-
|
|
58
|
-
describe('createSession', () => {
|
|
59
|
-
it('should create a new session and return its id', async () => {
|
|
60
|
-
// Setup
|
|
61
|
-
const sessionType = LobeSessionType.Agent;
|
|
62
|
-
const defaultValue = { meta: { title: 'New Session' } } as Partial<LobeAgentSession>;
|
|
63
|
-
|
|
64
|
-
// Execute
|
|
65
|
-
const sessionId = await sessionService.createSession(sessionType, defaultValue);
|
|
66
|
-
|
|
67
|
-
// Assert
|
|
68
|
-
expect(sessionId).toMatch(/^ssn_/);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe('removeSession', () => {
|
|
73
|
-
it('should remove a session by its id', async () => {
|
|
74
|
-
// Execute
|
|
75
|
-
await sessionService.removeSession(mockSessionId);
|
|
76
|
-
|
|
77
|
-
// Assert
|
|
78
|
-
|
|
79
|
-
const result = await clientDB.query.sessions.findFirst({
|
|
80
|
-
where: eq(sessions.id, mockSessionId),
|
|
81
|
-
});
|
|
82
|
-
// Assert
|
|
83
|
-
expect(result).toBeUndefined();
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('removeAllSessions', () => {
|
|
88
|
-
it('should clear all sessions from the table', async () => {
|
|
89
|
-
// Setup
|
|
90
|
-
await clientDB
|
|
91
|
-
.insert(sessions)
|
|
92
|
-
.values([{ userId: userId }, { userId: userId }, { userId: userId }]);
|
|
93
|
-
|
|
94
|
-
// Execute
|
|
95
|
-
await sessionService.removeAllSessions();
|
|
96
|
-
|
|
97
|
-
// Assert
|
|
98
|
-
const result = await clientDB.query.sessions.findMany({
|
|
99
|
-
where: eq(sessionGroups.userId, userId),
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
expect(result.length).toBe(0);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
describe('updateSession', () => {
|
|
107
|
-
it('should update the group of a session', async () => {
|
|
108
|
-
// Setup
|
|
109
|
-
const groupId = 'group-1';
|
|
110
|
-
|
|
111
|
-
// Execute
|
|
112
|
-
await sessionService.updateSession(mockSessionId, { group: groupId });
|
|
113
|
-
|
|
114
|
-
// Assert
|
|
115
|
-
const result = await clientDB.query.sessions.findFirst({
|
|
116
|
-
where: eq(sessions.id, mockSessionId),
|
|
117
|
-
});
|
|
118
|
-
expect(result).toMatchObject({ groupId });
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('should update the pinned status of a session', async () => {
|
|
122
|
-
// Setup
|
|
123
|
-
const pinned = true;
|
|
124
|
-
|
|
125
|
-
// Execute
|
|
126
|
-
await sessionService.updateSession(mockSessionId, { pinned });
|
|
127
|
-
|
|
128
|
-
// Assert
|
|
129
|
-
const result = await clientDB.query.sessions.findFirst({
|
|
130
|
-
where: eq(sessions.id, mockSessionId),
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
expect(result!.pinned).toBeTruthy();
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
describe('updateSessionConfig', () => {
|
|
138
|
-
it('should update the config of a session', async () => {
|
|
139
|
-
// Setup
|
|
140
|
-
const newConfig = { model: 'abc' } as LobeAgentConfig;
|
|
141
|
-
|
|
142
|
-
// Execute
|
|
143
|
-
await sessionService.updateSessionConfig(mockSessionId, newConfig);
|
|
144
|
-
|
|
145
|
-
// Assert
|
|
146
|
-
const result = await sessionService.getSessionConfig(mockSessionId);
|
|
147
|
-
expect(result).toMatchObject(newConfig);
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
describe('countSessions', () => {
|
|
152
|
-
it('should return false if no sessions exist', async () => {
|
|
153
|
-
await clientDB.delete(sessions);
|
|
154
|
-
|
|
155
|
-
// Execute
|
|
156
|
-
const result = await sessionService.countSessions();
|
|
157
|
-
|
|
158
|
-
// Assert
|
|
159
|
-
expect(result).toBe(0);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('should return true if sessions exist', async () => {
|
|
163
|
-
// Setup
|
|
164
|
-
await clientDB.delete(sessions);
|
|
165
|
-
await clientDB.insert(sessions).values([{ userId }]);
|
|
166
|
-
|
|
167
|
-
// Execute
|
|
168
|
-
const result = await sessionService.countSessions();
|
|
169
|
-
|
|
170
|
-
// Assert
|
|
171
|
-
expect(result).toBe(1);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
describe('searchSessions', () => {
|
|
176
|
-
it('should return sessions that match the keyword', async () => {
|
|
177
|
-
// Setup
|
|
178
|
-
await clientDB.insert(agents).values({ userId, id: 'agent-1', title: 'Session Name' });
|
|
179
|
-
await clientDB
|
|
180
|
-
.insert(agentsToSessions)
|
|
181
|
-
.values({ agentId: 'agent-1', sessionId: mockSessionId, userId });
|
|
182
|
-
|
|
183
|
-
// Execute
|
|
184
|
-
const keyword = 'Name';
|
|
185
|
-
const result = await sessionService.searchSessions(keyword);
|
|
186
|
-
|
|
187
|
-
// Assert
|
|
188
|
-
// TODO: 后续需要把这个搜索的标题和描述都加上,现在这个 client 搜索会有问题
|
|
189
|
-
expect(result).toMatchObject([{ id: mockSessionId }]);
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
describe('cloneSession', () => {
|
|
194
|
-
it('should duplicate a session and return its id', async () => {
|
|
195
|
-
// Setup
|
|
196
|
-
const newTitle = 'Duplicated Session';
|
|
197
|
-
const session: NewSession = {
|
|
198
|
-
id: 'duplicated-session-id',
|
|
199
|
-
title: '123',
|
|
200
|
-
userId,
|
|
201
|
-
};
|
|
202
|
-
await clientDB.insert(sessions).values([session]);
|
|
203
|
-
await clientDB.insert(agents).values({ userId, id: 'agent-1' });
|
|
204
|
-
await clientDB
|
|
205
|
-
.insert(agentsToSessions)
|
|
206
|
-
.values({ agentId: 'agent-1', sessionId: 'duplicated-session-id', userId });
|
|
207
|
-
|
|
208
|
-
// Execute
|
|
209
|
-
const duplicatedSessionId = await sessionService.cloneSession(mockSessionId, newTitle);
|
|
210
|
-
|
|
211
|
-
// Assert
|
|
212
|
-
|
|
213
|
-
const result = await clientDB.query.sessions.findFirst({
|
|
214
|
-
where: eq(sessions.id, duplicatedSessionId!),
|
|
215
|
-
});
|
|
216
|
-
expect(result).toMatchObject({ title: 'Duplicated Session' });
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
describe('getGroupedSessions', () => {
|
|
221
|
-
it('should retrieve sessions with their group', async () => {
|
|
222
|
-
// Execute
|
|
223
|
-
const sessionsWithGroup = await sessionService.getGroupedSessions();
|
|
224
|
-
|
|
225
|
-
expect(sessionsWithGroup).toMatchObject({
|
|
226
|
-
sessionGroups: [
|
|
227
|
-
{ id: 'group-2', name: 'group-B', sort: 1 },
|
|
228
|
-
{ id: 'group-1', name: 'group-A', sort: 2 },
|
|
229
|
-
],
|
|
230
|
-
sessions: [{ id: 'mock-session-id', type: 'agent' }],
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('getSessionsByType', () => {
|
|
236
|
-
it('should get sessions by type "all"', async () => {
|
|
237
|
-
const sessions = await sessionService.getSessionsByType('all');
|
|
238
|
-
expect(sessions).toBeDefined();
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
it('should get sessions by type "agent"', async () => {
|
|
242
|
-
const sessions = await sessionService.getSessionsByType('agent');
|
|
243
|
-
expect(sessions).toBeDefined();
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('should get sessions by type "group"', async () => {
|
|
247
|
-
const sessions = await sessionService.getSessionsByType('group');
|
|
248
|
-
expect(sessions).toBeDefined();
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
describe('getSessionConfig', () => {
|
|
253
|
-
it.skip('should get default config for INBOX_SESSION_ID', async () => {
|
|
254
|
-
const config = await sessionService.getSessionConfig(INBOX_SESSION_ID);
|
|
255
|
-
expect(config).toBeDefined();
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it('should throw error for non-existent session', async () => {
|
|
259
|
-
await expect(sessionService.getSessionConfig('non-existent')).rejects.toThrow(
|
|
260
|
-
'Session not found',
|
|
261
|
-
);
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
describe('updateSessionMeta', () => {
|
|
266
|
-
it('should not update meta for INBOX_SESSION_ID', async () => {
|
|
267
|
-
const result = await sessionService.updateSessionMeta(INBOX_SESSION_ID, {
|
|
268
|
-
title: 'New Title',
|
|
269
|
-
});
|
|
270
|
-
expect(result).toBeUndefined();
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
it('should update meta for normal session', async () => {
|
|
274
|
-
const meta = { title: 'Updated Title' };
|
|
275
|
-
await sessionService.updateSessionMeta(mockSessionId, meta);
|
|
276
|
-
|
|
277
|
-
const session = await clientDB.query.sessions.findFirst({
|
|
278
|
-
where: eq(sessions.id, mockSessionId),
|
|
279
|
-
});
|
|
280
|
-
expect(session).toBeDefined();
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
describe('updateSessionChatConfig', () => {
|
|
285
|
-
it('should update chat config', async () => {
|
|
286
|
-
const chatConfig = { temperature: 0.8 } as Partial<LobeAgentChatConfig>;
|
|
287
|
-
const result = await sessionService.updateSessionChatConfig(mockSessionId, chatConfig);
|
|
288
|
-
expect(result).toBeDefined();
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
describe('model getters', () => {
|
|
293
|
-
it('should return session model instance', () => {
|
|
294
|
-
// @ts-ignore - accessing private getter
|
|
295
|
-
const model = sessionService.sessionModel;
|
|
296
|
-
expect(model).toBeDefined();
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it('should return session group model instance', () => {
|
|
300
|
-
// @ts-ignore - accessing private getter
|
|
301
|
-
const model = sessionService.sessionGroupModel;
|
|
302
|
-
expect(model).toBeDefined();
|
|
303
|
-
});
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
// SessionGroup related tests
|
|
307
|
-
describe('createSessionGroup', () => {
|
|
308
|
-
it('should create a new session group and return its id', async () => {
|
|
309
|
-
// Setup
|
|
310
|
-
const groupName = 'New Group';
|
|
311
|
-
const sort = 1;
|
|
312
|
-
|
|
313
|
-
// Execute
|
|
314
|
-
const groupId = await sessionService.createSessionGroup(groupName, sort);
|
|
315
|
-
|
|
316
|
-
// Assert
|
|
317
|
-
expect(groupId).toMatch(/^sg_/);
|
|
318
|
-
|
|
319
|
-
const result = await clientDB.query.sessionGroups.findFirst({
|
|
320
|
-
where: eq(sessionGroups.id, groupId),
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
expect(result).toMatchObject({ id: groupId, name: groupName, sort });
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
describe('removeSessionGroup', () => {
|
|
328
|
-
it('should remove a session group by its id', async () => {
|
|
329
|
-
const groupId = 'group-1';
|
|
330
|
-
// Execute
|
|
331
|
-
await sessionService.removeSessionGroup(groupId);
|
|
332
|
-
|
|
333
|
-
const result = await clientDB.query.sessionGroups.findFirst({
|
|
334
|
-
where: eq(sessionGroups.id, groupId),
|
|
335
|
-
});
|
|
336
|
-
// Assert
|
|
337
|
-
expect(result).toBeUndefined();
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
describe('clearSessionGroups', () => {
|
|
342
|
-
it('should clear all session groups', async () => {
|
|
343
|
-
// Execute
|
|
344
|
-
await sessionService.removeSessionGroups();
|
|
345
|
-
|
|
346
|
-
// Assert
|
|
347
|
-
const result = await clientDB.query.sessionGroups.findMany({
|
|
348
|
-
where: eq(sessionGroups.userId, userId),
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
expect(result.length).toBe(0);
|
|
352
|
-
|
|
353
|
-
const result2 = await clientDB.query.sessionGroups.findMany({
|
|
354
|
-
where: not(eq(sessionGroups.userId, userId)),
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
expect(result2.length).toBeGreaterThan(0);
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
describe('getSessionGroups', () => {
|
|
362
|
-
it('should retrieve all session groups', async () => {
|
|
363
|
-
// Execute
|
|
364
|
-
const result = await sessionService.getSessionGroups();
|
|
365
|
-
|
|
366
|
-
// Assert
|
|
367
|
-
const groups = [
|
|
368
|
-
{ id: 'group-2', name: 'group-B', sort: 1 },
|
|
369
|
-
{ id: 'group-1', name: 'group-A', sort: 2 },
|
|
370
|
-
];
|
|
371
|
-
expect(result).toMatchObject(groups);
|
|
372
|
-
});
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
describe('updateSessionGroup', () => {
|
|
376
|
-
it('should update a session group', async () => {
|
|
377
|
-
// Setup
|
|
378
|
-
const groupId = 'group-1';
|
|
379
|
-
const data = { name: 'Updated Group', sort: 2 };
|
|
380
|
-
|
|
381
|
-
// Execute
|
|
382
|
-
await sessionService.updateSessionGroup(groupId, data);
|
|
383
|
-
|
|
384
|
-
// Assert
|
|
385
|
-
const result = await clientDB.query.sessionGroups.findFirst({
|
|
386
|
-
where: eq(sessionGroups.id, groupId),
|
|
387
|
-
});
|
|
388
|
-
expect(result).toMatchObject({ id: groupId, ...data });
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
describe('updateSessionGroupOrder', () => {
|
|
393
|
-
it('should update the order of session groups', async () => {
|
|
394
|
-
// Setup
|
|
395
|
-
const sortMap = [
|
|
396
|
-
{ id: 'group-1', sort: 2 },
|
|
397
|
-
{ id: 'group-2', sort: 1 },
|
|
398
|
-
];
|
|
399
|
-
|
|
400
|
-
// Execute
|
|
401
|
-
await sessionService.updateSessionGroupOrder(sortMap);
|
|
402
|
-
|
|
403
|
-
// Assert
|
|
404
|
-
const data = await clientDB.query.sessionGroups.findMany({
|
|
405
|
-
where: eq(sessionGroups.userId, userId),
|
|
406
|
-
});
|
|
407
|
-
expect(data).toMatchObject([
|
|
408
|
-
{ id: 'group-1', sort: 2 },
|
|
409
|
-
{ id: 'group-2', sort: 1 },
|
|
410
|
-
]);
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
});
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { AgentItem, LobeAgentConfig } from '@lobechat/types';
|
|
2
|
-
|
|
3
|
-
import { INBOX_SESSION_ID } from '@/const/session';
|
|
4
|
-
import { clientDB } from '@/database/client/db';
|
|
5
|
-
import { ChatGroupModel } from '@/database/models/chatGroup';
|
|
6
|
-
import { SessionModel } from '@/database/models/session';
|
|
7
|
-
import { SessionGroupModel } from '@/database/models/sessionGroup';
|
|
8
|
-
import { BaseClientService } from '@/services/baseClientService';
|
|
9
|
-
|
|
10
|
-
import { ISessionService } from './type';
|
|
11
|
-
|
|
12
|
-
export class ClientService extends BaseClientService implements ISessionService {
|
|
13
|
-
private get sessionModel(): SessionModel {
|
|
14
|
-
return new SessionModel(clientDB as any, this.userId);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
private get sessionGroupModel(): SessionGroupModel {
|
|
18
|
-
return new SessionGroupModel(clientDB as any, this.userId);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
private get chatGroupModel(): ChatGroupModel {
|
|
22
|
-
return new ChatGroupModel(clientDB as any, this.userId);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
hasSessions: ISessionService['hasSessions'] = async () => {
|
|
26
|
-
const result = await this.countSessions();
|
|
27
|
-
return result === 0;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
createSession: ISessionService['createSession'] = async (type, data) => {
|
|
31
|
-
const { config, group, meta, ...session } = data;
|
|
32
|
-
|
|
33
|
-
const item = await this.sessionModel.create({
|
|
34
|
-
config: { ...config, ...meta } as any,
|
|
35
|
-
session: { ...session, groupId: group },
|
|
36
|
-
type,
|
|
37
|
-
});
|
|
38
|
-
if (!item) {
|
|
39
|
-
throw new Error('session create Error');
|
|
40
|
-
}
|
|
41
|
-
return item.id;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
batchCreateSessions: ISessionService['batchCreateSessions'] = async (importSessions) => {
|
|
45
|
-
// @ts-ignore
|
|
46
|
-
return this.sessionModel.batchCreate(importSessions);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
cloneSession: ISessionService['cloneSession'] = async (id, newTitle) => {
|
|
50
|
-
const res = await this.sessionModel.duplicate(id, newTitle);
|
|
51
|
-
|
|
52
|
-
if (res) return res?.id;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
getGroupedSessions: ISessionService['getGroupedSessions'] = async () => {
|
|
56
|
-
const { sessions, sessionGroups } = await this.sessionModel.queryWithGroups();
|
|
57
|
-
const chatGroups = await this.chatGroupModel.queryWithMemberDetails();
|
|
58
|
-
|
|
59
|
-
const groupSessions = chatGroups.map((group) => {
|
|
60
|
-
const { title, description, avatar, backgroundColor, groupId, ...rest } = group;
|
|
61
|
-
return {
|
|
62
|
-
...rest,
|
|
63
|
-
group: groupId, // Map groupId to group for consistent API
|
|
64
|
-
meta: { avatar, backgroundColor, description, title },
|
|
65
|
-
type: 'group' as const,
|
|
66
|
-
};
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const allSessions = [...sessions, ...groupSessions].sort(
|
|
70
|
-
(a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
return { sessionGroups, sessions: allSessions };
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
getSessionConfig: ISessionService['getSessionConfig'] = async (id) => {
|
|
77
|
-
if (id === INBOX_SESSION_ID) {
|
|
78
|
-
const item = await this.sessionModel.findByIdOrSlug(INBOX_SESSION_ID);
|
|
79
|
-
|
|
80
|
-
// if there is no session for user, create one
|
|
81
|
-
if (!item) {
|
|
82
|
-
const defaultAgentConfig =
|
|
83
|
-
window.global_serverConfigStore.getState().serverConfig.defaultAgent?.config || {};
|
|
84
|
-
|
|
85
|
-
await this.sessionModel.createInbox(defaultAgentConfig);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const res = await this.sessionModel.findByIdOrSlug(id);
|
|
90
|
-
|
|
91
|
-
if (!res) throw new Error('Session not found');
|
|
92
|
-
|
|
93
|
-
return res.agent as LobeAgentConfig;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* 这个方法要对应移除的
|
|
98
|
-
*/
|
|
99
|
-
// @ts-ignore
|
|
100
|
-
getSessionsByType: ISessionService['getSessionsByType'] = async (type = 'all') => {
|
|
101
|
-
switch (type) {
|
|
102
|
-
// TODO: add a filter to get only agents or agents
|
|
103
|
-
case 'group':
|
|
104
|
-
case 'agent':
|
|
105
|
-
case 'all': {
|
|
106
|
-
return this.sessionModel.query();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
countSessions: ISessionService['countSessions'] = async (params) => {
|
|
112
|
-
return this.sessionModel.count(params);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
rankSessions: ISessionService['rankSessions'] = async (limit) => {
|
|
116
|
-
return this.sessionModel.rank(limit);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
searchSessions: ISessionService['searchSessions'] = async (keyword) => {
|
|
120
|
-
return this.sessionModel.queryByKeyword(keyword);
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
updateSession: ISessionService['updateSession'] = async (id, value) => {
|
|
124
|
-
return this.sessionModel.update(id, {
|
|
125
|
-
...value,
|
|
126
|
-
groupId: value.group === 'default' ? null : value.group,
|
|
127
|
-
});
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
updateSessionConfig: ISessionService['updateSessionConfig'] = async (activeId, config) => {
|
|
131
|
-
return this.sessionModel.updateConfig(activeId, config as AgentItem);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
updateSessionMeta: ISessionService['updateSessionMeta'] = async (activeId, meta) => {
|
|
135
|
-
// inbox 不允许修改 meta
|
|
136
|
-
if (activeId === INBOX_SESSION_ID) return;
|
|
137
|
-
|
|
138
|
-
return this.sessionModel.update(activeId, meta);
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
updateSessionChatConfig: ISessionService['updateSessionChatConfig'] = async (
|
|
142
|
-
activeId,
|
|
143
|
-
config,
|
|
144
|
-
) => {
|
|
145
|
-
return this.updateSessionConfig(activeId, { chatConfig: config });
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
removeSession: ISessionService['removeSession'] = async (id) => {
|
|
149
|
-
return this.sessionModel.delete(id);
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
removeAllSessions: ISessionService['removeAllSessions'] = async () => {
|
|
153
|
-
return this.sessionModel.deleteAll();
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// ************************************** //
|
|
157
|
-
// *********** SessionGroup *********** //
|
|
158
|
-
// ************************************** //
|
|
159
|
-
|
|
160
|
-
createSessionGroup: ISessionService['createSessionGroup'] = async (name, sort) => {
|
|
161
|
-
const item = await this.sessionGroupModel.create({ name, sort });
|
|
162
|
-
if (!item) {
|
|
163
|
-
throw new Error('session group create Error');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return item.id;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
170
|
-
batchCreateSessionGroups: ISessionService['batchCreateSessionGroups'] = async (_groups) => {
|
|
171
|
-
return { added: 0, ids: [], skips: [], success: true };
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
removeSessionGroup: ISessionService['removeSessionGroup'] = async (id) => {
|
|
175
|
-
return this.sessionGroupModel.delete(id);
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
updateSessionGroup: ISessionService['updateSessionGroup'] = async (id, data) => {
|
|
179
|
-
return this.sessionGroupModel.update(id, data);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
updateSessionGroupOrder: ISessionService['updateSessionGroupOrder'] = async (sortMap) => {
|
|
183
|
-
return this.sessionGroupModel.updateOrder(sortMap);
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
getSessionGroups: ISessionService['getSessionGroups'] = async () => {
|
|
187
|
-
return this.sessionGroupModel.query();
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
removeSessionGroups: ISessionService['removeSessionGroups'] = async () => {
|
|
191
|
-
return this.sessionGroupModel.deleteAll();
|
|
192
|
-
};
|
|
193
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { INBOX_SESSION_ID } from '@/const/session';
|
|
2
|
-
import { clientDB } from '@/database/client/db';
|
|
3
|
-
import { MessageModel } from '@/database/models/message';
|
|
4
|
-
import { ThreadModel } from '@/database/models/thread';
|
|
5
|
-
import { BaseClientService } from '@/services/baseClientService';
|
|
6
|
-
|
|
7
|
-
import { IThreadService } from './type';
|
|
8
|
-
|
|
9
|
-
export class ClientService extends BaseClientService implements IThreadService {
|
|
10
|
-
private get threadModel(): ThreadModel {
|
|
11
|
-
return new ThreadModel(clientDB as any, this.userId);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
private get messageModel(): MessageModel {
|
|
15
|
-
return new MessageModel(clientDB as any, this.userId);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
getThreads: IThreadService['getThreads'] = async (topicId) => {
|
|
19
|
-
return this.threadModel.queryByTopicId(topicId);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
createThreadWithMessage: IThreadService['createThreadWithMessage'] = async (input) => {
|
|
23
|
-
const thread = await this.threadModel.create({
|
|
24
|
-
parentThreadId: input.parentThreadId,
|
|
25
|
-
sourceMessageId: input.sourceMessageId,
|
|
26
|
-
title: input.message.content.slice(0, 20),
|
|
27
|
-
topicId: input.topicId,
|
|
28
|
-
type: input.type,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const message = await this.messageModel.create({
|
|
32
|
-
...input.message,
|
|
33
|
-
sessionId: this.toDbSessionId(input.message.sessionId) as string,
|
|
34
|
-
threadId: thread?.id,
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
return { messageId: message?.id, threadId: thread?.id };
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
updateThread: IThreadService['updateThread'] = async (id, data) => {
|
|
41
|
-
return this.threadModel.update(id, data);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
removeThread: IThreadService['removeThread'] = async (id) => {
|
|
45
|
-
return this.threadModel.delete(id);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
private toDbSessionId = (sessionId: string | undefined) => {
|
|
49
|
-
return sessionId === INBOX_SESSION_ID ? null : sessionId;
|
|
50
|
-
};
|
|
51
|
-
}
|