@lobehub/lobehub 2.0.0-next.12 → 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 +50 -0
- package/changelog/v1.json +18 -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/features/PromptInput/index.tsx +1 -1
- 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/libs/trpc/lambda/context.ts +4 -1
- 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
|
@@ -87,57 +87,6 @@ describe('chatMessage actions', () => {
|
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
describe('message creation', () => {
|
|
90
|
-
it('should create user message and trigger AI processing', async () => {
|
|
91
|
-
const { result } = renderHook(() => useChatStore());
|
|
92
|
-
|
|
93
|
-
await act(async () => {
|
|
94
|
-
await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE });
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
expect(messageService.createMessage).toHaveBeenCalledWith({
|
|
98
|
-
content: TEST_CONTENT.USER_MESSAGE,
|
|
99
|
-
files: undefined,
|
|
100
|
-
role: 'user',
|
|
101
|
-
sessionId: TEST_IDS.SESSION_ID,
|
|
102
|
-
topicId: TEST_IDS.TOPIC_ID,
|
|
103
|
-
});
|
|
104
|
-
expect(result.current.internal_coreProcessMessage).toHaveBeenCalled();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('should send message with files attached', async () => {
|
|
108
|
-
const { result } = renderHook(() => useChatStore());
|
|
109
|
-
const files = [{ id: TEST_IDS.FILE_ID } as UploadFileItem];
|
|
110
|
-
|
|
111
|
-
await act(async () => {
|
|
112
|
-
await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE, files });
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
expect(messageService.createMessage).toHaveBeenCalledWith({
|
|
116
|
-
content: TEST_CONTENT.USER_MESSAGE,
|
|
117
|
-
files: [TEST_IDS.FILE_ID],
|
|
118
|
-
role: 'user',
|
|
119
|
-
sessionId: TEST_IDS.SESSION_ID,
|
|
120
|
-
topicId: TEST_IDS.TOPIC_ID,
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('should send files without message content', async () => {
|
|
125
|
-
const { result } = renderHook(() => useChatStore());
|
|
126
|
-
const files = [{ id: TEST_IDS.FILE_ID } as UploadFileItem];
|
|
127
|
-
|
|
128
|
-
await act(async () => {
|
|
129
|
-
await result.current.sendMessage({ message: TEST_CONTENT.EMPTY, files });
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
expect(messageService.createMessage).toHaveBeenCalledWith({
|
|
133
|
-
content: TEST_CONTENT.EMPTY,
|
|
134
|
-
files: [TEST_IDS.FILE_ID],
|
|
135
|
-
role: 'user',
|
|
136
|
-
sessionId: TEST_IDS.SESSION_ID,
|
|
137
|
-
topicId: TEST_IDS.TOPIC_ID,
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
90
|
it('should not process AI when onlyAddUserMessage is true', async () => {
|
|
142
91
|
const { result } = renderHook(() => useChatStore());
|
|
143
92
|
|
|
@@ -169,196 +118,6 @@ describe('chatMessage actions', () => {
|
|
|
169
118
|
expect(result.current.internal_coreProcessMessage).not.toHaveBeenCalled();
|
|
170
119
|
});
|
|
171
120
|
});
|
|
172
|
-
|
|
173
|
-
describe('auto-create topic', () => {
|
|
174
|
-
const TOPIC_THRESHOLD = 5;
|
|
175
|
-
|
|
176
|
-
it('should create topic when threshold is reached and feature is enabled', async () => {
|
|
177
|
-
const { result } = renderHook(() => useChatStore());
|
|
178
|
-
|
|
179
|
-
const createTopicMock = vi.fn(() => Promise.resolve(TEST_IDS.NEW_TOPIC_ID));
|
|
180
|
-
const switchTopicMock = vi.fn();
|
|
181
|
-
|
|
182
|
-
act(() => {
|
|
183
|
-
setupMockSelectors({
|
|
184
|
-
agentConfig: {
|
|
185
|
-
enableAutoCreateTopic: true,
|
|
186
|
-
autoCreateTopicThreshold: TOPIC_THRESHOLD,
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
useChatStore.setState({
|
|
191
|
-
activeTopicId: undefined,
|
|
192
|
-
messagesMap: {
|
|
193
|
-
[messageMapKey(TEST_IDS.SESSION_ID)]: createMockMessages(TOPIC_THRESHOLD),
|
|
194
|
-
},
|
|
195
|
-
createTopic: createTopicMock,
|
|
196
|
-
switchTopic: switchTopicMock,
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
await act(async () => {
|
|
201
|
-
await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE });
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
expect(createTopicMock).toHaveBeenCalled();
|
|
205
|
-
expect(switchTopicMock).toHaveBeenCalledWith(TEST_IDS.NEW_TOPIC_ID, true);
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
describe('RAG integration', () => {
|
|
210
|
-
it('should include RAG query when RAG is enabled', async () => {
|
|
211
|
-
const { result } = renderHook(() => useChatStore());
|
|
212
|
-
vi.spyOn(result.current, 'internal_shouldUseRAG').mockReturnValue(true);
|
|
213
|
-
|
|
214
|
-
await act(async () => {
|
|
215
|
-
await result.current.sendMessage({ message: TEST_CONTENT.RAG_QUERY });
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
expect(result.current.internal_coreProcessMessage).toHaveBeenCalledWith(
|
|
219
|
-
expect.any(Array),
|
|
220
|
-
expect.any(String),
|
|
221
|
-
expect.objectContaining({
|
|
222
|
-
ragQuery: TEST_CONTENT.RAG_QUERY,
|
|
223
|
-
}),
|
|
224
|
-
);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it('should not use RAG when feature is disabled', async () => {
|
|
228
|
-
const { result } = renderHook(() => useChatStore());
|
|
229
|
-
vi.spyOn(result.current, 'internal_shouldUseRAG').mockReturnValue(false);
|
|
230
|
-
const retrieveChunksSpy = vi.spyOn(result.current, 'internal_retrieveChunks');
|
|
231
|
-
|
|
232
|
-
await act(async () => {
|
|
233
|
-
await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE });
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
expect(retrieveChunksSpy).not.toHaveBeenCalled();
|
|
237
|
-
expect(result.current.internal_coreProcessMessage).toHaveBeenCalledWith(
|
|
238
|
-
expect.any(Array),
|
|
239
|
-
expect.any(String),
|
|
240
|
-
expect.not.objectContaining({
|
|
241
|
-
ragQuery: expect.anything(),
|
|
242
|
-
}),
|
|
243
|
-
);
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
describe('special flags', () => {
|
|
248
|
-
it('should pass isWelcomeQuestion flag to processing', async () => {
|
|
249
|
-
const { result } = renderHook(() => useChatStore());
|
|
250
|
-
|
|
251
|
-
await act(async () => {
|
|
252
|
-
await result.current.sendMessage({
|
|
253
|
-
message: TEST_CONTENT.USER_MESSAGE,
|
|
254
|
-
isWelcomeQuestion: true,
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
expect(result.current.internal_coreProcessMessage).toHaveBeenCalledWith(
|
|
259
|
-
expect.anything(),
|
|
260
|
-
expect.anything(),
|
|
261
|
-
{ isWelcomeQuestion: true },
|
|
262
|
-
);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it('should return early when onlyAddUserMessage is true', async () => {
|
|
266
|
-
const { result } = renderHook(() => useChatStore());
|
|
267
|
-
|
|
268
|
-
await act(async () => {
|
|
269
|
-
await result.current.sendMessage({
|
|
270
|
-
message: TEST_CONTENT.USER_MESSAGE,
|
|
271
|
-
onlyAddUserMessage: true,
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
expect(result.current.internal_coreProcessMessage).not.toHaveBeenCalled();
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
describe('topic creation flow', () => {
|
|
280
|
-
it('should handle tempMessage during topic creation', async () => {
|
|
281
|
-
setupMockSelectors({
|
|
282
|
-
chatConfig: { enableAutoCreateTopic: true, autoCreateTopicThreshold: 2 },
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
act(() => {
|
|
286
|
-
useChatStore.setState({ activeTopicId: undefined });
|
|
287
|
-
setupStoreWithMessages(createMockMessages(5));
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
const { result } = renderHook(() => useChatStore());
|
|
291
|
-
const createTopicMock = vi
|
|
292
|
-
.spyOn(result.current, 'createTopic')
|
|
293
|
-
.mockResolvedValue(TEST_IDS.NEW_TOPIC_ID);
|
|
294
|
-
const toggleMessageLoadingSpy = vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
295
|
-
const createTmpMessageSpy = vi
|
|
296
|
-
.spyOn(result.current, 'internal_createTmpMessage')
|
|
297
|
-
.mockReturnValue('temp-id');
|
|
298
|
-
vi.spyOn(result.current, 'internal_fetchMessages').mockResolvedValue();
|
|
299
|
-
vi.spyOn(result.current, 'switchTopic').mockResolvedValue();
|
|
300
|
-
|
|
301
|
-
await act(async () => {
|
|
302
|
-
await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE });
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
expect(createTmpMessageSpy).toHaveBeenCalled();
|
|
306
|
-
expect(toggleMessageLoadingSpy).toHaveBeenCalledWith(true, 'temp-id');
|
|
307
|
-
expect(createTopicMock).toHaveBeenCalled();
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it('should call summaryTopicTitle after processing when new topic created', async () => {
|
|
311
|
-
setupMockSelectors({
|
|
312
|
-
chatConfig: { enableAutoCreateTopic: true, autoCreateTopicThreshold: 2 },
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
act(() => {
|
|
316
|
-
useChatStore.setState({ activeTopicId: undefined });
|
|
317
|
-
setupStoreWithMessages(createMockMessages(5));
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
const { result } = renderHook(() => useChatStore());
|
|
321
|
-
vi.spyOn(result.current, 'createTopic').mockResolvedValue(TEST_IDS.NEW_TOPIC_ID);
|
|
322
|
-
vi.spyOn(result.current, 'internal_createTmpMessage').mockReturnValue('temp-id');
|
|
323
|
-
vi.spyOn(result.current, 'internal_fetchMessages').mockResolvedValue();
|
|
324
|
-
vi.spyOn(result.current, 'switchTopic').mockResolvedValue();
|
|
325
|
-
|
|
326
|
-
const summaryTopicTitleSpy = vi
|
|
327
|
-
.spyOn(result.current, 'summaryTopicTitle')
|
|
328
|
-
.mockResolvedValue();
|
|
329
|
-
|
|
330
|
-
await act(async () => {
|
|
331
|
-
await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE });
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
expect(summaryTopicTitleSpy).toHaveBeenCalledWith(TEST_IDS.NEW_TOPIC_ID, expect.any(Array));
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it('should handle topic creation failure gracefully', async () => {
|
|
338
|
-
setupMockSelectors({
|
|
339
|
-
chatConfig: { enableAutoCreateTopic: true, autoCreateTopicThreshold: 2 },
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
act(() => {
|
|
343
|
-
useChatStore.setState({ activeTopicId: undefined });
|
|
344
|
-
setupStoreWithMessages(createMockMessages(5));
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
const { result } = renderHook(() => useChatStore());
|
|
348
|
-
vi.spyOn(result.current, 'createTopic').mockResolvedValue(undefined);
|
|
349
|
-
vi.spyOn(result.current, 'internal_createTmpMessage').mockReturnValue('temp-id');
|
|
350
|
-
const toggleLoadingSpy = vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
351
|
-
const updateTopicLoadingSpy = vi.spyOn(result.current, 'internal_updateTopicLoading');
|
|
352
|
-
|
|
353
|
-
await act(async () => {
|
|
354
|
-
await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE });
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
// Should still call the AI processing even if topic creation fails
|
|
358
|
-
expect(result.current.internal_coreProcessMessage).toHaveBeenCalled();
|
|
359
|
-
expect(updateTopicLoadingSpy).not.toHaveBeenCalled();
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
121
|
});
|
|
363
122
|
|
|
364
123
|
describe('regenerateMessage', () => {
|
|
@@ -19,8 +19,33 @@ import { resetTestEnvironment, setupMockSelectors, spyOnMessageService } from '.
|
|
|
19
19
|
// Keep zustand mock as it's needed globally
|
|
20
20
|
vi.mock('zustand/traditional');
|
|
21
21
|
|
|
22
|
+
// Mock AntdStaticMethods
|
|
23
|
+
vi.mock('@/components/AntdStaticMethods', () => ({
|
|
24
|
+
notification: {
|
|
25
|
+
error: vi.fn(),
|
|
26
|
+
success: vi.fn(),
|
|
27
|
+
info: vi.fn(),
|
|
28
|
+
warning: vi.fn(),
|
|
29
|
+
},
|
|
30
|
+
message: {
|
|
31
|
+
error: vi.fn(),
|
|
32
|
+
success: vi.fn(),
|
|
33
|
+
info: vi.fn(),
|
|
34
|
+
warning: vi.fn(),
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
// Mock sessionService to prevent TRPC requests
|
|
39
|
+
vi.mock('@/services/session', () => ({
|
|
40
|
+
sessionService: {
|
|
41
|
+
updateSession: vi.fn(),
|
|
42
|
+
updateSessionConfig: vi.fn(),
|
|
43
|
+
updateSessionChatConfig: vi.fn(),
|
|
44
|
+
},
|
|
45
|
+
}));
|
|
46
|
+
|
|
22
47
|
// Mock server mode for V2 tests
|
|
23
|
-
vi.mock('
|
|
48
|
+
vi.mock('@lobechat/const', async (importOriginal) => {
|
|
24
49
|
const module = await importOriginal();
|
|
25
50
|
return {
|
|
26
51
|
...(module as any),
|
|
@@ -60,7 +60,9 @@ export const spyOnMessageService = () => {
|
|
|
60
60
|
const createMessageSpy = vi
|
|
61
61
|
.spyOn(messageService, 'createMessage')
|
|
62
62
|
.mockResolvedValue(TEST_IDS.NEW_MESSAGE_ID);
|
|
63
|
-
const updateMessageSpy = vi
|
|
63
|
+
const updateMessageSpy = vi
|
|
64
|
+
.spyOn(messageService, 'updateMessage')
|
|
65
|
+
.mockResolvedValue({ messages: [], success: true });
|
|
64
66
|
const removeMessageSpy = vi.spyOn(messageService, 'removeMessage').mockResolvedValue(undefined);
|
|
65
67
|
const updateMessageErrorSpy = vi
|
|
66
68
|
.spyOn(messageService, 'updateMessageError')
|
|
@@ -17,15 +17,12 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
17
17
|
|
|
18
18
|
import { chatService } from '@/services/chat';
|
|
19
19
|
import { messageService } from '@/services/message';
|
|
20
|
-
import { useAgentStore } from '@/store/agent';
|
|
21
20
|
import { agentChatConfigSelectors, agentSelectors } from '@/store/agent/selectors';
|
|
22
21
|
import { getAgentStoreState } from '@/store/agent/store';
|
|
23
22
|
import { aiModelSelectors, aiProviderSelectors } from '@/store/aiInfra';
|
|
24
23
|
import { getAiInfraStoreState } from '@/store/aiInfra/store';
|
|
25
24
|
import { ChatStore } from '@/store/chat/store';
|
|
26
|
-
import { messageMapKey } from '@/store/chat/utils/messageMapKey';
|
|
27
25
|
import { getFileStoreState } from '@/store/file/store';
|
|
28
|
-
import { useSessionStore } from '@/store/session';
|
|
29
26
|
import { WebBrowsingManifest } from '@/tools/web-browsing';
|
|
30
27
|
import { Action, setNamespace } from '@/utils/storeDebug';
|
|
31
28
|
|
|
@@ -158,13 +155,7 @@ export const generateAIChat: StateCreator<
|
|
|
158
155
|
},
|
|
159
156
|
|
|
160
157
|
sendMessage: async ({ message, files, onlyAddUserMessage, isWelcomeQuestion }) => {
|
|
161
|
-
const {
|
|
162
|
-
internal_coreProcessMessage,
|
|
163
|
-
activeTopicId,
|
|
164
|
-
activeId,
|
|
165
|
-
activeThreadId,
|
|
166
|
-
sendMessageInServer,
|
|
167
|
-
} = get();
|
|
158
|
+
const { activeId, sendMessageInServer } = get();
|
|
168
159
|
if (!activeId) return;
|
|
169
160
|
|
|
170
161
|
const fileIdList = files?.map((f) => f.id);
|
|
@@ -177,134 +168,6 @@ export const generateAIChat: StateCreator<
|
|
|
177
168
|
// router to server mode send message
|
|
178
169
|
if (isServerMode)
|
|
179
170
|
return sendMessageInServer({ message, files, onlyAddUserMessage, isWelcomeQuestion });
|
|
180
|
-
|
|
181
|
-
set({ isCreatingMessage: true }, false, n('creatingMessage/start'));
|
|
182
|
-
|
|
183
|
-
const newMessage: CreateMessageParams = {
|
|
184
|
-
content: message,
|
|
185
|
-
// if message has attached with files, then add files to message and the agent
|
|
186
|
-
files: fileIdList,
|
|
187
|
-
role: 'user',
|
|
188
|
-
sessionId: activeId,
|
|
189
|
-
// if there is activeTopicId,then add topicId to message
|
|
190
|
-
topicId: activeTopicId,
|
|
191
|
-
threadId: activeThreadId,
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
const agentConfig = agentChatConfigSelectors.currentChatConfig(getAgentStoreState());
|
|
195
|
-
|
|
196
|
-
let tempMessageId: string | undefined = undefined;
|
|
197
|
-
let newTopicId: string | undefined = undefined;
|
|
198
|
-
|
|
199
|
-
// it should be the default topic, then
|
|
200
|
-
// if autoCreateTopic is enabled, check to whether we need to create a topic
|
|
201
|
-
if (!onlyAddUserMessage && !activeTopicId && agentConfig.enableAutoCreateTopic) {
|
|
202
|
-
// check activeTopic and then auto create topic
|
|
203
|
-
const chats = chatSelectors.activeBaseChats(get());
|
|
204
|
-
|
|
205
|
-
// we will add two messages (user and assistant), so the finial length should +2
|
|
206
|
-
const featureLength = chats.length + 2;
|
|
207
|
-
|
|
208
|
-
// if there is no activeTopicId and the feature length is greater than the threshold
|
|
209
|
-
// then create a new topic and active it
|
|
210
|
-
if (!activeTopicId && featureLength >= agentConfig.autoCreateTopicThreshold) {
|
|
211
|
-
// we need to create a temp message for optimistic update
|
|
212
|
-
tempMessageId = get().internal_createTmpMessage(newMessage);
|
|
213
|
-
get().internal_toggleMessageLoading(true, tempMessageId);
|
|
214
|
-
|
|
215
|
-
const topicId = await get().createTopic();
|
|
216
|
-
|
|
217
|
-
if (topicId) {
|
|
218
|
-
newTopicId = topicId;
|
|
219
|
-
newMessage.topicId = topicId;
|
|
220
|
-
|
|
221
|
-
// we need to copy the messages to the new topic or the message will disappear
|
|
222
|
-
const mapKey = chatSelectors.currentChatKey(get());
|
|
223
|
-
const newMaps = {
|
|
224
|
-
...get().messagesMap,
|
|
225
|
-
[messageMapKey(activeId, topicId)]: get().messagesMap[mapKey],
|
|
226
|
-
};
|
|
227
|
-
set({ messagesMap: newMaps }, false, n('moveMessagesToNewTopic'));
|
|
228
|
-
|
|
229
|
-
// make the topic loading
|
|
230
|
-
get().internal_updateTopicLoading(topicId, true);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
// update assistant update to make it rerank
|
|
235
|
-
useSessionStore.getState().triggerSessionUpdate(get().activeId);
|
|
236
|
-
|
|
237
|
-
const id = await get().internal_createMessage(newMessage, {
|
|
238
|
-
tempMessageId,
|
|
239
|
-
skipRefresh: !onlyAddUserMessage && newMessage.fileList?.length === 0,
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
if (!id) {
|
|
243
|
-
set({ isCreatingMessage: false }, false, n('creatingMessage/start'));
|
|
244
|
-
if (!!newTopicId) get().internal_updateTopicLoading(newTopicId, false);
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (tempMessageId) get().internal_toggleMessageLoading(false, tempMessageId);
|
|
249
|
-
|
|
250
|
-
// switch to the new topic if create the new topic
|
|
251
|
-
if (!!newTopicId) {
|
|
252
|
-
await get().switchTopic(newTopicId, true);
|
|
253
|
-
await get().internal_fetchMessages();
|
|
254
|
-
|
|
255
|
-
// delete previous messages
|
|
256
|
-
// remove the temp message map
|
|
257
|
-
const newMaps = { ...get().messagesMap, [messageMapKey(activeId, null)]: [] };
|
|
258
|
-
set({ messagesMap: newMaps }, false, 'internal_copyMessages');
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// if only add user message, then stop
|
|
262
|
-
if (onlyAddUserMessage) {
|
|
263
|
-
set({ isCreatingMessage: false }, false, 'creatingMessage/start');
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Get the current messages to generate AI response
|
|
268
|
-
const messages = chatSelectors.activeBaseChats(get());
|
|
269
|
-
const userFiles = chatSelectors.currentUserFiles(get()).map((f) => f.id);
|
|
270
|
-
|
|
271
|
-
await internal_coreProcessMessage(messages, id, {
|
|
272
|
-
isWelcomeQuestion,
|
|
273
|
-
ragQuery: get().internal_shouldUseRAG() ? message : undefined,
|
|
274
|
-
threadId: activeThreadId,
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
set({ isCreatingMessage: false }, false, n('creatingMessage/stop'));
|
|
278
|
-
|
|
279
|
-
const summaryTitle = async () => {
|
|
280
|
-
// if autoCreateTopic is false, then stop
|
|
281
|
-
if (!agentConfig.enableAutoCreateTopic) return;
|
|
282
|
-
|
|
283
|
-
// check activeTopic and then auto update topic title
|
|
284
|
-
if (newTopicId) {
|
|
285
|
-
const chats = chatSelectors.getBaseChatsByKey(messageMapKey(activeId, newTopicId))(get());
|
|
286
|
-
await get().summaryTopicTitle(newTopicId, chats);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (!activeTopicId) return;
|
|
291
|
-
const topic = topicSelectors.getTopicById(activeTopicId)(get());
|
|
292
|
-
|
|
293
|
-
if (topic && !topic.title) {
|
|
294
|
-
const chats = chatSelectors.getBaseChatsByKey(messageMapKey(activeId, topic.id))(get());
|
|
295
|
-
await get().summaryTopicTitle(topic.id, chats);
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
// if there is relative files, then add files to agent
|
|
300
|
-
// only available in server mode
|
|
301
|
-
const addFilesToAgent = async () => {
|
|
302
|
-
if (userFiles.length === 0 || !isServerMode) return;
|
|
303
|
-
|
|
304
|
-
await useAgentStore.getState().addFilesToAgent(userFiles, false);
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
await Promise.all([summaryTitle(), addFilesToAgent()]);
|
|
308
171
|
},
|
|
309
172
|
stopGenerateMessage: () => {
|
|
310
173
|
const { chatLoadingIdsAbortController, internal_toggleChatLoading } = get();
|
|
@@ -4,7 +4,6 @@ import { withSWR } from '~test-utils';
|
|
|
4
4
|
|
|
5
5
|
import { DEFAULT_PREFERENCE } from '@/const/user';
|
|
6
6
|
import { userService } from '@/services/user';
|
|
7
|
-
import { ClientService } from '@/services/user/_deprecated';
|
|
8
7
|
import { useUserStore } from '@/store/user';
|
|
9
8
|
import { preferenceSelectors } from '@/store/user/selectors';
|
|
10
9
|
import { GlobalServerConfig } from '@/types/serverConfig';
|
|
@@ -31,9 +30,7 @@ describe('createCommonSlice', () => {
|
|
|
31
30
|
const avatar = 'data:image/png;base64,';
|
|
32
31
|
|
|
33
32
|
const spyOn = vi.spyOn(result.current, 'refreshUserState');
|
|
34
|
-
const updateAvatarSpy = vi
|
|
35
|
-
.spyOn(ClientService.prototype, 'updateAvatar')
|
|
36
|
-
.mockResolvedValue(undefined);
|
|
33
|
+
const updateAvatarSpy = vi.spyOn(userService, 'updateAvatar').mockResolvedValue(undefined);
|
|
37
34
|
|
|
38
35
|
await act(async () => {
|
|
39
36
|
await result.current.updateAvatar(avatar);
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
|
|
2
|
-
import type { NextRequest } from 'next/server';
|
|
3
|
-
|
|
4
|
-
import { pino } from '@/libs/logger';
|
|
5
|
-
import { createEdgeContext } from '@/libs/trpc/edge/context';
|
|
6
|
-
import { edgeRouter } from '@/server/routers/edge';
|
|
7
|
-
|
|
8
|
-
const handler = (req: NextRequest) =>
|
|
9
|
-
fetchRequestHandler({
|
|
10
|
-
/**
|
|
11
|
-
* @link https://trpc.io/docs/v11/context
|
|
12
|
-
*/
|
|
13
|
-
createContext: () => createEdgeContext(req),
|
|
14
|
-
|
|
15
|
-
endpoint: '/trpc/edge',
|
|
16
|
-
|
|
17
|
-
onError: ({ error, path }) => {
|
|
18
|
-
pino.info(`Error in tRPC handler (edge) on path: ${path}`);
|
|
19
|
-
console.error(error);
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
req,
|
|
23
|
-
router: edgeRouter,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
export { handler as GET, handler as POST };
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { memo } from 'react';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
|
|
6
|
-
import Cell, { CellProps } from '@/components/Cell';
|
|
7
|
-
import DataImporter from '@/features/DataImporter';
|
|
8
|
-
import { configService } from '@/services/export/_deprecated';
|
|
9
|
-
|
|
10
|
-
const Category = memo(() => {
|
|
11
|
-
const { t } = useTranslation('common');
|
|
12
|
-
const items: CellProps[] = [
|
|
13
|
-
{
|
|
14
|
-
key: 'allAgent',
|
|
15
|
-
label: t('exportType.allAgent'),
|
|
16
|
-
onClick: configService.exportAgents,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
key: 'allAgentWithMessage',
|
|
20
|
-
label: t('exportType.allAgentWithMessage'),
|
|
21
|
-
onClick: configService.exportSessions,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
key: 'globalSetting',
|
|
25
|
-
label: t('exportType.globalSetting'),
|
|
26
|
-
onClick: configService.exportSettings,
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
type: 'divider',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
key: 'all',
|
|
33
|
-
label: t('exportType.all'),
|
|
34
|
-
onClick: configService.exportAll,
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
type: 'divider',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
key: 'import',
|
|
41
|
-
label: <DataImporter>{t('importData')}</DataImporter>,
|
|
42
|
-
},
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
return items?.map(({ key, ...item }, index) => <Cell key={key || index} {...item} />);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
export default Category;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { ChatHeader } from '@lobehub/ui/mobile';
|
|
4
|
-
import { useRouter } from 'next/navigation';
|
|
5
|
-
import { memo } from 'react';
|
|
6
|
-
import { useTranslation } from 'react-i18next';
|
|
7
|
-
import { Flexbox } from 'react-layout-kit';
|
|
8
|
-
|
|
9
|
-
import { mobileHeaderSticky } from '@/styles/mobileHeader';
|
|
10
|
-
|
|
11
|
-
const Header = memo(() => {
|
|
12
|
-
const { t } = useTranslation('common');
|
|
13
|
-
|
|
14
|
-
const router = useRouter();
|
|
15
|
-
return (
|
|
16
|
-
<ChatHeader
|
|
17
|
-
center={
|
|
18
|
-
<ChatHeader.Title
|
|
19
|
-
title={
|
|
20
|
-
<Flexbox align={'center'} gap={4} horizontal>
|
|
21
|
-
{t('userPanel.data')}
|
|
22
|
-
</Flexbox>
|
|
23
|
-
}
|
|
24
|
-
/>
|
|
25
|
-
}
|
|
26
|
-
onBackClick={() => router.push('/me')}
|
|
27
|
-
showBackButton
|
|
28
|
-
style={mobileHeaderSticky}
|
|
29
|
-
/>
|
|
30
|
-
);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
export default Header;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { PropsWithChildren } from 'react';
|
|
2
|
-
|
|
3
|
-
import MobileContentLayout from '@/components/server/MobileNavLayout';
|
|
4
|
-
|
|
5
|
-
import Header from './features/Header';
|
|
6
|
-
|
|
7
|
-
const Layout = ({ children }: PropsWithChildren) => {
|
|
8
|
-
return <MobileContentLayout header={<Header />}>{children}</MobileContentLayout>;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
Layout.displayName = 'MeDataLayout';
|
|
12
|
-
|
|
13
|
-
export default Layout;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { redirect } from 'next/navigation';
|
|
2
|
-
|
|
3
|
-
import { metadataModule } from '@/server/metadata';
|
|
4
|
-
import { translation } from '@/server/translation';
|
|
5
|
-
import { DynamicLayoutProps } from '@/types/next';
|
|
6
|
-
import { RouteVariants } from '@/utils/server/routeVariants';
|
|
7
|
-
|
|
8
|
-
import Category from './features/Category';
|
|
9
|
-
|
|
10
|
-
export const generateMetadata = async (props: DynamicLayoutProps) => {
|
|
11
|
-
const locale = await RouteVariants.getLocale(props);
|
|
12
|
-
const { t } = await translation('common', locale);
|
|
13
|
-
return metadataModule.generate({
|
|
14
|
-
title: t('userPanel.data'),
|
|
15
|
-
url: '/me/data',
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const Page = async (props: DynamicLayoutProps) => {
|
|
20
|
-
const mobile = await RouteVariants.getIsMobile(props);
|
|
21
|
-
|
|
22
|
-
if (!mobile) return redirect('/chat');
|
|
23
|
-
|
|
24
|
-
return <Category />;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
Page.displayName = 'MeData';
|
|
28
|
-
|
|
29
|
-
export default Page;
|