diff --git a/api/core/tools/tool_manager.py b/api/core/tools/tool_manager.py index 52e1e71d82..600b54f1c2 100644 --- a/api/core/tools/tool_manager.py +++ b/api/core/tools/tool_manager.py @@ -315,8 +315,9 @@ class ToolManager: for parameter in parameters: # save tool parameter to tool entity memory - value = ToolManager._init_runtime_parameter(parameter, workflow_tool.tool_configurations) - runtime_parameters[parameter.name] = value + if parameter.form == ToolParameter.ToolParameterForm.FORM: + value = ToolManager._init_runtime_parameter(parameter, workflow_tool.tool_configurations) + runtime_parameters[parameter.name] = value # decrypt runtime parameters encryption_manager = ToolParameterConfigurationManager( @@ -325,7 +326,9 @@ class ToolManager: provider_name=workflow_tool.provider_id, provider_type=workflow_tool.provider_type, ) - runtime_parameters = encryption_manager.decrypt_tool_parameters(runtime_parameters) + + if runtime_parameters: + runtime_parameters = encryption_manager.decrypt_tool_parameters(runtime_parameters) tool_entity.runtime.runtime_parameters.update(runtime_parameters) return tool_entity diff --git a/api/core/workflow/nodes/tool/tool_node.py b/api/core/workflow/nodes/tool/tool_node.py index 69a97fc206..c62e025e75 100644 --- a/api/core/workflow/nodes/tool/tool_node.py +++ b/api/core/workflow/nodes/tool/tool_node.py @@ -29,7 +29,6 @@ class ToolNode(BaseNode): # get parameters parameters = self._generate_parameters(variable_pool, node_data) - # get tool runtime try: tool_runtime = ToolManager.get_workflow_tool_runtime(self.tenant_id, node_data, None) @@ -41,7 +40,6 @@ class ToolNode(BaseNode): ) try: - # TODO: user_id messages = tool_runtime.invoke(self.user_id, parameters) except Exception as e: return NodeRunResult( @@ -68,7 +66,7 @@ class ToolNode(BaseNode): return { k.variable: k.value if k.variable_type == 'static' else - variable_pool.get_variable_value(k.value) if k.variable_type == 'selector' else '' + variable_pool.get_variable_value(k.value_selector) if k.variable_type == 'selector' else '' for k in node_data.tool_parameters } @@ -77,7 +75,12 @@ class ToolNode(BaseNode): Convert ToolInvokeMessages into tuple[plain_text, files] """ # transform message and handle file storage - messages = ToolFileMessageTransformer.transform_tool_invoke_messages(messages) + messages = ToolFileMessageTransformer.transform_tool_invoke_messages( + messages=messages, + user_id=self.user_id, + tenant_id=self.tenant_id, + conversation_id='', + ) # extract plain text and files files = self._extract_tool_response_binary(messages) plain_text = self._extract_tool_response_text(messages) diff --git a/api/tests/integration_tests/workflow/nodes/test_tool.py b/api/tests/integration_tests/workflow/nodes/test_tool.py new file mode 100644 index 0000000000..72e0d6f853 --- /dev/null +++ b/api/tests/integration_tests/workflow/nodes/test_tool.py @@ -0,0 +1,70 @@ +import pytest +from core.app.entities.app_invoke_entities import InvokeFrom + +from core.workflow.entities.variable_pool import VariablePool +from core.workflow.nodes.tool.tool_node import ToolNode +from models.workflow import WorkflowNodeExecutionStatus + +""" +class ToolEntity(BaseModel): + provider_id: str + provider_type: Literal['builtin', 'api'] + provider_name: str # redundancy + tool_name: str + tool_label: str # redundancy + tool_configurations: dict[str, ToolParameterValue] + +class ToolNodeData(BaseNodeData, ToolEntity): + class ToolInput(VariableSelector): + variable_type: Literal['selector', 'static'] + value: Optional[str] + + @validator('value') + def check_value(cls, value, values, **kwargs): + if values['variable_type'] == 'static' and value is None: + raise ValueError('value is required for static variable') + return value + + tool_parameters: list[ToolInput] + +""" + +def test_tool_invoke(): + pool = VariablePool(system_variables={}, user_inputs={}) + pool.append_variable(node_id='1', variable_key_list=['123', 'args1'], value='1+1') + + node = ToolNode( + tenant_id='1', + app_id='1', + workflow_id='1', + user_id='1', + user_from=InvokeFrom.WEB_APP, + config={ + 'id': '1', + 'data': { + 'title': 'a', + 'desc': 'a', + 'provider_id': 'maths', + 'provider_type': 'builtin', + 'provider_name': 'maths', + 'tool_name': 'eval_expression', + 'tool_label': 'eval_expression', + 'tool_configurations': {}, + 'tool_parameters': [ + { + 'variable': 'expression', + 'value_selector': ['1', '123', 'args1'], + 'variable_type': 'selector', + 'value': None + }, + ] + } + } + ) + + # execute node + result = node.run(pool) + + assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED + assert '2' in result.outputs['text'] + assert result.outputs['files'] == [] \ No newline at end of file