@lobehub/chat 1.76.1 → 1.77.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/common.json +13 -2
- package/locales/ar/error.json +10 -0
- package/locales/ar/models.json +9 -6
- package/locales/ar/setting.json +28 -0
- package/locales/bg-BG/common.json +13 -2
- package/locales/bg-BG/error.json +10 -0
- package/locales/bg-BG/models.json +9 -6
- package/locales/bg-BG/setting.json +28 -0
- package/locales/de-DE/common.json +13 -2
- package/locales/de-DE/error.json +10 -0
- package/locales/de-DE/models.json +9 -6
- package/locales/de-DE/setting.json +28 -0
- package/locales/en-US/common.json +13 -2
- package/locales/en-US/error.json +10 -0
- package/locales/en-US/models.json +9 -6
- package/locales/en-US/setting.json +28 -0
- package/locales/es-ES/common.json +13 -2
- package/locales/es-ES/error.json +10 -0
- package/locales/es-ES/models.json +9 -6
- package/locales/es-ES/setting.json +28 -0
- package/locales/fa-IR/common.json +13 -2
- package/locales/fa-IR/error.json +10 -0
- package/locales/fa-IR/models.json +9 -6
- package/locales/fa-IR/setting.json +28 -0
- package/locales/fr-FR/common.json +13 -2
- package/locales/fr-FR/error.json +10 -0
- package/locales/fr-FR/models.json +9 -6
- package/locales/fr-FR/setting.json +28 -0
- package/locales/it-IT/common.json +13 -2
- package/locales/it-IT/error.json +10 -0
- package/locales/it-IT/models.json +9 -6
- package/locales/it-IT/setting.json +28 -0
- package/locales/ja-JP/common.json +13 -2
- package/locales/ja-JP/error.json +10 -0
- package/locales/ja-JP/models.json +9 -6
- package/locales/ja-JP/setting.json +28 -0
- package/locales/ko-KR/common.json +13 -2
- package/locales/ko-KR/error.json +10 -0
- package/locales/ko-KR/models.json +9 -6
- package/locales/ko-KR/setting.json +28 -0
- package/locales/nl-NL/common.json +13 -2
- package/locales/nl-NL/error.json +10 -0
- package/locales/nl-NL/models.json +9 -6
- package/locales/nl-NL/setting.json +28 -0
- package/locales/pl-PL/common.json +13 -2
- package/locales/pl-PL/error.json +10 -0
- package/locales/pl-PL/models.json +9 -6
- package/locales/pl-PL/setting.json +28 -0
- package/locales/pt-BR/common.json +13 -2
- package/locales/pt-BR/error.json +10 -0
- package/locales/pt-BR/models.json +9 -6
- package/locales/pt-BR/setting.json +28 -0
- package/locales/ru-RU/common.json +13 -2
- package/locales/ru-RU/error.json +10 -0
- package/locales/ru-RU/models.json +9 -6
- package/locales/ru-RU/setting.json +28 -0
- package/locales/tr-TR/common.json +13 -2
- package/locales/tr-TR/error.json +10 -0
- package/locales/tr-TR/models.json +9 -6
- package/locales/tr-TR/setting.json +28 -0
- package/locales/vi-VN/common.json +13 -2
- package/locales/vi-VN/error.json +10 -0
- package/locales/vi-VN/models.json +9 -6
- package/locales/vi-VN/setting.json +28 -0
- package/locales/zh-CN/common.json +13 -2
- package/locales/zh-CN/error.json +10 -0
- package/locales/zh-CN/models.json +10 -7
- package/locales/zh-CN/setting.json +28 -0
- package/locales/zh-TW/common.json +13 -2
- package/locales/zh-TW/error.json +10 -0
- package/locales/zh-TW/models.json +9 -6
- package/locales/zh-TW/setting.json +28 -0
- package/package.json +1 -1
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +2 -2
- package/src/app/[variants]/(main)/chat/features/Migration/UpgradeButton.tsx +2 -1
- package/src/app/[variants]/(main)/settings/common/features/Common.tsx +0 -44
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +40 -14
- package/src/app/[variants]/(main)/settings/storage/Advanced.tsx +108 -0
- package/src/app/[variants]/(main)/settings/storage/IndexedDBStorage.tsx +55 -0
- package/src/app/[variants]/(main)/settings/storage/page.tsx +17 -0
- package/src/components/GroupIcon/index.tsx +25 -0
- package/src/components/IndexCard/index.tsx +143 -0
- package/src/components/ProgressItem/index.tsx +75 -0
- package/src/database/models/__tests__/session.test.ts +21 -0
- package/src/database/repositories/dataExporter/index.test.ts +330 -0
- package/src/database/repositories/dataExporter/index.ts +216 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/agents.json +65 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/agentsToSessions.json +541 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/topic.json +269 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/userSettings.json +18 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/with-client-id.json +778 -0
- package/src/database/repositories/dataImporter/__tests__/index.test.ts +120 -880
- package/src/database/repositories/dataImporter/deprecated/__tests__/index.test.ts +940 -0
- package/src/database/repositories/dataImporter/deprecated/index.ts +326 -0
- package/src/database/repositories/dataImporter/index.ts +684 -289
- package/src/database/server/models/session.ts +85 -9
- package/src/features/DataImporter/ImportDetail.tsx +203 -0
- package/src/features/DataImporter/SuccessResult.tsx +22 -6
- package/src/features/DataImporter/_deprecated.ts +43 -0
- package/src/features/DataImporter/config.ts +21 -0
- package/src/features/DataImporter/index.tsx +112 -31
- package/src/features/DevPanel/PostgresViewer/DataTable/index.tsx +6 -0
- package/src/features/User/UserPanel/useMenu.tsx +1 -36
- package/src/features/User/__tests__/useMenu.test.tsx +0 -2
- package/src/locales/default/common.ts +12 -1
- package/src/locales/default/error.ts +10 -0
- package/src/locales/default/setting.ts +28 -0
- package/src/server/routers/lambda/exporter.ts +25 -0
- package/src/server/routers/lambda/importer.ts +19 -3
- package/src/server/routers/lambda/index.ts +2 -0
- package/src/services/config.ts +80 -135
- package/src/services/export/_deprecated.ts +155 -0
- package/src/services/export/client.ts +15 -0
- package/src/services/export/index.ts +6 -0
- package/src/services/export/server.ts +9 -0
- package/src/services/export/type.ts +5 -0
- package/src/services/import/_deprecated.ts +42 -1
- package/src/services/import/client.test.ts +1 -1
- package/src/services/import/client.ts +30 -1
- package/src/services/import/server.ts +70 -2
- package/src/services/import/type.ts +10 -0
- package/src/store/global/initialState.ts +1 -0
- package/src/types/export.ts +11 -0
- package/src/types/exportConfig.ts +2 -0
- package/src/types/importer.ts +15 -0
- package/src/utils/client/exportFile.ts +21 -0
- package/vitest.config.ts +1 -1
- package/src/utils/config.ts +0 -109
- /package/src/database/repositories/dataImporter/{__tests__ → deprecated/__tests__}/fixtures/messages.json +0 -0
@@ -9,7 +9,6 @@ import {
|
|
9
9
|
Feather,
|
10
10
|
FileClockIcon,
|
11
11
|
HardDriveDownload,
|
12
|
-
HardDriveUpload,
|
13
12
|
LifeBuoy,
|
14
13
|
LogOut,
|
15
14
|
Mail,
|
@@ -32,10 +31,8 @@ import {
|
|
32
31
|
UTM_SOURCE,
|
33
32
|
mailTo,
|
34
33
|
} from '@/const/url';
|
35
|
-
import { isServerMode } from '@/const/version';
|
36
34
|
import DataImporter from '@/features/DataImporter';
|
37
35
|
import { usePWAInstall } from '@/hooks/usePWAInstall';
|
38
|
-
import { configService } from '@/services/config';
|
39
36
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
40
37
|
import { useUserStore } from '@/store/user';
|
41
38
|
import { authSelectors } from '@/store/user/selectors';
|
@@ -119,40 +116,8 @@ export const useMenu = () => {
|
|
119
116
|
{
|
120
117
|
icon: <Icon icon={HardDriveDownload} />,
|
121
118
|
key: 'import',
|
122
|
-
label: <DataImporter>{t('
|
119
|
+
label: <DataImporter>{t('importData')}</DataImporter>,
|
123
120
|
},
|
124
|
-
isServerMode
|
125
|
-
? null
|
126
|
-
: {
|
127
|
-
children: [
|
128
|
-
{
|
129
|
-
key: 'allAgent',
|
130
|
-
label: t('exportType.allAgent'),
|
131
|
-
onClick: configService.exportAgents,
|
132
|
-
},
|
133
|
-
{
|
134
|
-
key: 'allAgentWithMessage',
|
135
|
-
label: t('exportType.allAgentWithMessage'),
|
136
|
-
onClick: configService.exportSessions,
|
137
|
-
},
|
138
|
-
{
|
139
|
-
key: 'globalSetting',
|
140
|
-
label: t('exportType.globalSetting'),
|
141
|
-
onClick: configService.exportSettings,
|
142
|
-
},
|
143
|
-
{
|
144
|
-
type: 'divider',
|
145
|
-
},
|
146
|
-
{
|
147
|
-
key: 'all',
|
148
|
-
label: t('exportType.all'),
|
149
|
-
onClick: configService.exportAll,
|
150
|
-
},
|
151
|
-
],
|
152
|
-
icon: <Icon icon={HardDriveUpload} />,
|
153
|
-
key: 'export',
|
154
|
-
label: t('export'),
|
155
|
-
},
|
156
121
|
{
|
157
122
|
type: 'divider',
|
158
123
|
},
|
@@ -81,7 +81,6 @@ describe('useMenu', () => {
|
|
81
81
|
expect(mainItems?.some((item) => item?.key === 'profile')).toBe(true);
|
82
82
|
expect(mainItems?.some((item) => item?.key === 'setting')).toBe(true);
|
83
83
|
expect(mainItems?.some((item) => item?.key === 'import')).toBe(true);
|
84
|
-
expect(mainItems?.some((item) => item?.key === 'export')).toBe(true);
|
85
84
|
expect(mainItems?.some((item) => item?.key === 'changelog')).toBe(true);
|
86
85
|
expect(logoutItems.some((item) => item?.key === 'logout')).toBe(true);
|
87
86
|
});
|
@@ -100,7 +99,6 @@ describe('useMenu', () => {
|
|
100
99
|
expect(mainItems?.some((item) => item?.key === 'profile')).toBe(true);
|
101
100
|
expect(mainItems?.some((item) => item?.key === 'setting')).toBe(true);
|
102
101
|
expect(mainItems?.some((item) => item?.key === 'import')).toBe(true);
|
103
|
-
expect(mainItems?.some((item) => item?.key === 'export')).toBe(true);
|
104
102
|
expect(mainItems?.some((item) => item?.key === 'changelog')).toBe(true);
|
105
103
|
expect(logoutItems.some((item) => item?.key === 'logout')).toBe(false);
|
106
104
|
});
|
@@ -186,7 +186,7 @@ export default {
|
|
186
186
|
},
|
187
187
|
fullscreen: '全屏模式',
|
188
188
|
historyRange: '历史范围',
|
189
|
-
|
189
|
+
importData: '导入数据',
|
190
190
|
importModal: {
|
191
191
|
error: {
|
192
192
|
desc: '非常抱歉,数据导入过程发生异常。请尝试重新导入,或 <1>提交问题</1>,我们将会第一时间帮你排查问题。',
|
@@ -209,6 +209,7 @@ export default {
|
|
209
209
|
skips: '重复跳过',
|
210
210
|
topics: '话题',
|
211
211
|
type: '数据类型',
|
212
|
+
update: '记录更新',
|
212
213
|
},
|
213
214
|
title: '导入数据',
|
214
215
|
uploading: {
|
@@ -217,6 +218,16 @@ export default {
|
|
217
218
|
speed: '上传速度',
|
218
219
|
},
|
219
220
|
},
|
221
|
+
importPreview: {
|
222
|
+
confirmImport: '确认导入',
|
223
|
+
tables: {
|
224
|
+
count: '记录数',
|
225
|
+
name: '表名',
|
226
|
+
},
|
227
|
+
title: '导入数据预览',
|
228
|
+
totalRecords: '总计将导入 {{count}} 条记录',
|
229
|
+
totalTables: '{{count}} 个表',
|
230
|
+
},
|
220
231
|
information: '社区与资讯',
|
221
232
|
installPWA: '安装浏览器应用 (PWA)',
|
222
233
|
lang: {
|
@@ -16,6 +16,16 @@ export default {
|
|
16
16
|
detail: '错误详情',
|
17
17
|
title: '请求失败',
|
18
18
|
},
|
19
|
+
import: {
|
20
|
+
importConfigFile: {
|
21
|
+
description: '出错原因: {{reason}}',
|
22
|
+
title: '导入失败',
|
23
|
+
},
|
24
|
+
incompatible: {
|
25
|
+
description: '该文件由更高版本导出,请尝试升级到最新版本后再重新导入',
|
26
|
+
title: '当前应用不支持导入该文件',
|
27
|
+
},
|
28
|
+
},
|
19
29
|
loginRequired: {
|
20
30
|
desc: '即将自动跳转到登录页面',
|
21
31
|
title: '请登录后使用该功能',
|
@@ -348,6 +348,33 @@ export default {
|
|
348
348
|
},
|
349
349
|
title: '主题设置',
|
350
350
|
},
|
351
|
+
storage: {
|
352
|
+
actions: {
|
353
|
+
export: {
|
354
|
+
button: '导出',
|
355
|
+
exportType: {
|
356
|
+
agent: '导出助手设定',
|
357
|
+
agentWithMessage: '导出助手和消息',
|
358
|
+
all: '导出全局设置和所有助手数据',
|
359
|
+
allAgent: '导出所有助手设定',
|
360
|
+
allAgentWithMessage: '导出所有助手和消息',
|
361
|
+
globalSetting: '导出全局设置',
|
362
|
+
},
|
363
|
+
title: '导出数据',
|
364
|
+
},
|
365
|
+
import: {
|
366
|
+
button: '导入',
|
367
|
+
title: '导入数据',
|
368
|
+
},
|
369
|
+
title: '高级操作',
|
370
|
+
},
|
371
|
+
desc: '当前浏览器中的存储用量',
|
372
|
+
embeddings: {
|
373
|
+
used: '向量存储',
|
374
|
+
},
|
375
|
+
title: '数据存储',
|
376
|
+
used: '存储用量',
|
377
|
+
},
|
351
378
|
submitAgentModal: {
|
352
379
|
button: '提交助手',
|
353
380
|
identifier: 'identifier 助手标识符',
|
@@ -441,6 +468,7 @@ export default {
|
|
441
468
|
'hotkey': '快捷键',
|
442
469
|
'llm': '语言模型',
|
443
470
|
'provider': 'AI 服务商',
|
471
|
+
'storage': '数据存储',
|
444
472
|
'sync': '云端同步',
|
445
473
|
'system-agent': '系统助手',
|
446
474
|
'tts': '语音服务',
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { DrizzleMigrationModel } from '@/database/models/drizzleMigration';
|
2
|
+
import { DataExporterRepos } from '@/database/repositories/dataExporter';
|
3
|
+
import { serverDB } from '@/database/server';
|
4
|
+
import { authedProcedure, router } from '@/libs/trpc';
|
5
|
+
import { ExportDatabaseData } from '@/types/export';
|
6
|
+
|
7
|
+
const exportProcedure = authedProcedure.use(async (opts) => {
|
8
|
+
const { ctx } = opts;
|
9
|
+
const dataExporterRepos = new DataExporterRepos(serverDB, ctx.userId);
|
10
|
+
const drizzleMigration = new DrizzleMigrationModel(serverDB);
|
11
|
+
|
12
|
+
return opts.next({
|
13
|
+
ctx: { dataExporterRepos, drizzleMigration },
|
14
|
+
});
|
15
|
+
});
|
16
|
+
|
17
|
+
export const exporterRouter = router({
|
18
|
+
exportData: exportProcedure.mutation(async ({ ctx }): Promise<ExportDatabaseData> => {
|
19
|
+
const data = await ctx.dataExporterRepos.export(5);
|
20
|
+
|
21
|
+
const schemaHash = await ctx.drizzleMigration.getLatestMigrationHash();
|
22
|
+
|
23
|
+
return { data, schemaHash };
|
24
|
+
}),
|
25
|
+
});
|
@@ -5,7 +5,8 @@ import { DataImporterRepos } from '@/database/repositories/dataImporter';
|
|
5
5
|
import { serverDB } from '@/database/server';
|
6
6
|
import { authedProcedure, router } from '@/libs/trpc';
|
7
7
|
import { S3 } from '@/server/modules/S3';
|
8
|
-
import {
|
8
|
+
import { ImportPgDataStructure } from '@/types/export';
|
9
|
+
import { ImportResultData, ImporterEntryData } from '@/types/importer';
|
9
10
|
|
10
11
|
const importProcedure = authedProcedure.use(async (opts) => {
|
11
12
|
const { ctx } = opts;
|
@@ -19,7 +20,7 @@ const importProcedure = authedProcedure.use(async (opts) => {
|
|
19
20
|
export const importerRouter = router({
|
20
21
|
importByFile: importProcedure
|
21
22
|
.input(z.object({ pathname: z.string() }))
|
22
|
-
.mutation(async ({ input, ctx }): Promise<
|
23
|
+
.mutation(async ({ input, ctx }): Promise<ImportResultData> => {
|
23
24
|
let data: ImporterEntryData | undefined;
|
24
25
|
|
25
26
|
try {
|
@@ -37,6 +38,10 @@ export const importerRouter = router({
|
|
37
38
|
});
|
38
39
|
}
|
39
40
|
|
41
|
+
if ('schemaHash' in data) {
|
42
|
+
return ctx.dataImporterService.importPgData(data as unknown as ImportPgDataStructure);
|
43
|
+
}
|
44
|
+
|
40
45
|
return ctx.dataImporterService.importData(data);
|
41
46
|
}),
|
42
47
|
|
@@ -52,7 +57,18 @@ export const importerRouter = router({
|
|
52
57
|
}),
|
53
58
|
}),
|
54
59
|
)
|
55
|
-
.mutation(async ({ input, ctx }): Promise<
|
60
|
+
.mutation(async ({ input, ctx }): Promise<ImportResultData> => {
|
56
61
|
return ctx.dataImporterService.importData(input.data);
|
57
62
|
}),
|
63
|
+
importPgByPost: importProcedure
|
64
|
+
.input(
|
65
|
+
z.object({
|
66
|
+
data: z.record(z.string(), z.array(z.any())),
|
67
|
+
mode: z.enum(['pglite', 'postgres']),
|
68
|
+
schemaHash: z.string(),
|
69
|
+
}),
|
70
|
+
)
|
71
|
+
.mutation(async ({ input, ctx }): Promise<ImportResultData> => {
|
72
|
+
return ctx.dataImporterService.importPgData(input);
|
73
|
+
}),
|
58
74
|
});
|
@@ -7,6 +7,7 @@ import { agentRouter } from './agent';
|
|
7
7
|
import { aiModelRouter } from './aiModel';
|
8
8
|
import { aiProviderRouter } from './aiProvider';
|
9
9
|
import { chunkRouter } from './chunk';
|
10
|
+
import { exporterRouter } from './exporter';
|
10
11
|
import { fileRouter } from './file';
|
11
12
|
import { importerRouter } from './importer';
|
12
13
|
import { knowledgeBaseRouter } from './knowledgeBase';
|
@@ -24,6 +25,7 @@ export const lambdaRouter = router({
|
|
24
25
|
aiModel: aiModelRouter,
|
25
26
|
aiProvider: aiProviderRouter,
|
26
27
|
chunk: chunkRouter,
|
28
|
+
exporter: exporterRouter,
|
27
29
|
file: fileRouter,
|
28
30
|
healthcheck: publicProcedure.query(() => "i'm live!"),
|
29
31
|
importer: importerRouter,
|
package/src/services/config.ts
CHANGED
@@ -1,162 +1,107 @@
|
|
1
|
-
import
|
2
|
-
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import {
|
6
|
-
import {
|
7
|
-
import {
|
8
|
-
import {
|
9
|
-
|
10
|
-
import {
|
11
|
-
import {
|
12
|
-
|
13
|
-
export interface ImportResult {
|
14
|
-
added: number;
|
15
|
-
errors: number;
|
16
|
-
skips: number;
|
17
|
-
}
|
18
|
-
export interface ImportResults {
|
19
|
-
messages?: ImportResult;
|
20
|
-
sessionGroups?: ImportResult;
|
21
|
-
sessions?: ImportResult;
|
22
|
-
topics?: ImportResult;
|
23
|
-
type?: string;
|
24
|
-
}
|
1
|
+
import dayjs from 'dayjs';
|
2
|
+
|
3
|
+
import { BRANDING_NAME } from '@/const/branding';
|
4
|
+
import { isDeprecatedEdition, isServerMode } from '@/const/version';
|
5
|
+
import { CURRENT_CONFIG_VERSION } from '@/migrations';
|
6
|
+
import { ImportPgDataStructure } from '@/types/export';
|
7
|
+
import { downloadFile } from '@/utils/client/downloadFile';
|
8
|
+
import { exportJSONFile } from '@/utils/client/exportFile';
|
9
|
+
|
10
|
+
import { exportService } from './export';
|
11
|
+
import { configService as deprecatedExportService } from './export/_deprecated';
|
25
12
|
|
26
|
-
/**
|
27
|
-
* @deprecated
|
28
|
-
*/
|
29
13
|
class ConfigService {
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
14
|
+
exportAll = async () => {
|
15
|
+
// TODO: remove this in V2
|
16
|
+
if (isDeprecatedEdition) {
|
17
|
+
const config = await deprecatedExportService.exportAll();
|
18
|
+
const filename = `${BRANDING_NAME}-config-v${CURRENT_CONFIG_VERSION}.json`;
|
19
|
+
exportJSONFile(config, filename);
|
34
20
|
return;
|
35
21
|
}
|
36
22
|
|
37
|
-
|
38
|
-
|
39
|
-
}
|
40
|
-
|
41
|
-
await importService.importData(
|
42
|
-
{
|
43
|
-
messages: (config.state as any).messages || [],
|
44
|
-
sessionGroups: (config.state as any).sessionGroups || [],
|
45
|
-
sessions: (config.state as any).sessions || [],
|
46
|
-
topics: (config.state as any).topics || [],
|
47
|
-
version: config.version,
|
48
|
-
},
|
49
|
-
callbacks,
|
50
|
-
);
|
51
|
-
};
|
52
|
-
|
53
|
-
// TODO: Separate export feature into a new service like importService
|
54
|
-
|
55
|
-
/**
|
56
|
-
* export all agents
|
57
|
-
*/
|
58
|
-
exportAgents = async () => {
|
59
|
-
const agents = await sessionService.getSessionsByType('agent');
|
60
|
-
const sessionGroups = await sessionService.getSessionGroups();
|
61
|
-
|
62
|
-
const config = createConfigFile('agents', { sessionGroups, sessions: agents });
|
63
|
-
|
64
|
-
exportConfigFile(config, 'agents');
|
65
|
-
};
|
23
|
+
const { data, url } = await exportService.exportData();
|
24
|
+
const filename = `${dayjs().format('YYYY-MM-DD-hh-mm')}_${BRANDING_NAME}-data.json`;
|
66
25
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
const messages = await messageService.getAllMessages();
|
74
|
-
const topics = await topicService.getAllTopics();
|
26
|
+
// if url exists, means export data from server and upload the data to S3
|
27
|
+
// just need to download the file
|
28
|
+
if (url) {
|
29
|
+
await downloadFile(url, filename);
|
30
|
+
return;
|
31
|
+
}
|
75
32
|
|
76
|
-
|
33
|
+
// or export to file with the data
|
34
|
+
const result = await this.createDataStructure(data, isServerMode ? 'postgres' : 'pglite');
|
77
35
|
|
78
|
-
|
36
|
+
exportJSONFile(result, filename);
|
79
37
|
};
|
80
38
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
const topics = await topicService.getTopics({ sessionId: id });
|
90
|
-
|
91
|
-
const config = createConfigFile('singleSession', { messages, sessions: [session], topics });
|
92
|
-
|
93
|
-
exportConfigFile(config, `${session.meta?.title}-session`);
|
39
|
+
exportAgents = async () => {
|
40
|
+
// TODO: remove this in V2
|
41
|
+
if (isDeprecatedEdition) {
|
42
|
+
const config = await deprecatedExportService.exportAgents();
|
43
|
+
const filename = `${BRANDING_NAME}-agents-v${CURRENT_CONFIG_VERSION}.json`;
|
44
|
+
exportJSONFile(config, filename);
|
45
|
+
return;
|
46
|
+
}
|
94
47
|
};
|
95
48
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
if (!session) return;
|
102
|
-
|
103
|
-
const messages = await messageService.getMessages(sessionId, topicId);
|
104
|
-
const topics = await topicService.getTopics({ sessionId });
|
105
|
-
|
106
|
-
const topic = topics.find((item) => item.id === topicId);
|
107
|
-
if (!topic) return;
|
49
|
+
exportSingleAgent = async (agentId: string) => {
|
50
|
+
// TODO: remove this in V2
|
51
|
+
if (isDeprecatedEdition) {
|
52
|
+
const result = await deprecatedExportService.exportSingleAgent(agentId);
|
53
|
+
if (!result) return;
|
108
54
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
});
|
114
|
-
|
115
|
-
exportConfigFile(config, `${topic.title}-topic`);
|
55
|
+
const filename = `${BRANDING_NAME}-${result.title}-v${CURRENT_CONFIG_VERSION}.json`;
|
56
|
+
exportJSONFile(result.config, filename);
|
57
|
+
return;
|
58
|
+
}
|
116
59
|
};
|
117
60
|
|
118
|
-
|
119
|
-
|
120
|
-
if (
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
61
|
+
exportSessions = async () => {
|
62
|
+
// TODO: remove this in V2
|
63
|
+
if (isDeprecatedEdition) {
|
64
|
+
const config = await deprecatedExportService.exportSessions();
|
65
|
+
const filename = `${BRANDING_NAME}-sessions-v${CURRENT_CONFIG_VERSION}.json`;
|
66
|
+
exportJSONFile(config, filename);
|
67
|
+
return;
|
68
|
+
}
|
125
69
|
};
|
126
70
|
|
127
|
-
/**
|
128
|
-
* export settings
|
129
|
-
*/
|
130
71
|
exportSettings = async () => {
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
72
|
+
// TODO: remove this in V2
|
73
|
+
if (isDeprecatedEdition) {
|
74
|
+
const config = await deprecatedExportService.exportSessions();
|
75
|
+
const filename = `${BRANDING_NAME}-settings-v${CURRENT_CONFIG_VERSION}.json`;
|
76
|
+
exportJSONFile(config, filename);
|
77
|
+
return;
|
78
|
+
}
|
136
79
|
};
|
137
80
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
const sessionGroups = await sessionService.getSessionGroups();
|
144
|
-
const messages = await messageService.getAllMessages();
|
145
|
-
const topics = await topicService.getAllTopics();
|
146
|
-
const settings = this.getSettings();
|
147
|
-
|
148
|
-
const config = createConfigFile('all', { messages, sessionGroups, sessions, settings, topics });
|
81
|
+
exportSingleSession = async (sessionId: string) => {
|
82
|
+
// TODO: remove this in V2
|
83
|
+
if (isDeprecatedEdition) {
|
84
|
+
const data = await deprecatedExportService.exportSingleSession(sessionId);
|
85
|
+
if (!data) return;
|
149
86
|
|
150
|
-
|
87
|
+
const filename = `${BRANDING_NAME}-${data.title}-v${CURRENT_CONFIG_VERSION}.json`;
|
88
|
+
exportJSONFile(data.config, filename);
|
89
|
+
return;
|
90
|
+
}
|
151
91
|
};
|
152
92
|
|
153
|
-
private
|
154
|
-
|
155
|
-
|
156
|
-
|
93
|
+
private createDataStructure = async (
|
94
|
+
data: any,
|
95
|
+
mode: 'pglite' | 'postgres',
|
96
|
+
): Promise<ImportPgDataStructure> => {
|
97
|
+
const { default: json } = await import('@/database/client/migrations.json');
|
98
|
+
const latestHash = json.at(-1)?.hash;
|
99
|
+
if (!latestHash) {
|
100
|
+
throw new Error('Not find database sql hash');
|
101
|
+
}
|
157
102
|
|
158
|
-
|
159
|
-
|
103
|
+
return { data, mode, schemaHash: latestHash };
|
104
|
+
};
|
160
105
|
}
|
161
106
|
|
162
107
|
export const configService = new ConfigService();
|
@@ -0,0 +1,155 @@
|
|
1
|
+
import { Migration } from '@/migrations';
|
2
|
+
import { messageService } from '@/services/message';
|
3
|
+
import { sessionService } from '@/services/session';
|
4
|
+
import { topicService } from '@/services/topic';
|
5
|
+
import { useSessionStore } from '@/store/session';
|
6
|
+
import { sessionSelectors } from '@/store/session/selectors';
|
7
|
+
import { useUserStore } from '@/store/user';
|
8
|
+
import { settingsSelectors } from '@/store/user/selectors';
|
9
|
+
import {
|
10
|
+
ConfigFileAgents,
|
11
|
+
ConfigFileAll,
|
12
|
+
ConfigFileSessions,
|
13
|
+
ConfigFileSettings,
|
14
|
+
ConfigFileSingleSession,
|
15
|
+
ConfigModelMap,
|
16
|
+
ExportType,
|
17
|
+
} from '@/types/exportConfig';
|
18
|
+
|
19
|
+
type CreateConfigFileState<T extends ExportType> = ConfigModelMap[T]['state'];
|
20
|
+
|
21
|
+
type CreateConfigFile<T extends ExportType> = ConfigModelMap[T]['file'];
|
22
|
+
|
23
|
+
const createConfigFile = <T extends ExportType>(
|
24
|
+
type: T,
|
25
|
+
state: CreateConfigFileState<T>,
|
26
|
+
): CreateConfigFile<T> => {
|
27
|
+
switch (type) {
|
28
|
+
case 'agents': {
|
29
|
+
return {
|
30
|
+
exportType: 'agents',
|
31
|
+
state,
|
32
|
+
version: Migration.targetVersion,
|
33
|
+
} as ConfigFileAgents;
|
34
|
+
}
|
35
|
+
|
36
|
+
case 'sessions': {
|
37
|
+
return {
|
38
|
+
exportType: 'sessions',
|
39
|
+
state,
|
40
|
+
version: Migration.targetVersion,
|
41
|
+
} as ConfigFileSessions;
|
42
|
+
}
|
43
|
+
|
44
|
+
case 'settings': {
|
45
|
+
return {
|
46
|
+
exportType: 'settings',
|
47
|
+
state,
|
48
|
+
version: Migration.targetVersion,
|
49
|
+
} as ConfigFileSettings;
|
50
|
+
}
|
51
|
+
|
52
|
+
case 'singleSession': {
|
53
|
+
return {
|
54
|
+
exportType: 'sessions',
|
55
|
+
state,
|
56
|
+
version: Migration.targetVersion,
|
57
|
+
} as ConfigFileSingleSession;
|
58
|
+
}
|
59
|
+
|
60
|
+
case 'all': {
|
61
|
+
return {
|
62
|
+
exportType: 'all',
|
63
|
+
state,
|
64
|
+
version: Migration.targetVersion,
|
65
|
+
} as ConfigFileAll;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
throw new Error('缺少正确的导出类型,请检查实现...');
|
70
|
+
};
|
71
|
+
|
72
|
+
/**
|
73
|
+
* @deprecated
|
74
|
+
*/
|
75
|
+
export class ConfigService {
|
76
|
+
/**
|
77
|
+
* export all agents
|
78
|
+
*/
|
79
|
+
exportAgents = async () => {
|
80
|
+
const agents = await sessionService.getSessionsByType('agent');
|
81
|
+
const sessionGroups = await sessionService.getSessionGroups();
|
82
|
+
|
83
|
+
return createConfigFile('agents', { sessionGroups, sessions: agents });
|
84
|
+
};
|
85
|
+
|
86
|
+
/**
|
87
|
+
* export all sessions
|
88
|
+
*/
|
89
|
+
exportSessions = async () => {
|
90
|
+
const sessions = await sessionService.getSessionsByType();
|
91
|
+
const sessionGroups = await sessionService.getSessionGroups();
|
92
|
+
const messages = await messageService.getAllMessages();
|
93
|
+
const topics = await topicService.getAllTopics();
|
94
|
+
|
95
|
+
return createConfigFile('sessions', { messages, sessionGroups, sessions, topics });
|
96
|
+
};
|
97
|
+
|
98
|
+
/**
|
99
|
+
* export a session
|
100
|
+
*/
|
101
|
+
exportSingleSession = async (id: string) => {
|
102
|
+
const session = this.getSession(id);
|
103
|
+
if (!session) return;
|
104
|
+
|
105
|
+
const messages = await messageService.getAllMessagesInSession(id);
|
106
|
+
const topics = await topicService.getTopics({ sessionId: id });
|
107
|
+
|
108
|
+
const config = createConfigFile('singleSession', { messages, sessions: [session], topics });
|
109
|
+
return { config, title: `${session.meta?.title}-session` };
|
110
|
+
};
|
111
|
+
|
112
|
+
exportSingleAgent = async (id: string) => {
|
113
|
+
const agent = this.getAgent(id);
|
114
|
+
if (!agent) return;
|
115
|
+
|
116
|
+
const config = createConfigFile('agents', { sessionGroups: [], sessions: [agent] });
|
117
|
+
|
118
|
+
return { config, title: `${agent.meta?.title}-session` };
|
119
|
+
};
|
120
|
+
|
121
|
+
/**
|
122
|
+
* export settings
|
123
|
+
*/
|
124
|
+
exportSettings = async () => {
|
125
|
+
const settings = this.getSettings();
|
126
|
+
|
127
|
+
return createConfigFile('settings', { settings });
|
128
|
+
};
|
129
|
+
|
130
|
+
/**
|
131
|
+
* export all data
|
132
|
+
*/
|
133
|
+
exportAll = async () => {
|
134
|
+
const sessions = await sessionService.getSessionsByType();
|
135
|
+
const sessionGroups = await sessionService.getSessionGroups();
|
136
|
+
const messages = await messageService.getAllMessages();
|
137
|
+
const topics = await topicService.getAllTopics();
|
138
|
+
const settings = this.getSettings();
|
139
|
+
|
140
|
+
return createConfigFile('all', { messages, sessionGroups, sessions, settings, topics });
|
141
|
+
};
|
142
|
+
|
143
|
+
private getSettings = () => settingsSelectors.exportSettings(useUserStore.getState());
|
144
|
+
|
145
|
+
private getSession = (id: string) =>
|
146
|
+
sessionSelectors.getSessionById(id)(useSessionStore.getState());
|
147
|
+
|
148
|
+
private getAgent = (id: string) =>
|
149
|
+
sessionSelectors.getSessionById(id)(useSessionStore.getState());
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* @deprecated
|
154
|
+
*/
|
155
|
+
export const configService = new ConfigService();
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { clientDB } from '@/database/client/db';
|
2
|
+
import { DataExporterRepos } from '@/database/repositories/dataExporter';
|
3
|
+
import { BaseClientService } from '@/services/baseClientService';
|
4
|
+
|
5
|
+
export class ClientService extends BaseClientService {
|
6
|
+
private get dataExporterRepos(): DataExporterRepos {
|
7
|
+
return new DataExporterRepos(clientDB as any, this.userId);
|
8
|
+
}
|
9
|
+
|
10
|
+
exportData = async () => {
|
11
|
+
const data = await this.dataExporterRepos.export();
|
12
|
+
|
13
|
+
return { data, url: undefined };
|
14
|
+
};
|
15
|
+
}
|