mirror of
https://github.com/langgenius/dify.git
synced 2025-12-19 17:27:16 -05:00
fix: workflow end node validate error (#29473)
Co-authored-by: Novice <novice12185727@gmail.com>
This commit is contained in:
@@ -59,7 +59,7 @@ class OutputVariableEntity(BaseModel):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
variable: str
|
variable: str
|
||||||
value_type: OutputVariableType
|
value_type: OutputVariableType = OutputVariableType.ANY
|
||||||
value_selector: Sequence[str]
|
value_selector: Sequence[str]
|
||||||
|
|
||||||
@field_validator("value_type", mode="before")
|
@field_validator("value_type", mode="before")
|
||||||
|
|||||||
127
api/tests/fixtures/workflow/end_node_without_value_type_field_workflow.yml
vendored
Normal file
127
api/tests/fixtures/workflow/end_node_without_value_type_field_workflow.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
app:
|
||||||
|
description: 'End node without value_type field reproduction'
|
||||||
|
icon: 🤖
|
||||||
|
icon_background: '#FFEAD5'
|
||||||
|
mode: workflow
|
||||||
|
name: end_node_without_value_type_field_reproduction
|
||||||
|
use_icon_as_answer_icon: false
|
||||||
|
dependencies: []
|
||||||
|
kind: app
|
||||||
|
version: 0.5.0
|
||||||
|
workflow:
|
||||||
|
conversation_variables: []
|
||||||
|
environment_variables: []
|
||||||
|
features:
|
||||||
|
file_upload:
|
||||||
|
allowed_file_extensions:
|
||||||
|
- .JPG
|
||||||
|
- .JPEG
|
||||||
|
- .PNG
|
||||||
|
- .GIF
|
||||||
|
- .WEBP
|
||||||
|
- .SVG
|
||||||
|
allowed_file_types:
|
||||||
|
- image
|
||||||
|
allowed_file_upload_methods:
|
||||||
|
- local_file
|
||||||
|
- remote_url
|
||||||
|
enabled: false
|
||||||
|
fileUploadConfig:
|
||||||
|
audio_file_size_limit: 50
|
||||||
|
batch_count_limit: 5
|
||||||
|
file_size_limit: 15
|
||||||
|
image_file_batch_limit: 10
|
||||||
|
image_file_size_limit: 10
|
||||||
|
single_chunk_attachment_limit: 10
|
||||||
|
video_file_size_limit: 100
|
||||||
|
workflow_file_upload_limit: 10
|
||||||
|
image:
|
||||||
|
enabled: false
|
||||||
|
number_limits: 3
|
||||||
|
transfer_methods:
|
||||||
|
- local_file
|
||||||
|
- remote_url
|
||||||
|
number_limits: 3
|
||||||
|
opening_statement: ''
|
||||||
|
retriever_resource:
|
||||||
|
enabled: true
|
||||||
|
sensitive_word_avoidance:
|
||||||
|
enabled: false
|
||||||
|
speech_to_text:
|
||||||
|
enabled: false
|
||||||
|
suggested_questions: []
|
||||||
|
suggested_questions_after_answer:
|
||||||
|
enabled: false
|
||||||
|
text_to_speech:
|
||||||
|
enabled: false
|
||||||
|
language: ''
|
||||||
|
voice: ''
|
||||||
|
graph:
|
||||||
|
edges:
|
||||||
|
- data:
|
||||||
|
isInIteration: false
|
||||||
|
isInLoop: false
|
||||||
|
sourceType: start
|
||||||
|
targetType: end
|
||||||
|
id: 1765423445456-source-1765423454810-target
|
||||||
|
source: '1765423445456'
|
||||||
|
sourceHandle: source
|
||||||
|
target: '1765423454810'
|
||||||
|
targetHandle: target
|
||||||
|
type: custom
|
||||||
|
zIndex: 0
|
||||||
|
nodes:
|
||||||
|
- data:
|
||||||
|
selected: false
|
||||||
|
title: 用户输入
|
||||||
|
type: start
|
||||||
|
variables:
|
||||||
|
- default: ''
|
||||||
|
hint: ''
|
||||||
|
label: query
|
||||||
|
max_length: 48
|
||||||
|
options: []
|
||||||
|
placeholder: ''
|
||||||
|
required: true
|
||||||
|
type: text-input
|
||||||
|
variable: query
|
||||||
|
height: 109
|
||||||
|
id: '1765423445456'
|
||||||
|
position:
|
||||||
|
x: -48
|
||||||
|
y: 261
|
||||||
|
positionAbsolute:
|
||||||
|
x: -48
|
||||||
|
y: 261
|
||||||
|
selected: false
|
||||||
|
sourcePosition: right
|
||||||
|
targetPosition: left
|
||||||
|
type: custom
|
||||||
|
width: 242
|
||||||
|
- data:
|
||||||
|
outputs:
|
||||||
|
- value_selector:
|
||||||
|
- '1765423445456'
|
||||||
|
- query
|
||||||
|
variable: query
|
||||||
|
selected: true
|
||||||
|
title: 输出
|
||||||
|
type: end
|
||||||
|
height: 88
|
||||||
|
id: '1765423454810'
|
||||||
|
position:
|
||||||
|
x: 382
|
||||||
|
y: 282
|
||||||
|
positionAbsolute:
|
||||||
|
x: 382
|
||||||
|
y: 282
|
||||||
|
selected: true
|
||||||
|
sourcePosition: right
|
||||||
|
targetPosition: left
|
||||||
|
type: custom
|
||||||
|
width: 242
|
||||||
|
viewport:
|
||||||
|
x: 139
|
||||||
|
y: -135
|
||||||
|
zoom: 1
|
||||||
|
rag_pipeline_variables: []
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
"""
|
||||||
|
Test case for end node without value_type field (backward compatibility).
|
||||||
|
|
||||||
|
This test validates that end nodes work correctly even when the value_type
|
||||||
|
field is missing from the output configuration, ensuring backward compatibility
|
||||||
|
with older workflow definitions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from core.workflow.graph_events import (
|
||||||
|
GraphRunStartedEvent,
|
||||||
|
GraphRunSucceededEvent,
|
||||||
|
NodeRunStartedEvent,
|
||||||
|
NodeRunStreamChunkEvent,
|
||||||
|
NodeRunSucceededEvent,
|
||||||
|
)
|
||||||
|
|
||||||
|
from .test_table_runner import TableTestRunner, WorkflowTestCase
|
||||||
|
|
||||||
|
|
||||||
|
def test_end_node_without_value_type_field():
|
||||||
|
"""
|
||||||
|
Test that end node works without explicit value_type field.
|
||||||
|
|
||||||
|
The fixture implements a simple workflow that:
|
||||||
|
1. Takes a query input from start node
|
||||||
|
2. Passes it directly to end node
|
||||||
|
3. End node outputs the value without specifying value_type
|
||||||
|
4. Should correctly infer the type and output the value
|
||||||
|
|
||||||
|
This ensures backward compatibility with workflow definitions
|
||||||
|
created before value_type became a required field.
|
||||||
|
"""
|
||||||
|
fixture_name = "end_node_without_value_type_field_workflow"
|
||||||
|
|
||||||
|
case = WorkflowTestCase(
|
||||||
|
fixture_path=fixture_name,
|
||||||
|
inputs={"query": "test query"},
|
||||||
|
expected_outputs={"query": "test query"},
|
||||||
|
expected_event_sequence=[
|
||||||
|
# Graph start
|
||||||
|
GraphRunStartedEvent,
|
||||||
|
# Start node
|
||||||
|
NodeRunStartedEvent,
|
||||||
|
NodeRunStreamChunkEvent, # Start node streams the input value
|
||||||
|
NodeRunSucceededEvent,
|
||||||
|
# End node
|
||||||
|
NodeRunStartedEvent,
|
||||||
|
NodeRunSucceededEvent,
|
||||||
|
# Graph end
|
||||||
|
GraphRunSucceededEvent,
|
||||||
|
],
|
||||||
|
description="End node without value_type field should work correctly",
|
||||||
|
)
|
||||||
|
|
||||||
|
runner = TableTestRunner()
|
||||||
|
result = runner.run_test_case(case)
|
||||||
|
assert result.success, f"Test failed: {result.error}"
|
||||||
|
assert result.actual_outputs == {"query": "test query"}, (
|
||||||
|
f"Expected output to be {{'query': 'test query'}}, got {result.actual_outputs}"
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user