@lobehub/chat 0.107.14 → 0.107.16
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 +12 -25
- package/README.zh-CN.md +10 -25
- package/package.json +3 -3
- package/src/app/chat/features/Conversation/ChatList/index.tsx +2 -2
- package/src/database/models/__tests__/topic.test.ts +40 -0
- package/src/database/models/topic.ts +9 -2
- package/src/store/chat/actions/enhance.ts +2 -2
- package/src/store/chat/actions/message.ts +7 -7
- package/src/store/chat/actions/plugin.ts +2 -2
- package/src/store/chat/actions/topic.test.ts +391 -0
- package/src/store/chat/actions/topic.ts +6 -12
- package/src/store/chat/helpers.test.ts +109 -0
- package/src/store/chat/helpers.ts +10 -3
- package/src/store/chat/selectors/__tests__/chat.test.ts +251 -0
- package/src/store/chat/selectors/__tests__/topic.test.ts +1 -1
- package/src/store/chat/selectors/chat.ts +38 -38
- package/src/store/file/slices/images/action.ts +5 -5
- package/src/store/global/slices/agent.ts +2 -2
- package/src/store/global/slices/common.ts +6 -6
- package/src/store/global/slices/settings.ts +4 -4
- package/src/store/plugin/slices/customPlugin/action.ts +4 -4
- package/src/store/plugin/slices/plugin/action.ts +8 -8
- package/src/store/session/slices/session/action.ts +4 -4
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { DEFAULT_INBOX_AVATAR } from '@/const/meta';
|
|
4
|
+
import { INBOX_SESSION_ID } from '@/const/session';
|
|
5
|
+
import { ChatStore } from '@/store/chat';
|
|
6
|
+
import { initialState } from '@/store/chat/initialState';
|
|
7
|
+
import { useSessionStore } from '@/store/session';
|
|
8
|
+
import { ChatMessage } from '@/types/chatMessage';
|
|
9
|
+
import { MetaData } from '@/types/meta';
|
|
10
|
+
import { merge } from '@/utils/merge';
|
|
11
|
+
|
|
12
|
+
import { chatSelectors } from '../chat';
|
|
13
|
+
|
|
14
|
+
vi.mock('i18next', () => ({
|
|
15
|
+
t: vi.fn((key) => key), // Simplified mock return value
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
const initialStore = initialState as ChatStore;
|
|
19
|
+
|
|
20
|
+
const mockMessages = [
|
|
21
|
+
{
|
|
22
|
+
id: 'msg1',
|
|
23
|
+
content: 'Hello World',
|
|
24
|
+
role: 'user',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'msg2',
|
|
28
|
+
content: 'Goodbye World',
|
|
29
|
+
role: 'user',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'msg3',
|
|
33
|
+
content: 'Function Message',
|
|
34
|
+
role: 'function',
|
|
35
|
+
plugin: {
|
|
36
|
+
arguments: ['arg1', 'arg2'],
|
|
37
|
+
identifier: 'func1',
|
|
38
|
+
type: 'pluginType',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
] as ChatMessage[];
|
|
42
|
+
|
|
43
|
+
const mockedChats = [
|
|
44
|
+
{
|
|
45
|
+
id: 'msg1',
|
|
46
|
+
content: 'Hello World',
|
|
47
|
+
role: 'user',
|
|
48
|
+
meta: {
|
|
49
|
+
avatar: '😀',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'msg2',
|
|
54
|
+
content: 'Goodbye World',
|
|
55
|
+
role: 'user',
|
|
56
|
+
meta: {
|
|
57
|
+
avatar: '😀',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'msg3',
|
|
62
|
+
content: 'Function Message',
|
|
63
|
+
role: 'function',
|
|
64
|
+
meta: {
|
|
65
|
+
avatar: '🧩',
|
|
66
|
+
title: 'plugin-unknown',
|
|
67
|
+
},
|
|
68
|
+
plugin: {
|
|
69
|
+
arguments: ['arg1', 'arg2'],
|
|
70
|
+
identifier: 'func1',
|
|
71
|
+
type: 'pluginType',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
] as ChatMessage[];
|
|
75
|
+
|
|
76
|
+
const mockChatStore = { messages: mockMessages } as ChatStore;
|
|
77
|
+
|
|
78
|
+
describe('chatSelectors', () => {
|
|
79
|
+
describe('getMessageById', () => {
|
|
80
|
+
it('should return undefined if the message with the given id does not exist', () => {
|
|
81
|
+
const message = chatSelectors.getMessageById('non-existent-id')(initialStore);
|
|
82
|
+
expect(message).toBeUndefined();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should return the message object with the matching id', () => {
|
|
86
|
+
const state = merge(initialStore, { messages: mockMessages });
|
|
87
|
+
const message = chatSelectors.getMessageById('msg1')(state);
|
|
88
|
+
expect(message).toEqual(mockMessages[0]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return the message with the matching id', () => {
|
|
92
|
+
const message = chatSelectors.getMessageById('msg1')(mockChatStore);
|
|
93
|
+
expect(message).toEqual(mockMessages[0]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should return undefined if no message matches the id', () => {
|
|
97
|
+
const message = chatSelectors.getMessageById('nonexistent')(mockChatStore);
|
|
98
|
+
expect(message).toBeUndefined();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('getFunctionMessageProps', () => {
|
|
103
|
+
it('should return the properties of a function message', () => {
|
|
104
|
+
const state = merge(initialStore, {
|
|
105
|
+
messages: mockMessages,
|
|
106
|
+
chatLoadingId: 'msg3', // Assuming this id represents a loading state
|
|
107
|
+
});
|
|
108
|
+
const props = chatSelectors.getFunctionMessageProps(mockMessages[2])(state);
|
|
109
|
+
expect(props).toEqual({
|
|
110
|
+
arguments: ['arg1', 'arg2'],
|
|
111
|
+
command: mockMessages[2].plugin,
|
|
112
|
+
content: 'Function Message',
|
|
113
|
+
id: 'func1',
|
|
114
|
+
loading: true,
|
|
115
|
+
type: 'pluginType',
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should return loading as false if the message id is not the current loading id', () => {
|
|
120
|
+
const state = merge(initialStore, { messages: mockMessages, chatLoadingId: 'msg1' });
|
|
121
|
+
const props = chatSelectors.getFunctionMessageProps(mockMessages[2])(state);
|
|
122
|
+
expect(props.loading).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should return correct properties when no plugin is present', () => {
|
|
126
|
+
const messageWithoutPlugin = {
|
|
127
|
+
id: 'msg4',
|
|
128
|
+
content: 'No Plugin Message',
|
|
129
|
+
role: 'function',
|
|
130
|
+
// No plugin property
|
|
131
|
+
};
|
|
132
|
+
const state = merge(initialStore, {
|
|
133
|
+
messages: [...mockMessages, messageWithoutPlugin],
|
|
134
|
+
chatLoadingId: 'msg1',
|
|
135
|
+
});
|
|
136
|
+
const props = chatSelectors.getFunctionMessageProps(messageWithoutPlugin)(state);
|
|
137
|
+
expect(props).toEqual({
|
|
138
|
+
arguments: undefined,
|
|
139
|
+
command: undefined,
|
|
140
|
+
content: 'No Plugin Message',
|
|
141
|
+
id: undefined,
|
|
142
|
+
loading: false,
|
|
143
|
+
type: undefined,
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('currentChatsWithHistoryConfig', () => {
|
|
149
|
+
it('should slice the messages according to the current agent config', () => {
|
|
150
|
+
const state = merge(initialStore, { messages: mockMessages });
|
|
151
|
+
|
|
152
|
+
const chats = chatSelectors.currentChatsWithHistoryConfig(state);
|
|
153
|
+
expect(chats).toHaveLength(3);
|
|
154
|
+
expect(chats).toEqual(mockedChats);
|
|
155
|
+
});
|
|
156
|
+
it('should slice the messages according to config, assuming historyCount is mocked to 2', async () => {
|
|
157
|
+
const state = merge(initialStore, { messages: mockMessages });
|
|
158
|
+
|
|
159
|
+
useSessionStore.getState().updateAgentConfig({ historyCount: 2, enableHistoryCount: true });
|
|
160
|
+
|
|
161
|
+
const chats = chatSelectors.currentChatsWithHistoryConfig(state);
|
|
162
|
+
|
|
163
|
+
expect(chats).toHaveLength(2);
|
|
164
|
+
expect(chats).toEqual([
|
|
165
|
+
{
|
|
166
|
+
id: 'msg2',
|
|
167
|
+
content: 'Goodbye World',
|
|
168
|
+
role: 'user',
|
|
169
|
+
meta: {
|
|
170
|
+
avatar: '😀',
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: 'msg3',
|
|
175
|
+
content: 'Function Message',
|
|
176
|
+
role: 'function',
|
|
177
|
+
meta: {
|
|
178
|
+
avatar: '🧩',
|
|
179
|
+
title: 'plugin-unknown',
|
|
180
|
+
},
|
|
181
|
+
plugin: {
|
|
182
|
+
arguments: ['arg1', 'arg2'],
|
|
183
|
+
identifier: 'func1',
|
|
184
|
+
type: 'pluginType',
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
]);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('currentChatsWithGuideMessage', () => {
|
|
192
|
+
it('should return existing messages if there are any', () => {
|
|
193
|
+
const state = merge(initialStore, { messages: mockMessages, activeId: 'someActiveId' });
|
|
194
|
+
const chats = chatSelectors.currentChatsWithGuideMessage({} as MetaData)(state);
|
|
195
|
+
expect(chats).toEqual(mockedChats);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should add a guide message if the chat is brand new', () => {
|
|
199
|
+
const state = merge(initialStore, { messages: [], activeId: 'someActiveId' });
|
|
200
|
+
const metaData = { title: 'Mock Agent', description: 'Mock Description' };
|
|
201
|
+
|
|
202
|
+
const chats = chatSelectors.currentChatsWithGuideMessage(metaData)(state);
|
|
203
|
+
|
|
204
|
+
expect(chats).toHaveLength(1);
|
|
205
|
+
expect(chats[0].content).toBeDefined();
|
|
206
|
+
expect(chats[0].meta.avatar).toEqual(DEFAULT_INBOX_AVATAR);
|
|
207
|
+
expect(chats[0].meta).toEqual(expect.objectContaining(metaData));
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should use inbox message for INBOX_SESSION_ID', () => {
|
|
211
|
+
const state = merge(initialStore, { messages: [], activeId: INBOX_SESSION_ID });
|
|
212
|
+
const metaData = { title: 'Mock Agent', description: 'Mock Description' };
|
|
213
|
+
|
|
214
|
+
const chats = chatSelectors.currentChatsWithGuideMessage(metaData)(state);
|
|
215
|
+
|
|
216
|
+
expect(chats[0].content).toEqual('inbox.defaultMessage'); // Assuming translation returns a string containing this
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('should use agent default message for non-inbox sessions', () => {
|
|
220
|
+
const state = merge(initialStore, { messages: [], activeId: 'someActiveId' });
|
|
221
|
+
const metaData = { title: 'Mock Agent' };
|
|
222
|
+
|
|
223
|
+
const chats = chatSelectors.currentChatsWithGuideMessage(metaData)(state);
|
|
224
|
+
|
|
225
|
+
expect(chats[0].content).toMatch('agentDefaultMessage'); // Assuming translation returns a string containing this
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe('chatsMessageString', () => {
|
|
230
|
+
it('should concatenate the contents of all messages returned by currentChatsWithHistoryConfig', () => {
|
|
231
|
+
// Prepare a state with a few messages
|
|
232
|
+
const state = merge(initialStore, {
|
|
233
|
+
messages: mockMessages,
|
|
234
|
+
activeId: 'active-session',
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Assume that the currentChatsWithHistoryConfig will return the last two messages
|
|
238
|
+
const expectedString = mockMessages
|
|
239
|
+
.slice(-2)
|
|
240
|
+
.map((m) => m.content)
|
|
241
|
+
.join('');
|
|
242
|
+
|
|
243
|
+
// Call the selector and verify the result
|
|
244
|
+
const concatenatedString = chatSelectors.chatsMessageString(state);
|
|
245
|
+
expect(concatenatedString).toBe(expectedString);
|
|
246
|
+
|
|
247
|
+
// Restore the mocks after the test
|
|
248
|
+
vi.restoreAllMocks();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
});
|
|
@@ -3,13 +3,14 @@ import { t } from 'i18next';
|
|
|
3
3
|
|
|
4
4
|
import { DEFAULT_INBOX_AVATAR, DEFAULT_USER_AVATAR } from '@/const/meta';
|
|
5
5
|
import { INBOX_SESSION_ID } from '@/const/session';
|
|
6
|
-
import { chatHelpers } from '@/store/chat/helpers';
|
|
7
6
|
import { useGlobalStore } from '@/store/global';
|
|
8
7
|
import { useSessionStore } from '@/store/session';
|
|
9
8
|
import { agentSelectors } from '@/store/session/selectors';
|
|
10
9
|
import { ChatMessage } from '@/types/chatMessage';
|
|
10
|
+
import { MetaData } from '@/types/meta';
|
|
11
11
|
import { merge } from '@/utils/merge';
|
|
12
12
|
|
|
13
|
+
import { chatHelpers } from '../helpers';
|
|
13
14
|
import type { ChatStore } from '../store';
|
|
14
15
|
|
|
15
16
|
const getMeta = (message: ChatMessage) => {
|
|
@@ -47,40 +48,41 @@ const currentChats = (s: ChatStore): ChatMessage[] => {
|
|
|
47
48
|
|
|
48
49
|
const initTime = Date.now();
|
|
49
50
|
// 针对新助手添加初始化时的自定义消息
|
|
50
|
-
const currentChatsWithGuideMessage =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
51
|
+
const currentChatsWithGuideMessage =
|
|
52
|
+
(meta: MetaData) =>
|
|
53
|
+
(s: ChatStore): ChatMessage[] => {
|
|
54
|
+
const data = currentChats(s);
|
|
55
|
+
|
|
56
|
+
const isBrandNewChat = data.length === 0;
|
|
57
|
+
|
|
58
|
+
if (!isBrandNewChat) return data;
|
|
59
|
+
|
|
60
|
+
const [activeId, isInbox] = [s.activeId, s.activeId === INBOX_SESSION_ID];
|
|
61
|
+
|
|
62
|
+
const inboxMsg = t('inbox.defaultMessage', { ns: 'chat' });
|
|
63
|
+
const agentSystemRoleMsg = t('agentDefaultMessageWithSystemRole', {
|
|
64
|
+
name: meta.title || t('defaultAgent'),
|
|
65
|
+
ns: 'chat',
|
|
66
|
+
systemRole: meta.description,
|
|
67
|
+
});
|
|
68
|
+
const agentMsg = t('agentDefaultMessage', {
|
|
69
|
+
id: activeId,
|
|
70
|
+
name: meta.title || t('defaultAgent'),
|
|
71
|
+
ns: 'chat',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const emptyInboxGuideMessage = {
|
|
75
|
+
content: isInbox ? inboxMsg : !!meta.description ? agentSystemRoleMsg : agentMsg,
|
|
76
|
+
createdAt: initTime,
|
|
77
|
+
extra: {},
|
|
78
|
+
id: 'default',
|
|
79
|
+
meta: merge({ avatar: DEFAULT_INBOX_AVATAR }, meta),
|
|
80
|
+
role: 'assistant',
|
|
81
|
+
updatedAt: initTime,
|
|
82
|
+
} as ChatMessage;
|
|
83
|
+
|
|
84
|
+
return [emptyInboxGuideMessage];
|
|
85
|
+
};
|
|
84
86
|
|
|
85
87
|
const currentChatsWithHistoryConfig = (s: ChatStore): ChatMessage[] => {
|
|
86
88
|
const chats = currentChats(s);
|
|
@@ -105,9 +107,7 @@ const getFunctionMessageProps =
|
|
|
105
107
|
type: plugin?.type as LobePluginType,
|
|
106
108
|
});
|
|
107
109
|
|
|
108
|
-
const getMessageById = (id: string) => (s: ChatStore) =>
|
|
109
|
-
return s.messages.find((m) => m.id === id);
|
|
110
|
-
};
|
|
110
|
+
const getMessageById = (id: string) => (s: ChatStore) => chatHelpers.getMessageById(s.messages, id);
|
|
111
111
|
|
|
112
112
|
export const chatSelectors = {
|
|
113
113
|
chatsMessageString,
|
|
@@ -8,7 +8,7 @@ import { setNamespace } from '@/utils/storeDebug';
|
|
|
8
8
|
|
|
9
9
|
import { FileStore } from '../../store';
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const n = setNamespace('image');
|
|
12
12
|
|
|
13
13
|
export interface FileAction {
|
|
14
14
|
clearImageList: () => void;
|
|
@@ -28,7 +28,7 @@ export const createFileSlice: StateCreator<
|
|
|
28
28
|
FileAction
|
|
29
29
|
> = (set, get) => ({
|
|
30
30
|
clearImageList: () => {
|
|
31
|
-
set({ inputFilesList: [] }, false,
|
|
31
|
+
set({ inputFilesList: [] }, false, n('clearImageList'));
|
|
32
32
|
},
|
|
33
33
|
removeAllFiles: async () => {
|
|
34
34
|
await fileService.removeAllFiles();
|
|
@@ -39,7 +39,7 @@ export const createFileSlice: StateCreator<
|
|
|
39
39
|
set(
|
|
40
40
|
({ inputFilesList }) => ({ inputFilesList: inputFilesList.filter((i) => i !== id) }),
|
|
41
41
|
false,
|
|
42
|
-
|
|
42
|
+
n('removeFile'),
|
|
43
43
|
);
|
|
44
44
|
},
|
|
45
45
|
setImageMapItem: (id, item) => {
|
|
@@ -50,7 +50,7 @@ export const createFileSlice: StateCreator<
|
|
|
50
50
|
draft.imagesMap[id] = item;
|
|
51
51
|
}),
|
|
52
52
|
false,
|
|
53
|
-
|
|
53
|
+
n('setImageMapItem'),
|
|
54
54
|
);
|
|
55
55
|
},
|
|
56
56
|
uploadFile: async (file) => {
|
|
@@ -67,7 +67,7 @@ export const createFileSlice: StateCreator<
|
|
|
67
67
|
set(
|
|
68
68
|
({ inputFilesList }) => ({ inputFilesList: [...inputFilesList, data.id] }),
|
|
69
69
|
false,
|
|
70
|
-
|
|
70
|
+
n('uploadFile'),
|
|
71
71
|
);
|
|
72
72
|
} catch (error) {
|
|
73
73
|
// 提示用户上传失败
|
|
@@ -9,7 +9,7 @@ import { setNamespace } from '@/utils/storeDebug';
|
|
|
9
9
|
|
|
10
10
|
import type { GlobalStore } from '../store';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const n = setNamespace('settings');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* 设置操作
|
|
@@ -29,6 +29,6 @@ export const createAgentSlice: StateCreator<
|
|
|
29
29
|
draft.defaultAgent = merge(draft.defaultAgent, agent);
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
set({ settings }, false,
|
|
32
|
+
set({ settings }, false, n('updateDefaultAgent', agent));
|
|
33
33
|
},
|
|
34
34
|
});
|
|
@@ -11,7 +11,7 @@ import { setNamespace } from '@/utils/storeDebug';
|
|
|
11
11
|
import type { GlobalPreference, GlobalState, Guide, SidebarTabKey } from '../initialState';
|
|
12
12
|
import type { GlobalStore } from '../store';
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const n = setNamespace('settings');
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* 设置操作
|
|
@@ -37,25 +37,25 @@ export const createCommonSlice: StateCreator<
|
|
|
37
37
|
CommonAction
|
|
38
38
|
> = (set, get) => ({
|
|
39
39
|
switchSideBar: (key) => {
|
|
40
|
-
set({ sidebarKey: key }, false,
|
|
40
|
+
set({ sidebarKey: key }, false, n('switchSideBar', key));
|
|
41
41
|
},
|
|
42
42
|
toggleChatSideBar: (newValue) => {
|
|
43
43
|
const showChatSideBar =
|
|
44
44
|
typeof newValue === 'boolean' ? newValue : !get().preference.showChatSideBar;
|
|
45
45
|
|
|
46
|
-
get().updatePreference({ showChatSideBar },
|
|
46
|
+
get().updatePreference({ showChatSideBar }, n('toggleAgentPanel', newValue) as string);
|
|
47
47
|
},
|
|
48
48
|
toggleMobileTopic: (newValue) => {
|
|
49
49
|
const mobileShowTopic =
|
|
50
50
|
typeof newValue === 'boolean' ? newValue : !get().preference.mobileShowTopic;
|
|
51
51
|
|
|
52
|
-
get().updatePreference({ mobileShowTopic },
|
|
52
|
+
get().updatePreference({ mobileShowTopic }, n('toggleMobileTopic', newValue) as string);
|
|
53
53
|
},
|
|
54
54
|
toggleSystemRole: (newValue) => {
|
|
55
55
|
const showSystemRole =
|
|
56
56
|
typeof newValue === 'boolean' ? newValue : !get().preference.mobileShowTopic;
|
|
57
57
|
|
|
58
|
-
get().updatePreference({ showSystemRole },
|
|
58
|
+
get().updatePreference({ showSystemRole }, n('toggleMobileTopic', newValue) as string);
|
|
59
59
|
},
|
|
60
60
|
updateGuideState: (guide) => {
|
|
61
61
|
const { updatePreference } = get();
|
|
@@ -75,7 +75,7 @@ export const createCommonSlice: StateCreator<
|
|
|
75
75
|
useSWR('checkLatestVersion', featLatestVersion, {
|
|
76
76
|
onSuccess: (data: string) => {
|
|
77
77
|
if (gt(data, CURRENT_VERSION))
|
|
78
|
-
set({ hasNewVersion: true, latestVersion: data }, false,
|
|
78
|
+
set({ hasNewVersion: true, latestVersion: data }, false, n('checkLatestVersion'));
|
|
79
79
|
},
|
|
80
80
|
}),
|
|
81
81
|
});
|
|
@@ -12,7 +12,7 @@ import { setNamespace } from '@/utils/storeDebug';
|
|
|
12
12
|
|
|
13
13
|
import type { GlobalStore } from '../store';
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const n = setNamespace('settings');
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* 设置操作
|
|
@@ -58,10 +58,10 @@ export const createSettingsSlice: StateCreator<
|
|
|
58
58
|
const settings = produce(get().settings, (draft: GlobalSettings) => {
|
|
59
59
|
draft.defaultAgent = DEFAULT_AGENT;
|
|
60
60
|
});
|
|
61
|
-
set({ settings }, false,
|
|
61
|
+
set({ settings }, false, n('resetDefaultAgent'));
|
|
62
62
|
},
|
|
63
63
|
resetSettings: () => {
|
|
64
|
-
set({ settings: DEFAULT_SETTINGS }, false,
|
|
64
|
+
set({ settings: DEFAULT_SETTINGS }, false, n('resetSettings'));
|
|
65
65
|
},
|
|
66
66
|
setOpenAIConfig: (config) => {
|
|
67
67
|
get().setSettings({ languageModel: { openAI: config } });
|
|
@@ -73,7 +73,7 @@ export const createSettingsSlice: StateCreator<
|
|
|
73
73
|
|
|
74
74
|
if (isEqual(prevSetting, nextSettings)) return;
|
|
75
75
|
|
|
76
|
-
set({ settings: merge(prevSetting, settings) }, false,
|
|
76
|
+
set({ settings: merge(prevSetting, settings) }, false, n('setSettings', settings));
|
|
77
77
|
},
|
|
78
78
|
switchSettingTabs: (tab) => {
|
|
79
79
|
set({ settingsTab: tab });
|
|
@@ -8,7 +8,7 @@ import { PluginStore } from '../../store';
|
|
|
8
8
|
import { defaultCustomPlugin } from './initialState';
|
|
9
9
|
import { CustomPluginListDispatch, devPluginListReducer } from './reducers/customPluginList';
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const n = setNamespace('customPlugin');
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* 代理行为接口
|
|
@@ -40,11 +40,11 @@ export const createCustomPluginSlice: StateCreator<
|
|
|
40
40
|
const { customPluginList } = get();
|
|
41
41
|
|
|
42
42
|
const nextList = devPluginListReducer(customPluginList, payload);
|
|
43
|
-
set({ customPluginList: nextList }, false,
|
|
43
|
+
set({ customPluginList: nextList }, false, n('dispatchCustomPluginList', payload));
|
|
44
44
|
},
|
|
45
45
|
saveToCustomPluginList: (value) => {
|
|
46
46
|
get().dispatchCustomPluginList({ plugin: value, type: 'addItem' });
|
|
47
|
-
set({ newCustomPlugin: defaultCustomPlugin }, false,
|
|
47
|
+
set({ newCustomPlugin: defaultCustomPlugin }, false, n('saveToCustomPluginList'));
|
|
48
48
|
},
|
|
49
49
|
updateCustomPlugin: (id, value) => {
|
|
50
50
|
const { dispatchCustomPluginList, installPlugin } = get();
|
|
@@ -58,7 +58,7 @@ export const createCustomPluginSlice: StateCreator<
|
|
|
58
58
|
set(
|
|
59
59
|
{ newCustomPlugin: merge({}, get().newCustomPlugin, newCustomPlugin) },
|
|
60
60
|
false,
|
|
61
|
-
|
|
61
|
+
n('updateNewDevPlugin'),
|
|
62
62
|
);
|
|
63
63
|
},
|
|
64
64
|
});
|
|
@@ -17,7 +17,7 @@ import { setNamespace } from '@/utils/storeDebug';
|
|
|
17
17
|
import { PluginStore } from '../../store';
|
|
18
18
|
import { PluginDispatch, pluginManifestReducer } from './reducers/manifest';
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const n = setNamespace('plugin');
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* 插件接口
|
|
@@ -73,7 +73,7 @@ export const createPluginSlice: StateCreator<
|
|
|
73
73
|
|
|
74
74
|
await installPlugins(plugins);
|
|
75
75
|
|
|
76
|
-
set({ manifestPrepared: true }, false,
|
|
76
|
+
set({ manifestPrepared: true }, false, n('checkPluginsIsInstalled'));
|
|
77
77
|
},
|
|
78
78
|
deletePluginSettings: (id) => {
|
|
79
79
|
set(
|
|
@@ -81,14 +81,14 @@ export const createPluginSlice: StateCreator<
|
|
|
81
81
|
draft.pluginsSettings[id] = undefined;
|
|
82
82
|
}),
|
|
83
83
|
false,
|
|
84
|
-
|
|
84
|
+
n('deletePluginSettings'),
|
|
85
85
|
);
|
|
86
86
|
},
|
|
87
87
|
dispatchPluginManifest: (payload) => {
|
|
88
88
|
const { pluginManifestMap } = get();
|
|
89
89
|
const nextManifest = pluginManifestReducer(pluginManifestMap, payload);
|
|
90
90
|
|
|
91
|
-
set({ pluginManifestMap: nextManifest }, false,
|
|
91
|
+
set({ pluginManifestMap: nextManifest }, false, n('dispatchPluginManifest', payload));
|
|
92
92
|
},
|
|
93
93
|
installPlugin: async (name) => {
|
|
94
94
|
const plugin = pluginSelectors.getPluginMetaById(name)(get());
|
|
@@ -140,12 +140,12 @@ export const createPluginSlice: StateCreator<
|
|
|
140
140
|
loadPluginStore: async () => {
|
|
141
141
|
const pluginMarketIndex = await pluginService.getPluginList();
|
|
142
142
|
|
|
143
|
-
set({ pluginList: pluginMarketIndex.plugins }, false,
|
|
143
|
+
set({ pluginList: pluginMarketIndex.plugins }, false, n('loadPluginList'));
|
|
144
144
|
|
|
145
145
|
return pluginMarketIndex;
|
|
146
146
|
},
|
|
147
147
|
resetPluginSettings: () => {
|
|
148
|
-
set({ pluginsSettings: {} }, false,
|
|
148
|
+
set({ pluginsSettings: {} }, false, n('resetPluginSettings'));
|
|
149
149
|
},
|
|
150
150
|
updateManifestLoadingState: (key, value) => {
|
|
151
151
|
set(
|
|
@@ -153,7 +153,7 @@ export const createPluginSlice: StateCreator<
|
|
|
153
153
|
draft.pluginManifestLoading[key] = value;
|
|
154
154
|
}),
|
|
155
155
|
false,
|
|
156
|
-
|
|
156
|
+
n('updateManifestLoadingState'),
|
|
157
157
|
);
|
|
158
158
|
},
|
|
159
159
|
updatePluginSettings: (id, settings) => {
|
|
@@ -162,7 +162,7 @@ export const createPluginSlice: StateCreator<
|
|
|
162
162
|
draft.pluginsSettings[id] = merge({}, draft.pluginsSettings[id], settings);
|
|
163
163
|
}),
|
|
164
164
|
false,
|
|
165
|
-
|
|
165
|
+
n('updatePluginSettings'),
|
|
166
166
|
);
|
|
167
167
|
},
|
|
168
168
|
|
|
@@ -18,7 +18,7 @@ import { setNamespace } from '@/utils/storeDebug';
|
|
|
18
18
|
|
|
19
19
|
import { initLobeSession } from './initialState';
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const n = setNamespace('session');
|
|
22
22
|
|
|
23
23
|
const FETCH_SESSIONS_KEY = 'fetchSessions';
|
|
24
24
|
|
|
@@ -80,7 +80,7 @@ export const createSessionSlice: StateCreator<
|
|
|
80
80
|
SessionAction
|
|
81
81
|
> = (set, get) => ({
|
|
82
82
|
activeSession: (sessionId) => {
|
|
83
|
-
set({ activeId: sessionId }, false,
|
|
83
|
+
set({ activeId: sessionId }, false, n('activeSession'));
|
|
84
84
|
},
|
|
85
85
|
|
|
86
86
|
clearSessions: async () => {
|
|
@@ -153,7 +153,7 @@ export const createSessionSlice: StateCreator<
|
|
|
153
153
|
sessions: data,
|
|
154
154
|
},
|
|
155
155
|
false,
|
|
156
|
-
|
|
156
|
+
n('useFetchSessions/onSuccess', data),
|
|
157
157
|
);
|
|
158
158
|
},
|
|
159
159
|
}),
|
|
@@ -161,7 +161,7 @@ export const createSessionSlice: StateCreator<
|
|
|
161
161
|
useSearchSessions: (keyword) =>
|
|
162
162
|
useSWR<LobeSessions>(keyword, sessionService.searchSessions, {
|
|
163
163
|
onSuccess: (data) => {
|
|
164
|
-
set({ searchSessions: data }, false,
|
|
164
|
+
set({ searchSessions: data }, false, n('useSearchSessions(success)', data));
|
|
165
165
|
},
|
|
166
166
|
revalidateOnFocus: false,
|
|
167
167
|
}),
|