mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-03 21:48:02 +00:00
V4.9.12 feature (#5022)
* New chatinput (#4995) * feat: Change border style * refactor: Improve layout and styling of ChatInput component * style: Update ChatInput component styling and mobile layout * fix: update key detection for Enter key in ChatInput component * feat: 添加 WelcomePage 组件,支持变量输入和欢迎信息展示 * style: Updated the PC voice input interface of the VoiceInput component and optimized the layout and style * style: Optimize the layout and style of the WelcomePage component, and adjust the responsive design * feat: Dynamically load the WelcomePage component and optimize the welcome information display logic * refactor: Adjust the style and behavior of the ChatInput component and delete the WelcomePage component * style: Modify the minimum height setting of the ChatInput component to simplify responsive design * style: Optimize the layout and style of PC voice input components, and enhance the processing and drawing logic of waveform data * style: Adjust ChatInput component's margin and textarea height logic for improved layout and responsiveness; refine PCVoiceInput component's positioning and display elements * style: Enhance PCVoiceInput component's time display styling with custom font properties * feat: Change border style * refactor: Improve layout and styling of ChatInput component * style: Update ChatInput component styling and mobile layout * fix: update key detection for Enter key in ChatInput component * feat: 添加 WelcomePage 组件,支持变量输入和欢迎信息展示 * style: Updated the PC voice input interface of the VoiceInput component and optimized the layout and style * style: Optimize the layout and style of the WelcomePage component, and adjust the responsive design * feat: Dynamically load the WelcomePage component and optimize the welcome information display logic * refactor: Adjust the style and behavior of the ChatInput component and delete the WelcomePage component * style: Modify the minimum height setting of the ChatInput component to simplify responsive design * style: Optimize the layout and style of PC voice input components, and enhance the processing and drawing logic of waveform data * style: Adjust ChatInput component's margin and textarea height logic for improved layout and responsiveness; refine PCVoiceInput component's positioning and display elements * style: Enhance PCVoiceInput component's time display styling with custom font properties * style: Add new 'xxl' size to theme spacing for improved layout options * style: Update close icon fill color to use currentColor for better theming support * style: Enhance voice input functionality and UI responsiveness; improve waveform sensitivity and amplitude * style: Conditionally render file preview based on voice input state * style: 优化移动端音频波形渲染,增强清晰度和敏感度 * style: Update comments to English to enhance code readability and consistency * style: Adjust the mobile audio waveform update frequency and optimize rendering performance * style: Optimize the file preview rendering logic in voice input mode to enhance user experience * style: Optimize the file preview rendering logic in voice input mode to enhance user experience * style: Adjust the chat input box placeholder color and border color to enhance visual effects * fix: pg test * Test secret (#5011) * add http header auth config (#4982) * add http header auth config * optimize code * add mcp tools header auth * fix build * fix ui * fix * teamid * secret value encrypt (#5002) * perf: secret code * header auth ui (#5012) * header auth ui * fix i18n * doc * perf: type * header secret ui * reset ui * perf: check secret invalid --------- Co-authored-by: heheer <heheer@sealos.io> * feat: cq and extrat AI memory (#5013) * fix: login xss * feat: Users can download the invoice by self (#5015) * Users can download the invoice by themselves * Direct file stream implementation for transmission presentation * i18n * Chatbox-fix (#5018) * feat: Change border style * refactor: Improve layout and styling of ChatInput component * style: Update ChatInput component styling and mobile layout * fix: update key detection for Enter key in ChatInput component * feat: 添加 WelcomePage 组件,支持变量输入和欢迎信息展示 * style: Updated the PC voice input interface of the VoiceInput component and optimized the layout and style * style: Optimize the layout and style of the WelcomePage component, and adjust the responsive design * feat: Dynamically load the WelcomePage component and optimize the welcome information display logic * refactor: Adjust the style and behavior of the ChatInput component and delete the WelcomePage component * style: Modify the minimum height setting of the ChatInput component to simplify responsive design * style: Optimize the layout and style of PC voice input components, and enhance the processing and drawing logic of waveform data * style: Adjust ChatInput component's margin and textarea height logic for improved layout and responsiveness; refine PCVoiceInput component's positioning and display elements * style: Enhance PCVoiceInput component's time display styling with custom font properties * feat: Change border style * refactor: Improve layout and styling of ChatInput component * style: Update ChatInput component styling and mobile layout * fix: update key detection for Enter key in ChatInput component * feat: 添加 WelcomePage 组件,支持变量输入和欢迎信息展示 * style: Updated the PC voice input interface of the VoiceInput component and optimized the layout and style * style: Optimize the layout and style of the WelcomePage component, and adjust the responsive design * feat: Dynamically load the WelcomePage component and optimize the welcome information display logic * refactor: Adjust the style and behavior of the ChatInput component and delete the WelcomePage component * style: Modify the minimum height setting of the ChatInput component to simplify responsive design * style: Optimize the layout and style of PC voice input components, and enhance the processing and drawing logic of waveform data * style: Adjust ChatInput component's margin and textarea height logic for improved layout and responsiveness; refine PCVoiceInput component's positioning and display elements * style: Enhance PCVoiceInput component's time display styling with custom font properties * style: Add new 'xxl' size to theme spacing for improved layout options * style: Update close icon fill color to use currentColor for better theming support * style: Enhance voice input functionality and UI responsiveness; improve waveform sensitivity and amplitude * style: Conditionally render file preview based on voice input state * style: 优化移动端音频波形渲染,增强清晰度和敏感度 * style: Update comments to English to enhance code readability and consistency * style: Adjust the mobile audio waveform update frequency and optimize rendering performance * style: Optimize the file preview rendering logic in voice input mode to enhance user experience * style: Optimize the file preview rendering logic in voice input mode to enhance user experience * style: Adjust the chat input box placeholder color and border color to enhance visual effects * New chatinput (#4995) * feat: Change border style * refactor: Improve layout and styling of ChatInput component * style: Update ChatInput component styling and mobile layout * fix: update key detection for Enter key in ChatInput component * feat: 添加 WelcomePage 组件,支持变量输入和欢迎信息展示 * style: Updated the PC voice input interface of the VoiceInput component and optimized the layout and style * style: Optimize the layout and style of the WelcomePage component, and adjust the responsive design * feat: Dynamically load the WelcomePage component and optimize the welcome information display logic * refactor: Adjust the style and behavior of the ChatInput component and delete the WelcomePage component * style: Modify the minimum height setting of the ChatInput component to simplify responsive design * style: Optimize the layout and style of PC voice input components, and enhance the processing and drawing logic of waveform data * style: Adjust ChatInput component's margin and textarea height logic for improved layout and responsiveness; refine PCVoiceInput component's positioning and display elements * style: Enhance PCVoiceInput component's time display styling with custom font properties * feat: Change border style * refactor: Improve layout and styling of ChatInput component * style: Update ChatInput component styling and mobile layout * fix: update key detection for Enter key in ChatInput component * feat: 添加 WelcomePage 组件,支持变量输入和欢迎信息展示 * style: Updated the PC voice input interface of the VoiceInput component and optimized the layout and style * style: Optimize the layout and style of the WelcomePage component, and adjust the responsive design * feat: Dynamically load the WelcomePage component and optimize the welcome information display logic * refactor: Adjust the style and behavior of the ChatInput component and delete the WelcomePage component * style: Modify the minimum height setting of the ChatInput component to simplify responsive design * style: Optimize the layout and style of PC voice input components, and enhance the processing and drawing logic of waveform data * style: Adjust ChatInput component's margin and textarea height logic for improved layout and responsiveness; refine PCVoiceInput component's positioning and display elements * style: Enhance PCVoiceInput component's time display styling with custom font properties * style: Add new 'xxl' size to theme spacing for improved layout options * style: Update close icon fill color to use currentColor for better theming support * style: Enhance voice input functionality and UI responsiveness; improve waveform sensitivity and amplitude * style: Conditionally render file preview based on voice input state * style: 优化移动端音频波形渲染,增强清晰度和敏感度 * style: Update comments to English to enhance code readability and consistency * style: Adjust the mobile audio waveform update frequency and optimize rendering performance * style: Optimize the file preview rendering logic in voice input mode to enhance user experience * style: Optimize the file preview rendering logic in voice input mode to enhance user experience * style: Adjust the chat input box placeholder color and border color to enhance visual effects * fix: pg test * Test secret (#5011) * add http header auth config (#4982) * add http header auth config * optimize code * add mcp tools header auth * fix build * fix ui * fix * teamid * secret value encrypt (#5002) * perf: secret code * header auth ui (#5012) * header auth ui * fix i18n * doc * perf: type * header secret ui * reset ui * perf: check secret invalid --------- Co-authored-by: heheer <heheer@sealos.io> * feat: cq and extrat AI memory (#5013) * refactor: Refactored the ChatInput component, optimized the layout of the text area and button group, and improved the user experience * refactor: Updated ChatInput component, optimized layout and style, and enhanced user experience * feat: update docs --------- Co-authored-by: archer <545436317@qq.com> Co-authored-by: heheer <heheer@sealos.io> * input ui * fix: chat input ux * Return in JSON format to handle checkres (#5019) * Users can download the invoice by themselves * Direct file stream implementation for transmission presentation * Return in JSON format to handle checkres * fix: invoice * fix: ui * doc * update package * fix: ts * fix: login checker * fix: team plan * perf: aiproxy ux --------- Co-authored-by: Theresa <63280168+sd0ric4@users.noreply.github.com> Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: Zhuangzai fa <143257420+ctrlz526@users.noreply.github.com>
This commit is contained in:
@@ -59,25 +59,27 @@ export const dispatchAppRequest = async (props: Props): Promise<Response> => {
|
||||
const chatHistories = getHistories(history, histories);
|
||||
const { files } = chatValue2RuntimePrompt(query);
|
||||
|
||||
const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
|
||||
...props,
|
||||
runningAppInfo: {
|
||||
id: String(appData._id),
|
||||
teamId: String(appData.teamId),
|
||||
tmbId: String(appData.tmbId)
|
||||
},
|
||||
runtimeNodes: storeNodes2RuntimeNodes(
|
||||
appData.modules,
|
||||
getWorkflowEntryNodeIds(appData.modules)
|
||||
),
|
||||
runtimeEdges: storeEdges2RuntimeEdges(appData.edges),
|
||||
histories: chatHistories,
|
||||
query: runtimePrompt2ChatsValue({
|
||||
files,
|
||||
text: userChatInput
|
||||
}),
|
||||
variables: props.variables
|
||||
});
|
||||
const { flowResponses, flowUsages, assistantResponses, system_memories } = await dispatchWorkFlow(
|
||||
{
|
||||
...props,
|
||||
runningAppInfo: {
|
||||
id: String(appData._id),
|
||||
teamId: String(appData.teamId),
|
||||
tmbId: String(appData.tmbId)
|
||||
},
|
||||
runtimeNodes: storeNodes2RuntimeNodes(
|
||||
appData.modules,
|
||||
getWorkflowEntryNodeIds(appData.modules)
|
||||
),
|
||||
runtimeEdges: storeEdges2RuntimeEdges(appData.edges),
|
||||
histories: chatHistories,
|
||||
query: runtimePrompt2ChatsValue({
|
||||
files,
|
||||
text: userChatInput
|
||||
}),
|
||||
variables: props.variables
|
||||
}
|
||||
);
|
||||
|
||||
const completeMessages = chatHistories.concat([
|
||||
{
|
||||
@@ -94,6 +96,7 @@ export const dispatchAppRequest = async (props: Props): Promise<Response> => {
|
||||
|
||||
return {
|
||||
assistantResponses,
|
||||
system_memories,
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: {
|
||||
moduleLogo: appData.avatar,
|
||||
query: userChatInput,
|
||||
|
@@ -11,19 +11,17 @@ import type { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { getCQPrompt } from '@fastgpt/global/core/ai/prompt/agent';
|
||||
import { getCQSystemPrompt } from '@fastgpt/global/core/ai/prompt/agent';
|
||||
import { type LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||
import { getLLMModel } from '../../../ai/model';
|
||||
import { getHistories } from '../utils';
|
||||
import { formatModelChars2Points } from '../../../../support/wallet/usage/utils';
|
||||
import { type DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
|
||||
import { getHandleId } from '@fastgpt/global/core/workflow/utils';
|
||||
import { loadRequestMessages } from '../../../chat/utils';
|
||||
import { llmCompletionsBodyFormat, formatLLMResponse } from '../../../ai/utils';
|
||||
import { addLog } from '../../../../common/system/log';
|
||||
import { ModelTypeEnum } from '../../../../../global/core/ai/model';
|
||||
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||
|
||||
type Props = ModuleDispatchProps<{
|
||||
[NodeInputKeyEnum.aiModel]: string;
|
||||
@@ -35,12 +33,16 @@ type Props = ModuleDispatchProps<{
|
||||
type CQResponse = DispatchNodeResultType<{
|
||||
[NodeOutputKeyEnum.cqResult]: string;
|
||||
}>;
|
||||
type ActionProps = Props & { cqModel: LLMModelItemType };
|
||||
type ActionProps = Props & {
|
||||
cqModel: LLMModelItemType;
|
||||
lastMemory?: ClassifyQuestionAgentItemType;
|
||||
};
|
||||
|
||||
/* request openai chat */
|
||||
export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse> => {
|
||||
const {
|
||||
externalProvider,
|
||||
runningAppInfo,
|
||||
node: { nodeId, name },
|
||||
histories,
|
||||
params: { model, history = 6, agents, userChatInput }
|
||||
@@ -52,10 +54,16 @@ export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse
|
||||
|
||||
const cqModel = getLLMModel(model);
|
||||
|
||||
const memoryKey = `${runningAppInfo.id}-${nodeId}`;
|
||||
const chatHistories = getHistories(history, histories);
|
||||
// @ts-ignore
|
||||
const lastMemory = chatHistories[chatHistories.length - 1]?.memories?.[
|
||||
memoryKey
|
||||
] as ClassifyQuestionAgentItemType;
|
||||
|
||||
const { arg, inputTokens, outputTokens } = await completions({
|
||||
...props,
|
||||
lastMemory,
|
||||
histories: chatHistories,
|
||||
cqModel
|
||||
});
|
||||
@@ -74,6 +82,9 @@ export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse
|
||||
[DispatchNodeResponseKeyEnum.skipHandleId]: agents
|
||||
.filter((item) => item.key !== result.key)
|
||||
.map((item) => getHandleId(nodeId, 'source', item.key)),
|
||||
[DispatchNodeResponseKeyEnum.memories]: {
|
||||
[memoryKey]: result
|
||||
},
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: {
|
||||
totalPoints: externalProvider.openaiAccount?.key ? 0 : totalPoints,
|
||||
model: modelName,
|
||||
@@ -100,26 +111,35 @@ const completions = async ({
|
||||
cqModel,
|
||||
externalProvider,
|
||||
histories,
|
||||
params: { agents, systemPrompt = '', userChatInput },
|
||||
node: { version }
|
||||
lastMemory,
|
||||
params: { agents, systemPrompt = '', userChatInput }
|
||||
}: ActionProps) => {
|
||||
const messages: ChatItemType[] = [
|
||||
{
|
||||
obj: ChatRoleEnum.System,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: getCQSystemPrompt({
|
||||
systemPrompt,
|
||||
memory: lastMemory ? JSON.stringify(lastMemory) : '',
|
||||
typeList: JSON.stringify(
|
||||
agents.map((item) => ({ id: item.key, description: item.value }))
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
...histories,
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: replaceVariable(cqModel.customCQPrompt || getCQPrompt(version), {
|
||||
systemPrompt: systemPrompt || 'null',
|
||||
typeList: agents
|
||||
.map((item) => `{"类型ID":"${item.key}", "问题类型":"${item.value}"}`)
|
||||
.join('\n------\n'),
|
||||
history: histories
|
||||
.map((item) => `${item.obj}:${chatValue2RuntimePrompt(item.value).text}`)
|
||||
.join('\n------\n'),
|
||||
question: userChatInput
|
||||
})
|
||||
content: userChatInput
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -145,7 +165,6 @@ const completions = async ({
|
||||
const { text: answer, usage } = await formatLLMResponse(response);
|
||||
|
||||
// console.log(JSON.stringify(chats2GPTMessages({ messages, reserveId: false }), null, 2));
|
||||
// console.log(answer, '----');
|
||||
|
||||
const id =
|
||||
agents.find((item) => answer.includes(item.key))?.key ||
|
||||
|
@@ -13,7 +13,7 @@ import type { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { NodeOutputKeyEnum, toolValueTypeList } from '@fastgpt/global/core/workflow/constants';
|
||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { replaceVariable, sliceJsonStr } from '@fastgpt/global/common/string/tools';
|
||||
import { sliceJsonStr } from '@fastgpt/global/common/string/tools';
|
||||
import { type LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||
import { getHistories } from '../utils';
|
||||
import { getLLMModel } from '../../../ai/model';
|
||||
@@ -21,12 +21,10 @@ import { formatModelChars2Points } from '../../../../support/wallet/usage/utils'
|
||||
import json5 from 'json5';
|
||||
import {
|
||||
type ChatCompletionMessageParam,
|
||||
type ChatCompletionTool,
|
||||
type UnStreamChatType
|
||||
type ChatCompletionTool
|
||||
} from '@fastgpt/global/core/ai/type';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/constants';
|
||||
import { type DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
|
||||
import { llmCompletionsBodyFormat, formatLLMResponse } from '../../../ai/utils';
|
||||
import { ModelTypeEnum } from '../../../../../global/core/ai/model';
|
||||
import {
|
||||
@@ -46,14 +44,15 @@ type Response = DispatchNodeResultType<{
|
||||
[NodeOutputKeyEnum.contextExtractFields]: string;
|
||||
}>;
|
||||
|
||||
type ActionProps = Props & { extractModel: LLMModelItemType };
|
||||
type ActionProps = Props & { extractModel: LLMModelItemType; lastMemory?: Record<string, any> };
|
||||
|
||||
const agentFunName = 'request_function';
|
||||
|
||||
export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
const {
|
||||
externalProvider,
|
||||
node: { name },
|
||||
runningAppInfo,
|
||||
node: { nodeId, name },
|
||||
histories,
|
||||
params: { content, history = 6, model, description, extractKeys }
|
||||
} = props;
|
||||
@@ -65,18 +64,27 @@ export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
const extractModel = getLLMModel(model);
|
||||
const chatHistories = getHistories(history, histories);
|
||||
|
||||
const memoryKey = `${runningAppInfo.id}-${nodeId}`;
|
||||
// @ts-ignore
|
||||
const lastMemory = chatHistories[chatHistories.length - 1]?.memories?.[memoryKey] as Record<
|
||||
string,
|
||||
any
|
||||
>;
|
||||
|
||||
const { arg, inputTokens, outputTokens } = await (async () => {
|
||||
if (extractModel.toolChoice) {
|
||||
return toolChoice({
|
||||
...props,
|
||||
histories: chatHistories,
|
||||
extractModel
|
||||
extractModel,
|
||||
lastMemory
|
||||
});
|
||||
}
|
||||
return completions({
|
||||
...props,
|
||||
histories: chatHistories,
|
||||
extractModel
|
||||
extractModel,
|
||||
lastMemory
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -121,6 +129,9 @@ export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
return {
|
||||
[NodeOutputKeyEnum.success]: success,
|
||||
[NodeOutputKeyEnum.contextExtractFields]: JSON.stringify(arg),
|
||||
[DispatchNodeResponseKeyEnum.memories]: {
|
||||
[memoryKey]: arg
|
||||
},
|
||||
...arg,
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: {
|
||||
totalPoints: externalProvider.openaiAccount?.key ? 0 : totalPoints,
|
||||
@@ -144,39 +155,7 @@ export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
};
|
||||
}
|
||||
|
||||
const getFunctionCallSchema = async ({
|
||||
extractModel,
|
||||
histories,
|
||||
params: { content, extractKeys, description },
|
||||
node: { version }
|
||||
}: ActionProps) => {
|
||||
const messages: ChatItemType[] = [
|
||||
...histories,
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: replaceVariable(getExtractJsonToolPrompt(version), {
|
||||
description,
|
||||
content
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
const adaptMessages = chats2GPTMessages({ messages, reserveId: false });
|
||||
const filterMessages = await filterGPTMessageByMaxContext({
|
||||
messages: adaptMessages,
|
||||
maxContext: extractModel.maxContext
|
||||
});
|
||||
const requestMessages = await loadRequestMessages({
|
||||
messages: filterMessages,
|
||||
useVision: false
|
||||
});
|
||||
|
||||
const getJsonSchema = ({ params: { extractKeys } }: ActionProps) => {
|
||||
const properties: Record<
|
||||
string,
|
||||
{
|
||||
@@ -194,32 +173,71 @@ const getFunctionCallSchema = async ({
|
||||
...(item.enum ? { enum: item.enum.split('\n').filter(Boolean) } : {})
|
||||
};
|
||||
});
|
||||
// function body
|
||||
const agentFunction = {
|
||||
name: agentFunName,
|
||||
description: '需要执行的函数',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties,
|
||||
required: []
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
filterMessages: requestMessages,
|
||||
agentFunction
|
||||
};
|
||||
return properties;
|
||||
};
|
||||
|
||||
const toolChoice = async (props: ActionProps) => {
|
||||
const { externalProvider, extractModel } = props;
|
||||
const {
|
||||
externalProvider,
|
||||
extractModel,
|
||||
histories,
|
||||
params: { content, description },
|
||||
lastMemory
|
||||
} = props;
|
||||
|
||||
const { filterMessages, agentFunction } = await getFunctionCallSchema(props);
|
||||
const messages: ChatItemType[] = [
|
||||
{
|
||||
obj: ChatRoleEnum.System,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: getExtractJsonToolPrompt({
|
||||
systemPrompt: description,
|
||||
memory: lastMemory ? JSON.stringify(lastMemory) : undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
...histories,
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
const adaptMessages = chats2GPTMessages({ messages, reserveId: false });
|
||||
const filterMessages = await filterGPTMessageByMaxContext({
|
||||
messages: adaptMessages,
|
||||
maxContext: extractModel.maxContext
|
||||
});
|
||||
const requestMessages = await loadRequestMessages({
|
||||
messages: filterMessages,
|
||||
useVision: false
|
||||
});
|
||||
|
||||
const schema = getJsonSchema(props);
|
||||
|
||||
const tools: ChatCompletionTool[] = [
|
||||
{
|
||||
type: 'function',
|
||||
function: agentFunction
|
||||
function: {
|
||||
name: agentFunName,
|
||||
description: '需要执行的函数',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: schema,
|
||||
required: []
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -228,12 +246,13 @@ const toolChoice = async (props: ActionProps) => {
|
||||
stream: true,
|
||||
model: extractModel.model,
|
||||
temperature: 0.01,
|
||||
messages: filterMessages,
|
||||
messages: requestMessages,
|
||||
tools,
|
||||
tool_choice: { type: 'function', function: { name: agentFunName } }
|
||||
},
|
||||
extractModel
|
||||
);
|
||||
|
||||
const { response } = await createChatCompletion({
|
||||
body,
|
||||
userKey: externalProvider.openaiAccount
|
||||
@@ -242,7 +261,7 @@ const toolChoice = async (props: ActionProps) => {
|
||||
|
||||
const arg: Record<string, any> = (() => {
|
||||
try {
|
||||
return json5.parse(toolCalls?.[0]?.function?.arguments || '');
|
||||
return json5.parse(toolCalls?.[0]?.function?.arguments || text || '');
|
||||
} catch (error) {
|
||||
console.log('body', body);
|
||||
console.log('AI response', text, toolCalls?.[0]?.function);
|
||||
@@ -267,40 +286,39 @@ const toolChoice = async (props: ActionProps) => {
|
||||
};
|
||||
};
|
||||
|
||||
const completions = async ({
|
||||
extractModel,
|
||||
externalProvider,
|
||||
histories,
|
||||
params: { content, extractKeys, description = 'No special requirements' },
|
||||
node: { version }
|
||||
}: ActionProps) => {
|
||||
const completions = async (props: ActionProps) => {
|
||||
const {
|
||||
extractModel,
|
||||
externalProvider,
|
||||
histories,
|
||||
lastMemory,
|
||||
params: { content, description }
|
||||
} = props;
|
||||
|
||||
const messages: ChatItemType[] = [
|
||||
{
|
||||
obj: ChatRoleEnum.System,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: getExtractJsonPrompt({
|
||||
systemPrompt: description,
|
||||
memory: lastMemory ? JSON.stringify(lastMemory) : undefined,
|
||||
schema: JSON.stringify(getJsonSchema(props))
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
...histories,
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: replaceVariable(
|
||||
extractModel.customExtractPrompt || getExtractJsonPrompt(version),
|
||||
{
|
||||
description,
|
||||
json: extractKeys
|
||||
.map((item) => {
|
||||
const valueType = item.valueType || 'string';
|
||||
if (valueType !== 'string' && valueType !== 'number') {
|
||||
item.enum = undefined;
|
||||
}
|
||||
|
||||
return `{"type":${item.valueType || 'string'}, "key":"${item.key}", "description":"${item.desc}" ${
|
||||
item.enum ? `, "enum":"[${item.enum.split('\n')}]"` : ''
|
||||
}}`;
|
||||
})
|
||||
.join('\n'),
|
||||
text: `${histories.map((item) => `${item.obj}:${chatValue2RuntimePrompt(item.value).text}`).join('\n')}
|
||||
Human: ${content}`
|
||||
}
|
||||
)
|
||||
content
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@@ -223,6 +223,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
interactiveResponse: InteractiveNodeResponseType;
|
||||
}
|
||||
| undefined;
|
||||
let system_memories: Record<string, any> = {}; // Workflow node memories
|
||||
|
||||
/* Store special response field */
|
||||
function pushStore(
|
||||
@@ -235,7 +236,8 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
toolResponses,
|
||||
assistantResponses,
|
||||
rewriteHistories,
|
||||
runTimes = 1
|
||||
runTimes = 1,
|
||||
system_memories: newMemories
|
||||
}: Omit<
|
||||
DispatchNodeResultType<{
|
||||
[NodeOutputKeyEnum.answerText]?: string;
|
||||
@@ -249,6 +251,13 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
workflowRunTimes += runTimes;
|
||||
props.maxRunTimes -= runTimes;
|
||||
|
||||
if (newMemories) {
|
||||
system_memories = {
|
||||
...system_memories,
|
||||
...newMemories
|
||||
};
|
||||
}
|
||||
|
||||
if (responseData) {
|
||||
chatResponses.push(responseData);
|
||||
}
|
||||
@@ -771,7 +780,12 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
[DispatchNodeResponseKeyEnum.assistantResponses]:
|
||||
mergeAssistantResponseAnswerText(chatAssistantResponse),
|
||||
[DispatchNodeResponseKeyEnum.toolResponses]: toolRunResponse,
|
||||
newVariables: removeSystemVariable(variables, externalProvider.externalWorkflowVariables),
|
||||
[DispatchNodeResponseKeyEnum.newVariables]: removeSystemVariable(
|
||||
variables,
|
||||
externalProvider.externalWorkflowVariables
|
||||
),
|
||||
[DispatchNodeResponseKeyEnum.memories]:
|
||||
Object.keys(system_memories).length > 0 ? system_memories : undefined,
|
||||
durationSeconds
|
||||
};
|
||||
} catch (error) {
|
||||
|
@@ -80,32 +80,33 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
appId: String(plugin.id),
|
||||
...(externalProvider ? externalProvider.externalWorkflowVariables : {})
|
||||
};
|
||||
const { flowResponses, flowUsages, assistantResponses, runTimes } = await dispatchWorkFlow({
|
||||
...props,
|
||||
// Rewrite stream mode
|
||||
...(system_forbid_stream
|
||||
? {
|
||||
stream: false,
|
||||
workflowStreamResponse: undefined
|
||||
}
|
||||
: {}),
|
||||
runningAppInfo: {
|
||||
id: String(plugin.id),
|
||||
// 如果系统插件有 teamId 和 tmbId,则使用系统插件的 teamId 和 tmbId(管理员指定了插件作为系统插件)
|
||||
teamId: plugin.teamId || runningAppInfo.teamId,
|
||||
tmbId: plugin.tmbId || runningAppInfo.tmbId,
|
||||
isChildApp: true
|
||||
},
|
||||
variables: runtimeVariables,
|
||||
query: getPluginRunUserQuery({
|
||||
pluginInputs: getPluginInputsFromStoreNodes(plugin.nodes),
|
||||
const { flowResponses, flowUsages, assistantResponses, runTimes, system_memories } =
|
||||
await dispatchWorkFlow({
|
||||
...props,
|
||||
// Rewrite stream mode
|
||||
...(system_forbid_stream
|
||||
? {
|
||||
stream: false,
|
||||
workflowStreamResponse: undefined
|
||||
}
|
||||
: {}),
|
||||
runningAppInfo: {
|
||||
id: String(plugin.id),
|
||||
// 如果系统插件有 teamId 和 tmbId,则使用系统插件的 teamId 和 tmbId(管理员指定了插件作为系统插件)
|
||||
teamId: plugin.teamId || runningAppInfo.teamId,
|
||||
tmbId: plugin.tmbId || runningAppInfo.tmbId,
|
||||
isChildApp: true
|
||||
},
|
||||
variables: runtimeVariables,
|
||||
files
|
||||
}).value,
|
||||
chatConfig: {},
|
||||
runtimeNodes,
|
||||
runtimeEdges: storeEdges2RuntimeEdges(plugin.edges)
|
||||
});
|
||||
query: getPluginRunUserQuery({
|
||||
pluginInputs: getPluginInputsFromStoreNodes(plugin.nodes),
|
||||
variables: runtimeVariables,
|
||||
files
|
||||
}).value,
|
||||
chatConfig: {},
|
||||
runtimeNodes,
|
||||
runtimeEdges: storeEdges2RuntimeEdges(plugin.edges)
|
||||
});
|
||||
const output = flowResponses.find((item) => item.moduleType === FlowNodeTypeEnum.pluginOutput);
|
||||
if (output) {
|
||||
output.moduleLogo = plugin.avatar;
|
||||
@@ -119,6 +120,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
return {
|
||||
// 嵌套运行时,如果 childApp stream=false,实际上不会有任何内容输出给用户,所以不需要存储
|
||||
assistantResponses: system_forbid_stream ? [] : assistantResponses,
|
||||
system_memories,
|
||||
// responseData, // debug
|
||||
[DispatchNodeResponseKeyEnum.runTimes]: runTimes,
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: {
|
||||
|
@@ -124,30 +124,36 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
|
||||
? query
|
||||
: runtimePrompt2ChatsValue({ files: userInputFiles, text: userChatInput });
|
||||
|
||||
const { flowResponses, flowUsages, assistantResponses, runTimes, workflowInteractiveResponse } =
|
||||
await dispatchWorkFlow({
|
||||
...props,
|
||||
lastInteractive: childrenInteractive,
|
||||
// Rewrite stream mode
|
||||
...(system_forbid_stream
|
||||
? {
|
||||
stream: false,
|
||||
workflowStreamResponse: undefined
|
||||
}
|
||||
: {}),
|
||||
runningAppInfo: {
|
||||
id: String(appData._id),
|
||||
teamId: String(appData.teamId),
|
||||
tmbId: String(appData.tmbId),
|
||||
isChildApp: true
|
||||
},
|
||||
runtimeNodes,
|
||||
runtimeEdges,
|
||||
histories: chatHistories,
|
||||
variables: childrenRunVariables,
|
||||
query: theQuery,
|
||||
chatConfig
|
||||
});
|
||||
const {
|
||||
flowResponses,
|
||||
flowUsages,
|
||||
assistantResponses,
|
||||
runTimes,
|
||||
workflowInteractiveResponse,
|
||||
system_memories
|
||||
} = await dispatchWorkFlow({
|
||||
...props,
|
||||
lastInteractive: childrenInteractive,
|
||||
// Rewrite stream mode
|
||||
...(system_forbid_stream
|
||||
? {
|
||||
stream: false,
|
||||
workflowStreamResponse: undefined
|
||||
}
|
||||
: {}),
|
||||
runningAppInfo: {
|
||||
id: String(appData._id),
|
||||
teamId: String(appData.teamId),
|
||||
tmbId: String(appData.tmbId),
|
||||
isChildApp: true
|
||||
},
|
||||
runtimeNodes,
|
||||
runtimeEdges,
|
||||
histories: chatHistories,
|
||||
variables: childrenRunVariables,
|
||||
query: theQuery,
|
||||
chatConfig
|
||||
});
|
||||
|
||||
const completeMessages = chatHistories.concat([
|
||||
{
|
||||
@@ -165,6 +171,7 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
|
||||
const usagePoints = flowUsages.reduce((sum, item) => sum + (item.totalPoints || 0), 0);
|
||||
|
||||
return {
|
||||
system_memories,
|
||||
[DispatchNodeResponseKeyEnum.interactive]: workflowInteractiveResponse
|
||||
? {
|
||||
type: 'childrenInteractive',
|
||||
|
@@ -6,11 +6,14 @@ import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runti
|
||||
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { MCPClient } from '../../../app/mcp';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { type StoreSecretValueType } from '@fastgpt/global/common/secret/type';
|
||||
import { getSecretValue } from '../../../../common/secret/utils';
|
||||
|
||||
type RunToolProps = ModuleDispatchProps<{
|
||||
toolData: {
|
||||
name: string;
|
||||
url: string;
|
||||
headerSecret: StoreSecretValueType;
|
||||
};
|
||||
}>;
|
||||
|
||||
@@ -27,7 +30,12 @@ export const dispatchRunTool = async (props: RunToolProps): Promise<RunToolRespo
|
||||
const { toolData, ...restParams } = params;
|
||||
const { name: toolName, url } = toolData;
|
||||
|
||||
const mcpClient = new MCPClient({ url });
|
||||
const mcpClient = new MCPClient({
|
||||
url,
|
||||
headers: getSecretValue({
|
||||
storeSecret: toolData.headerSecret
|
||||
})
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await mcpClient.toolCall(toolName, restParams);
|
||||
|
@@ -29,6 +29,8 @@ import { createFileToken } from '../../../../support/permission/controller';
|
||||
import { JSONPath } from 'jsonpath-plus';
|
||||
import type { SystemPluginSpecialResponse } from '../../../../../plugins/type';
|
||||
import json5 from 'json5';
|
||||
import { getSecretValue } from '../../../../common/secret/utils';
|
||||
import type { StoreSecretValueType } from '@fastgpt/global/common/secret/type';
|
||||
|
||||
type PropsArrType = {
|
||||
key: string;
|
||||
@@ -37,6 +39,7 @@ type PropsArrType = {
|
||||
};
|
||||
type HttpRequestProps = ModuleDispatchProps<{
|
||||
[NodeInputKeyEnum.abandon_httpUrl]: string;
|
||||
[NodeInputKeyEnum.headerSecret]?: StoreSecretValueType;
|
||||
[NodeInputKeyEnum.httpMethod]: string;
|
||||
[NodeInputKeyEnum.httpReqUrl]: string;
|
||||
[NodeInputKeyEnum.httpHeaders]?: PropsArrType[];
|
||||
@@ -83,6 +86,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
||||
system_httpFormBody: httpFormBody = [],
|
||||
system_httpContentType: httpContentType = ContentTypes.json,
|
||||
system_httpTimeout: httpTimeout = 60,
|
||||
system_header_secret: headerSecret,
|
||||
[NodeInputKeyEnum.addInputParam]: dynamicInput,
|
||||
...body
|
||||
}
|
||||
@@ -156,110 +160,6 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
||||
|
||||
return String(val);
|
||||
};
|
||||
// Test cases for variable replacement in JSON body
|
||||
// const bodyTest = () => {
|
||||
// const testData = [
|
||||
// // 基本字符串替换
|
||||
// {
|
||||
// body: `{"name":"{{name}}","age":"18"}`,
|
||||
// variables: [{ key: '{{name}}', value: '测试' }],
|
||||
// result: `{"name":"测试","age":"18"}`
|
||||
// },
|
||||
// // 特殊字符处理
|
||||
// {
|
||||
// body: `{"text":"{{text}}"}`,
|
||||
// variables: [{ key: '{{text}}', value: '包含"引号"和\\反斜杠' }],
|
||||
// result: `{"text":"包含\\"引号\\"和\\反斜杠"}`
|
||||
// },
|
||||
// // 数字类型处理
|
||||
// {
|
||||
// body: `{"count":{{count}},"price":{{price}}}`,
|
||||
// variables: [
|
||||
// { key: '{{count}}', value: '42' },
|
||||
// { key: '{{price}}', value: '99.99' }
|
||||
// ],
|
||||
// result: `{"count":42,"price":99.99}`
|
||||
// },
|
||||
// // 布尔值处理
|
||||
// {
|
||||
// body: `{"isActive":{{isActive}},"hasData":{{hasData}}}`,
|
||||
// variables: [
|
||||
// { key: '{{isActive}}', value: 'true' },
|
||||
// { key: '{{hasData}}', value: 'false' }
|
||||
// ],
|
||||
// result: `{"isActive":true,"hasData":false}`
|
||||
// },
|
||||
// // 对象类型处理
|
||||
// {
|
||||
// body: `{"user":{{user}},"user2":"{{user2}}"}`,
|
||||
// variables: [
|
||||
// { key: '{{user}}', value: `{"id":1,"name":"张三"}` },
|
||||
// { key: '{{user2}}', value: `{"id":1,"name":"张三"}` }
|
||||
// ],
|
||||
// result: `{"user":{"id":1,"name":"张三"},"user2":"{\\"id\\":1,\\"name\\":\\"张三\\"}"}`
|
||||
// },
|
||||
// // 数组类型处理
|
||||
// {
|
||||
// body: `{"items":{{items}}}`,
|
||||
// variables: [{ key: '{{items}}', value: '[1, 2, 3]' }],
|
||||
// result: `{"items":[1,2,3]}`
|
||||
// },
|
||||
// // null 和 undefined 处理
|
||||
// {
|
||||
// body: `{"nullValue":{{nullValue}},"undefinedValue":{{undefinedValue}}}`,
|
||||
// variables: [
|
||||
// { key: '{{nullValue}}', value: 'null' },
|
||||
// { key: '{{undefinedValue}}', value: 'undefined' }
|
||||
// ],
|
||||
// result: `{"nullValue":null,"undefinedValue":null}`
|
||||
// },
|
||||
// // 嵌套JSON结构
|
||||
// {
|
||||
// body: `{"data":{"nested":{"value":"{{nestedValue}}"}}}`,
|
||||
// variables: [{ key: '{{nestedValue}}', value: '嵌套值' }],
|
||||
// result: `{"data":{"nested":{"value":"嵌套值"}}}`
|
||||
// },
|
||||
// // 多变量替换
|
||||
// {
|
||||
// body: `{"first":"{{first}}","second":"{{second}}","third":{{third}}}`,
|
||||
// variables: [
|
||||
// { key: '{{first}}', value: '第一' },
|
||||
// { key: '{{second}}', value: '第二' },
|
||||
// { key: '{{third}}', value: '3' }
|
||||
// ],
|
||||
// result: `{"first":"第一","second":"第二","third":3}`
|
||||
// },
|
||||
// // JSON字符串作为变量值
|
||||
// {
|
||||
// body: `{"config":{{config}}}`,
|
||||
// variables: [{ key: '{{config}}', value: '{"setting":"enabled","mode":"advanced"}' }],
|
||||
// result: `{"config":{"setting":"enabled","mode":"advanced"}}`
|
||||
// }
|
||||
// ];
|
||||
|
||||
// for (let i = 0; i < testData.length; i++) {
|
||||
// const item = testData[i];
|
||||
// let bodyStr = item.body;
|
||||
// for (const variable of item.variables) {
|
||||
// const isQuote = isVariableInQuotes(bodyStr, variable.key);
|
||||
// bodyStr = bodyStr.replace(variable.key, valToStr(variable.value, isQuote));
|
||||
// }
|
||||
// bodyStr = bodyStr.replace(/(".*?")\s*:\s*undefined\b/g, '$1:null');
|
||||
|
||||
// console.log(bodyStr === item.result, i);
|
||||
// if (bodyStr !== item.result) {
|
||||
// console.log(bodyStr);
|
||||
// console.log(item.result);
|
||||
// } else {
|
||||
// try {
|
||||
// JSON.parse(item.result);
|
||||
// } catch (error) {
|
||||
// console.log('反序列化异常', i, item.result);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// bodyTest();
|
||||
|
||||
// 1. Replace {{key.key}} variables
|
||||
const regex1 = /\{\{\$([^.]+)\.([^$]+)\$\}\}/g;
|
||||
@@ -313,16 +213,13 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
||||
|
||||
httpReqUrl = replaceStringVariables(httpReqUrl);
|
||||
|
||||
// parse header
|
||||
const headers = await (() => {
|
||||
const publicHeaders = await (async () => {
|
||||
try {
|
||||
const contentType = contentTypeMap[httpContentType];
|
||||
if (contentType) {
|
||||
httpHeader = [{ key: 'Content-Type', value: contentType, type: 'string' }, ...httpHeader];
|
||||
}
|
||||
|
||||
if (!httpHeader || httpHeader.length === 0) return {};
|
||||
// array
|
||||
return httpHeader.reduce((acc: Record<string, string>, item) => {
|
||||
const key = replaceStringVariables(item.key);
|
||||
const value = replaceStringVariables(item.value);
|
||||
@@ -333,6 +230,9 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
||||
return Promise.reject('Header 为非法 JSON 格式');
|
||||
}
|
||||
})();
|
||||
const sensitiveHeaders = getSecretValue({
|
||||
storeSecret: headerSecret
|
||||
});
|
||||
|
||||
const params = httpParams.reduce((acc: Record<string, string>, item) => {
|
||||
const key = replaceStringVariables(item.key);
|
||||
@@ -418,7 +318,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
||||
return fetchData({
|
||||
method: httpMethod,
|
||||
url: httpReqUrl,
|
||||
headers,
|
||||
headers: { ...sensitiveHeaders, ...publicHeaders },
|
||||
body: requestBody,
|
||||
params,
|
||||
timeout: httpTimeout
|
||||
@@ -471,7 +371,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
||||
totalPoints: 0,
|
||||
params: Object.keys(params).length > 0 ? params : undefined,
|
||||
body: Object.keys(formattedRequestBody).length > 0 ? formattedRequestBody : undefined,
|
||||
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
||||
headers: Object.keys(publicHeaders).length > 0 ? publicHeaders : undefined,
|
||||
httpResult: rawResponse
|
||||
},
|
||||
[DispatchNodeResponseKeyEnum.toolResponses]:
|
||||
@@ -486,7 +386,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: {
|
||||
params: Object.keys(params).length > 0 ? params : undefined,
|
||||
body: Object.keys(formattedRequestBody).length > 0 ? formattedRequestBody : undefined,
|
||||
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
||||
headers: Object.keys(publicHeaders).length > 0 ? publicHeaders : undefined,
|
||||
httpResult: { error: formatHttpError(error) }
|
||||
},
|
||||
[NodeOutputKeyEnum.httpRawResponse]: getErrText(error)
|
||||
|
@@ -25,7 +25,8 @@ export type DispatchFlowResponse = {
|
||||
[DispatchNodeResponseKeyEnum.toolResponses]: ToolRunResponseItemType;
|
||||
[DispatchNodeResponseKeyEnum.assistantResponses]: AIChatItemValueItemType[];
|
||||
[DispatchNodeResponseKeyEnum.runTimes]: number;
|
||||
newVariables: Record<string, string>;
|
||||
[DispatchNodeResponseKeyEnum.memories]?: Record<string, any>;
|
||||
[DispatchNodeResponseKeyEnum.newVariables]: Record<string, string>;
|
||||
durationSeconds: number;
|
||||
};
|
||||
|
||||
|
@@ -164,11 +164,18 @@ export const rewriteRuntimeWorkFlow = (
|
||||
const toolList =
|
||||
toolSetNode.inputs.find((input) => input.key === 'toolSetData')?.value?.toolList || [];
|
||||
const url = toolSetNode.inputs.find((input) => input.key === 'toolSetData')?.value?.url;
|
||||
const headerSecret = toolSetNode.inputs.find((input) => input.key === 'toolSetData')?.value
|
||||
?.headerSecret;
|
||||
|
||||
const incomingEdges = edges.filter((edge) => edge.target === toolSetNode.nodeId);
|
||||
|
||||
for (const tool of toolList) {
|
||||
const newToolNode = getMCPToolRuntimeNode({ avatar: toolSetNode.avatar, tool, url });
|
||||
const newToolNode = getMCPToolRuntimeNode({
|
||||
avatar: toolSetNode.avatar,
|
||||
tool,
|
||||
url,
|
||||
headerSecret
|
||||
});
|
||||
|
||||
nodes.push({ ...newToolNode, name: `${toolSetNode.name} / ${tool.name}` });
|
||||
|
||||
|
Reference in New Issue
Block a user