fix(api): normalize empty workflow tool file lists (#37125)

This commit is contained in:
Popper Li 2026-06-07 10:52:53 +08:00 committed by GitHub
parent 76fb1b6ea8
commit fad5656b2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 0 deletions

View File

@ -363,11 +363,24 @@ class WorkflowTool(Tool):
files.append(file_dict)
except Exception:
logger.exception("Failed to transform file %s", file)
elif parameter.type == ToolParameter.ToolParameterType.FILES:
value = tool_parameters.get(parameter.name)
if not parameter.required and self._is_empty_files_parameter_value(value):
value = []
parameters_result[parameter.name] = value
else:
parameters_result[parameter.name] = tool_parameters.get(parameter.name)
return parameters_result, files
@staticmethod
def _is_empty_files_parameter_value(value: Any) -> bool:
"""Identify empty optional file-list placeholders before workflow input validation."""
if value is None or value == "":
return True
return isinstance(value, list) and all(item is None or item == "" for item in value)
def _extract_files(self, outputs: dict[str, Any]) -> tuple[dict[str, Any], list[File]]:
"""
extract files from the result

View File

@ -696,6 +696,53 @@ def test_transform_args_invalid_files(monkeypatch: pytest.MonkeyPatch):
assert invalid_files == []
@pytest.mark.parametrize("empty_value", [None, "", [], [None], [""]])
def test_transform_args_normalizes_optional_files_parameter(
monkeypatch: pytest.MonkeyPatch,
empty_value: Any,
):
"""Pass optional workflow file-list inputs as an empty list when no files were provided."""
tool = _build_tool()
images_param = ToolParameter.get_simple_instance(
name="images",
llm_description="images",
typ=ToolParameter.ToolParameterType.FILES,
required=False,
)
images_param.form = ToolParameter.ToolParameterForm.FORM
monkeypatch.setattr(tool, "get_merged_runtime_parameters", lambda: [images_param])
params, files = tool._transform_args({"images": empty_value})
assert params == {"images": []}
assert files == []
def test_workflow_tool_invocation_normalizes_optional_files_parameter(monkeypatch: pytest.MonkeyPatch):
"""Ensure casted empty FILES values do not reach workflow input validation as [None]."""
tool = _build_tool()
images_param = ToolParameter.get_simple_instance(
name="images",
llm_description="images",
typ=ToolParameter.ToolParameterType.FILES,
required=False,
)
images_param.form = ToolParameter.ToolParameterForm.FORM
tool.entity.parameters = [images_param]
monkeypatch.setattr(tool, "_get_app", lambda *args, **kwargs: None)
monkeypatch.setattr(tool, "_get_workflow", lambda *args, **kwargs: None)
monkeypatch.setattr(tool, "_resolve_user", lambda *args, **kwargs: Mock())
generate_mock = MagicMock(return_value={"data": {}})
monkeypatch.setattr("core.app.apps.workflow.app_generator.WorkflowAppGenerator.generate", generate_mock)
list(tool.invoke("test_user", {"images": None}))
call_kwargs = generate_mock.call_args.kwargs
assert call_kwargs["args"]["inputs"]["images"] == []
def test_extract_files():
"""Extract file outputs into result and file list."""
tool = _build_tool()