diff --git a/api/core/workflow/nodes/llm/node.py b/api/core/workflow/nodes/llm/node.py index c413ad758b..28c4925456 100644 --- a/api/core/workflow/nodes/llm/node.py +++ b/api/core/workflow/nodes/llm/node.py @@ -573,7 +573,11 @@ class LLMNode(Node[LLMNodeData]): "tool_calls": [self._serialize_tool_call(item) for item in generation_data.tool_calls], "sequence": generation_data.sequence, } - files_to_output = generation_data.files + files_to_output = list(generation_data.files) + # Merge auto-collected/structured-output files from self._file_outputs + if self._file_outputs: + existing_ids = {f.id for f in files_to_output} + files_to_output.extend(f for f in self._file_outputs if f.id not in existing_ids) else: # Classical runtime: use pre-computed generation-specific text pair, # falling back to native model reasoning if no tags were found. @@ -2126,6 +2130,12 @@ class LLMNode(Node[LLMNodeData]): result = yield from self._process_tool_outputs(outputs) + # Auto-collect sandbox output/ files, deduplicate by id + collected_files = session.collect_output_files() + if collected_files: + existing_ids = {f.id for f in self._file_outputs} + self._file_outputs.extend(f for f in collected_files if f.id not in existing_ids) + if result is None: raise LLMNodeError("SandboxSession exited unexpectedly") diff --git a/web/app/components/workflow/constants.ts b/web/app/components/workflow/constants.ts index d49eacc7ac..73e80dd0a2 100644 --- a/web/app/components/workflow/constants.ts +++ b/web/app/components/workflow/constants.ts @@ -182,6 +182,10 @@ export const LLM_OUTPUT_STRUCT: Var[] = [ variable: 'usage', type: VarType.object, }, + { + variable: 'files', + type: VarType.arrayFile, + }, ] export const KNOWLEDGE_RETRIEVAL_OUTPUT_STRUCT: Var[] = [ diff --git a/web/app/components/workflow/nodes/llm/panel.tsx b/web/app/components/workflow/nodes/llm/panel.tsx index 4d8b24676a..06043da9a9 100644 --- a/web/app/components/workflow/nodes/llm/panel.tsx +++ b/web/app/components/workflow/nodes/llm/panel.tsx @@ -461,6 +461,11 @@ const Panel: FC> = ({ type="object" description={t(`${i18nPrefix}.outputVars.usage`, { ns: 'workflow' })} /> + {inputs.structured_output_enabled && ( <> diff --git a/web/i18n/en-US/workflow.json b/web/i18n/en-US/workflow.json index 78ee062559..bc4d22155a 100644 --- a/web/i18n/en-US/workflow.json +++ b/web/i18n/en-US/workflow.json @@ -828,6 +828,7 @@ "nodes.llm.jsonSchema.warningTips.saveSchema": "Please finish editing the current field before saving the schema", "nodes.llm.model": "model", "nodes.llm.notSetContextInPromptTip": "To enable the context feature, please fill in the context variable in PROMPT.", + "nodes.llm.outputVars.files": "Files produced during execution", "nodes.llm.outputVars.generation": "Generation Information", "nodes.llm.outputVars.output": "Generate content", "nodes.llm.outputVars.reasoning_content": "Reasoning Content", diff --git a/web/i18n/zh-Hans/workflow.json b/web/i18n/zh-Hans/workflow.json index 29ad24c01e..373c6553dd 100644 --- a/web/i18n/zh-Hans/workflow.json +++ b/web/i18n/zh-Hans/workflow.json @@ -828,6 +828,7 @@ "nodes.llm.jsonSchema.warningTips.saveSchema": "请先完成当前字段的编辑", "nodes.llm.model": "模型", "nodes.llm.notSetContextInPromptTip": "要启用上下文功能,请在提示中填写上下文变量。", + "nodes.llm.outputVars.files": "执行过程中产出的文件", "nodes.llm.outputVars.generation": "生成信息", "nodes.llm.outputVars.output": "生成内容", "nodes.llm.outputVars.reasoning_content": "推理内容",