@lobehub/chat 1.0.11 → 1.0.13

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.
Files changed (66) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/locales/ar/setting.json +5 -0
  3. package/locales/bg-BG/setting.json +5 -0
  4. package/locales/de-DE/setting.json +5 -0
  5. package/locales/en-US/setting.json +5 -0
  6. package/locales/es-ES/setting.json +5 -0
  7. package/locales/fr-FR/setting.json +5 -0
  8. package/locales/it-IT/setting.json +5 -0
  9. package/locales/ja-JP/setting.json +5 -0
  10. package/locales/ko-KR/setting.json +5 -0
  11. package/locales/nl-NL/setting.json +5 -0
  12. package/locales/pl-PL/setting.json +5 -0
  13. package/locales/pt-BR/setting.json +5 -0
  14. package/locales/ru-RU/setting.json +5 -0
  15. package/locales/tr-TR/setting.json +5 -0
  16. package/locales/vi-VN/setting.json +5 -0
  17. package/locales/zh-CN/setting.json +5 -0
  18. package/locales/zh-TW/setting.json +5 -0
  19. package/package.json +4 -3
  20. package/src/app/(main)/chat/(workspace)/@conversation/default.tsx +1 -1
  21. package/src/app/(main)/chat/settings/features/EditPage.tsx +2 -2
  22. package/src/app/(main)/settings/agent/index.tsx +1 -1
  23. package/src/app/(main)/settings/system-agent/features/AgentMeta.tsx +58 -0
  24. package/src/app/(main)/settings/system-agent/features/Topic.tsx +1 -0
  25. package/src/app/(main)/settings/system-agent/features/Translation.tsx +1 -0
  26. package/src/app/(main)/settings/system-agent/index.tsx +2 -0
  27. package/src/app/(main)/settings/system-agent/page.tsx +1 -1
  28. package/src/const/settings/systemAgent.ts +1 -0
  29. package/src/features/AgentSetting/AgentMeta/AutoGenerateAvatar.tsx +59 -0
  30. package/src/features/AgentSetting/AgentMeta/index.tsx +6 -9
  31. package/src/features/AgentSetting/AgentSettings.tsx +24 -0
  32. package/src/features/AgentSetting/AgentSettingsStore.tsx +14 -0
  33. package/src/features/AgentSetting/StoreUpdater.tsx +10 -5
  34. package/src/features/AgentSetting/hooks/useAgentSettings.ts +31 -0
  35. package/src/features/AgentSetting/index.tsx +3 -26
  36. package/src/features/AgentSetting/store/action.ts +36 -18
  37. package/src/features/ChatInput/useSend.ts +8 -0
  38. package/src/features/Conversation/Error/ErrorJsonViewer.tsx +1 -1
  39. package/src/features/Conversation/Messages/Assistant/ToolCalls/index.tsx +3 -2
  40. package/src/features/Conversation/Messages/Tool/index.tsx +3 -5
  41. package/src/features/Conversation/Messages/components/Arguments.tsx +20 -0
  42. package/src/features/Conversation/Messages/hooks/useYamlArguments.ts +11 -0
  43. package/src/features/ModelSelect/index.tsx +6 -4
  44. package/src/libs/agent-runtime/anthropic/index.test.ts +1 -31
  45. package/src/libs/agent-runtime/anthropic/index.ts +9 -63
  46. package/src/libs/agent-runtime/openai/index.test.ts +7 -7
  47. package/src/libs/agent-runtime/openai/index.ts +0 -6
  48. package/src/libs/agent-runtime/utils/anthropicHelpers.ts +2 -2
  49. package/src/libs/agent-runtime/utils/streams/anthropic.test.ts +102 -28
  50. package/src/libs/agent-runtime/utils/streams/anthropic.ts +29 -12
  51. package/src/libs/agent-runtime/utils/streams/protocol.ts +6 -1
  52. package/src/locales/default/setting.ts +5 -0
  53. package/src/services/message/server.ts +4 -0
  54. package/src/services/message/type.ts +1 -1
  55. package/src/store/agent/slices/chat/initialState.ts +2 -0
  56. package/src/store/chat/slices/message/action.ts +48 -48
  57. package/src/store/chat/slices/message/initialState.ts +2 -0
  58. package/src/store/chat/slices/message/selectors.ts +3 -0
  59. package/src/store/chat/slices/plugin/action.test.ts +15 -15
  60. package/src/store/chat/slices/plugin/action.ts +128 -115
  61. package/src/store/chat/utils/index.ts +19 -0
  62. package/src/store/user/slices/settings/action.ts +8 -2
  63. package/src/store/user/slices/settings/selectors/systemAgent.ts +2 -0
  64. package/src/types/message/index.ts +1 -1
  65. package/src/types/user/settings/systemAgent.ts +3 -0
  66. /package/src/{components/StoreHydration → app/(main)/chat/(workspace)/@conversation/features}/ChatHydration/index.tsx +0 -0
@@ -1,3 +1,4 @@
1
+ /* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
1
2
  import { PluginErrorType } from '@lobehub/chat-plugin-sdk';
2
3
  import { t } from 'i18next';
3
4
  import { Md5 } from 'ts-md5';
@@ -25,11 +26,6 @@ export interface ChatPluginAction {
25
26
  triggerAiMessage?: boolean,
26
27
  ) => Promise<void>;
27
28
 
28
- internal_callPluginApi: (id: string, payload: ChatToolPayload) => Promise<string | undefined>;
29
- internal_invokeDifferentTypePlugin: (id: string, payload: ChatToolPayload) => Promise<any>;
30
- internal_transformToolCalls: (toolCalls: MessageToolCall[]) => ChatToolPayload[];
31
- internal_updatePluginError: (id: string, error: any) => Promise<void>;
32
-
33
29
  invokeBuiltinTool: (id: string, payload: ChatToolPayload) => Promise<void>;
34
30
  invokeDefaultTypePlugin: (id: string, payload: any) => Promise<string | undefined>;
35
31
  invokeMarkdownTypePlugin: (id: string, payload: ChatToolPayload) => Promise<void>;
@@ -41,6 +37,16 @@ export interface ChatPluginAction {
41
37
 
42
38
  triggerToolCalls: (id: string) => Promise<void>;
43
39
  updatePluginState: (id: string, key: string, value: any) => Promise<void>;
40
+
41
+ internal_callPluginApi: (id: string, payload: ChatToolPayload) => Promise<string | undefined>;
42
+ internal_invokeDifferentTypePlugin: (id: string, payload: ChatToolPayload) => Promise<any>;
43
+ internal_togglePluginApiCalling: (
44
+ loading: boolean,
45
+ id?: string,
46
+ action?: string,
47
+ ) => AbortController | undefined;
48
+ internal_transformToolCalls: (toolCalls: MessageToolCall[]) => ChatToolPayload[];
49
+ internal_updatePluginError: (id: string, error: any) => Promise<void>;
44
50
  }
45
51
 
46
52
  export const chatPlugin: StateCreator<
@@ -69,124 +75,17 @@ export const chatPlugin: StateCreator<
69
75
 
70
76
  if (triggerAiMessage) await triggerAIMessage({ parentId: id });
71
77
  },
72
- internal_callPluginApi: async (id, payload) => {
73
- const { internal_updateMessageContent, refreshMessages, internal_toggleChatLoading } = get();
74
- let data: string;
75
-
76
- try {
77
- const abortController = internal_toggleChatLoading(
78
- true,
79
- id,
80
- n('fetchPlugin/start') as string,
81
- );
82
-
83
- const message = chatSelectors.getMessageById(id)(get());
84
-
85
- const res = await chatService.runPluginApi(payload, {
86
- signal: abortController?.signal,
87
- trace: { observationId: message?.observationId, traceId: message?.traceId },
88
- });
89
- data = res.text;
90
-
91
- // save traceId
92
- if (res.traceId) {
93
- await messageService.updateMessage(id, { traceId: res.traceId });
94
- }
95
- } catch (error) {
96
- console.log(error);
97
- const err = error as Error;
98
-
99
- // ignore the aborted request error
100
- if (!err.message.includes('The user aborted a request.')) {
101
- await messageService.updateMessageError(id, error as any);
102
- await refreshMessages();
103
- }
104
-
105
- data = '';
106
- }
107
-
108
- internal_toggleChatLoading(false, id, n('fetchPlugin/end') as string);
109
- // 如果报错则结束了
110
- if (!data) return;
111
-
112
- await internal_updateMessageContent(id, data);
113
-
114
- return data;
115
- },
116
-
117
- internal_invokeDifferentTypePlugin: async (id, payload) => {
118
- switch (payload.type) {
119
- case 'standalone': {
120
- return await get().invokeStandaloneTypePlugin(id, payload);
121
- }
122
-
123
- case 'markdown': {
124
- return await get().invokeMarkdownTypePlugin(id, payload);
125
- }
126
-
127
- case 'builtin': {
128
- return await get().invokeBuiltinTool(id, payload);
129
- }
130
-
131
- default: {
132
- return await get().invokeDefaultTypePlugin(id, payload);
133
- }
134
- }
135
- },
136
-
137
- internal_transformToolCalls: (toolCalls) => {
138
- return toolCalls
139
- .map((toolCall): ChatToolPayload | null => {
140
- let payload: ChatToolPayload;
141
-
142
- const [identifier, apiName, type] = toolCall.function.name.split(PLUGIN_SCHEMA_SEPARATOR);
143
-
144
- if (!apiName) return null;
145
-
146
- payload = {
147
- apiName,
148
- arguments: toolCall.function.arguments,
149
- id: toolCall.id,
150
- identifier,
151
- type: (type ?? 'default') as any,
152
- };
153
-
154
- // if the apiName is md5, try to find the correct apiName in the plugins
155
- if (apiName.startsWith(PLUGIN_SCHEMA_API_MD5_PREFIX)) {
156
- const md5 = apiName.replace(PLUGIN_SCHEMA_API_MD5_PREFIX, '');
157
- const manifest = pluginSelectors.getPluginManifestById(identifier)(
158
- useToolStore.getState(),
159
- );
160
-
161
- const api = manifest?.api.find((api) => Md5.hashStr(api.name).toString() === md5);
162
- if (api) {
163
- payload.apiName = api.name;
164
- }
165
- }
166
-
167
- return payload;
168
- })
169
- .filter(Boolean) as ChatToolPayload[];
170
- },
171
-
172
- internal_updatePluginError: async (id, error) => {
173
- const { refreshMessages } = get();
174
-
175
- await messageService.updateMessage(id, { pluginError: error });
176
- await refreshMessages();
177
- },
178
-
179
78
  invokeBuiltinTool: async (id, payload) => {
180
- const { internal_toggleChatLoading, internal_updateMessageContent } = get();
79
+ const { internal_togglePluginApiCalling, internal_updateMessageContent } = get();
181
80
  const params = JSON.parse(payload.arguments);
182
- internal_toggleChatLoading(true, id, n('invokeBuiltinTool') as string);
81
+ internal_togglePluginApiCalling(true, id, n('invokeBuiltinTool') as string);
183
82
  let data;
184
83
  try {
185
84
  data = await useToolStore.getState().invokeBuiltinTool(payload.apiName, params);
186
85
  } catch (error) {
187
86
  console.log(error);
188
87
  }
189
- internal_toggleChatLoading(false);
88
+ internal_togglePluginApiCalling(false);
190
89
 
191
90
  if (!data) return;
192
91
 
@@ -248,6 +147,8 @@ export const chatPlugin: StateCreator<
248
147
  const message = chatSelectors.getMessageById(id)(get());
249
148
  if (!message || message.role !== 'tool' || !message.plugin) return;
250
149
 
150
+ get().internal_updateMessageError(id, null);
151
+
251
152
  const payload: ChatToolPayload = { ...message.plugin, id: message.tool_call_id! };
252
153
 
253
154
  await get().internal_invokeDifferentTypePlugin(id, payload);
@@ -301,4 +202,116 @@ export const chatPlugin: StateCreator<
301
202
  await messageService.updateMessagePluginState(id, { [key]: value });
302
203
  await refreshMessages();
303
204
  },
205
+
206
+ internal_callPluginApi: async (id, payload) => {
207
+ const { internal_updateMessageContent, refreshMessages, internal_togglePluginApiCalling } =
208
+ get();
209
+ let data: string;
210
+
211
+ try {
212
+ const abortController = internal_togglePluginApiCalling(
213
+ true,
214
+ id,
215
+ n('fetchPlugin/start') as string,
216
+ );
217
+
218
+ const message = chatSelectors.getMessageById(id)(get());
219
+
220
+ const res = await chatService.runPluginApi(payload, {
221
+ signal: abortController?.signal,
222
+ trace: { observationId: message?.observationId, traceId: message?.traceId },
223
+ });
224
+ data = res.text;
225
+
226
+ // save traceId
227
+ if (res.traceId) {
228
+ await messageService.updateMessage(id, { traceId: res.traceId });
229
+ }
230
+ } catch (error) {
231
+ console.log(error);
232
+ const err = error as Error;
233
+
234
+ // ignore the aborted request error
235
+ if (!err.message.includes('The user aborted a request.')) {
236
+ await messageService.updateMessageError(id, error as any);
237
+ await refreshMessages();
238
+ }
239
+
240
+ data = '';
241
+ }
242
+
243
+ internal_togglePluginApiCalling(false, id, n('fetchPlugin/end') as string);
244
+ // 如果报错则结束了
245
+ if (!data) return;
246
+
247
+ await internal_updateMessageContent(id, data);
248
+
249
+ return data;
250
+ },
251
+
252
+ internal_invokeDifferentTypePlugin: async (id, payload) => {
253
+ switch (payload.type) {
254
+ case 'standalone': {
255
+ return await get().invokeStandaloneTypePlugin(id, payload);
256
+ }
257
+
258
+ case 'markdown': {
259
+ return await get().invokeMarkdownTypePlugin(id, payload);
260
+ }
261
+
262
+ case 'builtin': {
263
+ return await get().invokeBuiltinTool(id, payload);
264
+ }
265
+
266
+ default: {
267
+ return await get().invokeDefaultTypePlugin(id, payload);
268
+ }
269
+ }
270
+ },
271
+
272
+ internal_togglePluginApiCalling: (loading, id, action) => {
273
+ return get().internal_toggleLoadingArrays('pluginApiLoadingIds', loading, id, action);
274
+ },
275
+
276
+ internal_transformToolCalls: (toolCalls) => {
277
+ return toolCalls
278
+ .map((toolCall): ChatToolPayload | null => {
279
+ let payload: ChatToolPayload;
280
+
281
+ const [identifier, apiName, type] = toolCall.function.name.split(PLUGIN_SCHEMA_SEPARATOR);
282
+
283
+ if (!apiName) return null;
284
+
285
+ payload = {
286
+ apiName,
287
+ arguments: toolCall.function.arguments,
288
+ id: toolCall.id,
289
+ identifier,
290
+ type: (type ?? 'default') as any,
291
+ };
292
+
293
+ // if the apiName is md5, try to find the correct apiName in the plugins
294
+ if (apiName.startsWith(PLUGIN_SCHEMA_API_MD5_PREFIX)) {
295
+ const md5 = apiName.replace(PLUGIN_SCHEMA_API_MD5_PREFIX, '');
296
+ const manifest = pluginSelectors.getPluginManifestById(identifier)(
297
+ useToolStore.getState(),
298
+ );
299
+
300
+ const api = manifest?.api.find((api) => Md5.hashStr(api.name).toString() === md5);
301
+ if (api) {
302
+ payload.apiName = api.name;
303
+ }
304
+ }
305
+
306
+ return payload;
307
+ })
308
+ .filter(Boolean) as ChatToolPayload[];
309
+ },
310
+ internal_updatePluginError: async (id, error) => {
311
+ const { refreshMessages } = get();
312
+
313
+ get().internal_dispatchMessage({ id, type: 'updateMessages', value: { error } });
314
+ await messageService.updateMessage(id, { pluginError: error });
315
+ await refreshMessages();
316
+ },
304
317
  });
@@ -0,0 +1,19 @@
1
+ import { produce } from 'immer';
2
+
3
+ export const preventLeavingFn = (e: BeforeUnloadEvent) => {
4
+ // set returnValue to trigger alert modal
5
+ // Note: No matter what value is set, the browser will display the standard text
6
+ e.returnValue = '你有正在生成中的请求,确定要离开吗?';
7
+ };
8
+
9
+ export const toggleBooleanList = (ids: string[], id: string, loading: boolean) => {
10
+ return produce(ids, (draft) => {
11
+ if (loading) {
12
+ draft.push(id);
13
+ } else {
14
+ const index = draft.indexOf(id);
15
+
16
+ if (index >= 0) draft.splice(index, 1);
17
+ }
18
+ });
19
+ };
@@ -8,7 +8,13 @@ import { userService } from '@/services/user';
8
8
  import type { UserStore } from '@/store/user';
9
9
  import { LocaleMode } from '@/types/locale';
10
10
  import { LobeAgentSettings } from '@/types/session';
11
- import { UserGeneralConfig, UserKeyVaults, UserSettings } from '@/types/user/settings';
11
+ import {
12
+ SystemAgentItem,
13
+ UserGeneralConfig,
14
+ UserKeyVaults,
15
+ UserSettings,
16
+ UserSystemAgentConfigKey,
17
+ } from '@/types/user/settings';
12
18
  import { switchLang } from '@/utils/client/switchLang';
13
19
  import { difference } from '@/utils/difference';
14
20
  import { merge } from '@/utils/merge';
@@ -25,7 +31,7 @@ export interface UserSettingsAction {
25
31
  updateGeneralConfig: (settings: Partial<UserGeneralConfig>) => Promise<void>;
26
32
  updateKeyVaults: (settings: Partial<UserKeyVaults>) => Promise<void>;
27
33
 
28
- updateSystemAgent: (key: string, value: { model: string; provider: string }) => Promise<void>;
34
+ updateSystemAgent: (key: UserSystemAgentConfigKey, value: SystemAgentItem) => Promise<void>;
29
35
  }
30
36
 
31
37
  export const createSettingsSlice: StateCreator<
@@ -9,8 +9,10 @@ const currentSystemAgent = (s: UserStore) =>
9
9
 
10
10
  const translation = (s: UserStore) => currentSystemAgent(s).translation;
11
11
  const topic = (s: UserStore) => currentSystemAgent(s).topic;
12
+ const agentMeta = (s: UserStore) => currentSystemAgent(s).agentMeta;
12
13
 
13
14
  export const systemAgentSelectors = {
15
+ agentMeta,
14
16
  topic,
15
17
  translation,
16
18
  };
@@ -32,7 +32,7 @@ export * from './tools';
32
32
 
33
33
  export interface ChatMessage extends BaseDataModel {
34
34
  content: string;
35
- error?: ChatMessageError;
35
+ error?: ChatMessageError | null;
36
36
  // 扩展字段
37
37
  extra?: {
38
38
  fromModel?: string;
@@ -4,6 +4,9 @@ export interface SystemAgentItem {
4
4
  }
5
5
 
6
6
  export interface UserSystemAgentConfig {
7
+ agentMeta: SystemAgentItem;
7
8
  topic: SystemAgentItem;
8
9
  translation: SystemAgentItem;
9
10
  }
11
+
12
+ export type UserSystemAgentConfigKey = keyof UserSystemAgentConfig;