From c02a96a9167717b27c4bf7746ba07b0b5ebb4633 Mon Sep 17 00:00:00 2001 From: zhsama Date: Wed, 11 Feb 2026 21:14:52 +0800 Subject: [PATCH] feat: Exclude reasoning_format from LLM nodes when sandbox enabled --- web/app/components/workflow/features.tsx | 10 +++++++++- web/app/components/workflow/nodes/llm/panel.tsx | 12 +++++++----- web/app/components/workflow/nodes/llm/use-config.ts | 13 +++++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/web/app/components/workflow/features.tsx b/web/app/components/workflow/features.tsx index 13eb1a7323..66a84dec5d 100644 --- a/web/app/components/workflow/features.tsx +++ b/web/app/components/workflow/features.tsx @@ -7,6 +7,7 @@ import { useCallback, } from 'react' import { useNodes } from 'reactflow' +import { useStore as useAppStore } from '@/app/components/app/store' import { useFeaturesStore } from '@/app/components/base/features/hooks' import NewFeaturePanel from '@/app/components/base/features/new-feature-panel' import { webSocketClient } from '@/app/components/workflow/collaboration/core/websocket-manager' @@ -14,6 +15,7 @@ import { updateFeatures } from '@/service/workflow' import { useIsChatMode, useNodesReadOnly, + useNodesSyncDraft, } from './hooks' import useConfig from './nodes/start/use-config' import { useStore } from './store' @@ -22,8 +24,10 @@ import { InputVarType } from './types' const Features = () => { const setShowFeaturesPanel = useStore(s => s.setShowFeaturesPanel) const appId = useStore(s => s.appId) + const isSandboxRuntime = useAppStore(s => s.appDetail?.runtime_type === 'sandboxed') const isChatMode = useIsChatMode() const { nodesReadOnly } = useNodesReadOnly() + const { handleSyncWorkflowDraft } = useNodesSyncDraft() const featuresStore = useFeaturesStore() const nodes = useNodes() const startNode = nodes.find(node => node.data.type === 'start') @@ -49,6 +53,7 @@ const Features = () => { try { const currentFeatures = featuresStore.getState().features + const shouldSyncDraft = isSandboxRuntime || currentFeatures.sandbox?.enabled === true // Transform features to match the expected server format (same as doSyncWorkflowDraft) const transformedFeatures: WorkflowDraftFeaturesPayload = { @@ -68,6 +73,9 @@ const Features = () => { features: transformedFeatures, }) + if (shouldSyncDraft) + handleSyncWorkflowDraft(true, true) + // Emit update event to other connected clients const socket = webSocketClient.getSocket(appId) if (socket) { @@ -81,7 +89,7 @@ const Features = () => { } setShowFeaturesPanel(true) - }, [appId, featuresStore, setShowFeaturesPanel]) + }, [appId, featuresStore, handleSyncWorkflowDraft, isSandboxRuntime, setShowFeaturesPanel]) return ( > = ({ /> {/* Reasoning Format */} - + {!isSupportSandbox && ( + + )} diff --git a/web/app/components/workflow/nodes/llm/use-config.ts b/web/app/components/workflow/nodes/llm/use-config.ts index 3a68ae4ee2..94c8a67903 100644 --- a/web/app/components/workflow/nodes/llm/use-config.ts +++ b/web/app/components/workflow/nodes/llm/use-config.ts @@ -2,6 +2,7 @@ import type { Memory, PromptItem, PromptTemplateItem, ValueSelector, Var, Variab import type { LLMNodeType, StructuredOutput } from './types' import { produce } from 'immer' import { useCallback, useEffect, useRef, useState } from 'react' +import { useStore as useAppStore } from '@/app/components/app/store' import { useFeatures } from '@/app/components/base/features/hooks' import { checkHasContextBlock, checkHasHistoryBlock, checkHasQueryBlock } from '@/app/components/base/prompt-editor/constants' import { @@ -24,8 +25,9 @@ import useAvailableVarList from '../_base/hooks/use-available-var-list' const useConfig = (id: string, payload: LLMNodeType) => { const { nodesReadOnly: readOnly } = useNodesReadOnly() const isChatMode = useIsChatMode() + const isSandboxRuntime = useAppStore(s => s.appDetail?.runtime_type === 'sandboxed') const features = useFeatures(s => s.features) - const isSupportSandbox = !!features.sandbox?.enabled + const isSupportSandbox = isSandboxRuntime || features.sandbox?.enabled === true const defaultConfig = useStore(s => s.nodesDefaultConfigs)?.[payload.type] const [defaultRolePrefix, setDefaultRolePrefix] = useState<{ user: string, assistant: string }>({ user: '', assistant: '' }) @@ -66,6 +68,10 @@ const useConfig = (id: string, payload: LLMNodeType) => { } }) } + + newPayload = produce(newPayload, (draft) => { + delete draft.reasoning_format + }) } else { newPayload = produce(newPayload, (draft) => { @@ -364,11 +370,14 @@ const useConfig = (id: string, payload: LLMNodeType) => { // reasoning format const handleReasoningFormatChange = useCallback((reasoningFormat: 'tagged' | 'separated') => { + if (isSupportSandbox) + return + const newInputs = produce(inputRef.current, (draft) => { draft.reasoning_format = reasoningFormat }) setInputs(newInputs) - }, [setInputs]) + }, [isSupportSandbox, setInputs]) const { availableVars,