| 
									
										
										
										
											2024-06-24 15:46:16 +08:00
										 |  |  | import json | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | from collections.abc import Generator, Iterable | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | from copy import deepcopy | 
					
						
							| 
									
										
										
										
											2024-11-24 13:28:46 +08:00
										 |  |  | from datetime import UTC, datetime | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  | from mimetypes import guess_type | 
					
						
							| 
									
										
										
										
											2024-12-24 18:38:51 +08:00
										 |  |  | from typing import Any, Optional, Union, cast | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  | from yarl import URL | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | from core.app.entities.app_invoke_entities import InvokeFrom | 
					
						
							|  |  |  | from core.callback_handler.agent_tool_callback_handler import DifyAgentCallbackHandler | 
					
						
							|  |  |  | from core.callback_handler.workflow_tool_callback_handler import DifyWorkflowCallbackHandler | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  | from core.file import FileType | 
					
						
							|  |  |  | from core.file.models import FileTransferMethod | 
					
						
							| 
									
										
										
										
											2024-06-26 17:33:29 +08:00
										 |  |  | from core.ops.ops_trace_manager import TraceQueueManager | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | from core.tools.__base.tool import Tool | 
					
						
							|  |  |  | from core.tools.entities.tool_entities import ( | 
					
						
							|  |  |  |     ToolInvokeMessage, | 
					
						
							|  |  |  |     ToolInvokeMessageBinary, | 
					
						
							|  |  |  |     ToolInvokeMeta, | 
					
						
							|  |  |  |     ToolParameter, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | from core.tools.errors import ( | 
					
						
							|  |  |  |     ToolEngineInvokeError, | 
					
						
							|  |  |  |     ToolInvokeError, | 
					
						
							|  |  |  |     ToolNotFoundError, | 
					
						
							|  |  |  |     ToolNotSupportedError, | 
					
						
							|  |  |  |     ToolParameterValidationError, | 
					
						
							|  |  |  |     ToolProviderCredentialValidationError, | 
					
						
							|  |  |  |     ToolProviderNotFoundError, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | from core.tools.utils.message_transformer import ToolFileMessageTransformer | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | from core.tools.workflow_as_tool.tool import WorkflowTool | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | from extensions.ext_database import db | 
					
						
							| 
									
										
										
										
											2025-05-17 00:56:16 +08:00
										 |  |  | from models.enums import CreatorUserRole | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | from models.model import Message, MessageFile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ToolEngine: | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Tool runtime engine take care of the tool executions. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2024-06-26 17:33:29 +08:00
										 |  |  |     def agent_invoke( | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         tool: Tool, | 
					
						
							|  |  |  |         tool_parameters: Union[str, dict], | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         message: Message, | 
					
						
							|  |  |  |         invoke_from: InvokeFrom, | 
					
						
							| 
									
										
										
										
											2024-06-26 17:33:29 +08:00
										 |  |  |         agent_tool_callback: DifyAgentCallbackHandler, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         trace_manager: Optional[TraceQueueManager] = None, | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |         conversation_id: Optional[str] = None, | 
					
						
							|  |  |  |         app_id: Optional[str] = None, | 
					
						
							|  |  |  |         message_id: Optional[str] = None, | 
					
						
							|  |  |  |     ) -> tuple[str, list[str], ToolInvokeMeta]: | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Agent invokes the tool with the given arguments. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         # check if arguments is a string | 
					
						
							|  |  |  |         if isinstance(tool_parameters, str): | 
					
						
							|  |  |  |             # check if this tool has only one parameter | 
					
						
							|  |  |  |             parameters = [ | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 parameter | 
					
						
							| 
									
										
										
										
											2024-11-21 10:34:43 +08:00
										 |  |  |                 for parameter in tool.get_runtime_parameters() | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                 if parameter.form == ToolParameter.ToolParameterForm.LLM | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |             if parameters and len(parameters) == 1: | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 tool_parameters = {parameters[0].name: tool_parameters} | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2024-11-25 11:02:58 +08:00
										 |  |  |                 try: | 
					
						
							|  |  |  |                     tool_parameters = json.loads(tool_parameters) | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 except Exception: | 
					
						
							| 
									
										
										
										
											2024-11-25 11:02:58 +08:00
										 |  |  |                     pass | 
					
						
							|  |  |  |                 if not isinstance(tool_parameters, dict): | 
					
						
							|  |  |  |                     raise ValueError(f"tool_parameters should be a dict, but got a string: {tool_parameters}") | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             # hit the callback handler | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             agent_tool_callback.on_tool_start(tool_name=tool.entity.identity.name, tool_inputs=tool_parameters) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             messages = ToolEngine._invoke(tool, tool_parameters, user_id, conversation_id, app_id, message_id) | 
					
						
							|  |  |  |             invocation_meta_dict: dict[str, ToolInvokeMeta] = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def message_callback( | 
					
						
							|  |  |  |                 invocation_meta_dict: dict, messages: Generator[ToolInvokeMessage | ToolInvokeMeta, None, None] | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 for message in messages: | 
					
						
							|  |  |  |                     if isinstance(message, ToolInvokeMeta): | 
					
						
							|  |  |  |                         invocation_meta_dict["meta"] = message | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         yield message | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             messages = ToolFileMessageTransformer.transform_tool_invoke_messages( | 
					
						
							|  |  |  |                 messages=message_callback(invocation_meta_dict, messages), | 
					
						
							|  |  |  |                 user_id=user_id, | 
					
						
							|  |  |  |                 tenant_id=tenant_id, | 
					
						
							|  |  |  |                 conversation_id=message.conversation_id, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             message_list = list(messages) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             # extract binary data from tool invoke message | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             binary_files = ToolEngine._extract_tool_response_binary_and_text(message_list) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             # create message file | 
					
						
							|  |  |  |             message_files = ToolEngine._create_message_files( | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 tool_messages=binary_files, agent_message=message, invoke_from=invoke_from, user_id=user_id | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             plain_text = ToolEngine._convert_tool_response_to_str(message_list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             meta = invocation_meta_dict["meta"] | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # hit the callback handler | 
					
						
							|  |  |  |             agent_tool_callback.on_tool_end( | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 tool_name=tool.entity.identity.name, | 
					
						
							| 
									
										
										
										
											2024-06-26 17:33:29 +08:00
										 |  |  |                 tool_inputs=tool_parameters, | 
					
						
							|  |  |  |                 tool_outputs=plain_text, | 
					
						
							|  |  |  |                 message_id=message.id, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 trace_manager=trace_manager, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # transform tool invoke message to get LLM friendly message | 
					
						
							|  |  |  |             return plain_text, message_files, meta | 
					
						
							|  |  |  |         except ToolProviderCredentialValidationError as e: | 
					
						
							|  |  |  |             error_response = "Please check your tool provider credentials" | 
					
						
							|  |  |  |             agent_tool_callback.on_tool_error(e) | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         except (ToolNotFoundError, ToolNotSupportedError, ToolProviderNotFoundError) as e: | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             error_response = f"there is not a tool named {tool.entity.identity.name}" | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             agent_tool_callback.on_tool_error(e) | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         except ToolParameterValidationError as e: | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             error_response = f"tool parameters validation error: {e}, please check your tool parameters" | 
					
						
							|  |  |  |             agent_tool_callback.on_tool_error(e) | 
					
						
							|  |  |  |         except ToolInvokeError as e: | 
					
						
							|  |  |  |             error_response = f"tool invoke error: {e}" | 
					
						
							|  |  |  |             agent_tool_callback.on_tool_error(e) | 
					
						
							|  |  |  |         except ToolEngineInvokeError as e: | 
					
						
							| 
									
										
										
										
											2024-12-25 16:34:38 +08:00
										 |  |  |             meta = e.meta | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             error_response = f"tool invoke error: {meta.error}" | 
					
						
							|  |  |  |             agent_tool_callback.on_tool_error(e) | 
					
						
							|  |  |  |             return error_response, [], meta | 
					
						
							|  |  |  |         except Exception as e: | 
					
						
							|  |  |  |             error_response = f"unknown error: {e}" | 
					
						
							|  |  |  |             agent_tool_callback.on_tool_error(e) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return error_response, [], ToolInvokeMeta.error_instance(error_response) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |     def generic_invoke( | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         tool: Tool, | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |         tool_parameters: dict[str, Any], | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         user_id: str, | 
					
						
							|  |  |  |         workflow_tool_callback: DifyWorkflowCallbackHandler, | 
					
						
							|  |  |  |         workflow_call_depth: int, | 
					
						
							|  |  |  |         thread_pool_id: Optional[str] = None, | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |         conversation_id: Optional[str] = None, | 
					
						
							|  |  |  |         app_id: Optional[str] = None, | 
					
						
							|  |  |  |         message_id: Optional[str] = None, | 
					
						
							|  |  |  |     ) -> Generator[ToolInvokeMessage, None, None]: | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Workflow invokes the tool with the given arguments. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             # hit the callback handler | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             workflow_tool_callback.on_tool_start(tool_name=tool.entity.identity.name, tool_inputs=tool_parameters) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  |             if isinstance(tool, WorkflowTool): | 
					
						
							|  |  |  |                 tool.workflow_call_depth = workflow_call_depth + 1 | 
					
						
							| 
									
										
										
										
											2024-09-10 15:23:16 +08:00
										 |  |  |                 tool.thread_pool_id = thread_pool_id | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-22 15:29:39 +08:00
										 |  |  |             if tool.runtime and tool.runtime.runtime_parameters: | 
					
						
							|  |  |  |                 tool_parameters = {**tool.runtime.runtime_parameters, **tool_parameters} | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             response = tool.invoke( | 
					
						
							|  |  |  |                 user_id=user_id, | 
					
						
							|  |  |  |                 tool_parameters=tool_parameters, | 
					
						
							|  |  |  |                 conversation_id=conversation_id, | 
					
						
							|  |  |  |                 app_id=app_id, | 
					
						
							|  |  |  |                 message_id=message_id, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # hit the callback handler | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             response = workflow_tool_callback.on_tool_execution( | 
					
						
							|  |  |  |                 tool_name=tool.entity.identity.name, | 
					
						
							| 
									
										
										
										
											2024-06-26 17:33:29 +08:00
										 |  |  |                 tool_inputs=tool_parameters, | 
					
						
							|  |  |  |                 tool_outputs=response, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return response | 
					
						
							|  |  |  |         except Exception as e: | 
					
						
							|  |  |  |             workflow_tool_callback.on_tool_error(e) | 
					
						
							|  |  |  |             raise e | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |     def _invoke( | 
					
						
							|  |  |  |         tool: Tool, | 
					
						
							|  |  |  |         tool_parameters: dict, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         conversation_id: Optional[str] = None, | 
					
						
							|  |  |  |         app_id: Optional[str] = None, | 
					
						
							|  |  |  |         message_id: Optional[str] = None, | 
					
						
							|  |  |  |     ) -> Generator[ToolInvokeMessage | ToolInvokeMeta, None, None]: | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Invoke the tool with the given arguments. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-11-24 13:28:46 +08:00
										 |  |  |         started_at = datetime.now(UTC) | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         meta = ToolInvokeMeta( | 
					
						
							|  |  |  |             time_cost=0.0, | 
					
						
							|  |  |  |             error=None, | 
					
						
							|  |  |  |             tool_config={ | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 "tool_name": tool.entity.identity.name, | 
					
						
							|  |  |  |                 "tool_provider": tool.entity.identity.provider, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 "tool_provider_type": tool.tool_provider_type().value, | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 "tool_parameters": deepcopy(tool.runtime.runtime_parameters), | 
					
						
							|  |  |  |                 "tool_icon": tool.entity.identity.icon, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             yield from tool.invoke(user_id, tool_parameters, conversation_id, app_id, message_id) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         except Exception as e: | 
					
						
							|  |  |  |             meta.error = str(e) | 
					
						
							|  |  |  |             raise ToolEngineInvokeError(meta) | 
					
						
							|  |  |  |         finally: | 
					
						
							| 
									
										
										
										
											2024-11-24 13:28:46 +08:00
										 |  |  |             ended_at = datetime.now(UTC) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             meta.time_cost = (ended_at - started_at).total_seconds() | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             yield meta | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |     @staticmethod | 
					
						
							|  |  |  |     def _convert_tool_response_to_str(tool_response: list[ToolInvokeMessage]) -> str: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Handle tool response | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         result = "" | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         for response in tool_response: | 
					
						
							|  |  |  |             if response.type == ToolInvokeMessage.MessageType.TEXT: | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 result += cast(ToolInvokeMessage.TextMessage, response.message).text | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             elif response.type == ToolInvokeMessage.MessageType.LINK: | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 result += ( | 
					
						
							|  |  |  |                     f"result link: {cast(ToolInvokeMessage.TextMessage, response.message).text}." | 
					
						
							|  |  |  |                     + " please tell user to check it." | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-09-13 22:42:08 +08:00
										 |  |  |             elif response.type in {ToolInvokeMessage.MessageType.IMAGE_LINK, ToolInvokeMessage.MessageType.IMAGE}: | 
					
						
							| 
									
										
										
										
											2024-09-12 14:00:36 +08:00
										 |  |  |                 result += ( | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                     "image has been created and sent to user already, " | 
					
						
							|  |  |  |                     + "you do not need to create it, just tell the user to check it now." | 
					
						
							| 
									
										
										
										
											2024-09-12 14:00:36 +08:00
										 |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-06-24 15:46:16 +08:00
										 |  |  |             elif response.type == ToolInvokeMessage.MessageType.JSON: | 
					
						
							| 
									
										
										
										
											2025-04-28 09:27:46 +08:00
										 |  |  |                 result += json.dumps( | 
					
						
							| 
									
										
										
										
											2025-02-25 09:58:43 +08:00
										 |  |  |                     cast(ToolInvokeMessage.JsonMessage, response.message).json_object, ensure_ascii=False | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2025-02-25 09:58:43 +08:00
										 |  |  |                 result += str(response.message) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return result | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |     def _extract_tool_response_binary_and_text( | 
					
						
							|  |  |  |         tool_response: list[ToolInvokeMessage], | 
					
						
							|  |  |  |     ) -> Generator[ToolInvokeMessageBinary, None, None]: | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Extract tool response binary | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         for response in tool_response: | 
					
						
							| 
									
										
										
										
											2024-09-13 22:42:08 +08:00
										 |  |  |             if response.type in {ToolInvokeMessage.MessageType.IMAGE_LINK, ToolInvokeMessage.MessageType.IMAGE}: | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  |                 mimetype = None | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 if not response.meta: | 
					
						
							|  |  |  |                     raise ValueError("missing meta data") | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 if response.meta.get("mime_type"): | 
					
						
							|  |  |  |                     mimetype = response.meta.get("mime_type") | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     try: | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                         url = URL(cast(ToolInvokeMessage.TextMessage, response.message).text) | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  |                         extension = url.suffix | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                         guess_type_result, _ = guess_type(f"a{extension}") | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  |                         if guess_type_result: | 
					
						
							|  |  |  |                             mimetype = guess_type_result | 
					
						
							|  |  |  |                     except Exception: | 
					
						
							|  |  |  |                         pass | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-27 22:01:11 +08:00
										 |  |  |                 if not mimetype: | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                     mimetype = "image/jpeg" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 yield ToolInvokeMessageBinary( | 
					
						
							|  |  |  |                     mimetype=response.meta.get("mime_type", "image/jpeg"), | 
					
						
							|  |  |  |                     url=cast(ToolInvokeMessage.TextMessage, response.message).text, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             elif response.type == ToolInvokeMessage.MessageType.BLOB: | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                 if not response.meta: | 
					
						
							|  |  |  |                     raise ValueError("missing meta data") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 yield ToolInvokeMessageBinary( | 
					
						
							| 
									
										
										
										
											2025-03-10 09:49:27 +08:00
										 |  |  |                     mimetype=response.meta.get("mime_type", "application/octet-stream"), | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                     url=cast(ToolInvokeMessage.TextMessage, response.message).text, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 ) | 
					
						
							|  |  |  |             elif response.type == ToolInvokeMessage.MessageType.LINK: | 
					
						
							|  |  |  |                 # check if there is a mime type in meta | 
					
						
							|  |  |  |                 if response.meta and "mime_type" in response.meta: | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                     yield ToolInvokeMessageBinary( | 
					
						
							| 
									
										
										
										
											2025-03-10 09:49:27 +08:00
										 |  |  |                         mimetype=response.meta.get("mime_type", "application/octet-stream") | 
					
						
							|  |  |  |                         if response.meta | 
					
						
							|  |  |  |                         else "application/octet-stream", | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |                         url=cast(ToolInvokeMessage.TextMessage, response.message).text, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def _create_message_files( | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |         tool_messages: Iterable[ToolInvokeMessageBinary], | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |         agent_message: Message, | 
					
						
							|  |  |  |         invoke_from: InvokeFrom, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |     ) -> list[str]: | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Create message file | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |         :return: message file ids | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for message in tool_messages: | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |             if "image" in message.mimetype: | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |                 file_type = FileType.IMAGE | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |             elif "video" in message.mimetype: | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |                 file_type = FileType.VIDEO | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |             elif "audio" in message.mimetype: | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |                 file_type = FileType.AUDIO | 
					
						
							|  |  |  |             elif "text" in message.mimetype or "pdf" in message.mimetype: | 
					
						
							|  |  |  |                 file_type = FileType.DOCUMENT | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 file_type = FileType.CUSTOM | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |             # extract tool file id from url | 
					
						
							|  |  |  |             tool_file_id = message.url.split("/")[-1].split(".")[0] | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             message_file = MessageFile( | 
					
						
							|  |  |  |                 message_id=agent_message.id, | 
					
						
							|  |  |  |                 type=file_type, | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |                 transfer_method=FileTransferMethod.TOOL_FILE, | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |                 belongs_to="assistant", | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                 url=message.url, | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |                 upload_file_id=tool_file_id, | 
					
						
							|  |  |  |                 created_by_role=( | 
					
						
							| 
									
										
										
										
											2025-05-17 00:56:16 +08:00
										 |  |  |                     CreatorUserRole.ACCOUNT | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |                     if invoke_from in {InvokeFrom.EXPLORE, InvokeFrom.DEBUGGER} | 
					
						
							| 
									
										
										
										
											2025-05-17 00:56:16 +08:00
										 |  |  |                     else CreatorUserRole.END_USER | 
					
						
							| 
									
										
										
										
											2024-10-21 10:43:49 +08:00
										 |  |  |                 ), | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                 created_by=user_id, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             db.session.add(message_file) | 
					
						
							|  |  |  |             db.session.commit() | 
					
						
							|  |  |  |             db.session.refresh(message_file) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |             result.append(message_file.id) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         db.session.close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-10 17:00:20 +08:00
										 |  |  |         return result |