tools_transform_service.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. import json
  2. import logging
  3. from typing import Optional, Union
  4. from configs import dify_config
  5. from core.tools.entities.api_entities import UserTool, UserToolProvider
  6. from core.tools.entities.common_entities import I18nObject
  7. from core.tools.entities.tool_bundle import ApiToolBundle
  8. from core.tools.entities.tool_entities import (
  9. ApiProviderAuthType,
  10. ToolParameter,
  11. ToolProviderCredentials,
  12. ToolProviderType,
  13. )
  14. from core.tools.provider.api_tool_provider import ApiToolProviderController
  15. from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
  16. from core.tools.provider.workflow_tool_provider import WorkflowToolProviderController
  17. from core.tools.tool.tool import Tool
  18. from core.tools.tool.workflow_tool import WorkflowTool
  19. from core.tools.utils.configuration import ToolConfigurationManager
  20. from models.tools import ApiToolProvider, BuiltinToolProvider, WorkflowToolProvider
  21. logger = logging.getLogger(__name__)
  22. class ToolTransformService:
  23. @staticmethod
  24. def get_tool_provider_icon_url(provider_type: str, provider_name: str, icon: str) -> Union[str, dict]:
  25. """
  26. get tool provider icon url
  27. """
  28. url_prefix = dify_config.CONSOLE_API_URL + "/console/api/workspaces/current/tool-provider/"
  29. if provider_type == ToolProviderType.BUILT_IN.value:
  30. return url_prefix + "builtin/" + provider_name + "/icon"
  31. elif provider_type in {ToolProviderType.API.value, ToolProviderType.WORKFLOW.value}:
  32. try:
  33. return json.loads(icon)
  34. except:
  35. return {"background": "#252525", "content": "\ud83d\ude01"}
  36. return ""
  37. @staticmethod
  38. def repack_provider(provider: Union[dict, UserToolProvider]):
  39. """
  40. repack provider
  41. :param provider: the provider dict
  42. """
  43. if isinstance(provider, dict) and "icon" in provider:
  44. provider["icon"] = ToolTransformService.get_tool_provider_icon_url(
  45. provider_type=provider["type"], provider_name=provider["name"], icon=provider["icon"]
  46. )
  47. elif isinstance(provider, UserToolProvider):
  48. provider.icon = ToolTransformService.get_tool_provider_icon_url(
  49. provider_type=provider.type.value, provider_name=provider.name, icon=provider.icon
  50. )
  51. @staticmethod
  52. def builtin_provider_to_user_provider(
  53. provider_controller: BuiltinToolProviderController,
  54. db_provider: Optional[BuiltinToolProvider],
  55. decrypt_credentials: bool = True,
  56. ) -> UserToolProvider:
  57. """
  58. convert provider controller to user provider
  59. """
  60. result = UserToolProvider(
  61. id=provider_controller.identity.name,
  62. author=provider_controller.identity.author,
  63. name=provider_controller.identity.name,
  64. description=I18nObject(
  65. en_US=provider_controller.identity.description.en_US,
  66. zh_Hans=provider_controller.identity.description.zh_Hans,
  67. pt_BR=provider_controller.identity.description.pt_BR,
  68. ja_JP=provider_controller.identity.description.ja_JP,
  69. ),
  70. icon=provider_controller.identity.icon,
  71. label=I18nObject(
  72. en_US=provider_controller.identity.label.en_US,
  73. zh_Hans=provider_controller.identity.label.zh_Hans,
  74. pt_BR=provider_controller.identity.label.pt_BR,
  75. ja_JP=provider_controller.identity.label.ja_JP,
  76. ),
  77. type=ToolProviderType.BUILT_IN,
  78. masked_credentials={},
  79. is_team_authorization=False,
  80. tools=[],
  81. labels=provider_controller.tool_labels,
  82. )
  83. # get credentials schema
  84. schema = provider_controller.get_credentials_schema()
  85. for name, value in schema.items():
  86. result.masked_credentials[name] = ToolProviderCredentials.CredentialsType.default(value.type)
  87. # check if the provider need credentials
  88. if not provider_controller.need_credentials:
  89. result.is_team_authorization = True
  90. result.allow_delete = False
  91. elif db_provider:
  92. result.is_team_authorization = True
  93. if decrypt_credentials:
  94. credentials = db_provider.credentials
  95. # init tool configuration
  96. tool_configuration = ToolConfigurationManager(
  97. tenant_id=db_provider.tenant_id, provider_controller=provider_controller
  98. )
  99. # decrypt the credentials and mask the credentials
  100. decrypted_credentials = tool_configuration.decrypt_tool_credentials(credentials=credentials)
  101. masked_credentials = tool_configuration.mask_tool_credentials(credentials=decrypted_credentials)
  102. result.masked_credentials = masked_credentials
  103. result.original_credentials = decrypted_credentials
  104. return result
  105. @staticmethod
  106. def api_provider_to_controller(
  107. db_provider: ApiToolProvider,
  108. ) -> ApiToolProviderController:
  109. """
  110. convert provider controller to user provider
  111. """
  112. # package tool provider controller
  113. controller = ApiToolProviderController.from_db(
  114. db_provider=db_provider,
  115. auth_type=ApiProviderAuthType.API_KEY
  116. if db_provider.credentials["auth_type"] == "api_key"
  117. else ApiProviderAuthType.NONE,
  118. )
  119. return controller
  120. @staticmethod
  121. def workflow_provider_to_controller(db_provider: WorkflowToolProvider) -> WorkflowToolProviderController:
  122. """
  123. convert provider controller to provider
  124. """
  125. return WorkflowToolProviderController.from_db(db_provider)
  126. @staticmethod
  127. def workflow_provider_to_user_provider(
  128. provider_controller: WorkflowToolProviderController, labels: Optional[list[str]] = None
  129. ):
  130. """
  131. convert provider controller to user provider
  132. """
  133. return UserToolProvider(
  134. id=provider_controller.provider_id,
  135. author=provider_controller.identity.author,
  136. name=provider_controller.identity.name,
  137. description=I18nObject(
  138. en_US=provider_controller.identity.description.en_US,
  139. zh_Hans=provider_controller.identity.description.zh_Hans,
  140. ),
  141. icon=provider_controller.identity.icon,
  142. label=I18nObject(
  143. en_US=provider_controller.identity.label.en_US,
  144. zh_Hans=provider_controller.identity.label.zh_Hans,
  145. ),
  146. type=ToolProviderType.WORKFLOW,
  147. masked_credentials={},
  148. is_team_authorization=True,
  149. tools=[],
  150. labels=labels or [],
  151. )
  152. @staticmethod
  153. def api_provider_to_user_provider(
  154. provider_controller: ApiToolProviderController,
  155. db_provider: ApiToolProvider,
  156. decrypt_credentials: bool = True,
  157. labels: Optional[list[str]] = None,
  158. ) -> UserToolProvider:
  159. """
  160. convert provider controller to user provider
  161. """
  162. username = "Anonymous"
  163. try:
  164. username = db_provider.user.name
  165. except Exception as e:
  166. logger.error(f"failed to get user name for api provider {db_provider.id}: {str(e)}")
  167. # add provider into providers
  168. credentials = db_provider.credentials
  169. result = UserToolProvider(
  170. id=db_provider.id,
  171. author=username,
  172. name=db_provider.name,
  173. description=I18nObject(
  174. en_US=db_provider.description,
  175. zh_Hans=db_provider.description,
  176. ),
  177. icon=db_provider.icon,
  178. label=I18nObject(
  179. en_US=db_provider.name,
  180. zh_Hans=db_provider.name,
  181. ),
  182. type=ToolProviderType.API,
  183. masked_credentials={},
  184. is_team_authorization=True,
  185. tools=[],
  186. labels=labels or [],
  187. )
  188. if decrypt_credentials:
  189. # init tool configuration
  190. tool_configuration = ToolConfigurationManager(
  191. tenant_id=db_provider.tenant_id, provider_controller=provider_controller
  192. )
  193. # decrypt the credentials and mask the credentials
  194. decrypted_credentials = tool_configuration.decrypt_tool_credentials(credentials=credentials)
  195. masked_credentials = tool_configuration.mask_tool_credentials(credentials=decrypted_credentials)
  196. result.masked_credentials = masked_credentials
  197. return result
  198. @staticmethod
  199. def tool_to_user_tool(
  200. tool: Union[ApiToolBundle, WorkflowTool, Tool],
  201. credentials: Optional[dict] = None,
  202. tenant_id: Optional[str] = None,
  203. labels: Optional[list[str]] = None,
  204. ) -> UserTool:
  205. """
  206. convert tool to user tool
  207. """
  208. if isinstance(tool, Tool):
  209. # fork tool runtime
  210. tool = tool.fork_tool_runtime(
  211. runtime={
  212. "credentials": credentials,
  213. "tenant_id": tenant_id,
  214. }
  215. )
  216. # get tool parameters
  217. parameters = tool.parameters or []
  218. # get tool runtime parameters
  219. runtime_parameters = tool.get_runtime_parameters() or []
  220. # override parameters
  221. current_parameters = parameters.copy()
  222. for runtime_parameter in runtime_parameters:
  223. found = False
  224. for index, parameter in enumerate(current_parameters):
  225. if parameter.name == runtime_parameter.name and parameter.form == runtime_parameter.form:
  226. current_parameters[index] = runtime_parameter
  227. found = True
  228. break
  229. if not found and runtime_parameter.form == ToolParameter.ToolParameterForm.FORM:
  230. current_parameters.append(runtime_parameter)
  231. return UserTool(
  232. author=tool.identity.author,
  233. name=tool.identity.name,
  234. label=tool.identity.label,
  235. description=tool.description.human,
  236. parameters=current_parameters,
  237. labels=labels,
  238. )
  239. if isinstance(tool, ApiToolBundle):
  240. return UserTool(
  241. author=tool.author,
  242. name=tool.operation_id,
  243. label=I18nObject(en_US=tool.operation_id, zh_Hans=tool.operation_id),
  244. description=I18nObject(en_US=tool.summary or "", zh_Hans=tool.summary or ""),
  245. parameters=tool.parameters,
  246. labels=labels,
  247. )