@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
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { BaseModel } from '@/database/core';
|
|
2
|
+
import { DB_Topic, DB_TopicSchema } from '@/database/schemas/topic';
|
|
3
|
+
import { ChatTopic } from '@/types/topic';
|
|
4
|
+
import { nanoid } from '@/utils/uuid';
|
|
5
|
+
|
|
6
|
+
export interface CreateTopicParams {
|
|
7
|
+
favorite?: boolean;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
title: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface QueryTopicParams {
|
|
13
|
+
current?: number;
|
|
14
|
+
pageSize?: number;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class _TopicModel extends BaseModel {
|
|
19
|
+
constructor() {
|
|
20
|
+
super('topics', DB_TopicSchema);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async create({ title, favorite, sessionId }: CreateTopicParams, id = nanoid()) {
|
|
24
|
+
return this._add({ favorite: favorite ? 1 : 0, sessionId, title: title }, id);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async batchCreate(topics: CreateTopicParams[]) {
|
|
28
|
+
return this._batchAdd(topics.map((t) => ({ ...t, favorite: t.favorite ? 1 : 0 })));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async query({ pageSize = 9999, current = 0, sessionId }: QueryTopicParams): Promise<ChatTopic[]> {
|
|
32
|
+
const offset = current * pageSize;
|
|
33
|
+
|
|
34
|
+
// get all topics
|
|
35
|
+
const allTopics = await this.table.where('sessionId').equals(sessionId).toArray();
|
|
36
|
+
|
|
37
|
+
// 将所有主题按星标消息优先,时间倒序进行排序
|
|
38
|
+
const sortedTopics = allTopics.sort((a, b) => {
|
|
39
|
+
if (a.favorite && !b.favorite) return -1; // a是星标,b不是,a排前面
|
|
40
|
+
if (!a.favorite && b.favorite) return 1; // b是星标,a不是,b排前面
|
|
41
|
+
|
|
42
|
+
// 如果星标状态相同,则按时间倒序排序
|
|
43
|
+
return b.createdAt - a.createdAt;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// handle pageSize
|
|
47
|
+
const pagedTopics = sortedTopics.slice(offset, offset + pageSize);
|
|
48
|
+
|
|
49
|
+
return pagedTopics.map((i) => ({ ...i, favorite: !!i.favorite }));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async findBySessionId(sessionId: string) {
|
|
53
|
+
return this.table.where({ sessionId }).toArray();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async findById(id: string) {
|
|
57
|
+
return this.table.get(id);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Deletes a topic and all messages associated with it.
|
|
62
|
+
*/
|
|
63
|
+
async delete(id: string) {
|
|
64
|
+
return this.db.transaction('rw', [this.table, this.db.messages], async () => {
|
|
65
|
+
// Delete all messages associated with the topic
|
|
66
|
+
const messages = await this.db.messages.where('topicId').equals(id).toArray();
|
|
67
|
+
|
|
68
|
+
if (messages.length > 0) {
|
|
69
|
+
const messageIds = messages.map((msg) => msg.id);
|
|
70
|
+
await this.db.messages.bulkDelete(messageIds);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await this.table.delete(id);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Deletes multiple topic based on the sessionId.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} sessionId - The identifier of the assistant associated with the messages.
|
|
81
|
+
* @returns {Promise<void>}
|
|
82
|
+
*/
|
|
83
|
+
async batchDeleteBySessionId(sessionId: string): Promise<void> {
|
|
84
|
+
// use sessionId as the filter criteria in the query.
|
|
85
|
+
const query = this.table.where('sessionId').equals(sessionId);
|
|
86
|
+
|
|
87
|
+
// Retrieve a collection of message IDs that satisfy the criteria
|
|
88
|
+
const topicIds = await query.primaryKeys();
|
|
89
|
+
|
|
90
|
+
// Use the bulkDelete method to delete all selected messages in bulk
|
|
91
|
+
return this.table.bulkDelete(topicIds);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async clearTable() {
|
|
95
|
+
return this.table.clear();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async update(id: string, data: Partial<DB_Topic>) {
|
|
99
|
+
return super._update(id, { ...data, updatedAt: Date.now() });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async toggleFavorite(id: string, newState?: boolean) {
|
|
103
|
+
const topic = await this.findById(id);
|
|
104
|
+
if (!topic) {
|
|
105
|
+
throw new Error(`Topic with id ${id} not found`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Toggle the 'favorite' status
|
|
109
|
+
const nextState = typeof newState !== 'undefined' ? newState : !topic.favorite;
|
|
110
|
+
|
|
111
|
+
await this.update(id, { favorite: nextState ? 1 : 0 });
|
|
112
|
+
|
|
113
|
+
return nextState;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Deletes multiple topics and all messages associated with them in a transaction.
|
|
118
|
+
*/
|
|
119
|
+
async batchDelete(topicIds: string[]) {
|
|
120
|
+
return this.db.transaction('rw', [this.table, this.db.messages], async () => {
|
|
121
|
+
// Iterate over each topicId and delete related messages, then delete the topic itself
|
|
122
|
+
for (const topicId of topicIds) {
|
|
123
|
+
// Delete all messages associated with the topic
|
|
124
|
+
const messages = await this.db.messages.where('topicId').equals(topicId).toArray();
|
|
125
|
+
if (messages.length > 0) {
|
|
126
|
+
const messageIds = messages.map((msg) => msg.id);
|
|
127
|
+
await this.db.messages.bulkDelete(messageIds);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Delete the topic
|
|
131
|
+
await this.table.delete(topicId);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
queryAll() {
|
|
137
|
+
return this.table.orderBy('updatedAt').toArray();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Query topics by keyword in title, message content, or translated content
|
|
142
|
+
* @param keyword The keyword to search for
|
|
143
|
+
*/
|
|
144
|
+
async queryByKeyword(keyword: string): Promise<ChatTopic[]> {
|
|
145
|
+
if (!keyword) return [];
|
|
146
|
+
|
|
147
|
+
console.time('queryTopicsByKeyword');
|
|
148
|
+
const keywordLowerCase = keyword.toLowerCase();
|
|
149
|
+
|
|
150
|
+
// Find topics with matching title
|
|
151
|
+
const matchingTopicsPromise = this.table
|
|
152
|
+
.filter((topic) => topic.title.toLowerCase().includes(keywordLowerCase))
|
|
153
|
+
.toArray();
|
|
154
|
+
|
|
155
|
+
// Find messages with matching content or translate.content
|
|
156
|
+
const matchingMessagesPromise = this.db.messages
|
|
157
|
+
.filter((message) => {
|
|
158
|
+
// check content
|
|
159
|
+
if (message.content.toLowerCase().includes(keywordLowerCase)) return true;
|
|
160
|
+
|
|
161
|
+
// check translate content
|
|
162
|
+
if (message.translate && message.translate.content) {
|
|
163
|
+
return message.translate.content.toLowerCase().includes(keywordLowerCase);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return false;
|
|
167
|
+
})
|
|
168
|
+
.toArray();
|
|
169
|
+
|
|
170
|
+
// Resolve both promises
|
|
171
|
+
const [matchingTopics, matchingMessages] = await Promise.all([
|
|
172
|
+
matchingTopicsPromise,
|
|
173
|
+
matchingMessagesPromise,
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
// Extract topic IDs from messages
|
|
177
|
+
const topicIdsFromMessages = matchingMessages.map((message) => message.topicId);
|
|
178
|
+
|
|
179
|
+
// Combine topic IDs from both sources
|
|
180
|
+
const combinedTopicIds = new Set([
|
|
181
|
+
...topicIdsFromMessages,
|
|
182
|
+
...matchingTopics.map((topic) => topic.id),
|
|
183
|
+
]);
|
|
184
|
+
|
|
185
|
+
// Retrieve unique topics by IDs
|
|
186
|
+
const uniqueTopics = await this.table
|
|
187
|
+
.where('id')
|
|
188
|
+
.anyOf([...combinedTopicIds])
|
|
189
|
+
.toArray();
|
|
190
|
+
|
|
191
|
+
console.timeEnd('queryTopicsByKeyword');
|
|
192
|
+
return uniqueTopics.map((i) => ({ ...i, favorite: !!i.favorite }));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const TopicModel = new _TopicModel();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const DB_FileSchema = z.object({
|
|
4
4
|
/**
|
|
5
5
|
* create Time
|
|
6
6
|
*/
|
|
@@ -35,4 +35,4 @@ export const LocalFileSchema = z.object({
|
|
|
35
35
|
url: z.string().url().optional(),
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
export type
|
|
38
|
+
export type DB_File = z.infer<typeof DB_FileSchema>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
const TranslateSchema = z.object({
|
|
5
|
+
from: z.string().optional(),
|
|
6
|
+
to: z.string(),
|
|
7
|
+
content: z.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const PluginSchema = z.object({
|
|
11
|
+
identifier: z.string(),
|
|
12
|
+
arguments: z.string(),
|
|
13
|
+
apiName: z.string(),
|
|
14
|
+
type: z.enum(['default', 'standalone']).default('default'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const DB_MessageSchema = z.object({
|
|
18
|
+
role: z.enum(['user', 'system', 'assistant', 'function']),
|
|
19
|
+
content: z.string(),
|
|
20
|
+
files: z.array(z.string()).optional(),
|
|
21
|
+
favorite: z.number().int().min(0).max(1).optional(),
|
|
22
|
+
error: z.any().optional(),
|
|
23
|
+
|
|
24
|
+
plugin: PluginSchema.optional(),
|
|
25
|
+
pluginState: z.any().optional(),
|
|
26
|
+
fromModel: z.string().optional(),
|
|
27
|
+
translate: TranslateSchema.optional().or(z.null()),
|
|
28
|
+
tts: z.any().optional(),
|
|
29
|
+
|
|
30
|
+
// foreign keys
|
|
31
|
+
parentId: z.string().optional(),
|
|
32
|
+
quotaId: z.string().optional(),
|
|
33
|
+
sessionId: z.string(),
|
|
34
|
+
topicId: z.string().optional(),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export type DB_Message = z.infer<typeof DB_MessageSchema>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import { LobeMetaDataSchema } from '@/types/meta';
|
|
4
|
+
|
|
5
|
+
const fewShotsSchema = z.array(
|
|
6
|
+
z.object({
|
|
7
|
+
content: z.string(),
|
|
8
|
+
role: z.string(),
|
|
9
|
+
}),
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
const ttsSchema = z.object({
|
|
13
|
+
showAllLocaleVoice: z.boolean().optional(),
|
|
14
|
+
sttLocale: z.string().default('auto'),
|
|
15
|
+
ttsService: z.string().default('openai'),
|
|
16
|
+
voice: z
|
|
17
|
+
.object({
|
|
18
|
+
edge: z.string().optional(),
|
|
19
|
+
microsoft: z.string().optional(),
|
|
20
|
+
openai: z.string().default(''),
|
|
21
|
+
})
|
|
22
|
+
.optional(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const AgentSchema = z.object({
|
|
26
|
+
autoCreateTopicThreshold: z.number().default(2),
|
|
27
|
+
compressThreshold: z.number().optional(),
|
|
28
|
+
displayMode: z.enum(['chat', 'docs']).optional(),
|
|
29
|
+
enableAutoCreateTopic: z.boolean().default(true),
|
|
30
|
+
enableCompressThreshold: z.boolean().optional(),
|
|
31
|
+
enableHistoryCount: z.boolean().optional(),
|
|
32
|
+
enableMaxTokens: z.boolean().optional(),
|
|
33
|
+
fewShots: fewShotsSchema.optional(),
|
|
34
|
+
historyCount: z.number().default(8).optional(),
|
|
35
|
+
inputTemplate: z.string().optional(),
|
|
36
|
+
model: z.string().default('gpt-3.5-turbo'),
|
|
37
|
+
params: z.object({
|
|
38
|
+
frequency_penalty: z.number().default(0).optional(),
|
|
39
|
+
max_tokens: z.number().optional(),
|
|
40
|
+
presence_penalty: z.number().default(0).optional(),
|
|
41
|
+
temperature: z.number().default(0.6).optional(),
|
|
42
|
+
top_p: z.number().default(1).optional(),
|
|
43
|
+
}),
|
|
44
|
+
plugins: z.array(z.string()).optional(),
|
|
45
|
+
systemRole: z.string().default(''),
|
|
46
|
+
tts: ttsSchema.optional(),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export const DB_SessionSchema = z.object({
|
|
50
|
+
config: AgentSchema,
|
|
51
|
+
group: z.string().default('default'),
|
|
52
|
+
meta: LobeMetaDataSchema,
|
|
53
|
+
type: z.enum(['agent', 'group']).default('agent'),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export type DB_Session = z.infer<typeof DB_SessionSchema>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
export const DB_TopicSchema = z.object({
|
|
5
|
+
title: z.string(),
|
|
6
|
+
favorite: z.number().int().default(0),
|
|
7
|
+
|
|
8
|
+
// foreign keys
|
|
9
|
+
sessionId: z.string().optional(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export type DB_Topic = z.infer<typeof DB_TopicSchema>;
|
|
@@ -114,7 +114,14 @@ const AgentConfig = memo(() => {
|
|
|
114
114
|
const model: ItemGroup = {
|
|
115
115
|
children: [
|
|
116
116
|
{
|
|
117
|
-
children:
|
|
117
|
+
children: (
|
|
118
|
+
<Select
|
|
119
|
+
options={modelList.map(({ name, displayName }) => ({
|
|
120
|
+
label: displayName,
|
|
121
|
+
value: name,
|
|
122
|
+
}))}
|
|
123
|
+
/>
|
|
124
|
+
),
|
|
118
125
|
desc: t('settingModel.model.desc'),
|
|
119
126
|
label: t('settingModel.model.title'),
|
|
120
127
|
name: 'model',
|
|
@@ -7,8 +7,8 @@ import { useTranslation } from 'react-i18next';
|
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
9
|
import { useTTS } from '@/hooks/useTTS';
|
|
10
|
+
import { TTSServer } from '@/types/agent';
|
|
10
11
|
import { ChatMessageError } from '@/types/chatMessage';
|
|
11
|
-
import { TTSServer } from '@/types/session';
|
|
12
12
|
import { getMessageError } from '@/utils/fetch';
|
|
13
13
|
|
|
14
14
|
interface SelectWithTTSPreviewProps extends SelectProps {
|
|
@@ -5,8 +5,8 @@ import { chainSummaryAgentName } from '@/chains/summaryAgentName';
|
|
|
5
5
|
import { chainSummaryDescription } from '@/chains/summaryDescription';
|
|
6
6
|
import { chainSummaryTags } from '@/chains/summaryTags';
|
|
7
7
|
import { chatService } from '@/services/chat';
|
|
8
|
+
import { LobeAgentConfig } from '@/types/agent';
|
|
8
9
|
import { MetaData } from '@/types/meta';
|
|
9
|
-
import { LobeAgentConfig } from '@/types/session';
|
|
10
10
|
import { setNamespace } from '@/utils/storeDebug';
|
|
11
11
|
|
|
12
12
|
import { SessionLoadingState } from '../store/initialState';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_AGENT_META } from '@/const/meta';
|
|
2
2
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
3
3
|
import { MetaData } from '@/types/meta';
|
|
4
|
-
import { LobeAgentConfig } from '@/types/
|
|
4
|
+
import { LobeAgentConfig } from '@/types/agent';
|
|
5
5
|
|
|
6
6
|
export interface State {
|
|
7
7
|
autocompleteLoading: SessionLoadingState;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { produce } from 'immer';
|
|
2
2
|
|
|
3
3
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
4
|
-
import { LobeAgentConfig } from '@/types/
|
|
4
|
+
import { LobeAgentConfig } from '@/types/agent';
|
|
5
5
|
import { merge } from '@/utils/merge';
|
|
6
6
|
|
|
7
7
|
export type ConfigDispatch =
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { Icon } from '@lobehub/ui';
|
|
2
|
+
import { Button, Result, Table, Upload } from 'antd';
|
|
3
|
+
import { createStyles } from 'antd-style';
|
|
4
|
+
import { BadgeCheck, ImportIcon } from 'lucide-react';
|
|
5
|
+
import React, { ReactNode, memo, useState } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { Center, Flexbox } from 'react-layout-kit';
|
|
8
|
+
|
|
9
|
+
import DataStyleModal from '@/components/DataStyleModal';
|
|
10
|
+
import { useImportConfig } from '@/hooks/useImportConfig';
|
|
11
|
+
import { ImportResult, ImportResults } from '@/services/config';
|
|
12
|
+
|
|
13
|
+
const useStyles = createStyles(({ css, token }) => {
|
|
14
|
+
const size = 28;
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
loader: css`
|
|
18
|
+
transform: translateX(-${size * 2}px);
|
|
19
|
+
|
|
20
|
+
aspect-ratio: 1;
|
|
21
|
+
width: 6px;
|
|
22
|
+
|
|
23
|
+
color: ${token.colorPrimary};
|
|
24
|
+
|
|
25
|
+
border-radius: 50%;
|
|
26
|
+
box-shadow:
|
|
27
|
+
${size}px -${size}px 0 0,
|
|
28
|
+
${size * 2}px -${size}px 0 0,
|
|
29
|
+
${size * 3}px -${size}px 0 0,
|
|
30
|
+
${size}px 0 0 5px,
|
|
31
|
+
${size * 2}px 0 0 5px,
|
|
32
|
+
${size * 3}px 0 0 5px,
|
|
33
|
+
${size}px ${size}px 0 0,
|
|
34
|
+
${size * 2}px ${size}px 0 0,
|
|
35
|
+
${size * 3}px ${size}px 0 0;
|
|
36
|
+
|
|
37
|
+
animation: loading 2s infinite linear;
|
|
38
|
+
|
|
39
|
+
@keyframes loading {
|
|
40
|
+
12.5% {
|
|
41
|
+
box-shadow:
|
|
42
|
+
${size}px -${size}px 0 0,
|
|
43
|
+
${size * 2}px -${size}px 0 0,
|
|
44
|
+
${size * 3}px -${size}px 0 5px,
|
|
45
|
+
${size}px 0 0 5px,
|
|
46
|
+
${size * 2}px 0 0 0,
|
|
47
|
+
${size * 3}px 0 0 5px,
|
|
48
|
+
${size}px ${size}px 0 0,
|
|
49
|
+
${size * 2}px ${size}px 0 0,
|
|
50
|
+
${size * 3}px ${size}px 0 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
25% {
|
|
54
|
+
box-shadow:
|
|
55
|
+
${size}px -${size}px 0 5px,
|
|
56
|
+
${size * 2}px -${size}px 0 0,
|
|
57
|
+
${size * 3}px -${size}px 0 5px,
|
|
58
|
+
${size}px 0 0 0,
|
|
59
|
+
${size * 2}px 0 0 0,
|
|
60
|
+
${size * 3}px 0 0 0,
|
|
61
|
+
${size}px ${size}px 0 0,
|
|
62
|
+
${size * 2}px ${size}px 0 5px,
|
|
63
|
+
${size * 3}px ${size}px 0 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
50% {
|
|
67
|
+
box-shadow:
|
|
68
|
+
${size}px -${size}px 0 5px,
|
|
69
|
+
${size * 2}px -${size}px 0 5px,
|
|
70
|
+
${size * 3}px -${size}px 0 0,
|
|
71
|
+
${size}px 0 0 0,
|
|
72
|
+
${size * 2}px 0 0 0,
|
|
73
|
+
${size * 3}px 0 0 0,
|
|
74
|
+
${size}px ${size}px 0 0,
|
|
75
|
+
${size * 2}px ${size}px 0 0,
|
|
76
|
+
${size * 3}px ${size}px 0 5px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
62.5% {
|
|
80
|
+
box-shadow:
|
|
81
|
+
${size}px -${size}px 0 0,
|
|
82
|
+
${size * 2}px -${size}px 0 0,
|
|
83
|
+
${size * 3}px -${size}px 0 0,
|
|
84
|
+
${size}px 0 0 5px,
|
|
85
|
+
${size * 2}px 0 0 0,
|
|
86
|
+
${size * 3}px 0 0 0,
|
|
87
|
+
${size}px ${size}px 0 0,
|
|
88
|
+
${size * 2}px ${size}px 0 5px,
|
|
89
|
+
${size * 3}px ${size}px 0 5px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
75% {
|
|
93
|
+
box-shadow:
|
|
94
|
+
${size}px -${size}px 0 0,
|
|
95
|
+
${size * 2}px -${size}px 0 5px,
|
|
96
|
+
${size * 3}px -${size}px 0 0,
|
|
97
|
+
${size}px 0 0 0,
|
|
98
|
+
${size * 2}px 0 0 0,
|
|
99
|
+
${size * 3}px 0 0 5px,
|
|
100
|
+
${size}px ${size}px 0 0,
|
|
101
|
+
${size * 2}px ${size}px 0 0,
|
|
102
|
+
${size * 3}px ${size}px 0 5px;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
87.5% {
|
|
106
|
+
box-shadow:
|
|
107
|
+
${size}px -${size}px 0 0,
|
|
108
|
+
${size * 2}px -${size}px 0 5px,
|
|
109
|
+
${size * 3}px -${size}px 0 0,
|
|
110
|
+
${size}px 0 0 0,
|
|
111
|
+
${size * 2}px 0 0 5px,
|
|
112
|
+
${size * 3}px 0 0 0,
|
|
113
|
+
${size}px ${size}px 0 5px,
|
|
114
|
+
${size * 2}px ${size}px 0 0,
|
|
115
|
+
${size * 3}px ${size}px 0 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
`,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
enum ImportState {
|
|
123
|
+
Start,
|
|
124
|
+
Loading,
|
|
125
|
+
Finished,
|
|
126
|
+
Close,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface DataImporterProps {
|
|
130
|
+
children?: ReactNode;
|
|
131
|
+
onFinishImport?: () => void;
|
|
132
|
+
}
|
|
133
|
+
const DataImporter = memo<DataImporterProps>(({ children, onFinishImport }) => {
|
|
134
|
+
const { t } = useTranslation('common');
|
|
135
|
+
const { importConfig } = useImportConfig();
|
|
136
|
+
const [duration, setDuration] = useState(0);
|
|
137
|
+
const [importState, setImportState] = useState(ImportState.Start);
|
|
138
|
+
const [importData, setImportData] = useState<ImportResults | undefined>();
|
|
139
|
+
const { styles } = useStyles();
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<>
|
|
143
|
+
<DataStyleModal
|
|
144
|
+
icon={ImportIcon}
|
|
145
|
+
open={importState === ImportState.Loading || importState === ImportState.Finished}
|
|
146
|
+
title={t('importModal.title')}
|
|
147
|
+
width={importState === ImportState.Finished ? 500 : 400}
|
|
148
|
+
>
|
|
149
|
+
<Center
|
|
150
|
+
gap={24}
|
|
151
|
+
padding={40}
|
|
152
|
+
style={{
|
|
153
|
+
paddingBlock: importState === ImportState.Finished ? 0 : undefined,
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
{importState === ImportState.Finished ? (
|
|
157
|
+
// TODO: 在这里加个撒花效果
|
|
158
|
+
<Result
|
|
159
|
+
extra={
|
|
160
|
+
<Button
|
|
161
|
+
onClick={() => {
|
|
162
|
+
setImportState(ImportState.Close);
|
|
163
|
+
|
|
164
|
+
onFinishImport?.();
|
|
165
|
+
}}
|
|
166
|
+
size={'large'}
|
|
167
|
+
type={'primary'}
|
|
168
|
+
>
|
|
169
|
+
{t('importModal.finish.start')}
|
|
170
|
+
</Button>
|
|
171
|
+
}
|
|
172
|
+
icon={<Icon icon={BadgeCheck} />}
|
|
173
|
+
status={'success'}
|
|
174
|
+
style={{ paddingBlock: 24 }}
|
|
175
|
+
subTitle={
|
|
176
|
+
// if there is no importData, means it's only import the settings
|
|
177
|
+
!importData ? (
|
|
178
|
+
t('importModal.finish.onlySettings')
|
|
179
|
+
) : (
|
|
180
|
+
<Flexbox gap={16} width={400}>
|
|
181
|
+
{t('importModal.finish.subTitle', { duration: (duration / 1000).toFixed(2) })}
|
|
182
|
+
<Table
|
|
183
|
+
bordered
|
|
184
|
+
columns={[
|
|
185
|
+
{ dataIndex: 'title', title: t('importModal.result.type') },
|
|
186
|
+
{ dataIndex: 'added', title: t('importModal.result.added') },
|
|
187
|
+
{ dataIndex: 'skips', title: t('importModal.result.skips') },
|
|
188
|
+
{ dataIndex: 'error', title: t('importModal.result.errors') },
|
|
189
|
+
]}
|
|
190
|
+
dataSource={Object.entries(importData).map(
|
|
191
|
+
([item, value]: [string, ImportResult]) => ({
|
|
192
|
+
added: value.added,
|
|
193
|
+
error: value.errors,
|
|
194
|
+
skips: value.skips,
|
|
195
|
+
title: t(`importModal.result.${item as keyof ImportResults}`),
|
|
196
|
+
}),
|
|
197
|
+
)}
|
|
198
|
+
pagination={false}
|
|
199
|
+
size={'small'}
|
|
200
|
+
/>
|
|
201
|
+
</Flexbox>
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
title={t('importModal.finish.title')}
|
|
205
|
+
/>
|
|
206
|
+
) : (
|
|
207
|
+
<>
|
|
208
|
+
<Center style={{ height: 80 }}>
|
|
209
|
+
<div className={styles.loader} />
|
|
210
|
+
</Center>
|
|
211
|
+
<p>{t('importModal.loading')}</p>
|
|
212
|
+
</>
|
|
213
|
+
)}
|
|
214
|
+
</Center>
|
|
215
|
+
</DataStyleModal>
|
|
216
|
+
<Upload
|
|
217
|
+
beforeUpload={async (file) => {
|
|
218
|
+
setImportState(ImportState.Loading);
|
|
219
|
+
const time = Date.now();
|
|
220
|
+
const data = await importConfig(file);
|
|
221
|
+
|
|
222
|
+
if (data) {
|
|
223
|
+
setImportData(data);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
setDuration(Date.now() - time);
|
|
227
|
+
setImportState(ImportState.Finished);
|
|
228
|
+
|
|
229
|
+
return false;
|
|
230
|
+
}}
|
|
231
|
+
maxCount={1}
|
|
232
|
+
showUploadList={false}
|
|
233
|
+
>
|
|
234
|
+
{children}
|
|
235
|
+
</Upload>
|
|
236
|
+
</>
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
export default DataImporter;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Icon } from '@lobehub/ui';
|
|
2
|
+
import { App, FloatButton, Spin } from 'antd';
|
|
3
|
+
import { DatabaseIcon, Loader2 } from 'lucide-react';
|
|
4
|
+
import { memo, useState } from 'react';
|
|
5
|
+
|
|
6
|
+
import { debugService } from '@/services/debug';
|
|
7
|
+
|
|
8
|
+
const DebugUI = memo(() => {
|
|
9
|
+
const [loading, setLoading] = useState(false);
|
|
10
|
+
const { message } = App.useApp();
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
{loading && <Spin fullscreen />}
|
|
14
|
+
<FloatButton
|
|
15
|
+
icon={<Icon icon={loading ? Loader2 : DatabaseIcon} spin={loading} />}
|
|
16
|
+
onClick={async () => {
|
|
17
|
+
setLoading(true);
|
|
18
|
+
|
|
19
|
+
const startTime = Date.now();
|
|
20
|
+
|
|
21
|
+
await debugService.insertLargeDataToDB();
|
|
22
|
+
|
|
23
|
+
const duration = Date.now() - startTime;
|
|
24
|
+
|
|
25
|
+
setLoading(false);
|
|
26
|
+
message.success(`插入成功,耗时:${(duration / 1000).toFixed(1)} s`);
|
|
27
|
+
}}
|
|
28
|
+
tooltip={'性能压测,插入100w数据'}
|
|
29
|
+
/>
|
|
30
|
+
</>
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export default DebugUI;
|