@lobehub/chat 0.156.1 → 0.157.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 +42 -0
- package/Dockerfile +4 -1
- package/package.json +3 -2
- package/src/config/modelProviders/anthropic.ts +3 -0
- package/src/config/modelProviders/google.ts +3 -0
- package/src/config/modelProviders/groq.ts +5 -1
- package/src/config/modelProviders/minimax.ts +10 -7
- package/src/config/modelProviders/mistral.ts +1 -0
- package/src/config/modelProviders/moonshot.ts +3 -0
- package/src/config/modelProviders/zhipu.ts +2 -6
- package/src/config/server/provider.ts +1 -1
- package/src/database/client/core/db.ts +32 -0
- package/src/database/client/core/schemas.ts +9 -0
- package/src/database/client/models/__tests__/message.test.ts +2 -2
- package/src/database/client/schemas/message.ts +8 -1
- package/src/features/AgentSetting/store/action.ts +15 -6
- package/src/features/Conversation/Actions/Tool.tsx +16 -0
- package/src/features/Conversation/Actions/index.ts +2 -2
- package/src/features/Conversation/Messages/Assistant/ToolCalls/index.tsx +78 -0
- package/src/features/Conversation/Messages/Assistant/ToolCalls/style.ts +25 -0
- package/src/features/Conversation/Messages/Assistant/index.tsx +47 -0
- package/src/features/Conversation/Messages/Default.tsx +4 -1
- package/src/features/Conversation/{Plugins → Messages/Tool}/Inspector/index.tsx +34 -35
- package/src/features/Conversation/Messages/Tool/index.tsx +44 -0
- package/src/features/Conversation/Messages/index.ts +3 -2
- package/src/features/Conversation/Plugins/Render/StandaloneType/Iframe.tsx +1 -1
- package/src/features/Conversation/components/SkeletonList.tsx +2 -2
- package/src/features/Conversation/index.tsx +2 -3
- package/src/libs/agent-runtime/BaseAI.ts +2 -9
- package/src/libs/agent-runtime/anthropic/index.test.ts +195 -0
- package/src/libs/agent-runtime/anthropic/index.ts +71 -15
- package/src/libs/agent-runtime/azureOpenai/index.ts +12 -13
- package/src/libs/agent-runtime/bedrock/index.ts +24 -18
- package/src/libs/agent-runtime/google/index.test.ts +154 -0
- package/src/libs/agent-runtime/google/index.ts +91 -10
- package/src/libs/agent-runtime/groq/index.test.ts +41 -72
- package/src/libs/agent-runtime/groq/index.ts +7 -0
- package/src/libs/agent-runtime/minimax/index.test.ts +2 -2
- package/src/libs/agent-runtime/minimax/index.ts +14 -37
- package/src/libs/agent-runtime/mistral/index.test.ts +0 -53
- package/src/libs/agent-runtime/mistral/index.ts +1 -0
- package/src/libs/agent-runtime/moonshot/index.test.ts +1 -71
- package/src/libs/agent-runtime/ollama/index.test.ts +197 -0
- package/src/libs/agent-runtime/ollama/index.ts +3 -3
- package/src/libs/agent-runtime/openai/index.test.ts +0 -53
- package/src/libs/agent-runtime/openrouter/index.test.ts +1 -53
- package/src/libs/agent-runtime/perplexity/index.test.ts +0 -71
- package/src/libs/agent-runtime/perplexity/index.ts +2 -3
- package/src/libs/agent-runtime/togetherai/__snapshots__/index.test.ts.snap +886 -0
- package/src/libs/agent-runtime/togetherai/fixtures/models.json +8111 -0
- package/src/libs/agent-runtime/togetherai/index.test.ts +16 -54
- package/src/libs/agent-runtime/types/chat.ts +19 -3
- package/src/libs/agent-runtime/utils/anthropicHelpers.test.ts +120 -1
- package/src/libs/agent-runtime/utils/anthropicHelpers.ts +67 -4
- package/src/libs/agent-runtime/utils/debugStream.test.ts +70 -0
- package/src/libs/agent-runtime/utils/debugStream.ts +39 -9
- package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.test.ts +521 -0
- package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts +76 -5
- package/src/libs/agent-runtime/utils/response.ts +12 -0
- package/src/libs/agent-runtime/utils/streams/anthropic.test.ts +197 -0
- package/src/libs/agent-runtime/utils/streams/anthropic.ts +91 -0
- package/src/libs/agent-runtime/utils/streams/bedrock/claude.ts +21 -0
- package/src/libs/agent-runtime/utils/streams/bedrock/common.ts +32 -0
- package/src/libs/agent-runtime/utils/streams/bedrock/index.ts +3 -0
- package/src/libs/agent-runtime/utils/streams/bedrock/llama.test.ts +196 -0
- package/src/libs/agent-runtime/utils/streams/bedrock/llama.ts +51 -0
- package/src/libs/agent-runtime/utils/streams/google-ai.test.ts +97 -0
- package/src/libs/agent-runtime/utils/streams/google-ai.ts +68 -0
- package/src/libs/agent-runtime/utils/streams/index.ts +7 -0
- package/src/libs/agent-runtime/utils/streams/minimax.ts +39 -0
- package/src/libs/agent-runtime/utils/streams/ollama.test.ts +77 -0
- package/src/libs/agent-runtime/utils/streams/ollama.ts +38 -0
- package/src/libs/agent-runtime/utils/streams/openai.test.ts +263 -0
- package/src/libs/agent-runtime/utils/streams/openai.ts +79 -0
- package/src/libs/agent-runtime/utils/streams/protocol.ts +100 -0
- package/src/libs/agent-runtime/zeroone/index.test.ts +1 -53
- package/src/libs/agent-runtime/zhipu/index.test.ts +1 -1
- package/src/libs/agent-runtime/zhipu/index.ts +3 -2
- package/src/locales/default/plugin.ts +3 -4
- package/src/migrations/FromV4ToV5/fixtures/from-v1-to-v5-output.json +245 -0
- package/src/migrations/FromV4ToV5/fixtures/function-input-v4.json +96 -0
- package/src/migrations/FromV4ToV5/fixtures/function-output-v5.json +120 -0
- package/src/migrations/FromV4ToV5/index.ts +58 -0
- package/src/migrations/FromV4ToV5/migrations.test.ts +49 -0
- package/src/migrations/FromV4ToV5/types/v4.ts +21 -0
- package/src/migrations/FromV4ToV5/types/v5.ts +27 -0
- package/src/migrations/index.ts +8 -1
- package/src/services/__tests__/chat.test.ts +10 -20
- package/src/services/chat.ts +78 -65
- package/src/store/chat/slices/enchance/action.ts +15 -10
- package/src/store/chat/slices/message/action.test.ts +36 -86
- package/src/store/chat/slices/message/action.ts +70 -79
- package/src/store/chat/slices/message/reducer.ts +18 -1
- package/src/store/chat/slices/message/selectors.test.ts +38 -68
- package/src/store/chat/slices/message/selectors.ts +1 -22
- package/src/store/chat/slices/plugin/action.test.ts +147 -203
- package/src/store/chat/slices/plugin/action.ts +96 -82
- package/src/store/chat/slices/share/action.test.ts +3 -3
- package/src/store/chat/slices/share/action.ts +1 -1
- package/src/store/chat/slices/topic/action.ts +7 -2
- package/src/store/tool/selectors/tool.ts +6 -24
- package/src/store/tool/slices/builtin/action.test.ts +90 -0
- package/src/types/llm.ts +1 -1
- package/src/types/message/index.ts +9 -4
- package/src/types/message/tools.ts +57 -0
- package/src/types/openai/chat.ts +6 -0
- package/src/utils/fetch.test.ts +245 -1
- package/src/utils/fetch.ts +120 -44
- package/src/utils/toolCall.ts +21 -0
- package/src/features/Conversation/Messages/Assistant.tsx +0 -26
- package/src/features/Conversation/Messages/Function.tsx +0 -35
- package/src/libs/agent-runtime/ollama/stream.ts +0 -31
- /package/src/features/Conversation/{Plugins → Messages/Tool}/Inspector/PluginResultJSON.tsx +0 -0
- /package/src/features/Conversation/{Plugins → Messages/Tool}/Inspector/Settings.tsx +0 -0
- /package/src/features/Conversation/{Plugins → Messages/Tool}/Inspector/style.ts +0 -0
|
@@ -3,14 +3,14 @@ import { t } from 'i18next';
|
|
|
3
3
|
import { Md5 } from 'ts-md5';
|
|
4
4
|
import { StateCreator } from 'zustand/vanilla';
|
|
5
5
|
|
|
6
|
+
import { LOADING_FLAT } from '@/const/message';
|
|
6
7
|
import { PLUGIN_SCHEMA_API_MD5_PREFIX, PLUGIN_SCHEMA_SEPARATOR } from '@/const/plugin';
|
|
7
8
|
import { chatService } from '@/services/chat';
|
|
8
9
|
import { CreateMessageParams, messageService } from '@/services/message';
|
|
9
10
|
import { ChatStore } from '@/store/chat/store';
|
|
10
11
|
import { useToolStore } from '@/store/tool';
|
|
11
12
|
import { pluginSelectors } from '@/store/tool/selectors';
|
|
12
|
-
import {
|
|
13
|
-
import { OpenAIToolCall } from '@/types/openai/functionCall';
|
|
13
|
+
import { ChatToolPayload, MessageToolCall } from '@/types/message';
|
|
14
14
|
import { setNamespace } from '@/utils/storeDebug';
|
|
15
15
|
|
|
16
16
|
import { chatSelectors } from '../../slices/message/selectors';
|
|
@@ -24,13 +24,15 @@ export interface ChatPluginAction {
|
|
|
24
24
|
content: string,
|
|
25
25
|
triggerAiMessage?: boolean,
|
|
26
26
|
) => Promise<void>;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
internal_transformToolCalls: (toolCalls: MessageToolCall[]) => ChatToolPayload[];
|
|
28
|
+
invokeBuiltinTool: (id: string, payload: ChatToolPayload) => Promise<void>;
|
|
29
|
+
invokeDefaultTypePlugin: (id: string, payload: any) => Promise<string | undefined>;
|
|
30
|
+
invokeMarkdownTypePlugin: (id: string, payload: ChatToolPayload) => Promise<void>;
|
|
31
|
+
invokeStandaloneTypePlugin: (id: string, payload: ChatToolPayload) => Promise<void>;
|
|
32
|
+
runPluginApi: (id: string, payload: ChatToolPayload) => Promise<string | undefined>;
|
|
33
|
+
triggerAIMessage: (params: { parentId?: string; traceId?: string }) => Promise<void>;
|
|
34
|
+
triggerToolCalls: (id: string) => Promise<void>;
|
|
35
|
+
|
|
34
36
|
updatePluginState: (id: string, key: string, value: any) => Promise<void>;
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -58,7 +60,42 @@ export const chatPlugin: StateCreator<
|
|
|
58
60
|
|
|
59
61
|
await internal_updateMessageContent(id, content);
|
|
60
62
|
|
|
61
|
-
if (triggerAiMessage) await triggerAIMessage(id);
|
|
63
|
+
if (triggerAiMessage) await triggerAIMessage({ parentId: id });
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
internal_transformToolCalls: (toolCalls) => {
|
|
67
|
+
return toolCalls
|
|
68
|
+
.map((toolCall): ChatToolPayload | null => {
|
|
69
|
+
let payload: ChatToolPayload;
|
|
70
|
+
|
|
71
|
+
const [identifier, apiName, type] = toolCall.function.name.split(PLUGIN_SCHEMA_SEPARATOR);
|
|
72
|
+
|
|
73
|
+
if (!apiName) return null;
|
|
74
|
+
|
|
75
|
+
payload = {
|
|
76
|
+
apiName,
|
|
77
|
+
arguments: toolCall.function.arguments,
|
|
78
|
+
id: toolCall.id,
|
|
79
|
+
identifier,
|
|
80
|
+
type: (type ?? 'default') as any,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// if the apiName is md5, try to find the correct apiName in the plugins
|
|
84
|
+
if (apiName.startsWith(PLUGIN_SCHEMA_API_MD5_PREFIX)) {
|
|
85
|
+
const md5 = apiName.replace(PLUGIN_SCHEMA_API_MD5_PREFIX, '');
|
|
86
|
+
const manifest = pluginSelectors.getPluginManifestById(identifier)(
|
|
87
|
+
useToolStore.getState(),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const api = manifest?.api.find((api) => Md5.hashStr(api.name).toString() === md5);
|
|
91
|
+
if (api) {
|
|
92
|
+
payload.apiName = api.name;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return payload;
|
|
97
|
+
})
|
|
98
|
+
.filter(Boolean) as ChatToolPayload[];
|
|
62
99
|
},
|
|
63
100
|
|
|
64
101
|
invokeBuiltinTool: async (id, payload) => {
|
|
@@ -94,14 +131,13 @@ export const chatPlugin: StateCreator<
|
|
|
94
131
|
},
|
|
95
132
|
|
|
96
133
|
invokeDefaultTypePlugin: async (id, payload) => {
|
|
97
|
-
const { runPluginApi
|
|
134
|
+
const { runPluginApi } = get();
|
|
98
135
|
|
|
99
136
|
const data = await runPluginApi(id, payload);
|
|
100
137
|
|
|
101
138
|
if (!data) return;
|
|
102
|
-
const traceId = chatSelectors.getTraceIdByMessageId(id)(get());
|
|
103
139
|
|
|
104
|
-
|
|
140
|
+
return data;
|
|
105
141
|
},
|
|
106
142
|
|
|
107
143
|
invokeMarkdownTypePlugin: async (id, payload) => {
|
|
@@ -175,95 +211,73 @@ export const chatPlugin: StateCreator<
|
|
|
175
211
|
return data;
|
|
176
212
|
},
|
|
177
213
|
|
|
178
|
-
triggerAIMessage: async (
|
|
214
|
+
triggerAIMessage: async ({ parentId, traceId }) => {
|
|
179
215
|
const { internal_coreProcessMessage } = get();
|
|
180
216
|
const chats = chatSelectors.currentChats(get());
|
|
181
|
-
await internal_coreProcessMessage(chats, id, { traceId });
|
|
217
|
+
await internal_coreProcessMessage(chats, parentId ?? chats.at(-1)!.id, { traceId });
|
|
182
218
|
},
|
|
183
219
|
|
|
184
|
-
|
|
185
|
-
const message = chatSelectors.getMessageById(
|
|
186
|
-
if (!message) return;
|
|
220
|
+
triggerToolCalls: async (assistantId) => {
|
|
221
|
+
const message = chatSelectors.getMessageById(assistantId)(get());
|
|
222
|
+
if (!message || !message.tools) return;
|
|
187
223
|
|
|
188
224
|
const {
|
|
189
225
|
invokeDefaultTypePlugin,
|
|
190
226
|
invokeMarkdownTypePlugin,
|
|
191
227
|
invokeStandaloneTypePlugin,
|
|
192
228
|
invokeBuiltinTool,
|
|
193
|
-
|
|
194
|
-
internal_resendMessage,
|
|
195
|
-
deleteMessage,
|
|
229
|
+
triggerAIMessage,
|
|
196
230
|
} = get();
|
|
197
231
|
|
|
198
|
-
let
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
232
|
+
let shouldCreateMessage = false;
|
|
233
|
+
let latestToolId = '';
|
|
234
|
+
const messagePools = message.tools.map(async (payload) => {
|
|
235
|
+
const toolMessage: CreateMessageParams = {
|
|
236
|
+
content: LOADING_FLAT,
|
|
237
|
+
parentId: assistantId,
|
|
238
|
+
plugin: payload,
|
|
239
|
+
role: 'tool',
|
|
240
|
+
sessionId: get().activeId,
|
|
241
|
+
tool_call_id: payload.id,
|
|
242
|
+
topicId: get().activeTopicId, // if there is activeTopicId,then add it to topicId
|
|
205
243
|
};
|
|
206
244
|
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
payload.apiName = api.name;
|
|
245
|
+
const id = await get().internal_createMessage(toolMessage);
|
|
246
|
+
|
|
247
|
+
switch (payload.type) {
|
|
248
|
+
case 'standalone': {
|
|
249
|
+
await invokeStandaloneTypePlugin(id, payload);
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
case 'markdown': {
|
|
254
|
+
await invokeMarkdownTypePlugin(id, payload);
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
case 'builtin': {
|
|
259
|
+
await invokeBuiltinTool(id, payload);
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
default: {
|
|
264
|
+
const data = await invokeDefaultTypePlugin(id, payload);
|
|
265
|
+
if (data) {
|
|
266
|
+
shouldCreateMessage = true;
|
|
267
|
+
latestToolId = id;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
233
270
|
}
|
|
234
|
-
} else {
|
|
235
|
-
if (message.plugin) payload = message.plugin;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (!payload.apiName) return;
|
|
239
|
-
|
|
240
|
-
await messageService.updateMessage(id, {
|
|
241
|
-
content: !!message.content ? '' : undefined,
|
|
242
|
-
plugin: payload,
|
|
243
|
-
role: 'function',
|
|
244
271
|
});
|
|
245
|
-
await refreshMessages();
|
|
246
272
|
|
|
247
|
-
|
|
248
|
-
case 'standalone': {
|
|
249
|
-
await invokeStandaloneTypePlugin(id, payload);
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
273
|
+
await Promise.all(messagePools);
|
|
252
274
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
break;
|
|
256
|
-
}
|
|
275
|
+
// only default type tool calls should trigger AI message
|
|
276
|
+
if (!shouldCreateMessage) return;
|
|
257
277
|
|
|
258
|
-
|
|
259
|
-
await invokeBuiltinTool(id, payload);
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
278
|
+
const traceId = chatSelectors.getTraceIdByMessageId(latestToolId)(get());
|
|
262
279
|
|
|
263
|
-
|
|
264
|
-
await invokeDefaultTypePlugin(id, payload);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
280
|
+
await triggerAIMessage({ traceId });
|
|
267
281
|
},
|
|
268
282
|
|
|
269
283
|
updatePluginState: async (id, key, value) => {
|
|
@@ -85,7 +85,7 @@ describe('shareSlice actions', () => {
|
|
|
85
85
|
it('should include plugin information when withPluginInfo is true', async () => {
|
|
86
86
|
// 模拟带有插件信息的消息
|
|
87
87
|
const pluginMessage = {
|
|
88
|
-
role: '
|
|
88
|
+
role: 'tool',
|
|
89
89
|
content: 'plugin content',
|
|
90
90
|
plugin: {
|
|
91
91
|
type: 'default',
|
|
@@ -118,7 +118,7 @@ describe('shareSlice actions', () => {
|
|
|
118
118
|
|
|
119
119
|
it('should not include plugin information when withPluginInfo is false', async () => {
|
|
120
120
|
const pluginMessage = {
|
|
121
|
-
role: '
|
|
121
|
+
role: 'tool',
|
|
122
122
|
content: 'plugin content',
|
|
123
123
|
plugin: {
|
|
124
124
|
type: 'default',
|
|
@@ -154,7 +154,7 @@ describe('shareSlice actions', () => {
|
|
|
154
154
|
{ role: 'user', content: 'user message', id: '1' },
|
|
155
155
|
{ role: 'assistant', content: 'assistant message', id: '2' },
|
|
156
156
|
{
|
|
157
|
-
role: '
|
|
157
|
+
role: 'tool',
|
|
158
158
|
content: 'plugin content',
|
|
159
159
|
plugin: {
|
|
160
160
|
type: 'default',
|
|
@@ -134,8 +134,13 @@ export const chatTopic: StateCreator<
|
|
|
134
134
|
onLoadingChange: (loading) => {
|
|
135
135
|
internal_updateTopicLoading(topicId, loading);
|
|
136
136
|
},
|
|
137
|
-
onMessageHandle: (
|
|
138
|
-
|
|
137
|
+
onMessageHandle: (chunk) => {
|
|
138
|
+
switch (chunk.type) {
|
|
139
|
+
case 'text': {
|
|
140
|
+
output += chunk.text;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
139
144
|
updateTopicTitleInSummary(topicId, output);
|
|
140
145
|
},
|
|
141
146
|
params: await chainSummaryTitle(messages),
|
|
@@ -1,35 +1,16 @@
|
|
|
1
1
|
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
|
|
2
2
|
import { uniqBy } from 'lodash-es';
|
|
3
|
-
import { Md5 } from 'ts-md5';
|
|
4
3
|
|
|
5
|
-
import { PLUGIN_SCHEMA_API_MD5_PREFIX, PLUGIN_SCHEMA_SEPARATOR } from '@/const/plugin';
|
|
6
4
|
import { MetaData } from '@/types/meta';
|
|
7
5
|
import { ChatCompletionTool } from '@/types/openai/chat';
|
|
8
6
|
import { LobeToolMeta } from '@/types/tool/tool';
|
|
7
|
+
import { genToolCallingName } from '@/utils/toolCall';
|
|
9
8
|
|
|
10
9
|
import { pluginHelpers } from '../helpers';
|
|
11
10
|
import { ToolStoreState } from '../initialState';
|
|
12
11
|
import { builtinToolSelectors } from '../slices/builtin/selectors';
|
|
13
12
|
import { pluginSelectors } from '../slices/plugin/selectors';
|
|
14
13
|
|
|
15
|
-
const getAPIName = (identifier: string, name: string, type?: string) => {
|
|
16
|
-
const pluginType = type && type !== 'default' ? `${PLUGIN_SCHEMA_SEPARATOR + type}` : '';
|
|
17
|
-
|
|
18
|
-
// 将插件的 identifier 作为前缀,避免重复
|
|
19
|
-
let apiName = identifier + PLUGIN_SCHEMA_SEPARATOR + name + pluginType;
|
|
20
|
-
|
|
21
|
-
// OpenAI GPT function_call name can't be longer than 64 characters
|
|
22
|
-
// So we need to use md5 to shorten the name
|
|
23
|
-
// and then find the correct apiName in response by md5
|
|
24
|
-
if (apiName.length >= 64) {
|
|
25
|
-
const md5Content = PLUGIN_SCHEMA_API_MD5_PREFIX + Md5.hashStr(name).toString();
|
|
26
|
-
|
|
27
|
-
apiName = identifier + PLUGIN_SCHEMA_SEPARATOR + md5Content + pluginType;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return apiName;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
14
|
const enabledSchema =
|
|
34
15
|
(tools: string[] = []) =>
|
|
35
16
|
(s: ToolStoreState): ChatCompletionTool[] => {
|
|
@@ -41,7 +22,7 @@ const enabledSchema =
|
|
|
41
22
|
.flatMap((manifest) =>
|
|
42
23
|
manifest.api.map((m) => ({
|
|
43
24
|
description: m.description,
|
|
44
|
-
name:
|
|
25
|
+
name: genToolCallingName(manifest.identifier, m.name, manifest.type),
|
|
45
26
|
parameters: m.parameters,
|
|
46
27
|
})),
|
|
47
28
|
);
|
|
@@ -67,9 +48,10 @@ const enabledSystemRoles =
|
|
|
67
48
|
|
|
68
49
|
const methods = manifest.api
|
|
69
50
|
.map((m) =>
|
|
70
|
-
[
|
|
71
|
-
|
|
72
|
-
|
|
51
|
+
[
|
|
52
|
+
`#### ${genToolCallingName(manifest.identifier, m.name, manifest.type)}`,
|
|
53
|
+
m.description,
|
|
54
|
+
].join('\n\n'),
|
|
73
55
|
)
|
|
74
56
|
.join('\n\n');
|
|
75
57
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { act, renderHook } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { useToolStore } from '../../store';
|
|
5
|
+
|
|
6
|
+
vi.mock('zustand/traditional');
|
|
7
|
+
|
|
8
|
+
describe('createBuiltinToolSlice', () => {
|
|
9
|
+
describe('invokeBuiltinTool', () => {
|
|
10
|
+
it('should return if the tool is already loading', async () => {
|
|
11
|
+
// Given
|
|
12
|
+
const key = 'text2image';
|
|
13
|
+
const params = {};
|
|
14
|
+
|
|
15
|
+
const mockFn = vi.fn();
|
|
16
|
+
const { result } = renderHook(() => useToolStore());
|
|
17
|
+
|
|
18
|
+
act(() => {
|
|
19
|
+
useToolStore.setState({
|
|
20
|
+
text2image: mockFn,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await act(async () => {
|
|
25
|
+
// When
|
|
26
|
+
const data = await result.current.invokeBuiltinTool(key, params);
|
|
27
|
+
expect(data).toBeUndefined();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Then
|
|
31
|
+
expect(mockFn).toHaveBeenCalled();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should invoke the specified tool action and return the stringified result', async () => {
|
|
35
|
+
// Given
|
|
36
|
+
const key = 'text2image';
|
|
37
|
+
|
|
38
|
+
const mockFn = vi.fn();
|
|
39
|
+
const { result } = renderHook(() => useToolStore());
|
|
40
|
+
|
|
41
|
+
const params = {
|
|
42
|
+
prompts: ['test prompt'],
|
|
43
|
+
size: '512x512',
|
|
44
|
+
quality: 'standard',
|
|
45
|
+
style: 'vivid',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
act(() => {
|
|
49
|
+
useToolStore.setState({
|
|
50
|
+
builtinToolLoading: { [key]: false },
|
|
51
|
+
text2image: mockFn,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
// When
|
|
55
|
+
await act(async () => {
|
|
56
|
+
await result.current.invokeBuiltinTool(key, params);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(mockFn).toBeCalledWith({
|
|
60
|
+
prompts: ['test prompt'],
|
|
61
|
+
quality: 'standard',
|
|
62
|
+
size: '512x512',
|
|
63
|
+
style: 'vivid',
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('text2image', () => {
|
|
69
|
+
it('should map the prompts to DallEImageItem objects', () => {
|
|
70
|
+
// When
|
|
71
|
+
const { result } = renderHook(() => useToolStore());
|
|
72
|
+
|
|
73
|
+
const data = result.current.text2image(
|
|
74
|
+
{
|
|
75
|
+
prompts: ['prompt1', 'prompt2'],
|
|
76
|
+
size: '1024x1024',
|
|
77
|
+
quality: 'standard',
|
|
78
|
+
style: 'vivid',
|
|
79
|
+
},
|
|
80
|
+
'a',
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Then
|
|
84
|
+
expect(data).toEqual([
|
|
85
|
+
{ prompt: 'prompt1', quality: 'standard', size: '1024x1024', style: 'vivid' },
|
|
86
|
+
{ prompt: 'prompt2', quality: 'standard', size: '1024x1024', style: 'vivid' },
|
|
87
|
+
]);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/types/llm.ts
CHANGED
|
@@ -3,11 +3,12 @@ import { IPluginErrorType } from '@lobehub/chat-plugin-sdk';
|
|
|
3
3
|
import { ILobeAgentRuntimeErrorType } from '@/libs/agent-runtime';
|
|
4
4
|
import { ErrorType } from '@/types/fetch';
|
|
5
5
|
|
|
6
|
-
import { LLMRoleType } from '../llm';
|
|
7
6
|
import { BaseDataModel } from '../meta';
|
|
8
|
-
import { ChatPluginPayload } from './tools';
|
|
7
|
+
import { ChatPluginPayload, ChatToolPayload } from './tools';
|
|
9
8
|
import { Translate } from './translate';
|
|
10
9
|
|
|
10
|
+
export type MessageRoleType = 'user' | 'system' | 'assistant' | 'tool';
|
|
11
|
+
|
|
11
12
|
/**
|
|
12
13
|
* 聊天消息错误对象
|
|
13
14
|
*/
|
|
@@ -51,9 +52,10 @@ export interface ChatMessage extends BaseDataModel {
|
|
|
51
52
|
* parent message id
|
|
52
53
|
*/
|
|
53
54
|
parentId?: string;
|
|
54
|
-
plugin?: ChatPluginPayload;
|
|
55
55
|
|
|
56
|
+
plugin?: ChatPluginPayload;
|
|
56
57
|
pluginState?: any;
|
|
58
|
+
|
|
57
59
|
/**
|
|
58
60
|
* quoted other message's id
|
|
59
61
|
*/
|
|
@@ -61,9 +63,12 @@ export interface ChatMessage extends BaseDataModel {
|
|
|
61
63
|
/**
|
|
62
64
|
* message role type
|
|
63
65
|
*/
|
|
64
|
-
role:
|
|
66
|
+
role: MessageRoleType;
|
|
65
67
|
sessionId?: string;
|
|
66
68
|
|
|
69
|
+
tool_call_id?: string;
|
|
70
|
+
tools?: ChatToolPayload[];
|
|
71
|
+
|
|
67
72
|
/**
|
|
68
73
|
* 保存到主题的消息
|
|
69
74
|
*/
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { DeepPartial } from 'utility-types';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
1
4
|
import { LobeToolRenderType } from '@/types/tool';
|
|
2
5
|
|
|
3
6
|
export interface ChatPluginPayload {
|
|
@@ -6,3 +9,57 @@ export interface ChatPluginPayload {
|
|
|
6
9
|
identifier: string;
|
|
7
10
|
type: LobeToolRenderType;
|
|
8
11
|
}
|
|
12
|
+
|
|
13
|
+
export interface ChatToolPayload {
|
|
14
|
+
apiName: string;
|
|
15
|
+
arguments: string;
|
|
16
|
+
id: string;
|
|
17
|
+
identifier: string;
|
|
18
|
+
type: LobeToolRenderType;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The function that the model called.
|
|
23
|
+
*/
|
|
24
|
+
export interface ToolFunction {
|
|
25
|
+
/**
|
|
26
|
+
* The arguments to call the function with, as generated by the model in JSON
|
|
27
|
+
* format. Note that the model does not always generate valid JSON, and may
|
|
28
|
+
* hallucinate parameters not defined by your function schema. Validate the
|
|
29
|
+
* arguments in your code before calling your function.
|
|
30
|
+
*/
|
|
31
|
+
arguments: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The name of the function to call.
|
|
35
|
+
*/
|
|
36
|
+
name: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface MessageToolCall {
|
|
40
|
+
/**
|
|
41
|
+
* The function that the model called.
|
|
42
|
+
*/
|
|
43
|
+
function: ToolFunction;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The ID of the tool call.
|
|
47
|
+
*/
|
|
48
|
+
id: string;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The type of the tool. Currently, only `function` is supported.
|
|
52
|
+
*/
|
|
53
|
+
type: 'function' | string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type MessageToolCallChunk = DeepPartial<MessageToolCall> & { index: number };
|
|
57
|
+
|
|
58
|
+
export const MessageToolCallSchema = z.object({
|
|
59
|
+
function: z.object({
|
|
60
|
+
arguments: z.string(),
|
|
61
|
+
name: z.string(),
|
|
62
|
+
}),
|
|
63
|
+
id: z.string(),
|
|
64
|
+
type: z.string(),
|
|
65
|
+
});
|
package/src/types/openai/chat.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LLMRoleType } from '@/types/llm';
|
|
2
|
+
import { MessageToolCall } from '@/types/message';
|
|
2
3
|
|
|
3
4
|
import { OpenAIFunctionCall } from './functionCall';
|
|
4
5
|
|
|
@@ -23,6 +24,9 @@ export interface OpenAIChatMessage {
|
|
|
23
24
|
*/
|
|
24
25
|
content: string | UserMessageContentPart[];
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated
|
|
29
|
+
*/
|
|
26
30
|
function_call?: OpenAIFunctionCall;
|
|
27
31
|
name?: string;
|
|
28
32
|
/**
|
|
@@ -30,6 +34,8 @@ export interface OpenAIChatMessage {
|
|
|
30
34
|
* @description 消息发送者的角色
|
|
31
35
|
*/
|
|
32
36
|
role: LLMRoleType;
|
|
37
|
+
tool_call_id?: string;
|
|
38
|
+
tool_calls?: MessageToolCall[];
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
/**
|