@lobehub/chat 0.105.2 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +18 -0
- package/README.zh-CN.md +18 -0
- package/docs/Environment-Variable.md +4 -2
- package/docs/Environment-Variable.zh-CN.md +4 -2
- package/locales/en_US/common.json +19 -0
- package/locales/en_US/migration.json +45 -0
- package/locales/en_US/setting.json +7 -7
- package/locales/ja_JP/common.json +19 -0
- package/locales/ja_JP/migration.json +45 -0
- package/locales/ja_JP/setting.json +2 -2
- package/locales/ko_KR/common.json +19 -0
- package/locales/ko_KR/migration.json +45 -0
- package/locales/ko_KR/setting.json +2 -2
- package/locales/ru_RU/common.json +19 -0
- package/locales/ru_RU/migration.json +45 -0
- package/locales/ru_RU/setting.json +2 -2
- package/locales/zh_CN/common.json +19 -0
- package/locales/zh_CN/migration.json +45 -0
- package/locales/zh_CN/setting.json +1 -1
- package/locales/zh_TW/common.json +19 -0
- package/locales/zh_TW/migration.json +45 -0
- package/locales/zh_TW/setting.json +2 -2
- package/package.json +2 -1
- package/src/app/api/openai/chat/createChatCompletion.test.ts +4 -4
- package/src/app/api/openai/chat/createChatCompletion.ts +4 -10
- package/src/app/api/openai/createBizOpenAI/index.ts +1 -1
- package/src/app/api/openai/errorResponse.test.ts +1 -1
- package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +2 -1
- package/src/app/chat/(mobile)/features/ChatInput/SendButton.tsx +2 -2
- package/src/app/chat/features/ChatHeader/ShareButton/Inner.tsx +2 -5
- package/src/app/chat/features/ChatHeader/ShareButton/index.tsx +2 -2
- package/src/app/chat/features/ChatInput/ActionBar/Clear.tsx +2 -2
- package/src/app/chat/features/ChatInput/ActionBar/ModelSwitch.tsx +1 -1
- package/src/app/chat/features/ChatInput/ActionBar/Token/TokenTag.tsx +8 -2
- package/src/app/chat/features/ChatInput/InputAreaInner/index.tsx +2 -2
- package/src/app/chat/features/ChatInput/STT/index.tsx +2 -2
- package/src/app/chat/features/ChatInput/Topic/index.tsx +2 -2
- package/src/app/chat/features/ChatInput/useSend.ts +3 -3
- package/src/app/chat/features/Conversation/ChatList/Actions/index.ts +2 -2
- package/src/app/chat/features/Conversation/ChatList/Error/ApiKeyForm.tsx +2 -2
- package/src/app/chat/features/Conversation/ChatList/Error/InvalidAccess.tsx +2 -2
- package/src/app/chat/features/Conversation/ChatList/Error/Plugin/PluginSettings.tsx +2 -2
- package/src/app/chat/features/Conversation/ChatList/Extras/Assistant.test.tsx +4 -4
- package/src/app/chat/features/Conversation/ChatList/Extras/Assistant.tsx +30 -31
- package/src/app/chat/features/Conversation/ChatList/Extras/TTS.tsx +2 -2
- package/src/app/chat/features/Conversation/ChatList/Extras/Translate.tsx +2 -2
- package/src/app/chat/features/Conversation/ChatList/Extras/User.tsx +8 -5
- package/src/app/chat/features/Conversation/ChatList/Extras/index.ts +3 -3
- package/src/app/chat/features/Conversation/ChatList/Extras/type.ts +5 -0
- package/src/app/chat/features/Conversation/ChatList/Messages/Assistant.tsx +10 -6
- package/src/app/chat/features/Conversation/ChatList/Messages/Default.tsx +7 -3
- package/src/app/chat/features/Conversation/ChatList/Messages/Function.tsx +7 -6
- package/src/app/chat/features/Conversation/ChatList/Messages/index.ts +7 -7
- package/src/app/chat/features/Conversation/ChatList/Plugins/Render/StandaloneType/Iframe.tsx +6 -6
- package/src/app/chat/features/Conversation/ChatList/index.tsx +16 -24
- package/src/app/chat/features/Conversation/ScrollAnchor/index.tsx +2 -2
- package/src/app/chat/features/Conversation/index.tsx +3 -3
- package/src/app/chat/features/Conversation/useInitConversation.ts +43 -0
- package/src/app/chat/features/Migration/ExportConfigButton.tsx +33 -0
- package/src/app/chat/features/Migration/Failed.tsx +115 -0
- package/src/app/chat/features/Migration/Modal.tsx +80 -0
- package/src/app/chat/features/Migration/Start.tsx +106 -0
- package/src/app/chat/features/Migration/UpgradeButton.tsx +74 -0
- package/src/app/chat/features/Migration/const.ts +15 -0
- package/src/app/chat/features/Migration/index.tsx +44 -0
- package/src/app/chat/features/SessionListContent/DefaultMode.tsx +54 -0
- package/src/app/chat/features/SessionListContent/List/Item/Actions.tsx +5 -4
- package/src/app/chat/features/SessionListContent/List/Item/index.tsx +22 -28
- package/src/app/chat/features/SessionListContent/SearchMode.tsx +15 -0
- package/src/app/chat/features/SessionListContent/index.tsx +4 -44
- package/src/app/chat/features/SessionSearchBar/index.tsx +11 -3
- package/src/app/chat/features/TopicListContent/Header.tsx +4 -4
- package/src/app/chat/features/TopicListContent/Topic/TopicContent.tsx +11 -9
- package/src/app/chat/features/TopicListContent/Topic/TopicItem.tsx +15 -13
- package/src/app/chat/features/TopicListContent/Topic/index.tsx +9 -16
- package/src/app/chat/features/TopicListContent/TopicSearchBar/index.tsx +13 -4
- package/src/app/chat/features/TopicListContent/index.tsx +1 -2
- package/src/app/chat/page.tsx +6 -1
- package/src/app/chat/settings/features/HeaderContent.tsx +3 -3
- package/src/app/home/Redirect.tsx +13 -7
- package/src/app/settings/(mobile)/features/ExtraList.tsx +12 -4
- package/src/app/settings/common/Common.tsx +16 -4
- package/src/app/welcome/features/Banner/index.tsx +9 -10
- package/src/chains/summaryTitle.ts +5 -2
- package/src/components/DataStyleModal/index.tsx +64 -0
- package/src/config/client.ts +5 -0
- package/src/const/session.ts +21 -0
- package/src/const/settings.ts +1 -1
- package/src/database/core/__tests__/db.test.ts +8 -5
- package/src/database/core/__tests__/model.test.ts +3 -3
- package/src/database/core/db.ts +38 -10
- package/src/database/core/index.ts +1 -0
- package/src/database/core/model.ts +121 -10
- package/src/database/core/schemas.ts +22 -0
- package/src/database/core/types/db.ts +13 -0
- package/src/database/models/__DEBUG.ts +119 -0
- package/src/database/models/{file.test.ts → __tests__/file.test.ts} +19 -6
- package/src/database/models/__tests__/message.test.ts +314 -0
- package/src/database/models/__tests__/session.test.ts +117 -0
- package/src/database/models/__tests__/topic.test.ts +250 -0
- package/src/database/models/file.ts +9 -5
- package/src/database/models/message.ts +186 -0
- package/src/database/models/session.ts +160 -0
- package/src/database/models/topic.ts +196 -0
- package/src/{types/database → database/schemas}/files.ts +2 -2
- package/src/database/schemas/message.ts +37 -0
- package/src/database/schemas/session.ts +56 -0
- package/src/database/schemas/topic.ts +12 -0
- package/src/features/AgentSetting/AgentConfig/index.tsx +8 -1
- package/src/features/AgentSetting/AgentTTS/SelectWithTTSPreview.tsx +1 -1
- package/src/features/AgentSetting/store/action.ts +1 -1
- package/src/features/AgentSetting/store/initialState.ts +1 -1
- package/src/features/AgentSetting/store/reducers/config.ts +1 -1
- package/src/features/DataImporter/index.tsx +240 -0
- package/src/features/DebugUI/index.tsx +34 -0
- package/src/features/SideBar/BottomActions.tsx +8 -14
- package/src/hooks/useImportConfig.ts +13 -30
- package/src/hooks/useTTS.ts +1 -1
- package/src/layout/GlobalLayout/index.tsx +16 -1
- package/src/locales/default/common.ts +19 -0
- package/src/locales/default/migration.ts +47 -0
- package/src/locales/default/setting.ts +1 -1
- package/src/locales/resources/en_US.ts +2 -0
- package/src/locales/resources/ja_JP.ts +2 -0
- package/src/locales/resources/ko_KR.ts +2 -0
- package/src/locales/resources/ru_RU.ts +2 -0
- package/src/locales/resources/zh_CN.ts +2 -0
- package/src/locales/resources/zh_TW.ts +2 -0
- package/src/migrations/FromV0ToV1.ts +2 -4
- package/src/migrations/FromV1ToV2/fixtures/input-v1-session.json +191 -0
- package/src/migrations/FromV1ToV2/fixtures/output-v2.json +202 -0
- package/src/migrations/FromV1ToV2/index.ts +82 -0
- package/src/migrations/FromV1ToV2/migrations.test.ts +224 -0
- package/src/migrations/FromV1ToV2/types/v1.ts +78 -0
- package/src/migrations/FromV1ToV2/types/v2.ts +52 -0
- package/src/{utils → migrations}/VersionController.test.ts +1 -3
- package/src/{utils → migrations}/VersionController.ts +5 -2
- package/src/migrations/index.ts +17 -3
- package/src/services/__tests__/file.test.ts +3 -3
- package/src/services/chat.ts +66 -5
- package/src/services/config.ts +184 -0
- package/src/services/debug.ts +13 -0
- package/src/services/file.ts +6 -2
- package/src/services/github.ts +25 -0
- package/src/services/message.ts +79 -0
- package/src/services/session.ts +63 -0
- package/src/services/topic.ts +56 -0
- package/src/store/chat/actions/enhance.ts +95 -0
- package/src/store/{session/slices/chat → chat}/actions/message.ts +225 -247
- package/src/store/{session/slices/chat → chat}/actions/plugin.ts +29 -34
- package/src/store/{session/slices/chat → chat}/actions/share.ts +9 -13
- package/src/store/chat/actions/topic.ts +197 -0
- package/src/store/chat/helpers.ts +23 -0
- package/src/store/chat/index.ts +3 -0
- package/src/store/chat/initialState.ts +48 -0
- package/src/store/chat/reducers/message.test.ts +83 -0
- package/src/store/chat/reducers/message.ts +83 -0
- package/src/store/chat/selectors/__tests__/topic.test.ts +43 -0
- package/src/store/chat/selectors/chat.ts +119 -0
- package/src/store/chat/selectors/index.ts +2 -0
- package/src/store/chat/selectors/topic.ts +28 -0
- package/src/store/chat/store.ts +63 -0
- package/src/store/files/slices/images/action.ts +6 -4
- package/src/store/global/selectors/__snapshots__/settings.test.ts.snap +99 -0
- package/src/store/global/selectors/settings.test.ts +51 -0
- package/src/store/global/selectors/settings.ts +36 -5
- package/src/store/global/store.ts +1 -1
- package/src/store/middleware/createHyperStorage/index.ts +40 -24
- package/src/store/middleware/createHyperStorage/keyMapper.ts +8 -2
- package/src/store/middleware/createHyperStorage/type.ts +10 -8
- package/src/store/plugin/slices/plugin/action.ts +1 -1
- package/src/store/plugin/store.ts +2 -4
- package/src/store/session/helpers.ts +1 -1
- package/src/store/session/hooks/useSessionHydrated.ts +6 -10
- package/src/store/session/initialState.ts +26 -7
- package/src/store/session/selectors.ts +1 -2
- package/src/store/session/slices/agent/action.ts +26 -35
- package/src/store/session/slices/agent/selectors.ts +32 -37
- package/src/store/session/slices/session/action.ts +81 -88
- package/src/store/session/slices/session/helpers.ts +19 -0
- package/src/store/session/slices/session/initialState.ts +7 -10
- package/src/store/session/slices/session/selectors/export.ts +12 -9
- package/src/store/session/slices/session/selectors/index.ts +2 -35
- package/src/store/session/slices/session/selectors/list.test.ts +25 -203
- package/src/store/session/slices/session/selectors/list.ts +40 -78
- package/src/store/session/store.ts +11 -17
- package/src/types/agent/index.ts +61 -0
- package/src/types/chatMessage.ts +11 -20
- package/src/types/exportConfig.ts +7 -2
- package/src/types/files.ts +2 -2
- package/src/types/llm.ts +1 -1
- package/src/types/meta.ts +24 -12
- package/src/types/openai/chat.ts +9 -1
- package/src/types/openai/functionCall.ts +4 -0
- package/src/types/session.ts +10 -94
- package/src/types/settings.ts +2 -0
- package/src/types/translate.ts +2 -1
- package/src/utils/config.ts +5 -11
- package/src/utils/fetch.ts +8 -2
- package/src/app/chat/features/Conversation/usePluginsInit.ts +0 -14
- package/src/database/core/schema.ts +0 -9
- package/src/helpers/export.ts +0 -69
- package/src/hooks/useExportConfig.ts +0 -6
- package/src/store/session/slices/chat/actions/index.ts +0 -32
- package/src/store/session/slices/chat/actions/topic.ts +0 -171
- package/src/store/session/slices/chat/actions/translate.ts +0 -113
- package/src/store/session/slices/chat/helpers.ts +0 -9
- package/src/store/session/slices/chat/initialState.ts +0 -13
- package/src/store/session/slices/chat/reducers/message.test.ts +0 -319
- package/src/store/session/slices/chat/reducers/message.ts +0 -156
- package/src/store/session/slices/chat/reducers/topic.test.ts +0 -179
- package/src/store/session/slices/chat/reducers/topic.ts +0 -81
- package/src/store/session/slices/chat/selectors/chat.ts +0 -111
- package/src/store/session/slices/chat/selectors/index.ts +0 -26
- package/src/store/session/slices/chat/selectors/topic.ts +0 -30
- package/src/store/session/slices/chat/selectors/utils.test.ts +0 -385
- package/src/store/session/slices/chat/selectors/utils.ts +0 -91
- package/src/store/session/slices/chat/utils.ts +0 -13
- package/src/store/session/slices/session/reducers/session.test.ts +0 -577
- package/src/store/session/slices/session/reducers/session.ts +0 -182
- package/src/types/database/db.ts +0 -4
- /package/src/store/{session/slices/chat → chat}/reducers/files.test.ts +0 -0
- /package/src/store/{session/slices/chat → chat}/reducers/files.ts +0 -0
package/src/migrations/index.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
|
+
import { VersionController } from '@/migrations/VersionController';
|
|
1
2
|
import { ConfigStateAll } from '@/types/exportConfig';
|
|
2
|
-
|
|
3
|
+
|
|
4
|
+
import { MigrationV0ToV1 } from './FromV0ToV1';
|
|
5
|
+
import { MigrationV1ToV2 } from './FromV1ToV2';
|
|
3
6
|
|
|
4
7
|
// 当前最新的版本号
|
|
5
|
-
export const CURRENT_CONFIG_VERSION =
|
|
8
|
+
export const CURRENT_CONFIG_VERSION = 2;
|
|
6
9
|
|
|
7
10
|
// 历史记录版本升级模块
|
|
8
|
-
|
|
11
|
+
const ConfigMigrations = [
|
|
12
|
+
/**
|
|
13
|
+
* 2023.11.27
|
|
14
|
+
* 从单 key 数据库转换为基于 dexie 的关系型结构
|
|
15
|
+
*/
|
|
16
|
+
MigrationV1ToV2,
|
|
17
|
+
/**
|
|
18
|
+
* 2023.07.11
|
|
19
|
+
* just the first version, Nothing to do
|
|
20
|
+
*/
|
|
21
|
+
MigrationV0ToV1,
|
|
22
|
+
];
|
|
9
23
|
|
|
10
24
|
export const Migration = new VersionController<ConfigStateAll>(
|
|
11
25
|
ConfigMigrations,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { FileModel } from '@/database/models/file';
|
|
4
|
-
import {
|
|
4
|
+
import { DB_File } from '@/database/schemas/files';
|
|
5
5
|
|
|
6
6
|
import { fileService } from '../file';
|
|
7
7
|
|
|
@@ -25,7 +25,7 @@ describe('FileService', () => {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
it('uploadFile should save the file to the database', async () => {
|
|
28
|
-
const localFile:
|
|
28
|
+
const localFile: DB_File = {
|
|
29
29
|
name: 'test',
|
|
30
30
|
data: new ArrayBuffer(1),
|
|
31
31
|
fileType: 'image/png',
|
|
@@ -53,7 +53,7 @@ describe('FileService', () => {
|
|
|
53
53
|
|
|
54
54
|
it('getFile should retrieve and convert file info to FilePreview', async () => {
|
|
55
55
|
const fileId = '1';
|
|
56
|
-
const fileData:
|
|
56
|
+
const fileData: DB_File = {
|
|
57
57
|
name: 'test',
|
|
58
58
|
data: new ArrayBuffer(1),
|
|
59
59
|
fileType: 'image/png',
|
package/src/services/chat.ts
CHANGED
|
@@ -3,9 +3,12 @@ import { merge } from 'lodash-es';
|
|
|
3
3
|
|
|
4
4
|
import { VISION_MODEL_WHITE_LIST } from '@/const/llm';
|
|
5
5
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
6
|
+
import { filesSelectors, useFileStore } from '@/store/files';
|
|
6
7
|
import { usePluginStore } from '@/store/plugin';
|
|
7
8
|
import { pluginSelectors } from '@/store/plugin/selectors';
|
|
8
|
-
import
|
|
9
|
+
import { ChatMessage } from '@/types/chatMessage';
|
|
10
|
+
import type { OpenAIChatMessage, OpenAIChatStreamPayload } from '@/types/openai/chat';
|
|
11
|
+
import { UserMessageContentPart } from '@/types/openai/chat';
|
|
9
12
|
import { fetchAIFactory, getMessageError } from '@/utils/fetch';
|
|
10
13
|
|
|
11
14
|
import { createHeaderWithOpenAI } from './_header';
|
|
@@ -15,9 +18,13 @@ interface FetchOptions {
|
|
|
15
18
|
signal?: AbortSignal | undefined;
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
interface GetChatCompletionPayload extends Partial<Omit<OpenAIChatStreamPayload, 'messages'>> {
|
|
22
|
+
messages: ChatMessage[];
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
class ChatService {
|
|
19
|
-
|
|
20
|
-
{ plugins: enabledPlugins, ...params }:
|
|
26
|
+
createAssistantMessage = async (
|
|
27
|
+
{ plugins: enabledPlugins, messages, ...params }: GetChatCompletionPayload,
|
|
21
28
|
options?: FetchOptions,
|
|
22
29
|
) => {
|
|
23
30
|
const payload = merge(
|
|
@@ -28,7 +35,11 @@ class ChatService {
|
|
|
28
35
|
},
|
|
29
36
|
params,
|
|
30
37
|
);
|
|
31
|
-
// ============
|
|
38
|
+
// ============ 1. preprocess messages ============ //
|
|
39
|
+
|
|
40
|
+
const oaiMessages = this.processMessages(messages);
|
|
41
|
+
|
|
42
|
+
// ============ 2. preprocess tools ============ //
|
|
32
43
|
|
|
33
44
|
const filterTools = pluginSelectors.enabledSchema(enabledPlugins)(usePluginStore.getState());
|
|
34
45
|
|
|
@@ -41,8 +52,21 @@ class ChatService {
|
|
|
41
52
|
|
|
42
53
|
const functions = shouldUseTools ? filterTools : undefined;
|
|
43
54
|
|
|
55
|
+
return this.getChatCompletion({ ...params, functions, messages: oaiMessages }, options);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
getChatCompletion = (params: Partial<OpenAIChatStreamPayload>, options?: FetchOptions) => {
|
|
59
|
+
const payload = merge(
|
|
60
|
+
{
|
|
61
|
+
model: DEFAULT_AGENT_CONFIG.model,
|
|
62
|
+
stream: true,
|
|
63
|
+
...DEFAULT_AGENT_CONFIG.params,
|
|
64
|
+
},
|
|
65
|
+
params,
|
|
66
|
+
);
|
|
67
|
+
|
|
44
68
|
return fetch(OPENAI_URLS.chat, {
|
|
45
|
-
body: JSON.stringify(
|
|
69
|
+
body: JSON.stringify(payload),
|
|
46
70
|
headers: createHeaderWithOpenAI({ 'Content-Type': 'application/json' }),
|
|
47
71
|
method: 'POST',
|
|
48
72
|
signal: options?.signal,
|
|
@@ -79,6 +103,43 @@ class ChatService {
|
|
|
79
103
|
};
|
|
80
104
|
|
|
81
105
|
fetchPresetTaskResult = fetchAIFactory(this.getChatCompletion);
|
|
106
|
+
|
|
107
|
+
private processMessages = (messages: ChatMessage[]): OpenAIChatMessage[] => {
|
|
108
|
+
// handle content type for vision model
|
|
109
|
+
// for the models with visual ability, add image url to content
|
|
110
|
+
// refs: https://platform.openai.com/docs/guides/vision/quick-start
|
|
111
|
+
const getContent = (m: ChatMessage) => {
|
|
112
|
+
if (!m.files) return m.content;
|
|
113
|
+
|
|
114
|
+
const imageList = filesSelectors.getImageUrlOrBase64ByList(m.files)(useFileStore.getState());
|
|
115
|
+
|
|
116
|
+
if (imageList.length === 0) return m.content;
|
|
117
|
+
|
|
118
|
+
return [
|
|
119
|
+
{ text: m.content, type: 'text' },
|
|
120
|
+
...imageList.map(
|
|
121
|
+
(i) => ({ image_url: { detail: 'auto', url: i.url }, type: 'image_url' }) as const,
|
|
122
|
+
),
|
|
123
|
+
] as UserMessageContentPart[];
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return messages.map((m): OpenAIChatMessage => {
|
|
127
|
+
switch (m.role) {
|
|
128
|
+
case 'user': {
|
|
129
|
+
return { content: getContent(m), role: m.role };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
case 'function': {
|
|
133
|
+
const name = m.plugin?.identifier as string;
|
|
134
|
+
return { content: m.content, name, role: m.role };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
default: {
|
|
138
|
+
return { content: m.content, role: m.role };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
};
|
|
82
143
|
}
|
|
83
144
|
|
|
84
145
|
export const chatService = new ChatService();
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { messageService } from '@/services/message';
|
|
2
|
+
import { sessionService } from '@/services/session';
|
|
3
|
+
import { topicService } from '@/services/topic';
|
|
4
|
+
import { settingsSelectors, useGlobalStore } from '@/store/global';
|
|
5
|
+
import { useSessionStore } from '@/store/session';
|
|
6
|
+
import { sessionExportSelectors, sessionSelectors } from '@/store/session/selectors';
|
|
7
|
+
import { ChatMessage } from '@/types/chatMessage';
|
|
8
|
+
import { ConfigFile } from '@/types/exportConfig';
|
|
9
|
+
import { LobeSessions } from '@/types/session';
|
|
10
|
+
import { GlobalSettings } from '@/types/settings';
|
|
11
|
+
import { ChatTopic } from '@/types/topic';
|
|
12
|
+
import { createConfigFile, exportConfigFile } from '@/utils/config';
|
|
13
|
+
|
|
14
|
+
export interface ImportResult {
|
|
15
|
+
added: number;
|
|
16
|
+
errors: number;
|
|
17
|
+
skips: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ImportResults {
|
|
20
|
+
messages?: ImportResult;
|
|
21
|
+
sessions: ImportResult;
|
|
22
|
+
topics?: ImportResult;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class ConfigService {
|
|
26
|
+
/**
|
|
27
|
+
* import sessions from files
|
|
28
|
+
* @param sessions
|
|
29
|
+
*/
|
|
30
|
+
importSessions = async (sessions: LobeSessions) => {
|
|
31
|
+
return await sessionService.batchCreateSessions(sessions);
|
|
32
|
+
};
|
|
33
|
+
importMessages = async (messages: ChatMessage[]) => {
|
|
34
|
+
return messageService.batchCreate(messages);
|
|
35
|
+
};
|
|
36
|
+
importSettings = async (settings: GlobalSettings) => {
|
|
37
|
+
useGlobalStore.getState().importAppSettings(settings);
|
|
38
|
+
};
|
|
39
|
+
importTopics = async (topics: ChatTopic[]) => {
|
|
40
|
+
return topicService.batchCreateTopics(topics);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
importConfigState = async (config: ConfigFile): Promise<ImportResults | undefined> => {
|
|
44
|
+
switch (config.exportType) {
|
|
45
|
+
case 'settings': {
|
|
46
|
+
await this.importSettings(config.state.settings);
|
|
47
|
+
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
case 'agents': {
|
|
52
|
+
const data = await this.importSessions(config.state.sessions);
|
|
53
|
+
return {
|
|
54
|
+
sessions: this.mapImportResult(data),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
case 'all': {
|
|
59
|
+
await this.importSettings(config.state.settings);
|
|
60
|
+
|
|
61
|
+
const [sessions, messages, topics] = await Promise.all([
|
|
62
|
+
this.importSessions(config.state.sessions),
|
|
63
|
+
this.importMessages(config.state.messages),
|
|
64
|
+
this.importTopics(config.state.topics),
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
messages: this.mapImportResult(messages),
|
|
69
|
+
sessions: this.mapImportResult(sessions),
|
|
70
|
+
topics: this.mapImportResult(topics),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
case 'sessions': {
|
|
75
|
+
const [sessions, messages, topics] = await Promise.all([
|
|
76
|
+
this.importSessions(config.state.sessions),
|
|
77
|
+
this.importMessages(config.state.messages),
|
|
78
|
+
this.importTopics(config.state.topics),
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
messages: this.mapImportResult(messages),
|
|
83
|
+
sessions: this.mapImportResult(sessions),
|
|
84
|
+
topics: this.mapImportResult(topics),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* export all agents
|
|
92
|
+
*/
|
|
93
|
+
exportAgents = async () => {
|
|
94
|
+
const agents = await sessionService.getAllAgents();
|
|
95
|
+
|
|
96
|
+
const config = createConfigFile('agents', { sessions: agents });
|
|
97
|
+
|
|
98
|
+
exportConfigFile(config, 'agents');
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* export all sessions
|
|
103
|
+
*/
|
|
104
|
+
exportSessions = async () => {
|
|
105
|
+
const sessions = await sessionService.getSessions();
|
|
106
|
+
const messages = await messageService.getAllMessages();
|
|
107
|
+
const topics = await topicService.getAllTopics();
|
|
108
|
+
|
|
109
|
+
const config = createConfigFile('sessions', { messages, sessions, topics });
|
|
110
|
+
|
|
111
|
+
exportConfigFile(config, 'sessions');
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* export a session
|
|
116
|
+
*/
|
|
117
|
+
exportSingleSession = async (id: string) => {
|
|
118
|
+
const session = this.getSession(id);
|
|
119
|
+
if (!session) return;
|
|
120
|
+
|
|
121
|
+
const messages = await messageService.getMessages(id);
|
|
122
|
+
const topics = await topicService.getTopics({ sessionId: id });
|
|
123
|
+
|
|
124
|
+
const config = createConfigFile('singleSession', { messages, sessions: [session], topics });
|
|
125
|
+
|
|
126
|
+
exportConfigFile(config, `${session.meta?.title}-session`);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
exportSingleAgent = async (id: string) => {
|
|
130
|
+
const agent = this.getAgent(id);
|
|
131
|
+
if (!agent) return;
|
|
132
|
+
|
|
133
|
+
const config = createConfigFile('agents', { sessions: [agent] });
|
|
134
|
+
|
|
135
|
+
exportConfigFile(config, agent.meta?.title || 'agent');
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* export settings
|
|
140
|
+
*/
|
|
141
|
+
exportSettings = async () => {
|
|
142
|
+
const settings = this.getSettings();
|
|
143
|
+
|
|
144
|
+
const config = createConfigFile('settings', { settings });
|
|
145
|
+
|
|
146
|
+
exportConfigFile(config, 'settings');
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* export all data
|
|
151
|
+
*/
|
|
152
|
+
exportAll = async () => {
|
|
153
|
+
const sessions = await sessionService.getSessions();
|
|
154
|
+
const messages = await messageService.getAllMessages();
|
|
155
|
+
const topics = await topicService.getAllTopics();
|
|
156
|
+
const settings = this.getSettings();
|
|
157
|
+
|
|
158
|
+
const config = createConfigFile('all', { messages, sessions, settings, topics });
|
|
159
|
+
|
|
160
|
+
exportConfigFile(config, 'config');
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
private getSettings = () => settingsSelectors.exportSettings(useGlobalStore.getState());
|
|
164
|
+
|
|
165
|
+
private getSession = (id: string) =>
|
|
166
|
+
sessionSelectors.getSessionById(id)(useSessionStore.getState());
|
|
167
|
+
|
|
168
|
+
private getAgent = (id: string) =>
|
|
169
|
+
sessionExportSelectors.getExportAgent(id)(useSessionStore.getState());
|
|
170
|
+
|
|
171
|
+
private mapImportResult = (input: {
|
|
172
|
+
added: number;
|
|
173
|
+
errors?: Error[];
|
|
174
|
+
skips: string[];
|
|
175
|
+
}): ImportResult => {
|
|
176
|
+
return {
|
|
177
|
+
added: input.added,
|
|
178
|
+
errors: input.errors?.length || 0,
|
|
179
|
+
skips: input.skips.length,
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const configService = new ConfigService();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DEBUG_MODEL } from '@/database/models/__DEBUG';
|
|
2
|
+
|
|
3
|
+
class DebugService {
|
|
4
|
+
async insertLargeDataToDB() {
|
|
5
|
+
return DEBUG_MODEL.createRandomData({
|
|
6
|
+
messageCount: 400_000,
|
|
7
|
+
sessionCount: 40,
|
|
8
|
+
topicCount: 200,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const debugService = new DebugService();
|
package/src/services/file.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FileModel } from '@/database/models/file';
|
|
2
|
-
import {
|
|
2
|
+
import { DB_File } from '@/database/schemas/files';
|
|
3
3
|
import { FilePreview } from '@/types/files';
|
|
4
4
|
|
|
5
5
|
class FileService {
|
|
6
|
-
async uploadFile(file:
|
|
6
|
+
async uploadFile(file: DB_File) {
|
|
7
7
|
// save to local storage
|
|
8
8
|
// we may want to save to a remote server later
|
|
9
9
|
return FileModel.create(file);
|
|
@@ -13,6 +13,10 @@ class FileService {
|
|
|
13
13
|
return FileModel.delete(id);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
async removeAllFiles() {
|
|
17
|
+
return FileModel.clear();
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
async getFile(id: string): Promise<FilePreview> {
|
|
17
21
|
const item = await FileModel.findById(id);
|
|
18
22
|
if (!item) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import qs from 'query-string';
|
|
2
|
+
import urlJoin from 'url-join';
|
|
3
|
+
|
|
4
|
+
import { GITHUB } from '@/const/url';
|
|
5
|
+
|
|
6
|
+
class GitHubService {
|
|
7
|
+
submitDBV1UpgradeError = (version: number, error?: { message: string }) => {
|
|
8
|
+
const body = ['```json', JSON.stringify(error, null, 2), '```'].join('\n');
|
|
9
|
+
|
|
10
|
+
const message = error?.message || '';
|
|
11
|
+
|
|
12
|
+
const url = qs.stringifyUrl({
|
|
13
|
+
query: {
|
|
14
|
+
body,
|
|
15
|
+
labels: '❌ Database Migration Error',
|
|
16
|
+
title: `[Migration Error V${version}] ${message}`,
|
|
17
|
+
},
|
|
18
|
+
url: urlJoin(GITHUB, '/issues/new'),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
window.open(url, '_blank');
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const githubService = new GitHubService();
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { CreateMessageParams, MessageModel } from '@/database/models/message';
|
|
2
|
+
import {
|
|
3
|
+
ChatMessage,
|
|
4
|
+
ChatMessageError,
|
|
5
|
+
ChatPluginPayload,
|
|
6
|
+
ChatTTS,
|
|
7
|
+
ChatTranslate,
|
|
8
|
+
} from '@/types/chatMessage';
|
|
9
|
+
import { LLMRoleType } from '@/types/llm';
|
|
10
|
+
|
|
11
|
+
export class MessageService {
|
|
12
|
+
async create(data: CreateMessageParams) {
|
|
13
|
+
const { id } = await MessageModel.create(data);
|
|
14
|
+
|
|
15
|
+
return id;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async batchCreate(messages: ChatMessage[]) {
|
|
19
|
+
return MessageModel.batchCreate(messages);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async hasMessages() {
|
|
23
|
+
const isEmpty = await MessageModel.isEmpty();
|
|
24
|
+
return !isEmpty;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async getMessages(sessionId: string, topicId?: string): Promise<ChatMessage[]> {
|
|
28
|
+
return MessageModel.query({ sessionId, topicId });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async removeMessage(id: string) {
|
|
32
|
+
return MessageModel.delete(id);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async updateMessageContent(id: string, content: string) {
|
|
36
|
+
return MessageModel.update(id, { content });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async updateMessageError(id: string, error: ChatMessageError) {
|
|
40
|
+
return MessageModel.update(id, { error });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async updateMessageTranslate(id: string, data: Partial<ChatTranslate> | null) {
|
|
44
|
+
return MessageModel.update(id, { translate: data as ChatTranslate });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async updateMessageTTS(id: string, data: Partial<ChatTTS> | null) {
|
|
48
|
+
return MessageModel.update(id, { tts: data as ChatTTS });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async removeMessages(assistantId: string, topicId?: string) {
|
|
52
|
+
return MessageModel.batchDelete(assistantId, topicId);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async clearAllMessage() {
|
|
56
|
+
return MessageModel.clearTable();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async bindMessagesToTopic(topicId: string, messageIds: string[]) {
|
|
60
|
+
return MessageModel.batchUpdate(messageIds, { topicId });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async updateMessageRole(id: string, role: LLMRoleType) {
|
|
64
|
+
return MessageModel.update(id, { role });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async updateMessagePlugin(id: string, plugin: ChatPluginPayload) {
|
|
68
|
+
return MessageModel.update(id, { plugin });
|
|
69
|
+
}
|
|
70
|
+
async updateMessagePluginState(id: string, key: string, value: any) {
|
|
71
|
+
return MessageModel.update(id, { pluginState: { [key]: value } });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async getAllMessages() {
|
|
75
|
+
return MessageModel.queryAll();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const messageService = new MessageService();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DeepPartial } from 'utility-types';
|
|
2
|
+
|
|
3
|
+
import { SessionModel } from '@/database/models/session';
|
|
4
|
+
import { LobeAgentConfig } from '@/types/agent';
|
|
5
|
+
import { MetaData } from '@/types/meta';
|
|
6
|
+
import { LobeAgentSession, LobeSessionType, LobeSessions, SessionGroupKey } from '@/types/session';
|
|
7
|
+
|
|
8
|
+
class SessionService {
|
|
9
|
+
async createNewSession(
|
|
10
|
+
type: LobeSessionType,
|
|
11
|
+
defaultValue: Partial<LobeAgentSession>,
|
|
12
|
+
): Promise<string> {
|
|
13
|
+
const item = await SessionModel.create(type, defaultValue);
|
|
14
|
+
if (!item) {
|
|
15
|
+
throw new Error('session create Error');
|
|
16
|
+
}
|
|
17
|
+
return item.id;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async batchCreateSessions(importSessions: LobeSessions) {
|
|
21
|
+
return SessionModel.batchCreate(importSessions);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async getSessions(): Promise<LobeSessions> {
|
|
25
|
+
return SessionModel.query();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async getAllAgents(): Promise<LobeSessions> {
|
|
29
|
+
// TODO: add a filter to get only agents
|
|
30
|
+
return await SessionModel.query();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async removeSession(id: string) {
|
|
34
|
+
return SessionModel.delete(id);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async removeAllSessions() {
|
|
38
|
+
return SessionModel.clearTable();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async updateSessionGroup(id: string, group: SessionGroupKey) {
|
|
42
|
+
return SessionModel.update(id, { group });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async updateSessionMeta(activeId: string, meta: Partial<MetaData>) {
|
|
46
|
+
return SessionModel.update(activeId, { meta });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async updateSessionConfig(activeId: string, config: DeepPartial<LobeAgentConfig>) {
|
|
50
|
+
return SessionModel.updateConfig(activeId, config);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async hasSessions() {
|
|
54
|
+
const isEmpty = await SessionModel.isEmpty();
|
|
55
|
+
return !isEmpty;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async searchSessions(keyword: string) {
|
|
59
|
+
return SessionModel.queryByKeyword(keyword);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const sessionService = new SessionService();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CreateTopicParams, QueryTopicParams, TopicModel } from '@/database/models/topic';
|
|
2
|
+
import { ChatTopic } from '@/types/topic';
|
|
3
|
+
|
|
4
|
+
class TopicService {
|
|
5
|
+
async createTopic(params: CreateTopicParams): Promise<string> {
|
|
6
|
+
const item = await TopicModel.create(params);
|
|
7
|
+
|
|
8
|
+
if (!item) {
|
|
9
|
+
throw new Error('topic create Error');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return item.id;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async getTopics(params: QueryTopicParams): Promise<ChatTopic[]> {
|
|
16
|
+
return TopicModel.query(params);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async removeTopic(id: string) {
|
|
20
|
+
return TopicModel.delete(id);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async removeTopics(sessionId: string) {
|
|
24
|
+
return TopicModel.batchDeleteBySessionId(sessionId);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async batchRemoveTopics(topics: string[]) {
|
|
28
|
+
return TopicModel.batchDelete(topics);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async removeAllTopic() {
|
|
32
|
+
return TopicModel.clearTable();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async updateFavorite(id: string, newState?: boolean) {
|
|
36
|
+
return TopicModel.toggleFavorite(id, newState);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async batchCreateTopics(importTopics: ChatTopic[]) {
|
|
40
|
+
return TopicModel.batchCreate(importTopics as any);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
updateTitle(topicId: string, text: string) {
|
|
44
|
+
return TopicModel.update(topicId, { title: text });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async getAllTopics() {
|
|
48
|
+
return TopicModel.queryAll();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async searchTopics(keyword: string) {
|
|
52
|
+
return TopicModel.queryByKeyword(keyword);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const topicService = new TopicService();
|