From 29d6d030f81659e49fb988da0a23e93bdf7fba74 Mon Sep 17 00:00:00 2001 From: zxhlyh Date: Wed, 11 Feb 2026 16:36:38 +0800 Subject: [PATCH] fix: llm node output variable --- .../nodes/_base/components/variable/utils.ts | 8 +-- .../_base/hooks/use-available-var-list.ts | 14 ++-- .../components/workflow/nodes/llm/panel.tsx | 70 ++++++++++--------- .../workflow/nodes/variable-assigner/hooks.ts | 28 +++++++- web/app/components/workflow/types.ts | 1 + 5 files changed, 77 insertions(+), 44 deletions(-) diff --git a/web/app/components/workflow/nodes/_base/components/variable/utils.ts b/web/app/components/workflow/nodes/_base/components/variable/utils.ts index 5b2e2f58f4..58c4dca8b1 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/utils.ts +++ b/web/app/components/workflow/nodes/_base/components/variable/utils.ts @@ -343,12 +343,7 @@ const findExceptVarInObject = ( } const getLLMNodeOutputVars = (llmNodeData: LLMNodeType): Var[] => { - const isComputerUseEnabled = !!llmNodeData.computer_use - const vars = [...LLM_OUTPUT_STRUCT].filter((item) => { - if (isComputerUseEnabled) - return true - return item.variable !== 'generation' - }) + const vars = [...LLM_OUTPUT_STRUCT] if ( llmNodeData.structured_output_enabled @@ -379,6 +374,7 @@ const formatItem = ( nodeId: id, title: data.title, vars: [], + nodeType: data?.type, } switch (data.type) { case BlockEnum.Start: { diff --git a/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts b/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts index 861f99bf11..5b7b19c99f 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts @@ -1,13 +1,14 @@ import type { Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types' import { useMemo } from 'react' import { useShallow } from 'zustand/react/shallow' +import { useFeatures } from '@/app/components/base/features/hooks' import { useIsChatMode, useWorkflow, useWorkflowVariables, } from '@/app/components/workflow/hooks' import { useStore as useWorkflowStore } from '@/app/components/workflow/store' -import { BlockEnum } from '@/app/components/workflow/types' +import { BlockEnum, VarType } from '@/app/components/workflow/types' import { inputVarTypeToVarType } from '../../data-source/utils' import useNodeInfo from './use-node-info' @@ -33,6 +34,8 @@ const useAvailableVarList = (nodeId: string, { const { getTreeLeafNodes, getNodeById, getBeforeNodesInSameBranchIncludeParent } = useWorkflow() const { getNodeAvailableVars } = useWorkflowVariables() const isChatMode = useIsChatMode() + const features = useFeatures(s => s.features) + const isSupportSandbox = !!features.sandbox?.enabled const baseAvailableNodes = useMemo(() => { return passedInAvailableNodes || (onlyLeafNodeVar ? getTreeLeafNodes(nodeId) : getBeforeNodesInSameBranchIncludeParent(nodeId)) }, [passedInAvailableNodes, onlyLeafNodeVar, nodeId, getTreeLeafNodes, getBeforeNodesInSameBranchIncludeParent]) @@ -105,9 +108,12 @@ const useAvailableVarList = (nodeId: string, { .map((nodeVar) => { if (!llmNodeIds.has(nodeVar.nodeId)) return nodeVar - const nextVars = nodeVar.vars.filter(item => item.variable !== 'context') - if (nextVars.length === nodeVar.vars.length) - return nodeVar + const nextVars = nodeVar.vars.filter(item => item.variable !== 'context').filter((item) => { + if (isSupportSandbox && item.type === VarType.string) + return item.variable !== 'text' && item.variable !== 'reasoning_content' + + return true + }) return { ...nodeVar, vars: nextVars, diff --git a/web/app/components/workflow/nodes/llm/panel.tsx b/web/app/components/workflow/nodes/llm/panel.tsx index cb42478481..167877b1e2 100644 --- a/web/app/components/workflow/nodes/llm/panel.tsx +++ b/web/app/components/workflow/nodes/llm/panel.tsx @@ -405,40 +405,46 @@ const Panel: FC> = ({ )} > <> - {!!inputs.computer_use && ( - - )} - + { + !isSupportSandbox && ( + + ) + } + { + !isSupportSandbox && ( + + ) + } { const store = useStoreApi() @@ -129,6 +130,8 @@ export const useGetAvailableVars = () => { const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow() const { getNodeAvailableVars } = useWorkflowVariables() const isChatMode = useIsChatMode() + const features = useFeatures(s => s.features) + const isSupportSandbox = !!features.sandbox?.enabled const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => { const availableNodes: Node[] = [] const currentNode = nodes.find(node => node.id === nodeId)! @@ -152,6 +155,17 @@ export const useGetAvailableVars = () => { ...node, vars: node.isStartNode ? node.vars.filter(v => !v.variable.startsWith('sys.')) : node.vars, })) + .map((node) => { + return { + ...node, + vars: node.vars.filter((item) => { + if (isSupportSandbox && item.type === VarType.string && node.nodeType === BlockEnum.LLM) + return item.variable !== 'text' && item.variable !== 'reasoning_content' + + return true + }), + } + }) .filter(item => item.vars.length > 0) } @@ -160,8 +174,18 @@ export const useGetAvailableVars = () => { beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId), isChatMode, filterVar, + }).map((node) => { + return { + ...node, + vars: node.vars.filter((item) => { + if (isSupportSandbox && item.type === VarType.string && node.nodeType === BlockEnum.LLM) + return item.variable !== 'text' && item.variable !== 'reasoning_content' + + return true + }), + } }) - }, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode]) + }, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode, isSupportSandbox]) return getAvailableVars } diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index d17afcc48d..1aa720a105 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -355,6 +355,7 @@ export type NodeOutPutVar = { isStartNode?: boolean isLoop?: boolean isFlat?: boolean + nodeType?: BlockEnum } // allow node default validators with narrower payload types to be stored in shared collections.