feat(code_node): add more check (#11949)

Signed-off-by: -LAN- <laipz8200@outlook.com>
This commit is contained in:
-LAN- 2024-12-22 10:40:43 +08:00 committed by GitHub
parent 2ad2a402fb
commit a056a9d601
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 17 additions and 14 deletions

View File

@ -118,7 +118,7 @@ class CodeExecutor:
return response.data.stdout or "" return response.data.stdout or ""
@classmethod @classmethod
def execute_workflow_code_template(cls, language: CodeLanguage, code: str, inputs: Mapping[str, Any]) -> dict: def execute_workflow_code_template(cls, language: CodeLanguage, code: str, inputs: Mapping[str, Any]):
""" """
Execute code Execute code
:param language: code language :param language: code language

View File

@ -25,7 +25,7 @@ class TemplateTransformer(ABC):
return runner_script, preload_script return runner_script, preload_script
@classmethod @classmethod
def extract_result_str_from_response(cls, response: str) -> str: def extract_result_str_from_response(cls, response: str):
result = re.search(rf"{cls._result_tag}(.*){cls._result_tag}", response, re.DOTALL) result = re.search(rf"{cls._result_tag}(.*){cls._result_tag}", response, re.DOTALL)
if not result: if not result:
raise ValueError("Failed to parse result") raise ValueError("Failed to parse result")
@ -33,15 +33,20 @@ class TemplateTransformer(ABC):
return result return result
@classmethod @classmethod
def transform_response(cls, response: str): def transform_response(cls, response: str) -> Mapping[str, Any]:
""" """
Transform response to dict Transform response to dict
:param response: response :param response: response
:return: :return:
""" """
result = json.loads(cls.extract_result_str_from_response(response)) try:
result = json.loads(cls.extract_result_str_from_response(response))
except json.JSONDecodeError:
raise ValueError("failed to parse response")
if not isinstance(result, dict): if not isinstance(result, dict):
raise ValueError("Result must be a dict") raise ValueError("result must be a dict")
if not all(isinstance(k, str) for k in result):
raise ValueError("result keys must be strings")
return result return result
@classmethod @classmethod

View File

@ -59,7 +59,7 @@ class CodeNode(BaseNode[CodeNodeData]):
) )
# Transform result # Transform result
result = self._transform_result(result, self.node_data.outputs) result = self._transform_result(result=result, output_schema=self.node_data.outputs)
except (CodeExecutionError, CodeNodeError) as e: except (CodeExecutionError, CodeNodeError) as e:
return NodeRunResult( return NodeRunResult(
status=WorkflowNodeExecutionStatus.FAILED, inputs=variables, error=str(e), error_type=type(e).__name__ status=WorkflowNodeExecutionStatus.FAILED, inputs=variables, error=str(e), error_type=type(e).__name__
@ -116,14 +116,12 @@ class CodeNode(BaseNode[CodeNodeData]):
return value return value
def _transform_result( def _transform_result(
self, result: dict, output_schema: Optional[dict[str, CodeNodeData.Output]], prefix: str = "", depth: int = 1 self,
) -> dict: result: Mapping[str, Any],
""" output_schema: Optional[dict[str, CodeNodeData.Output]],
Transform result prefix: str = "",
:param result: result depth: int = 1,
:param output_schema: output schema ):
:return:
"""
if depth > dify_config.CODE_MAX_DEPTH: if depth > dify_config.CODE_MAX_DEPTH:
raise DepthLimitError(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.")