|
|
|
@@ -12,6 +12,12 @@ from core.workflow.nodes.code.entities import CodeNodeData |
|
|
|
from core.workflow.nodes.enums import NodeType |
|
|
|
from models.workflow import WorkflowNodeExecutionStatus |
|
|
|
|
|
|
|
from .exc import ( |
|
|
|
CodeNodeError, |
|
|
|
DepthLimitError, |
|
|
|
OutputValidationError, |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
_node_data_cls = CodeNodeData |
|
|
|
@@ -60,7 +66,7 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
|
|
|
|
# Transform result |
|
|
|
result = self._transform_result(result, self.node_data.outputs) |
|
|
|
except (CodeExecutionError, ValueError) as e: |
|
|
|
except (CodeExecutionError, CodeNodeError) as e: |
|
|
|
return NodeRunResult(status=WorkflowNodeExecutionStatus.FAILED, inputs=variables, error=str(e)) |
|
|
|
|
|
|
|
return NodeRunResult(status=WorkflowNodeExecutionStatus.SUCCEEDED, inputs=variables, outputs=result) |
|
|
|
@@ -76,10 +82,10 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if value is None: |
|
|
|
return None |
|
|
|
else: |
|
|
|
raise ValueError(f"Output variable `{variable}` must be a string") |
|
|
|
raise OutputValidationError(f"Output variable `{variable}` must be a string") |
|
|
|
|
|
|
|
if len(value) > dify_config.CODE_MAX_STRING_LENGTH: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"The length of output variable `{variable}` must be" |
|
|
|
f" less than {dify_config.CODE_MAX_STRING_LENGTH} characters" |
|
|
|
) |
|
|
|
@@ -97,10 +103,10 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if value is None: |
|
|
|
return None |
|
|
|
else: |
|
|
|
raise ValueError(f"Output variable `{variable}` must be a number") |
|
|
|
raise OutputValidationError(f"Output variable `{variable}` must be a number") |
|
|
|
|
|
|
|
if value > dify_config.CODE_MAX_NUMBER or value < dify_config.CODE_MIN_NUMBER: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output variable `{variable}` is out of range," |
|
|
|
f" it must be between {dify_config.CODE_MIN_NUMBER} and {dify_config.CODE_MAX_NUMBER}." |
|
|
|
) |
|
|
|
@@ -108,7 +114,7 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if isinstance(value, float): |
|
|
|
# raise error if precision is too high |
|
|
|
if len(str(value).split(".")[1]) > dify_config.CODE_MAX_PRECISION: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output variable `{variable}` has too high precision," |
|
|
|
f" it must be less than {dify_config.CODE_MAX_PRECISION} digits." |
|
|
|
) |
|
|
|
@@ -125,7 +131,7 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
:return: |
|
|
|
""" |
|
|
|
if depth > dify_config.CODE_MAX_DEPTH: |
|
|
|
raise ValueError(f"Depth limit ${dify_config.CODE_MAX_DEPTH} reached, object too deep.") |
|
|
|
raise DepthLimitError(f"Depth limit ${dify_config.CODE_MAX_DEPTH} reached, object too deep.") |
|
|
|
|
|
|
|
transformed_result = {} |
|
|
|
if output_schema is None: |
|
|
|
@@ -177,14 +183,14 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
depth=depth + 1, |
|
|
|
) |
|
|
|
else: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output {prefix}.{output_name} is not a valid array." |
|
|
|
f" make sure all elements are of the same type." |
|
|
|
) |
|
|
|
elif output_value is None: |
|
|
|
pass |
|
|
|
else: |
|
|
|
raise ValueError(f"Output {prefix}.{output_name} is not a valid type.") |
|
|
|
raise OutputValidationError(f"Output {prefix}.{output_name} is not a valid type.") |
|
|
|
|
|
|
|
return result |
|
|
|
|
|
|
|
@@ -192,7 +198,7 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
for output_name, output_config in output_schema.items(): |
|
|
|
dot = "." if prefix else "" |
|
|
|
if output_name not in result: |
|
|
|
raise ValueError(f"Output {prefix}{dot}{output_name} is missing.") |
|
|
|
raise OutputValidationError(f"Output {prefix}{dot}{output_name} is missing.") |
|
|
|
|
|
|
|
if output_config.type == "object": |
|
|
|
# check if output is object |
|
|
|
@@ -200,7 +206,7 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if isinstance(result.get(output_name), type(None)): |
|
|
|
transformed_result[output_name] = None |
|
|
|
else: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output {prefix}{dot}{output_name} is not an object," |
|
|
|
f" got {type(result.get(output_name))} instead." |
|
|
|
) |
|
|
|
@@ -228,13 +234,13 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if isinstance(result[output_name], type(None)): |
|
|
|
transformed_result[output_name] = None |
|
|
|
else: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output {prefix}{dot}{output_name} is not an array," |
|
|
|
f" got {type(result.get(output_name))} instead." |
|
|
|
) |
|
|
|
else: |
|
|
|
if len(result[output_name]) > dify_config.CODE_MAX_NUMBER_ARRAY_LENGTH: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"The length of output variable `{prefix}{dot}{output_name}` must be" |
|
|
|
f" less than {dify_config.CODE_MAX_NUMBER_ARRAY_LENGTH} elements." |
|
|
|
) |
|
|
|
@@ -249,13 +255,13 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if isinstance(result[output_name], type(None)): |
|
|
|
transformed_result[output_name] = None |
|
|
|
else: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output {prefix}{dot}{output_name} is not an array," |
|
|
|
f" got {type(result.get(output_name))} instead." |
|
|
|
) |
|
|
|
else: |
|
|
|
if len(result[output_name]) > dify_config.CODE_MAX_STRING_ARRAY_LENGTH: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"The length of output variable `{prefix}{dot}{output_name}` must be" |
|
|
|
f" less than {dify_config.CODE_MAX_STRING_ARRAY_LENGTH} elements." |
|
|
|
) |
|
|
|
@@ -270,13 +276,13 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if isinstance(result[output_name], type(None)): |
|
|
|
transformed_result[output_name] = None |
|
|
|
else: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output {prefix}{dot}{output_name} is not an array," |
|
|
|
f" got {type(result.get(output_name))} instead." |
|
|
|
) |
|
|
|
else: |
|
|
|
if len(result[output_name]) > dify_config.CODE_MAX_OBJECT_ARRAY_LENGTH: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"The length of output variable `{prefix}{dot}{output_name}` must be" |
|
|
|
f" less than {dify_config.CODE_MAX_OBJECT_ARRAY_LENGTH} elements." |
|
|
|
) |
|
|
|
@@ -286,7 +292,7 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
if value is None: |
|
|
|
pass |
|
|
|
else: |
|
|
|
raise ValueError( |
|
|
|
raise OutputValidationError( |
|
|
|
f"Output {prefix}{dot}{output_name}[{i}] is not an object," |
|
|
|
f" got {type(value)} instead at index {i}." |
|
|
|
) |
|
|
|
@@ -303,13 +309,13 @@ class CodeNode(BaseNode[CodeNodeData]): |
|
|
|
for i, value in enumerate(result[output_name]) |
|
|
|
] |
|
|
|
else: |
|
|
|
raise ValueError(f"Output type {output_config.type} is not supported.") |
|
|
|
raise OutputValidationError(f"Output type {output_config.type} is not supported.") |
|
|
|
|
|
|
|
parameters_validated[output_name] = True |
|
|
|
|
|
|
|
# check if all output parameters are validated |
|
|
|
if len(parameters_validated) != len(result): |
|
|
|
raise ValueError("Not all output parameters are validated.") |
|
|
|
raise CodeNodeError("Not all output parameters are validated.") |
|
|
|
|
|
|
|
return transformed_result |
|
|
|
|