diff --git a/frontend/src/agents/workflow/WorkflowBuilder.tsx b/frontend/src/agents/workflow/WorkflowBuilder.tsx index 5f458e78..0b7b7f41 100644 --- a/frontend/src/agents/workflow/WorkflowBuilder.tsx +++ b/frontend/src/agents/workflow/WorkflowBuilder.tsx @@ -68,24 +68,20 @@ import { ConditionCase, WorkflowNode } from '../types/workflow'; import { createDefaultCodeConfig, normalizeCodeConfig, - parseCodeInputs, parseCodeJsonSchemaDraft, serializeCodeConfig, - stringifyCodeInputs, validateCodeJsonSchema, } from './codeNodeConfig'; import MobileBlocker from './components/MobileBlocker'; +import NodeDocumentsControl from './components/NodeDocumentsControl'; import PromptTextArea, { extractUpstreamVariables, } from './components/PromptTextArea'; import { - documentsModeToInputDocuments, FILE_PASSING_OPTIONS, FilePassing, - getDocumentsMode, normalizeFilePassing, toDocumentVariableOptions, - withChosenDocumentOptions, } from './documentConfig'; import { AgentNode, @@ -359,9 +355,6 @@ function WorkflowBuilderInner() { const reactFlowWrapper = useRef(null); const [selectedNode, setSelectedNode] = useState(null); - // Node id for which the author explicitly entered "Choose…" documents mode, - // so the picker shows even before any document is selected (empty reads as None). - const [docChooseNodeId, setDocChooseNodeId] = useState(null); const [workflowName, setWorkflowName] = useState('New Workflow'); const [workflowDescription, setWorkflowDescription] = useState(''); const [showWorkflowSettings, setShowWorkflowSettings] = useState(false); @@ -1478,6 +1471,13 @@ function WorkflowBuilderInner() { ); }, [selectedNode, nodes, edges]); + const selectedCodeDocumentOptions = useMemo(() => { + if (!selectedNode || selectedNode.type !== 'code') return []; + return toDocumentVariableOptions( + extractUpstreamVariables(nodes, edges, selectedNode.id), + ); + }, [selectedNode, nodes, edges]); + const selectedCodeJsonSchemaText = useMemo(() => { if (!selectedNode || selectedNode.type !== 'code') return ''; @@ -2214,144 +2214,60 @@ function WorkflowBuilderInner() { emptyText="No sources available" /> - {(() => { - const inputDocuments = - selectedNode.data.config?.input_documents; - const documentsMode = - getDocumentsMode(inputDocuments); - const showChoose = - documentsMode === 'choose' || - docChooseNodeId === selectedNode.id; - const chosenDocuments = showChoose - ? documentsModeToInputDocuments( - 'choose', - inputDocuments ?? [], - ) - : []; - const filePassing = normalizeFilePassing( - selectedNode.data.config?.file_passing, - ); - const setInputDocuments = ( - nextInputDocuments: string[], - ) => + handleUpdateNodeData({ config: { ...(selectedNode.data.config || {}), input_documents: nextInputDocuments, }, - }); - return ( - <> -
- -
- {( - [ - ['all', 'All input docs'], - ['none', 'None'], - ['choose', 'Choose…'], - ] as const - ).map(([mode, modeLabel]) => ( - - ))} -
- {showChoose && ( -
- - setInputDocuments( - documentsModeToInputDocuments( - 'choose', - nextDocuments, - ), - ) - } - placeholder="Select documents..." - searchPlaceholder="Search variables..." - emptyText="No upstream documents" - /> -
- )} -

- Documents passed to this agent from - uploads or upstream nodes. -

-
-
- - + handleUpdateNodeData({ + config: { + ...(selectedNode.data.config || {}), + file_passing: value as FilePassing, + }, + }) + } + > + + + + + {FILE_PASSING_OPTIONS.map((option) => ( + - - - - - {FILE_PASSING_OPTIONS.map( - (option) => ( - - {option.label} - - ), - )} - - -

- Auto: send native when the model - supports it, otherwise extract text. -

-
- - ); - })()} + {option.label} + + ))} + + +

+ Auto: send native when the model supports + it, otherwise extract text. +

+
-
- -