tools_transform_service.py 11 KB

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