From 8f9203c0536f0835804200e23752ca510f194d57 Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Tue, 7 May 2024 15:27:05 +0800 Subject: [PATCH] 4.8 test (#1382) * perf: some log, chatTest histories slice; http request failed tip * fix: ssr render * perf: if else node ui and fix value type select --- .../workflow/template/system/ifElse/index.ts | 2 +- packages/global/core/workflow/type/index.d.ts | 7 ++- packages/service/core/ai/rerank/index.ts | 5 +- .../dispatch/agent/runTool/functionCall.ts | 1 + .../dispatch/agent/runTool/promptCall.ts | 1 + .../dispatch/agent/runTool/toolChoice.ts | 1 + .../workflow/dispatch/init/workflowStart.tsx | 7 ++- .../core/workflow/dispatch/tools/http468.ts | 27 +++++---- .../core/workflow/dispatch/tools/runIfElse.ts | 8 ++- packages/web/hooks/useBeforeunload.ts | 4 +- pnpm-lock.yaml | 2 +- .../app/src/components/Markdown/index.tsx | 12 ++-- .../core/workflow/Flow/ChatTest.tsx | 2 +- .../Flow/nodes/NodeIfElse/ListItem.tsx | 17 +++--- .../Flow/nodes/NodeVariableUpdate.tsx | 20 ++----- .../workflow/Flow/nodes/render/NodeCard.tsx | 49 ++++++++-------- .../src/components/core/workflow/context.tsx | 52 +++++++++-------- .../app/src/pages/api/core/workflow/debug.ts | 5 +- .../app/detail/components/FlowEdit/Header.tsx | 56 ++++++++++--------- .../detail/components/SimpleEdit/ChatTest.tsx | 2 +- projects/app/src/web/core/workflow/utils.ts | 21 +++++++ 21 files changed, 164 insertions(+), 137 deletions(-) diff --git a/packages/global/core/workflow/template/system/ifElse/index.ts b/packages/global/core/workflow/template/system/ifElse/index.ts index f030e4abe..0a244d662 100644 --- a/packages/global/core/workflow/template/system/ifElse/index.ts +++ b/packages/global/core/workflow/template/system/ifElse/index.ts @@ -46,7 +46,7 @@ export const IfElseNode: FlowNodeTemplateType = { { id: NodeOutputKeyEnum.ifElseResult, key: NodeOutputKeyEnum.ifElseResult, - label: 'IF ELSE', + label: '判断结果', valueType: WorkflowIOValueTypeEnum.string, type: FlowNodeOutputTypeEnum.static } diff --git a/packages/global/core/workflow/type/index.d.ts b/packages/global/core/workflow/type/index.d.ts index aca28d433..549145465 100644 --- a/packages/global/core/workflow/type/index.d.ts +++ b/packages/global/core/workflow/type/index.d.ts @@ -40,7 +40,7 @@ export type FlowNodeCommonType = { }; export type FlowNodeTemplateType = FlowNodeCommonType & { - id: string; // module id, unique + id: string; // node id, unique templateType: `${FlowNodeTemplateTypeEnum}`; // show handle @@ -132,11 +132,12 @@ export type ChatDispatchProps = { chatId?: string; responseChatItemId?: string; histories: ChatItemType[]; - variables: Record; - query: UserChatItemValueItemType[]; + variables: Record; // global variable + query: UserChatItemValueItemType[]; // trigger query stream: boolean; detail: boolean; // response detail maxRunTimes: number; + isToolCall?: boolean; }; export type ModuleDispatchProps = ChatDispatchProps & { diff --git a/packages/service/core/ai/rerank/index.ts b/packages/service/core/ai/rerank/index.ts index b881a2c33..b72c96ceb 100644 --- a/packages/service/core/ai/rerank/index.ts +++ b/packages/service/core/ai/rerank/index.ts @@ -1,3 +1,4 @@ +import { addLog } from '../../../common/system/log'; import { POST } from '../../../common/api/serverRequest'; type PostReRankResponse = { @@ -38,7 +39,7 @@ export function reRankRecall({ } ) .then((data) => { - console.log('rerank time:', Date.now() - start); + addLog.info('ReRank finish:', { time: Date.now() - start }); return data?.results?.map((item) => ({ id: documents[item.index].id, @@ -46,7 +47,7 @@ export function reRankRecall({ })); }) .catch((err) => { - console.log('rerank error:', err); + addLog.error('rerank error', err); return []; }); diff --git a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts index fc5f42e5d..3e4ab34f9 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts @@ -161,6 +161,7 @@ export const runToolWithFunctionCall = async ( const toolRunResponse = await dispatchWorkFlow({ ...props, + isToolCall: true, runtimeNodes: runtimeNodes.map((item) => item.nodeId === toolNode.nodeId ? { diff --git a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts index 74104d008..783f272cf 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts @@ -185,6 +185,7 @@ export const runToolWithPromptCall = async ( const moduleRunResponse = await dispatchWorkFlow({ ...props, + isToolCall: true, runtimeNodes: runtimeNodes.map((item) => item.nodeId === toolNode.nodeId ? { diff --git a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts b/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts index f3f619abd..3b5747f70 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts @@ -182,6 +182,7 @@ export const runToolWithToolChoice = async ( const toolRunResponse = await dispatchWorkFlow({ ...props, + isToolCall: true, runtimeNodes: runtimeNodes.map((item) => item.nodeId === toolNode.nodeId ? { diff --git a/packages/service/core/workflow/dispatch/init/workflowStart.tsx b/packages/service/core/workflow/dispatch/init/workflowStart.tsx index 8b3547b11..9a9590618 100644 --- a/packages/service/core/workflow/dispatch/init/workflowStart.tsx +++ b/packages/service/core/workflow/dispatch/init/workflowStart.tsx @@ -8,12 +8,15 @@ export type UserChatInputProps = ModuleDispatchProps<{ }>; export const dispatchWorkflowStart = (props: Record) => { - const { query } = props as UserChatInputProps; + const { + query, + params: { userChatInput } + } = props as UserChatInputProps; const { text, files } = chatValue2RuntimePrompt(query); return { - [NodeInputKeyEnum.userChatInput]: text, + [NodeInputKeyEnum.userChatInput]: text || userChatInput, [NodeInputKeyEnum.inputFiles]: files }; }; diff --git a/packages/service/core/workflow/dispatch/tools/http468.ts b/packages/service/core/workflow/dispatch/tools/http468.ts index a06e5856b..c2b76f34f 100644 --- a/packages/service/core/workflow/dispatch/tools/http468.ts +++ b/packages/service/core/workflow/dispatch/tools/http468.ts @@ -49,6 +49,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise 0 ? params : undefined, - body: Object.keys(requestBody).length > 0 ? requestBody : undefined, - headers: Object.keys(headers).length > 0 ? headers : undefined, - httpResult: { error: formatHttpError(error) } - }, - [NodeOutputKeyEnum.httpRawResponse]: getErrText(error) - }; + + if (isToolCall) { + return { + [NodeOutputKeyEnum.failed]: true, + [DispatchNodeResponseKeyEnum.nodeResponse]: { + totalPoints: 0, + params: Object.keys(params).length > 0 ? params : undefined, + body: Object.keys(requestBody).length > 0 ? requestBody : undefined, + headers: Object.keys(headers).length > 0 ? headers : undefined, + httpResult: { error: formatHttpError(error) } + }, + [NodeOutputKeyEnum.httpRawResponse]: getErrText(error) + }; + } + return Promise.reject(error); } }; diff --git a/packages/service/core/workflow/dispatch/tools/runIfElse.ts b/packages/service/core/workflow/dispatch/tools/runIfElse.ts index ffa6d8480..e4b2dd498 100644 --- a/packages/service/core/workflow/dispatch/tools/runIfElse.ts +++ b/packages/service/core/workflow/dispatch/tools/runIfElse.ts @@ -1,4 +1,4 @@ -import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; import { VariableConditionEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant'; @@ -15,6 +15,9 @@ type Props = ModuleDispatchProps<{ [NodeInputKeyEnum.condition]: IfElseConditionType; [NodeInputKeyEnum.ifElseList]: IfElseListItemType[]; }>; +type Response = DispatchNodeResultType<{ + [NodeOutputKeyEnum.ifElseResult]: string; +}>; function checkCondition(condition: VariableConditionEnum, variableValue: any, value: string) { const operations = { @@ -63,7 +66,7 @@ function getResult( return condition === 'AND' ? listResult.every(Boolean) : listResult.some(Boolean); } -export const dispatchIfElse = async (props: Props): Promise> => { +export const dispatchIfElse = async (props: Props): Promise => { const { params, runtimeNodes, @@ -88,6 +91,7 @@ export const dispatchIfElse = async (props: Props): Promise any; tip?: string }) e.returnValue = tip; callback?.(); } - : () => {}; + : () => { + callback?.(); + }; window.addEventListener('beforeunload', listen); return () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29ebbd096..73c666de6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' settings: autoInstallPeers: true diff --git a/projects/app/src/components/Markdown/index.tsx b/projects/app/src/components/Markdown/index.tsx index ef0f733f9..a32867f9e 100644 --- a/projects/app/src/components/Markdown/index.tsx +++ b/projects/app/src/components/Markdown/index.tsx @@ -17,13 +17,13 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; import { getFileAndOpen } from '@/web/core/dataset/utils'; import { MARKDOWN_QUOTE_SIGN } from '@fastgpt/global/core/chat/constants'; -const CodeLight = dynamic(() => import('./CodeLight')); -const MermaidCodeBlock = dynamic(() => import('./img/MermaidCodeBlock')); -const MdImage = dynamic(() => import('./img/Image')); -const EChartsCodeBlock = dynamic(() => import('./img/EChartsCodeBlock')); +const CodeLight = dynamic(() => import('./CodeLight'), { ssr: false }); +const MermaidCodeBlock = dynamic(() => import('./img/MermaidCodeBlock'), { ssr: false }); +const MdImage = dynamic(() => import('./img/Image'), { ssr: false }); +const EChartsCodeBlock = dynamic(() => import('./img/EChartsCodeBlock'), { ssr: false }); -const ChatGuide = dynamic(() => import('./chat/Guide')); -const QuestionGuide = dynamic(() => import('./chat/QuestionGuide')); +const ChatGuide = dynamic(() => import('./chat/Guide'), { ssr: false }); +const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false }); export enum CodeClassName { guide = 'guide', diff --git a/projects/app/src/components/core/workflow/Flow/ChatTest.tsx b/projects/app/src/components/core/workflow/Flow/ChatTest.tsx index a9cb91cbb..41eec354e 100644 --- a/projects/app/src/components/core/workflow/Flow/ChatTest.tsx +++ b/projects/app/src/components/core/workflow/Flow/ChatTest.tsx @@ -65,7 +65,7 @@ const ChatTest = ( } }); }); - const history = chatList.slice(-historyMaxLen - 2, -2); + const history = chatList.slice(-(historyMaxLen * 2) - 2, -2); // 流请求,获取数据 const { responseText, responseData, newVariables } = await streamFetch({ diff --git a/projects/app/src/components/core/workflow/Flow/nodes/NodeIfElse/ListItem.tsx b/projects/app/src/components/core/workflow/Flow/nodes/NodeIfElse/ListItem.tsx index b00bb757b..057623f6b 100644 --- a/projects/app/src/components/core/workflow/Flow/nodes/NodeIfElse/ListItem.tsx +++ b/projects/app/src/components/core/workflow/Flow/nodes/NodeIfElse/ListItem.tsx @@ -24,6 +24,7 @@ import MyInput from '@/components/MyInput'; import { getHandleId } from '@fastgpt/global/core/workflow/utils'; import { SourceHandle } from '../render/Handle'; import { Position, useReactFlow } from 'reactflow'; +import { getReferenceDataValueType } from '@/web/core/workflow/utils'; const ListItem = ({ provided, @@ -305,19 +306,17 @@ const ConditionSelect = ({ variable?: ReferenceValueProps; onSelect: (e: VariableConditionEnum) => void; }) => { + const { t } = useTranslation(); const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList); // get condition type const valueType = useMemo(() => { - if (!variable) return; - const node = nodeList.find((node) => node.nodeId === variable[0]); - - if (!node) return WorkflowIOValueTypeEnum.any; - const output = node.outputs.find((item) => item.id === variable[1]); - - if (!output) return WorkflowIOValueTypeEnum.any; - return output.valueType; - }, [nodeList, variable]); + return getReferenceDataValueType({ + variable, + nodeList, + t + }); + }, [nodeList, t, variable]); const conditionList = useMemo(() => { if (valueType === WorkflowIOValueTypeEnum.string) return stringConditionList; diff --git a/projects/app/src/components/core/workflow/Flow/nodes/NodeVariableUpdate.tsx b/projects/app/src/components/core/workflow/Flow/nodes/NodeVariableUpdate.tsx index 5f15c67d3..faca0125c 100644 --- a/projects/app/src/components/core/workflow/Flow/nodes/NodeVariableUpdate.tsx +++ b/projects/app/src/components/core/workflow/Flow/nodes/NodeVariableUpdate.tsx @@ -30,7 +30,7 @@ import { SmallAddIcon } from '@chakra-ui/icons'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { ReferenceValueProps } from '@fastgpt/global/core/workflow/type/io'; import { ReferSelector, useReference } from './render/RenderInput/templates/Reference'; -import { getWorkflowGlobalVariables } from '@/web/core/workflow/utils'; +import { getReferenceDataValueType } from '@/web/core/workflow/utils'; import { isReferenceValue } from '@fastgpt/global/core/workflow/utils'; const NodeVariableUpdate = ({ data, selected }: NodeProps) => { @@ -82,19 +82,11 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps) => return ( <> {updateList.map((updateItem, index) => { - const valueType = (() => { - const variable = updateItem.variable; - const variableNodeId = variable?.[0]; - const variableNode = nodeList.find((node) => node.nodeId === variableNodeId); - const systemVariables = getWorkflowGlobalVariables(nodeList, t); - - const variableInput = !variableNode - ? systemVariables.find((item) => item.key === variable?.[1]) - : variableNode.outputs.find((output) => output.id === variable?.[1]); - - if (!variableInput) return WorkflowIOValueTypeEnum.any; - return variableInput.valueType; - })(); + const valueType = getReferenceDataValueType({ + variable: updateItem.variable, + nodeList, + t + }); const renderTypeData = menuList.find((item) => item.renderType === updateItem.renderType); const handleUpdate = (newValue: ReferenceValueProps | string) => { diff --git a/projects/app/src/components/core/workflow/Flow/nodes/render/NodeCard.tsx b/projects/app/src/components/core/workflow/Flow/nodes/render/NodeCard.tsx index 60a8007cb..929db47a9 100644 --- a/projects/app/src/components/core/workflow/Flow/nodes/render/NodeCard.tsx +++ b/projects/app/src/components/core/workflow/Flow/nodes/render/NodeCard.tsx @@ -79,7 +79,6 @@ const NodeCard = (props: Props) => { return ( {/* debug */} - {/* tool target handle */} {showToolHandle && } @@ -134,7 +133,6 @@ const NodeCard = (props: Props) => { ); }, [ nodeId, - debugResult, showToolHandle, avatar, t, @@ -179,6 +177,7 @@ const NodeCard = (props: Props) => { borderColor: selected ? 'primary.600' : 'borderColor.base' })} > + {Header} {children} @@ -259,6 +258,22 @@ const MenuRender = React.memo(function MenuRender({ }, [setEdges, setNodes] ); + const onclickSyncVersion = useCallback(async () => { + if (!pluginId) return; + try { + setLoading(true); + onResetNode({ + id: nodeId, + node: await getPreviewPluginModule(pluginId) + }); + } catch (e) { + return toast({ + status: 'error', + title: getErrText(e, t('plugin.Get Plugin Module Detail Failed')) + }); + } + setLoading(false); + }, [nodeId, onResetNode, pluginId, setLoading, t, toast]); const Render = useMemo(() => { const menuList = [ @@ -288,25 +303,7 @@ const MenuRender = React.memo(function MenuRender({ icon: 'common/refreshLight', label: t('plugin.Synchronous version'), variant: 'whiteBase', - onClick: () => { - if (!pluginId) return; - onOpenConfirmSync(async () => { - try { - setLoading(true); - const pluginModule = await getPreviewPluginModule(pluginId); - onResetNode({ - id: nodeId, - module: pluginModule - }); - } catch (e) { - return toast({ - status: 'error', - title: getErrText(e, t('plugin.Get Plugin Module Detail Failed')) - }); - } - setLoading(false); - })(); - } + onClick: onOpenConfirmSync(onclickSyncVersion) } ] : []), @@ -370,12 +367,9 @@ const MenuRender = React.memo(function MenuRender({ onDelNode, onOpenConfirmDeleteNode, onOpenConfirmSync, - onResetNode, + onclickSyncVersion, openDebugNode, - pluginId, - setLoading, - t, - toast + t ]); return Render; @@ -530,7 +524,8 @@ const NodeDebugResponse = React.memo(function NodeDebugResponse({ top={0} zIndex={10} w={'420px'} - maxH={'540px'} + maxH={'100%'} + minH={'300px'} overflowY={'auto'} border={'base'} > diff --git a/projects/app/src/components/core/workflow/context.tsx b/projects/app/src/components/core/workflow/context.tsx index 5105a5a65..adac2697e 100644 --- a/projects/app/src/components/core/workflow/context.tsx +++ b/projects/app/src/components/core/workflow/context.tsx @@ -55,7 +55,7 @@ type WorkflowContextType = { hoverNodeId?: string; setHoverNodeId: React.Dispatch>; onUpdateNodeError: (node: string, isError: Boolean) => void; - onResetNode: (e: { id: string; module: FlowNodeTemplateType }) => void; + onResetNode: (e: { id: string; node: FlowNodeTemplateType }) => void; onChangeNode: (e: FlowNodeChangeProps) => void; // edges @@ -159,7 +159,7 @@ export const WorkflowContext = createContext({ onEdgesChange: function (changes: EdgeChange[]): void { throw new Error('Function not implemented.'); }, - onResetNode: function (e: { id: string; module: FlowNodeTemplateType }): void { + onResetNode: function (e: { id: string; node: FlowNodeTemplateType }): void { throw new Error('Function not implemented.'); }, onDelEdge: function (e: { @@ -279,31 +279,30 @@ const WorkflowContextProvider = ({ }); // reset a node data. delete edge and replace it - const onResetNode = useMemoizedFn( - ({ id, module }: { id: string; module: FlowNodeTemplateType }) => { - setNodes((state) => - state.map((node) => { - if (node.id === id) { - // delete edge - node.data.inputs.forEach((item) => { - onDelEdge({ nodeId: id, targetHandle: item.key }); - }); - node.data.outputs.forEach((item) => { - onDelEdge({ nodeId: id, sourceHandle: item.key }); - }); - return { + const onResetNode = useMemoizedFn(({ id, node }: { id: string; node: FlowNodeTemplateType }) => { + setNodes((state) => + state.map((item) => { + if (item.id === id) { + return { + ...item, + data: { + ...item.data, ...node, - data: { - ...node.data, - ...module - } - }; - } - return node; - }) - ); - } - ); + inputs: node.inputs.map((input) => { + const value = + item.data.inputs.find((i) => i.key === input.key)?.value ?? input.value; + return { + ...input, + value + }; + }) + } + }; + } + return item; + }) + ); + }); const onChangeNode = useMemoizedFn((props: FlowNodeChangeProps) => { const { nodeId, type } = props; @@ -431,7 +430,6 @@ const WorkflowContextProvider = ({ const initData = useMemoizedFn( async (e: { nodes: StoreNodeItemType[]; edges: StoreEdgeItemType[] }) => { setNodes(e.nodes?.map((item) => storeNode2FlowNode({ item }))); - setEdges(e.edges?.map((item) => storeEdgesRenderEdge({ edge: item }))); } ); diff --git a/projects/app/src/pages/api/core/workflow/debug.ts b/projects/app/src/pages/api/core/workflow/debug.ts index 7a92b62d8..f0fef3ba3 100644 --- a/projects/app/src/pages/api/core/workflow/debug.ts +++ b/projects/app/src/pages/api/core/workflow/debug.ts @@ -53,10 +53,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) appId, runtimeNodes: nodes, runtimeEdges: edges, - variables: { - ...variables, - userChatInput: '' - }, + variables, query: [], histories: [], stream: false, diff --git a/projects/app/src/pages/app/detail/components/FlowEdit/Header.tsx b/projects/app/src/pages/app/detail/components/FlowEdit/Header.tsx index 42c952d19..35993000c 100644 --- a/projects/app/src/pages/app/detail/components/FlowEdit/Header.tsx +++ b/projects/app/src/pages/app/detail/components/FlowEdit/Header.tsx @@ -75,6 +75,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ WorkflowContext, (v) => v.setIsShowVersionHistories ); + const workflowDebugData = useContextSelector(WorkflowContext, (v) => v.workflowDebugData); const flowData2StoreDataAndCheck = useCallback(async () => { const { nodes } = await getWorkflowStore(); @@ -93,35 +94,40 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ } }, [edges, onUpdateNodeError, t, toast]); - const onclickSave = useCallback(async () => { - if (isShowVersionHistories) return; - const { nodes } = await getWorkflowStore(); + const onclickSave = useCallback( + async (forbid?: boolean) => { + // version preview / debug mode, not save + if (isShowVersionHistories || forbid) return; - if (nodes.length === 0) return null; - setIsSaving(true); + const { nodes } = await getWorkflowStore(); - const storeWorkflow = flowNode2StoreNodes({ nodes, edges }); + if (nodes.length === 0) return null; + setIsSaving(true); - try { - await updateAppDetail(app._id, { - ...storeWorkflow, - type: AppTypeEnum.advanced, - //@ts-ignore - version: 'v2' - }); + const storeWorkflow = flowNode2StoreNodes({ nodes, edges }); - setSaveLabel( - t('core.app.Auto Save time', { - time: formatTime2HM() - }) - ); - // ChatTestRef.current?.resetChatTest(); - } catch (error) {} + try { + await updateAppDetail(app._id, { + ...storeWorkflow, + type: AppTypeEnum.advanced, + //@ts-ignore + version: 'v2' + }); - setIsSaving(false); + setSaveLabel( + t('core.app.Auto Save time', { + time: formatTime2HM() + }) + ); + // ChatTestRef.current?.resetChatTest(); + } catch (error) {} - return null; - }, [isShowVersionHistories, edges, updateAppDetail, app._id, t]); + setIsSaving(false); + + return null; + }, + [isShowVersionHistories, edges, updateAppDetail, app._id, t] + ); const onclickPublish = useCallback(async () => { setIsSaving(true); @@ -182,7 +188,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ useInterval(() => { if (!app._id) return; - onclickSave(); + onclickSave(!!workflowDebugData); }, 20000); const Render = useMemo(() => { @@ -221,7 +227,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ display={'inline-block'} borderRadius={'xs'} cursor={'pointer'} - onClick={onclickSave} + onClick={() => onclickSave()} color={'myGray.500'} > {saveLabel} diff --git a/projects/app/src/pages/app/detail/components/SimpleEdit/ChatTest.tsx b/projects/app/src/pages/app/detail/components/SimpleEdit/ChatTest.tsx index b280208be..83e10789f 100644 --- a/projects/app/src/pages/app/detail/components/SimpleEdit/ChatTest.tsx +++ b/projects/app/src/pages/app/detail/components/SimpleEdit/ChatTest.tsx @@ -62,7 +62,7 @@ const ChatTest = ({ } }); }); - const history = chatList.slice(-historyMaxLen - 2, -2); + const history = chatList.slice(-(historyMaxLen * 2) - 2, -2); // 流请求,获取数据 const { responseText, responseData } = await streamFetch({ diff --git a/projects/app/src/web/core/workflow/utils.ts b/projects/app/src/web/core/workflow/utils.ts index 200b3216a..9cd549346 100644 --- a/projects/app/src/web/core/workflow/utils.ts +++ b/projects/app/src/web/core/workflow/utils.ts @@ -24,6 +24,7 @@ import { } from '@fastgpt/global/core/workflow/utils'; import { getSystemVariables } from '../app/utils'; import { TFunction } from 'next-i18next'; +import { ReferenceValueProps } from '@fastgpt/global/core/workflow/type/io'; export const nodeTemplate2FlowNode = ({ template, @@ -140,6 +141,26 @@ export const computedNodeInputReference = ({ return sourceNodes; }; +export const getReferenceDataValueType = ({ + variable, + nodeList, + t +}: { + variable?: ReferenceValueProps; + nodeList: FlowNodeItemType[]; + t: TFunction; +}) => { + if (!variable) return WorkflowIOValueTypeEnum.any; + + const node = nodeList.find((node) => node.nodeId === variable[0]); + const systemVariables = getWorkflowGlobalVariables(nodeList, t); + + if (!node) return systemVariables.find((item) => item.key === variable?.[1])?.valueType; + + const output = node.outputs.find((item) => item.id === variable[1]); + if (!output) return WorkflowIOValueTypeEnum.any; + return output.valueType; +}; /* Connection rules */ export const checkWorkflowNodeAndConnection = ({