@lobehub/chat 1.0.12 → 1.0.14
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 +16 -14
- package/README.zh-CN.md +16 -14
- package/docs/self-hosting/advanced/feature-flags.zh-CN.mdx +2 -1
- package/docs/self-hosting/advanced/model-list.zh-CN.mdx +1 -0
- package/docs/self-hosting/advanced/server-database.mdx +4 -3
- package/docs/self-hosting/advanced/server-database.zh-CN.mdx +1 -0
- package/docs/self-hosting/advanced/settings-url-share.mdx +5 -4
- package/docs/self-hosting/advanced/settings-url-share.zh-CN.mdx +5 -4
- package/docs/self-hosting/advanced/sso-providers/zitadel.mdx +3 -3
- package/docs/self-hosting/advanced/sso-providers/zitadel.zh-CN.mdx +2 -1
- package/docs/self-hosting/advanced/upstream-sync.zh-CN.mdx +10 -10
- package/docs/self-hosting/examples/ollama.mdx +23 -23
- package/docs/self-hosting/examples/ollama.zh-CN.mdx +23 -24
- package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +2 -3
- package/docs/self-hosting/platform/vercel.mdx +2 -2
- package/docs/self-hosting/platform/vercel.zh-CN.mdx +2 -1
- package/docs/self-hosting/platform/zeabur.mdx +6 -7
- package/docs/self-hosting/platform/zeabur.zh-CN.mdx +6 -7
- package/docs/usage/agents/prompt.mdx +1 -1
- package/docs/usage/agents/prompt.zh-CN.mdx +1 -1
- package/docs/usage/features/auth.mdx +13 -8
- package/docs/usage/features/auth.zh-CN.mdx +5 -3
- package/docs/usage/features/database.mdx +20 -14
- package/docs/usage/features/database.zh-CN.mdx +1 -1
- package/docs/usage/features/local-llm.mdx +5 -0
- package/docs/usage/features/local-llm.zh-CN.mdx +5 -0
- package/docs/usage/features/multi-ai-providers.mdx +5 -0
- package/docs/usage/features/multi-ai-providers.zh-CN.mdx +5 -0
- package/docs/usage/features/plugin-system.zh-CN.mdx +2 -1
- package/docs/usage/features/pwa.mdx +3 -2
- package/docs/usage/features/pwa.zh-CN.mdx +3 -2
- package/docs/usage/providers/01ai.mdx +86 -0
- package/docs/usage/providers/01ai.zh-CN.mdx +85 -0
- package/docs/usage/providers/anthropic.mdx +79 -0
- package/docs/usage/providers/anthropic.zh-CN.mdx +74 -0
- package/docs/usage/providers/azure.mdx +89 -0
- package/docs/usage/providers/azure.zh-CN.mdx +82 -0
- package/docs/usage/providers/bedrock.mdx +140 -0
- package/docs/usage/providers/bedrock.zh-CN.mdx +135 -0
- package/docs/usage/providers/deepseek.mdx +91 -0
- package/docs/usage/providers/deepseek.zh-CN.mdx +86 -0
- package/docs/usage/providers/gemini.mdx +83 -0
- package/docs/usage/providers/gemini.zh-CN.mdx +80 -0
- package/docs/usage/providers/groq.mdx +1 -3
- package/docs/usage/providers/groq.zh-CN.mdx +1 -1
- package/docs/usage/providers/minimax.mdx +89 -0
- package/docs/usage/providers/minimax.zh-CN.mdx +85 -0
- package/docs/usage/providers/mistral.mdx +71 -0
- package/docs/usage/providers/mistral.zh-CN.mdx +66 -0
- package/docs/usage/providers/moonshot.mdx +70 -0
- package/docs/usage/providers/moonshot.zh-CN.mdx +66 -0
- package/docs/usage/providers/ollama/gemma.mdx +1 -1
- package/docs/usage/providers/ollama/gemma.zh-CN.mdx +1 -1
- package/docs/usage/providers/ollama/qwen.mdx +1 -1
- package/docs/usage/providers/ollama/qwen.zh-CN.mdx +1 -1
- package/docs/usage/providers/ollama.mdx +1 -1
- package/docs/usage/providers/ollama.zh-CN.mdx +1 -1
- package/docs/usage/providers/openai.mdx +95 -0
- package/docs/usage/providers/openai.zh-CN.mdx +87 -0
- package/docs/usage/providers/openrouter.mdx +111 -0
- package/docs/usage/providers/openrouter.zh-CN.mdx +109 -0
- package/docs/usage/providers/perplexity.mdx +64 -0
- package/docs/usage/providers/perplexity.zh-CN.mdx +61 -0
- package/docs/usage/providers/qwen.mdx +93 -0
- package/docs/usage/providers/qwen.zh-CN.mdx +86 -0
- package/docs/usage/providers/stepfun.mdx +69 -0
- package/docs/usage/providers/stepfun.zh-CN.mdx +64 -0
- package/docs/usage/providers/togetherai.mdx +74 -0
- package/docs/usage/providers/togetherai.zh-CN.mdx +71 -0
- package/docs/usage/providers/zhipu.mdx +69 -0
- package/docs/usage/providers/zhipu.zh-CN.mdx +64 -0
- package/docs/usage/providers.mdx +36 -0
- package/docs/usage/providers.zh-CN.mdx +34 -0
- package/docs/usage/start.mdx +2 -0
- package/docs/usage/start.zh-CN.mdx +2 -0
- package/locales/ar/setting.json +1 -0
- package/locales/bg-BG/setting.json +1 -0
- package/locales/de-DE/setting.json +1 -0
- package/locales/en-US/setting.json +1 -0
- package/locales/es-ES/setting.json +1 -0
- package/locales/fr-FR/setting.json +1 -0
- package/locales/it-IT/setting.json +1 -0
- package/locales/ja-JP/setting.json +1 -0
- package/locales/ko-KR/setting.json +1 -0
- package/locales/nl-NL/setting.json +1 -0
- package/locales/pl-PL/setting.json +1 -0
- package/locales/pt-BR/setting.json +1 -0
- package/locales/ru-RU/setting.json +1 -0
- package/locales/tr-TR/setting.json +1 -0
- package/locales/vi-VN/setting.json +1 -0
- package/locales/zh-CN/setting.json +1 -0
- package/locales/zh-TW/setting.json +1 -0
- package/package.json +9 -7
- package/src/app/(main)/settings/llm/ProviderList/providers.tsx +33 -4
- package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +41 -11
- package/src/app/(main)/settings/llm/index.tsx +1 -2
- package/src/features/ChatInput/useSend.ts +2 -1
- package/src/features/Conversation/Error/ErrorJsonViewer.tsx +1 -1
- package/src/features/Conversation/Messages/Assistant/ToolCalls/index.tsx +4 -3
- package/src/features/Conversation/Messages/Tool/index.tsx +3 -5
- package/src/features/Conversation/Messages/components/Arguments.tsx +22 -0
- package/src/features/Conversation/Messages/hooks/useYamlArguments.ts +14 -0
- package/src/libs/agent-runtime/anthropic/index.test.ts +1 -31
- package/src/libs/agent-runtime/anthropic/index.ts +9 -63
- package/src/libs/agent-runtime/openai/index.test.ts +7 -7
- package/src/libs/agent-runtime/openai/index.ts +0 -6
- package/src/libs/agent-runtime/utils/anthropicHelpers.ts +2 -2
- package/src/libs/agent-runtime/utils/streams/anthropic.test.ts +102 -28
- package/src/libs/agent-runtime/utils/streams/anthropic.ts +29 -12
- package/src/libs/agent-runtime/utils/streams/protocol.ts +6 -1
- package/src/locales/default/setting.ts +1 -0
- package/src/services/message/server.ts +4 -0
- package/src/services/message/type.ts +1 -1
- package/src/store/chat/slices/message/action.ts +48 -48
- package/src/store/chat/slices/message/initialState.ts +2 -0
- package/src/store/chat/slices/message/selectors.ts +3 -0
- package/src/store/chat/slices/plugin/action.test.ts +20 -20
- package/src/store/chat/slices/plugin/action.ts +133 -116
- package/src/store/chat/utils/index.ts +19 -0
- package/src/store/tool/slices/builtin/action.test.ts +8 -11
- package/src/store/tool/slices/builtin/action.ts +9 -9
- package/src/types/message/index.ts +1 -1
|
@@ -112,7 +112,7 @@ describe('ChatPluginAction', () => {
|
|
|
112
112
|
|
|
113
113
|
vi.spyOn(storeState, 'refreshMessages');
|
|
114
114
|
vi.spyOn(storeState, 'triggerAIMessage').mockResolvedValue(undefined);
|
|
115
|
-
vi.spyOn(storeState, '
|
|
115
|
+
vi.spyOn(storeState, 'internal_togglePluginApiCalling').mockReturnValue(undefined);
|
|
116
116
|
|
|
117
117
|
const runSpy = vi.spyOn(chatService, 'runPluginApi').mockResolvedValue({
|
|
118
118
|
text: pluginApiResponse,
|
|
@@ -125,7 +125,7 @@ describe('ChatPluginAction', () => {
|
|
|
125
125
|
await result.current.invokeDefaultTypePlugin(messageId, pluginPayload);
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
expect(storeState.
|
|
128
|
+
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
129
129
|
true,
|
|
130
130
|
messageId,
|
|
131
131
|
expect.any(String),
|
|
@@ -135,7 +135,7 @@ describe('ChatPluginAction', () => {
|
|
|
135
135
|
content: pluginApiResponse,
|
|
136
136
|
});
|
|
137
137
|
expect(storeState.refreshMessages).toHaveBeenCalled();
|
|
138
|
-
expect(storeState.
|
|
138
|
+
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
139
139
|
false,
|
|
140
140
|
'message-id',
|
|
141
141
|
'plugin/fetchPlugin/end',
|
|
@@ -150,7 +150,7 @@ describe('ChatPluginAction', () => {
|
|
|
150
150
|
const storeState = useChatStore.getState();
|
|
151
151
|
vi.spyOn(storeState, 'refreshMessages');
|
|
152
152
|
vi.spyOn(storeState, 'triggerAIMessage').mockResolvedValue(undefined);
|
|
153
|
-
vi.spyOn(storeState, '
|
|
153
|
+
vi.spyOn(storeState, 'internal_togglePluginApiCalling').mockReturnValue(undefined);
|
|
154
154
|
|
|
155
155
|
vi.spyOn(chatService, 'runPluginApi').mockRejectedValue(error);
|
|
156
156
|
|
|
@@ -159,7 +159,7 @@ describe('ChatPluginAction', () => {
|
|
|
159
159
|
await result.current.invokeDefaultTypePlugin(messageId, pluginPayload);
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
-
expect(storeState.
|
|
162
|
+
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
163
163
|
true,
|
|
164
164
|
messageId,
|
|
165
165
|
expect.any(String),
|
|
@@ -167,7 +167,7 @@ describe('ChatPluginAction', () => {
|
|
|
167
167
|
expect(chatService.runPluginApi).toHaveBeenCalledWith(pluginPayload, { trace: {} });
|
|
168
168
|
expect(messageService.updateMessageError).toHaveBeenCalledWith(messageId, error);
|
|
169
169
|
expect(storeState.refreshMessages).toHaveBeenCalled();
|
|
170
|
-
expect(storeState.
|
|
170
|
+
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
171
171
|
false,
|
|
172
172
|
'message-id',
|
|
173
173
|
'plugin/fetchPlugin/end',
|
|
@@ -463,11 +463,11 @@ describe('ChatPluginAction', () => {
|
|
|
463
463
|
const toolResponse = JSON.stringify({ abc: 'data' });
|
|
464
464
|
|
|
465
465
|
useToolStore.setState({
|
|
466
|
-
|
|
466
|
+
transformApiArgumentsToAiState: vi.fn().mockResolvedValue(toolResponse),
|
|
467
467
|
});
|
|
468
468
|
|
|
469
469
|
useChatStore.setState({
|
|
470
|
-
|
|
470
|
+
internal_togglePluginApiCalling: vi.fn(),
|
|
471
471
|
internal_updateMessageContent: vi.fn(),
|
|
472
472
|
text2image: vi.fn(),
|
|
473
473
|
});
|
|
@@ -479,7 +479,7 @@ describe('ChatPluginAction', () => {
|
|
|
479
479
|
});
|
|
480
480
|
|
|
481
481
|
// Verify that the builtin tool was invoked with the correct arguments
|
|
482
|
-
expect(useToolStore.getState().
|
|
482
|
+
expect(useToolStore.getState().transformApiArgumentsToAiState).toHaveBeenCalledWith(
|
|
483
483
|
payload.apiName,
|
|
484
484
|
JSON.parse(payload.arguments),
|
|
485
485
|
);
|
|
@@ -491,12 +491,12 @@ describe('ChatPluginAction', () => {
|
|
|
491
491
|
);
|
|
492
492
|
|
|
493
493
|
// Verify that loading was toggled correctly
|
|
494
|
-
expect(result.current.
|
|
494
|
+
expect(result.current.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
495
495
|
true,
|
|
496
496
|
messageId,
|
|
497
497
|
expect.any(String),
|
|
498
498
|
);
|
|
499
|
-
expect(result.current.
|
|
499
|
+
expect(result.current.internal_togglePluginApiCalling).toHaveBeenCalledWith(false);
|
|
500
500
|
expect(useChatStore.getState().text2image).toHaveBeenCalled();
|
|
501
501
|
});
|
|
502
502
|
|
|
@@ -511,12 +511,12 @@ describe('ChatPluginAction', () => {
|
|
|
511
511
|
|
|
512
512
|
act(() => {
|
|
513
513
|
useToolStore.setState({
|
|
514
|
-
|
|
514
|
+
transformApiArgumentsToAiState: vi.fn().mockResolvedValue(toolResponse),
|
|
515
515
|
text2image: vi.fn(),
|
|
516
516
|
});
|
|
517
517
|
|
|
518
518
|
useChatStore.setState({
|
|
519
|
-
|
|
519
|
+
internal_togglePluginApiCalling: vi.fn(),
|
|
520
520
|
text2image: vi.fn(),
|
|
521
521
|
internal_updateMessageContent: vi.fn(),
|
|
522
522
|
});
|
|
@@ -528,7 +528,7 @@ describe('ChatPluginAction', () => {
|
|
|
528
528
|
});
|
|
529
529
|
|
|
530
530
|
// Verify that the builtin tool was invoked with the correct arguments
|
|
531
|
-
expect(useToolStore.getState().
|
|
531
|
+
expect(useToolStore.getState().transformApiArgumentsToAiState).toHaveBeenCalledWith(
|
|
532
532
|
payload.apiName,
|
|
533
533
|
JSON.parse(payload.arguments),
|
|
534
534
|
);
|
|
@@ -540,12 +540,12 @@ describe('ChatPluginAction', () => {
|
|
|
540
540
|
);
|
|
541
541
|
|
|
542
542
|
// Verify that loading was toggled correctly
|
|
543
|
-
expect(result.current.
|
|
543
|
+
expect(result.current.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
544
544
|
true,
|
|
545
545
|
messageId,
|
|
546
546
|
expect.any(String),
|
|
547
547
|
);
|
|
548
|
-
expect(result.current.
|
|
548
|
+
expect(result.current.internal_togglePluginApiCalling).toHaveBeenCalledWith(false);
|
|
549
549
|
expect(useChatStore.getState().text2image).not.toHaveBeenCalled();
|
|
550
550
|
});
|
|
551
551
|
|
|
@@ -559,11 +559,11 @@ describe('ChatPluginAction', () => {
|
|
|
559
559
|
const error = new Error('Builtin tool failed');
|
|
560
560
|
|
|
561
561
|
useToolStore.setState({
|
|
562
|
-
|
|
562
|
+
transformApiArgumentsToAiState: vi.fn().mockRejectedValue(error),
|
|
563
563
|
});
|
|
564
564
|
|
|
565
565
|
useChatStore.setState({
|
|
566
|
-
|
|
566
|
+
internal_togglePluginApiCalling: vi.fn(),
|
|
567
567
|
internal_updateMessageContent: vi.fn(),
|
|
568
568
|
text2image: vi.fn(),
|
|
569
569
|
refreshMessages: vi.fn(),
|
|
@@ -576,12 +576,12 @@ describe('ChatPluginAction', () => {
|
|
|
576
576
|
});
|
|
577
577
|
|
|
578
578
|
// Verify that loading was toggled correctly
|
|
579
|
-
expect(result.current.
|
|
579
|
+
expect(result.current.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
580
580
|
true,
|
|
581
581
|
messageId,
|
|
582
582
|
expect.any(String),
|
|
583
583
|
);
|
|
584
|
-
expect(result.current.
|
|
584
|
+
expect(result.current.internal_togglePluginApiCalling).toHaveBeenCalledWith(false);
|
|
585
585
|
|
|
586
586
|
// Verify that the message content was not updated
|
|
587
587
|
expect(result.current.internal_updateMessageContent).not.toHaveBeenCalled();
|
|
@@ -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,129 +75,23 @@ 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 {
|
|
79
|
+
const { internal_togglePluginApiCalling, internal_updateMessageContent } = get();
|
|
181
80
|
const params = JSON.parse(payload.arguments);
|
|
182
|
-
|
|
81
|
+
internal_togglePluginApiCalling(true, id, n('invokeBuiltinTool') as string);
|
|
183
82
|
let data;
|
|
184
83
|
try {
|
|
185
|
-
data = await useToolStore.getState().
|
|
84
|
+
data = await useToolStore.getState().transformApiArgumentsToAiState(payload.apiName, params);
|
|
186
85
|
} catch (error) {
|
|
187
86
|
console.log(error);
|
|
188
87
|
}
|
|
189
|
-
|
|
88
|
+
internal_togglePluginApiCalling(false);
|
|
190
89
|
|
|
191
90
|
if (!data) return;
|
|
192
91
|
|
|
193
92
|
await internal_updateMessageContent(id, data);
|
|
194
93
|
|
|
94
|
+
// run tool api call
|
|
195
95
|
// postToolCalling
|
|
196
96
|
// @ts-ignore
|
|
197
97
|
const { [payload.apiName]: action } = get();
|
|
@@ -248,6 +148,11 @@ export const chatPlugin: StateCreator<
|
|
|
248
148
|
const message = chatSelectors.getMessageById(id)(get());
|
|
249
149
|
if (!message || message.role !== 'tool' || !message.plugin) return;
|
|
250
150
|
|
|
151
|
+
// if there is error content, then clear the error
|
|
152
|
+
if (!!message.error) {
|
|
153
|
+
get().internal_updateMessageError(id, null);
|
|
154
|
+
}
|
|
155
|
+
|
|
251
156
|
const payload: ChatToolPayload = { ...message.plugin, id: message.tool_call_id! };
|
|
252
157
|
|
|
253
158
|
await get().internal_invokeDifferentTypePlugin(id, payload);
|
|
@@ -301,4 +206,116 @@ export const chatPlugin: StateCreator<
|
|
|
301
206
|
await messageService.updateMessagePluginState(id, { [key]: value });
|
|
302
207
|
await refreshMessages();
|
|
303
208
|
},
|
|
209
|
+
|
|
210
|
+
internal_callPluginApi: async (id, payload) => {
|
|
211
|
+
const { internal_updateMessageContent, refreshMessages, internal_togglePluginApiCalling } =
|
|
212
|
+
get();
|
|
213
|
+
let data: string;
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const abortController = internal_togglePluginApiCalling(
|
|
217
|
+
true,
|
|
218
|
+
id,
|
|
219
|
+
n('fetchPlugin/start') as string,
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
const message = chatSelectors.getMessageById(id)(get());
|
|
223
|
+
|
|
224
|
+
const res = await chatService.runPluginApi(payload, {
|
|
225
|
+
signal: abortController?.signal,
|
|
226
|
+
trace: { observationId: message?.observationId, traceId: message?.traceId },
|
|
227
|
+
});
|
|
228
|
+
data = res.text;
|
|
229
|
+
|
|
230
|
+
// save traceId
|
|
231
|
+
if (res.traceId) {
|
|
232
|
+
await messageService.updateMessage(id, { traceId: res.traceId });
|
|
233
|
+
}
|
|
234
|
+
} catch (error) {
|
|
235
|
+
console.log(error);
|
|
236
|
+
const err = error as Error;
|
|
237
|
+
|
|
238
|
+
// ignore the aborted request error
|
|
239
|
+
if (!err.message.includes('The user aborted a request.')) {
|
|
240
|
+
await messageService.updateMessageError(id, error as any);
|
|
241
|
+
await refreshMessages();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
data = '';
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
internal_togglePluginApiCalling(false, id, n('fetchPlugin/end') as string);
|
|
248
|
+
// 如果报错则结束了
|
|
249
|
+
if (!data) return;
|
|
250
|
+
|
|
251
|
+
await internal_updateMessageContent(id, data);
|
|
252
|
+
|
|
253
|
+
return data;
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
internal_invokeDifferentTypePlugin: async (id, payload) => {
|
|
257
|
+
switch (payload.type) {
|
|
258
|
+
case 'standalone': {
|
|
259
|
+
return await get().invokeStandaloneTypePlugin(id, payload);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
case 'markdown': {
|
|
263
|
+
return await get().invokeMarkdownTypePlugin(id, payload);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
case 'builtin': {
|
|
267
|
+
return await get().invokeBuiltinTool(id, payload);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
default: {
|
|
271
|
+
return await get().invokeDefaultTypePlugin(id, payload);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
internal_togglePluginApiCalling: (loading, id, action) => {
|
|
277
|
+
return get().internal_toggleLoadingArrays('pluginApiLoadingIds', loading, id, action);
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
internal_transformToolCalls: (toolCalls) => {
|
|
281
|
+
return toolCalls
|
|
282
|
+
.map((toolCall): ChatToolPayload | null => {
|
|
283
|
+
let payload: ChatToolPayload;
|
|
284
|
+
|
|
285
|
+
const [identifier, apiName, type] = toolCall.function.name.split(PLUGIN_SCHEMA_SEPARATOR);
|
|
286
|
+
|
|
287
|
+
if (!apiName) return null;
|
|
288
|
+
|
|
289
|
+
payload = {
|
|
290
|
+
apiName,
|
|
291
|
+
arguments: toolCall.function.arguments,
|
|
292
|
+
id: toolCall.id,
|
|
293
|
+
identifier,
|
|
294
|
+
type: (type ?? 'default') as any,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// if the apiName is md5, try to find the correct apiName in the plugins
|
|
298
|
+
if (apiName.startsWith(PLUGIN_SCHEMA_API_MD5_PREFIX)) {
|
|
299
|
+
const md5 = apiName.replace(PLUGIN_SCHEMA_API_MD5_PREFIX, '');
|
|
300
|
+
const manifest = pluginSelectors.getPluginManifestById(identifier)(
|
|
301
|
+
useToolStore.getState(),
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
const api = manifest?.api.find((api) => Md5.hashStr(api.name).toString() === md5);
|
|
305
|
+
if (api) {
|
|
306
|
+
payload.apiName = api.name;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return payload;
|
|
311
|
+
})
|
|
312
|
+
.filter(Boolean) as ChatToolPayload[];
|
|
313
|
+
},
|
|
314
|
+
internal_updatePluginError: async (id, error) => {
|
|
315
|
+
const { refreshMessages } = get();
|
|
316
|
+
|
|
317
|
+
get().internal_dispatchMessage({ id, type: 'updateMessages', value: { error } });
|
|
318
|
+
await messageService.updateMessage(id, { pluginError: error });
|
|
319
|
+
await refreshMessages();
|
|
320
|
+
},
|
|
304
321
|
});
|
|
@@ -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
|
+
};
|
|
@@ -23,7 +23,7 @@ describe('createBuiltinToolSlice', () => {
|
|
|
23
23
|
|
|
24
24
|
await act(async () => {
|
|
25
25
|
// When
|
|
26
|
-
const data = await result.current.
|
|
26
|
+
const data = await result.current.transformApiArgumentsToAiState(key, params);
|
|
27
27
|
expect(data).toBeUndefined();
|
|
28
28
|
});
|
|
29
29
|
|
|
@@ -53,7 +53,7 @@ describe('createBuiltinToolSlice', () => {
|
|
|
53
53
|
});
|
|
54
54
|
// When
|
|
55
55
|
await act(async () => {
|
|
56
|
-
await result.current.
|
|
56
|
+
await result.current.transformApiArgumentsToAiState(key, params);
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
expect(mockFn).toBeCalledWith({
|
|
@@ -70,15 +70,12 @@ describe('createBuiltinToolSlice', () => {
|
|
|
70
70
|
// When
|
|
71
71
|
const { result } = renderHook(() => useToolStore());
|
|
72
72
|
|
|
73
|
-
const data = result.current.text2image(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
},
|
|
80
|
-
'a',
|
|
81
|
-
);
|
|
73
|
+
const data = result.current.text2image({
|
|
74
|
+
prompts: ['prompt1', 'prompt2'],
|
|
75
|
+
size: '1024x1024',
|
|
76
|
+
quality: 'standard',
|
|
77
|
+
style: 'vivid',
|
|
78
|
+
});
|
|
82
79
|
|
|
83
80
|
// Then
|
|
84
81
|
expect(data).toEqual([
|
|
@@ -16,9 +16,9 @@ interface Text2ImageParams extends Pick<OpenAIImagePayload, 'quality' | 'style'
|
|
|
16
16
|
* 代理行为接口
|
|
17
17
|
*/
|
|
18
18
|
export interface BuiltinToolAction {
|
|
19
|
-
|
|
20
|
-
text2image: (params: Text2ImageParams, messageId: string) => DallEImageItem[];
|
|
19
|
+
text2image: (params: Text2ImageParams) => DallEImageItem[];
|
|
21
20
|
toggleBuiltinToolLoading: (key: string, value: boolean) => void;
|
|
21
|
+
transformApiArgumentsToAiState: (key: string, params: any) => Promise<string | undefined>;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export const createBuiltinToolSlice: StateCreator<
|
|
@@ -27,7 +27,13 @@ export const createBuiltinToolSlice: StateCreator<
|
|
|
27
27
|
[],
|
|
28
28
|
BuiltinToolAction
|
|
29
29
|
> = (set, get) => ({
|
|
30
|
-
|
|
30
|
+
text2image: ({ prompts, size = '1024x1024' as const, quality = 'standard', style = 'vivid' }) =>
|
|
31
|
+
prompts.map((p) => ({ prompt: p, quality, size, style })),
|
|
32
|
+
toggleBuiltinToolLoading: (key, value) => {
|
|
33
|
+
set({ builtinToolLoading: { [key]: value } }, false, n('toggleBuiltinToolLoading'));
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
transformApiArgumentsToAiState: async (key, params) => {
|
|
31
37
|
const { builtinToolLoading, toggleBuiltinToolLoading } = get();
|
|
32
38
|
|
|
33
39
|
if (builtinToolLoading[key]) return;
|
|
@@ -45,10 +51,4 @@ export const createBuiltinToolSlice: StateCreator<
|
|
|
45
51
|
|
|
46
52
|
return JSON.stringify(result);
|
|
47
53
|
},
|
|
48
|
-
text2image: ({ prompts, size = '1024x1024' as const, quality = 'standard', style = 'vivid' }) =>
|
|
49
|
-
prompts.map((p) => ({ prompt: p, quality, size, style })),
|
|
50
|
-
|
|
51
|
-
toggleBuiltinToolLoading: (key, value) => {
|
|
52
|
-
set({ builtinToolLoading: { [key]: value } }, false, n('toggleBuiltinToolLoading'));
|
|
53
|
-
},
|
|
54
54
|
});
|