@lobehub/chat 0.107.15 → 0.108.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.
@@ -0,0 +1,109 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+
3
+ import { LobeAgentConfig } from '@/types/agent';
4
+ import { ChatMessage } from '@/types/chatMessage';
5
+ import { OpenAIChatMessage } from '@/types/openai/chat';
6
+ import { encodeAsync } from '@/utils/tokenizer';
7
+ import * as tokenizerObj from '@/utils/tokenizer';
8
+
9
+ import { chatHelpers } from './helpers';
10
+
11
+ // Mock encodeAsync function
12
+ vi.mock('@/utils/tokenizer', () => ({
13
+ encodeAsync: vi.fn((text) => Promise.resolve(text.length)),
14
+ }));
15
+
16
+ describe('chatHelpers', () => {
17
+ describe('getMessagesTokenCount', () => {
18
+ it('returns token count for a list of messages', async () => {
19
+ const messages = [{ content: 'Hello' }, { content: 'World' }] as OpenAIChatMessage[];
20
+ const tokenCount = await chatHelpers.getMessagesTokenCount(messages);
21
+ expect(tokenCount).toBe('HelloWorld'.length);
22
+ });
23
+
24
+ it('returns 0 for an empty array', async () => {
25
+ const tokenCount = await chatHelpers.getMessagesTokenCount([]);
26
+ expect(tokenCount).toBe(0);
27
+ });
28
+
29
+ it('handles messages with empty content', async () => {
30
+ const messages = [
31
+ { content: 'Hello' },
32
+ { content: '' },
33
+ { content: 'World' },
34
+ ] as OpenAIChatMessage[];
35
+ const tokenCount = await chatHelpers.getMessagesTokenCount(messages);
36
+ expect(tokenCount).toBe('HelloWorld'.length);
37
+ });
38
+
39
+ it('throws an error when encodeAsync fails', async () => {
40
+ vi.spyOn(tokenizerObj, 'encodeAsync').mockRejectedValue(new Error('Test error'));
41
+ await expect(
42
+ chatHelpers.getMessagesTokenCount([{ content: 'Hello' }] as OpenAIChatMessage[]),
43
+ ).rejects.toThrow('Test error');
44
+ });
45
+ });
46
+
47
+ describe('getMessageById', () => {
48
+ const messages = [
49
+ { id: '1', content: 'Hello' },
50
+ { id: '2', content: 'World' },
51
+ ] as ChatMessage[];
52
+
53
+ it('finds a message by id', () => {
54
+ const message = chatHelpers.getMessageById(messages, '1');
55
+ expect(message).toEqual({ id: '1', content: 'Hello' });
56
+ });
57
+
58
+ it('returns undefined for an invalid id', () => {
59
+ const message = chatHelpers.getMessageById(messages, '3');
60
+ expect(message).toBeUndefined();
61
+ });
62
+
63
+ it('returns undefined for an empty array', () => {
64
+ const message = chatHelpers.getMessageById([], '1');
65
+ expect(message).toBeUndefined();
66
+ });
67
+ });
68
+
69
+ describe('getSlicedMessagesWithConfig', () => {
70
+ const messages = [
71
+ { id: '1', content: 'First' },
72
+ { id: '2', content: 'Second' },
73
+ { id: '3', content: 'Third' },
74
+ ] as ChatMessage[];
75
+
76
+ it('returns all messages if history is disabled', () => {
77
+ const config = { enableHistoryCount: false, historyCount: 0 } as LobeAgentConfig;
78
+ const slicedMessages = chatHelpers.getSlicedMessagesWithConfig(messages, config);
79
+ expect(slicedMessages).toEqual(messages);
80
+ });
81
+
82
+ it('returns last N messages based on historyCount', () => {
83
+ const config = { enableHistoryCount: true, historyCount: 2 } as LobeAgentConfig;
84
+ const slicedMessages = chatHelpers.getSlicedMessagesWithConfig(messages, config);
85
+ expect(slicedMessages).toEqual([
86
+ { id: '2', content: 'Second' },
87
+ { id: '3', content: 'Third' },
88
+ ]);
89
+ });
90
+
91
+ it('returns empty array when historyCount is negative', () => {
92
+ const config = { enableHistoryCount: true, historyCount: -1 } as LobeAgentConfig;
93
+ const slicedMessages = chatHelpers.getSlicedMessagesWithConfig(messages, config);
94
+ expect(slicedMessages).toEqual([]);
95
+ });
96
+
97
+ it('returns all messages if historyCount exceeds the array length', () => {
98
+ const config = { enableHistoryCount: true, historyCount: 5 } as LobeAgentConfig;
99
+ const slicedMessages = chatHelpers.getSlicedMessagesWithConfig(messages, config);
100
+ expect(slicedMessages).toEqual(messages);
101
+ });
102
+
103
+ it('returns an empty array for an empty message array', () => {
104
+ const config = { enableHistoryCount: true, historyCount: 2 } as LobeAgentConfig;
105
+ const slicedMessages = chatHelpers.getSlicedMessagesWithConfig([], config);
106
+ expect(slicedMessages).toEqual([]);
107
+ });
108
+ });
109
+ });
@@ -6,18 +6,25 @@ import { encodeAsync } from '@/utils/tokenizer';
6
6
  export const getMessagesTokenCount = async (messages: OpenAIChatMessage[]) =>
7
7
  encodeAsync(messages.map((m) => m.content).join(''));
8
8
 
9
+ export const getMessageById = (messages: ChatMessage[], id: string) =>
10
+ messages.find((m) => m.id === id);
11
+
9
12
  const getSlicedMessagesWithConfig = (
10
13
  messages: ChatMessage[],
11
14
  config: LobeAgentConfig,
12
15
  ): ChatMessage[] => {
13
- // 如果没有开启历史消息数限制,或者限制为 0,则直接返回
16
+ // if historyCount is not enabled or set to 0, return all messages
14
17
  if (!config.enableHistoryCount || !config.historyCount) return messages;
15
18
 
16
- // 如果开启了,则返回尾部的N条消息
17
- return messages.reverse().slice(0, config.historyCount).reverse();
19
+ // if historyCount is negative, return empty array
20
+ if (config.historyCount <= 0) return [];
21
+
22
+ // if historyCount is positive, return last N messages
23
+ return messages.slice(-config.historyCount);
18
24
  };
19
25
 
20
26
  export const chatHelpers = {
27
+ getMessageById,
21
28
  getMessagesTokenCount,
22
29
  getSlicedMessagesWithConfig,
23
30
  };
@@ -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
+ });
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
- import { ChatStore, ChatStoreState } from '@/store/chat';
3
+ import { ChatStore } from '@/store/chat';
4
4
  import { initialState } from '@/store/chat/initialState';
5
5
  import { merge } from '@/utils/merge';
6
6
 
@@ -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 = (s: ChatStore): ChatMessage[] => {
51
- const data = currentChats(s);
52
-
53
- const isBrandNewChat = data.length === 0;
54
-
55
- if (!isBrandNewChat) return data;
56
-
57
- const [activeId, isInbox] = [s.activeId, s.activeId === INBOX_SESSION_ID];
58
- const meta = agentSelectors.currentAgentMeta(useSessionStore.getState());
59
-
60
- const inboxMsg = t('inbox.defaultMessage', { ns: 'chat' });
61
- const agentSystemRoleMsg = t('agentDefaultMessageWithSystemRole', {
62
- name: meta.title || t('defaultAgent'),
63
- ns: 'chat',
64
- systemRole: meta.description,
65
- });
66
- const agentMsg = t('agentDefaultMessage', {
67
- id: activeId,
68
- name: meta.title || t('defaultAgent'),
69
- ns: 'chat',
70
- });
71
-
72
- const emptyInboxGuideMessage = {
73
- content: isInbox ? inboxMsg : !!meta.description ? agentSystemRoleMsg : agentMsg,
74
- createdAt: initTime,
75
- extra: {},
76
- id: 'default',
77
- meta: merge({ avatar: DEFAULT_INBOX_AVATAR }, meta),
78
- role: 'assistant',
79
- updatedAt: initTime,
80
- } as ChatMessage;
81
-
82
- return [emptyInboxGuideMessage];
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 t = setNamespace('image');
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, t('clearImageList'));
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
- t('removeFile'),
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
- t('setImageMapItem'),
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
- t('uploadFile'),
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 t = setNamespace('settings');
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, t('updateDefaultAgent', agent));
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 t = setNamespace('settings');
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, t('switchSideBar', key));
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 }, t('toggleAgentPanel', newValue) as string);
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 }, t('toggleMobileTopic', newValue) as string);
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 }, t('toggleMobileTopic', newValue) as string);
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, t('checkLatestVersion'));
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 t = setNamespace('settings');
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, t('resetDefaultAgent'));
61
+ set({ settings }, false, n('resetDefaultAgent'));
62
62
  },
63
63
  resetSettings: () => {
64
- set({ settings: DEFAULT_SETTINGS }, false, t('resetSettings'));
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, t('setSettings', settings));
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 t = setNamespace('customPlugin');
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, t('dispatchCustomPluginList', payload));
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, t('saveToCustomPluginList'));
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
- t('updateNewDevPlugin'),
61
+ n('updateNewDevPlugin'),
62
62
  );
63
63
  },
64
64
  });