tool_providers.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. import io
  2. from flask import send_file
  3. from flask_login import current_user
  4. from flask_restful import Resource, reqparse
  5. from werkzeug.exceptions import Forbidden
  6. from configs import dify_config
  7. from controllers.console import api
  8. from controllers.console.wraps import account_initialization_required, enterprise_license_required, setup_required
  9. from core.model_runtime.utils.encoders import jsonable_encoder
  10. from libs.helper import alphanumeric, uuid_value
  11. from libs.login import login_required
  12. from services.tools.api_tools_manage_service import ApiToolManageService
  13. from services.tools.builtin_tools_manage_service import BuiltinToolManageService
  14. from services.tools.tool_labels_service import ToolLabelsService
  15. from services.tools.tools_manage_service import ToolCommonService
  16. from services.tools.workflow_tools_manage_service import WorkflowToolManageService
  17. class ToolProviderListApi(Resource):
  18. @setup_required
  19. @login_required
  20. @account_initialization_required
  21. def get(self):
  22. user = current_user
  23. user_id = user.id
  24. tenant_id = user.current_tenant_id
  25. req = reqparse.RequestParser()
  26. req.add_argument(
  27. "type",
  28. type=str,
  29. choices=["builtin", "model", "api", "workflow"],
  30. required=False,
  31. nullable=True,
  32. location="args",
  33. )
  34. args = req.parse_args()
  35. return ToolCommonService.list_tool_providers(user_id, tenant_id, args.get("type", None))
  36. class ToolBuiltinProviderListToolsApi(Resource):
  37. @setup_required
  38. @login_required
  39. @account_initialization_required
  40. def get(self, provider):
  41. user = current_user
  42. user_id = user.id
  43. tenant_id = user.current_tenant_id
  44. return jsonable_encoder(
  45. BuiltinToolManageService.list_builtin_tool_provider_tools(
  46. user_id,
  47. tenant_id,
  48. provider,
  49. )
  50. )
  51. class ToolBuiltinProviderInfoApi(Resource):
  52. @setup_required
  53. @login_required
  54. @account_initialization_required
  55. def get(self, provider):
  56. user = current_user
  57. user_id = user.id
  58. tenant_id = user.current_tenant_id
  59. return jsonable_encoder(BuiltinToolManageService.get_builtin_tool_provider_info(user_id, tenant_id, provider))
  60. class ToolBuiltinProviderDeleteApi(Resource):
  61. @setup_required
  62. @login_required
  63. @account_initialization_required
  64. def post(self, provider):
  65. user = current_user
  66. if not user.is_admin_or_owner:
  67. raise Forbidden()
  68. user_id = user.id
  69. tenant_id = user.current_tenant_id
  70. return BuiltinToolManageService.delete_builtin_tool_provider(
  71. user_id,
  72. tenant_id,
  73. provider,
  74. )
  75. class ToolBuiltinProviderUpdateApi(Resource):
  76. @setup_required
  77. @login_required
  78. @account_initialization_required
  79. def post(self, provider):
  80. user = current_user
  81. if not user.is_admin_or_owner:
  82. raise Forbidden()
  83. user_id = user.id
  84. tenant_id = user.current_tenant_id
  85. parser = reqparse.RequestParser()
  86. parser.add_argument("credentials", type=dict, required=True, nullable=False, location="json")
  87. args = parser.parse_args()
  88. return BuiltinToolManageService.update_builtin_tool_provider(
  89. user_id,
  90. tenant_id,
  91. provider,
  92. args["credentials"],
  93. )
  94. class ToolBuiltinProviderGetCredentialsApi(Resource):
  95. @setup_required
  96. @login_required
  97. @account_initialization_required
  98. def get(self, provider):
  99. user = current_user
  100. user_id = user.id
  101. tenant_id = user.current_tenant_id
  102. return BuiltinToolManageService.get_builtin_tool_provider_credentials(
  103. user_id,
  104. tenant_id,
  105. provider,
  106. )
  107. class ToolBuiltinProviderIconApi(Resource):
  108. @setup_required
  109. def get(self, provider):
  110. icon_bytes, mimetype = BuiltinToolManageService.get_builtin_tool_provider_icon(provider)
  111. icon_cache_max_age = dify_config.TOOL_ICON_CACHE_MAX_AGE
  112. return send_file(io.BytesIO(icon_bytes), mimetype=mimetype, max_age=icon_cache_max_age)
  113. class ToolApiProviderAddApi(Resource):
  114. @setup_required
  115. @login_required
  116. @account_initialization_required
  117. def post(self):
  118. user = current_user
  119. if not user.is_admin_or_owner:
  120. raise Forbidden()
  121. user_id = user.id
  122. tenant_id = user.current_tenant_id
  123. parser = reqparse.RequestParser()
  124. parser.add_argument("credentials", type=dict, required=True, nullable=False, location="json")
  125. parser.add_argument("schema_type", type=str, required=True, nullable=False, location="json")
  126. parser.add_argument("schema", type=str, required=True, nullable=False, location="json")
  127. parser.add_argument("provider", type=str, required=True, nullable=False, location="json")
  128. parser.add_argument("icon", type=dict, required=True, nullable=False, location="json")
  129. parser.add_argument("privacy_policy", type=str, required=False, nullable=True, location="json")
  130. parser.add_argument("labels", type=list[str], required=False, nullable=True, location="json", default=[])
  131. parser.add_argument("custom_disclaimer", type=str, required=False, nullable=True, location="json")
  132. args = parser.parse_args()
  133. return ApiToolManageService.create_api_tool_provider(
  134. user_id,
  135. tenant_id,
  136. args["provider"],
  137. args["icon"],
  138. args["credentials"],
  139. args["schema_type"],
  140. args["schema"],
  141. args.get("privacy_policy", ""),
  142. args.get("custom_disclaimer", ""),
  143. args.get("labels", []),
  144. )
  145. class ToolApiProviderGetRemoteSchemaApi(Resource):
  146. @setup_required
  147. @login_required
  148. @account_initialization_required
  149. def get(self):
  150. user = current_user
  151. user_id = user.id
  152. tenant_id = user.current_tenant_id
  153. parser = reqparse.RequestParser()
  154. parser.add_argument("url", type=str, required=True, nullable=False, location="args")
  155. args = parser.parse_args()
  156. return ApiToolManageService.get_api_tool_provider_remote_schema(
  157. user_id,
  158. tenant_id,
  159. args["url"],
  160. )
  161. class ToolApiProviderListToolsApi(Resource):
  162. @setup_required
  163. @login_required
  164. @account_initialization_required
  165. def get(self):
  166. user = current_user
  167. user_id = user.id
  168. tenant_id = user.current_tenant_id
  169. parser = reqparse.RequestParser()
  170. parser.add_argument("provider", type=str, required=True, nullable=False, location="args")
  171. args = parser.parse_args()
  172. return jsonable_encoder(
  173. ApiToolManageService.list_api_tool_provider_tools(
  174. user_id,
  175. tenant_id,
  176. args["provider"],
  177. )
  178. )
  179. class ToolApiProviderUpdateApi(Resource):
  180. @setup_required
  181. @login_required
  182. @account_initialization_required
  183. def post(self):
  184. user = current_user
  185. if not user.is_admin_or_owner:
  186. raise Forbidden()
  187. user_id = user.id
  188. tenant_id = user.current_tenant_id
  189. parser = reqparse.RequestParser()
  190. parser.add_argument("credentials", type=dict, required=True, nullable=False, location="json")
  191. parser.add_argument("schema_type", type=str, required=True, nullable=False, location="json")
  192. parser.add_argument("schema", type=str, required=True, nullable=False, location="json")
  193. parser.add_argument("provider", type=str, required=True, nullable=False, location="json")
  194. parser.add_argument("original_provider", type=str, required=True, nullable=False, location="json")
  195. parser.add_argument("icon", type=dict, required=True, nullable=False, location="json")
  196. parser.add_argument("privacy_policy", type=str, required=True, nullable=True, location="json")
  197. parser.add_argument("labels", type=list[str], required=False, nullable=True, location="json")
  198. parser.add_argument("custom_disclaimer", type=str, required=True, nullable=True, location="json")
  199. args = parser.parse_args()
  200. return ApiToolManageService.update_api_tool_provider(
  201. user_id,
  202. tenant_id,
  203. args["provider"],
  204. args["original_provider"],
  205. args["icon"],
  206. args["credentials"],
  207. args["schema_type"],
  208. args["schema"],
  209. args["privacy_policy"],
  210. args["custom_disclaimer"],
  211. args.get("labels", []),
  212. )
  213. class ToolApiProviderDeleteApi(Resource):
  214. @setup_required
  215. @login_required
  216. @account_initialization_required
  217. def post(self):
  218. user = current_user
  219. if not user.is_admin_or_owner:
  220. raise Forbidden()
  221. user_id = user.id
  222. tenant_id = user.current_tenant_id
  223. parser = reqparse.RequestParser()
  224. parser.add_argument("provider", type=str, required=True, nullable=False, location="json")
  225. args = parser.parse_args()
  226. return ApiToolManageService.delete_api_tool_provider(
  227. user_id,
  228. tenant_id,
  229. args["provider"],
  230. )
  231. class ToolApiProviderGetApi(Resource):
  232. @setup_required
  233. @login_required
  234. @account_initialization_required
  235. def get(self):
  236. user = current_user
  237. user_id = user.id
  238. tenant_id = user.current_tenant_id
  239. parser = reqparse.RequestParser()
  240. parser.add_argument("provider", type=str, required=True, nullable=False, location="args")
  241. args = parser.parse_args()
  242. return ApiToolManageService.get_api_tool_provider(
  243. user_id,
  244. tenant_id,
  245. args["provider"],
  246. )
  247. class ToolBuiltinProviderCredentialsSchemaApi(Resource):
  248. @setup_required
  249. @login_required
  250. @account_initialization_required
  251. def get(self, provider):
  252. user = current_user
  253. user_id = user.id
  254. tenant_id = user.current_tenant_id
  255. return BuiltinToolManageService.list_builtin_provider_credentials_schema(provider, tenant_id)
  256. class ToolApiProviderSchemaApi(Resource):
  257. @setup_required
  258. @login_required
  259. @account_initialization_required
  260. def post(self):
  261. parser = reqparse.RequestParser()
  262. parser.add_argument("schema", type=str, required=True, nullable=False, location="json")
  263. args = parser.parse_args()
  264. return ApiToolManageService.parser_api_schema(
  265. schema=args["schema"],
  266. )
  267. class ToolApiProviderPreviousTestApi(Resource):
  268. @setup_required
  269. @login_required
  270. @account_initialization_required
  271. def post(self):
  272. parser = reqparse.RequestParser()
  273. parser.add_argument("tool_name", type=str, required=True, nullable=False, location="json")
  274. parser.add_argument("provider_name", type=str, required=False, nullable=False, location="json")
  275. parser.add_argument("credentials", type=dict, required=True, nullable=False, location="json")
  276. parser.add_argument("parameters", type=dict, required=True, nullable=False, location="json")
  277. parser.add_argument("schema_type", type=str, required=True, nullable=False, location="json")
  278. parser.add_argument("schema", type=str, required=True, nullable=False, location="json")
  279. args = parser.parse_args()
  280. return ApiToolManageService.test_api_tool_preview(
  281. current_user.current_tenant_id,
  282. args["provider_name"] or "",
  283. args["tool_name"],
  284. args["credentials"],
  285. args["parameters"],
  286. args["schema_type"],
  287. args["schema"],
  288. )
  289. class ToolWorkflowProviderCreateApi(Resource):
  290. @setup_required
  291. @login_required
  292. @account_initialization_required
  293. def post(self):
  294. user = current_user
  295. if not user.is_admin_or_owner:
  296. raise Forbidden()
  297. user_id = user.id
  298. tenant_id = user.current_tenant_id
  299. reqparser = reqparse.RequestParser()
  300. reqparser.add_argument("workflow_app_id", type=uuid_value, required=True, nullable=False, location="json")
  301. reqparser.add_argument("name", type=alphanumeric, required=True, nullable=False, location="json")
  302. reqparser.add_argument("label", type=str, required=True, nullable=False, location="json")
  303. reqparser.add_argument("description", type=str, required=True, nullable=False, location="json")
  304. reqparser.add_argument("icon", type=dict, required=True, nullable=False, location="json")
  305. reqparser.add_argument("parameters", type=list[dict], required=True, nullable=False, location="json")
  306. reqparser.add_argument("privacy_policy", type=str, required=False, nullable=True, location="json", default="")
  307. reqparser.add_argument("labels", type=list[str], required=False, nullable=True, location="json")
  308. args = reqparser.parse_args()
  309. return WorkflowToolManageService.create_workflow_tool(
  310. user_id=user_id,
  311. tenant_id=tenant_id,
  312. workflow_app_id=args["workflow_app_id"],
  313. name=args["name"],
  314. label=args["label"],
  315. icon=args["icon"],
  316. description=args["description"],
  317. parameters=args["parameters"],
  318. privacy_policy=args["privacy_policy"],
  319. )
  320. class ToolWorkflowProviderUpdateApi(Resource):
  321. @setup_required
  322. @login_required
  323. @account_initialization_required
  324. def post(self):
  325. user = current_user
  326. if not user.is_admin_or_owner:
  327. raise Forbidden()
  328. user_id = user.id
  329. tenant_id = user.current_tenant_id
  330. reqparser = reqparse.RequestParser()
  331. reqparser.add_argument("workflow_tool_id", type=uuid_value, required=True, nullable=False, location="json")
  332. reqparser.add_argument("name", type=alphanumeric, required=True, nullable=False, location="json")
  333. reqparser.add_argument("label", type=str, required=True, nullable=False, location="json")
  334. reqparser.add_argument("description", type=str, required=True, nullable=False, location="json")
  335. reqparser.add_argument("icon", type=dict, required=True, nullable=False, location="json")
  336. reqparser.add_argument("parameters", type=list[dict], required=True, nullable=False, location="json")
  337. reqparser.add_argument("privacy_policy", type=str, required=False, nullable=True, location="json", default="")
  338. reqparser.add_argument("labels", type=list[str], required=False, nullable=True, location="json")
  339. args = reqparser.parse_args()
  340. if not args["workflow_tool_id"]:
  341. raise ValueError("incorrect workflow_tool_id")
  342. return WorkflowToolManageService.update_workflow_tool(
  343. user_id,
  344. tenant_id,
  345. args["workflow_tool_id"],
  346. args["name"],
  347. args["label"],
  348. args["icon"],
  349. args["description"],
  350. args["parameters"],
  351. args["privacy_policy"],
  352. args.get("labels", []),
  353. )
  354. class ToolWorkflowProviderDeleteApi(Resource):
  355. @setup_required
  356. @login_required
  357. @account_initialization_required
  358. def post(self):
  359. user = current_user
  360. if not user.is_admin_or_owner:
  361. raise Forbidden()
  362. user_id = user.id
  363. tenant_id = user.current_tenant_id
  364. reqparser = reqparse.RequestParser()
  365. reqparser.add_argument("workflow_tool_id", type=uuid_value, required=True, nullable=False, location="json")
  366. args = reqparser.parse_args()
  367. return WorkflowToolManageService.delete_workflow_tool(
  368. user_id,
  369. tenant_id,
  370. args["workflow_tool_id"],
  371. )
  372. class ToolWorkflowProviderGetApi(Resource):
  373. @setup_required
  374. @login_required
  375. @account_initialization_required
  376. def get(self):
  377. user = current_user
  378. user_id = user.id
  379. tenant_id = user.current_tenant_id
  380. parser = reqparse.RequestParser()
  381. parser.add_argument("workflow_tool_id", type=uuid_value, required=False, nullable=True, location="args")
  382. parser.add_argument("workflow_app_id", type=uuid_value, required=False, nullable=True, location="args")
  383. args = parser.parse_args()
  384. if args.get("workflow_tool_id"):
  385. tool = WorkflowToolManageService.get_workflow_tool_by_tool_id(
  386. user_id,
  387. tenant_id,
  388. args["workflow_tool_id"],
  389. )
  390. elif args.get("workflow_app_id"):
  391. tool = WorkflowToolManageService.get_workflow_tool_by_app_id(
  392. user_id,
  393. tenant_id,
  394. args["workflow_app_id"],
  395. )
  396. else:
  397. raise ValueError("incorrect workflow_tool_id or workflow_app_id")
  398. return jsonable_encoder(tool)
  399. class ToolWorkflowProviderListToolApi(Resource):
  400. @setup_required
  401. @login_required
  402. @account_initialization_required
  403. def get(self):
  404. user = current_user
  405. user_id = user.id
  406. tenant_id = user.current_tenant_id
  407. parser = reqparse.RequestParser()
  408. parser.add_argument("workflow_tool_id", type=uuid_value, required=True, nullable=False, location="args")
  409. args = parser.parse_args()
  410. return jsonable_encoder(
  411. WorkflowToolManageService.list_single_workflow_tools(
  412. user_id,
  413. tenant_id,
  414. args["workflow_tool_id"],
  415. )
  416. )
  417. class ToolBuiltinListApi(Resource):
  418. @setup_required
  419. @login_required
  420. @account_initialization_required
  421. def get(self):
  422. user = current_user
  423. user_id = user.id
  424. tenant_id = user.current_tenant_id
  425. return jsonable_encoder(
  426. [
  427. provider.to_dict()
  428. for provider in BuiltinToolManageService.list_builtin_tools(
  429. user_id,
  430. tenant_id,
  431. )
  432. ]
  433. )
  434. class ToolApiListApi(Resource):
  435. @setup_required
  436. @login_required
  437. @account_initialization_required
  438. def get(self):
  439. user = current_user
  440. user_id = user.id
  441. tenant_id = user.current_tenant_id
  442. return jsonable_encoder(
  443. [
  444. provider.to_dict()
  445. for provider in ApiToolManageService.list_api_tools(
  446. user_id,
  447. tenant_id,
  448. )
  449. ]
  450. )
  451. class ToolWorkflowListApi(Resource):
  452. @setup_required
  453. @login_required
  454. @account_initialization_required
  455. def get(self):
  456. user = current_user
  457. user_id = user.id
  458. tenant_id = user.current_tenant_id
  459. return jsonable_encoder(
  460. [
  461. provider.to_dict()
  462. for provider in WorkflowToolManageService.list_tenant_workflow_tools(
  463. user_id,
  464. tenant_id,
  465. )
  466. ]
  467. )
  468. class ToolLabelsApi(Resource):
  469. @setup_required
  470. @login_required
  471. @account_initialization_required
  472. @enterprise_license_required
  473. def get(self):
  474. return jsonable_encoder(ToolLabelsService.list_tool_labels())
  475. # tool provider
  476. api.add_resource(ToolProviderListApi, "/workspaces/current/tool-providers")
  477. # builtin tool provider
  478. api.add_resource(ToolBuiltinProviderListToolsApi, "/workspaces/current/tool-provider/builtin/<path:provider>/tools")
  479. api.add_resource(ToolBuiltinProviderInfoApi, "/workspaces/current/tool-provider/builtin/<path:provider>/info")
  480. api.add_resource(ToolBuiltinProviderDeleteApi, "/workspaces/current/tool-provider/builtin/<path:provider>/delete")
  481. api.add_resource(ToolBuiltinProviderUpdateApi, "/workspaces/current/tool-provider/builtin/<path:provider>/update")
  482. api.add_resource(
  483. ToolBuiltinProviderGetCredentialsApi, "/workspaces/current/tool-provider/builtin/<path:provider>/credentials"
  484. )
  485. api.add_resource(
  486. ToolBuiltinProviderCredentialsSchemaApi,
  487. "/workspaces/current/tool-provider/builtin/<path:provider>/credentials_schema",
  488. )
  489. api.add_resource(ToolBuiltinProviderIconApi, "/workspaces/current/tool-provider/builtin/<path:provider>/icon")
  490. # api tool provider
  491. api.add_resource(ToolApiProviderAddApi, "/workspaces/current/tool-provider/api/add")
  492. api.add_resource(ToolApiProviderGetRemoteSchemaApi, "/workspaces/current/tool-provider/api/remote")
  493. api.add_resource(ToolApiProviderListToolsApi, "/workspaces/current/tool-provider/api/tools")
  494. api.add_resource(ToolApiProviderUpdateApi, "/workspaces/current/tool-provider/api/update")
  495. api.add_resource(ToolApiProviderDeleteApi, "/workspaces/current/tool-provider/api/delete")
  496. api.add_resource(ToolApiProviderGetApi, "/workspaces/current/tool-provider/api/get")
  497. api.add_resource(ToolApiProviderSchemaApi, "/workspaces/current/tool-provider/api/schema")
  498. api.add_resource(ToolApiProviderPreviousTestApi, "/workspaces/current/tool-provider/api/test/pre")
  499. # workflow tool provider
  500. api.add_resource(ToolWorkflowProviderCreateApi, "/workspaces/current/tool-provider/workflow/create")
  501. api.add_resource(ToolWorkflowProviderUpdateApi, "/workspaces/current/tool-provider/workflow/update")
  502. api.add_resource(ToolWorkflowProviderDeleteApi, "/workspaces/current/tool-provider/workflow/delete")
  503. api.add_resource(ToolWorkflowProviderGetApi, "/workspaces/current/tool-provider/workflow/get")
  504. api.add_resource(ToolWorkflowProviderListToolApi, "/workspaces/current/tool-provider/workflow/tools")
  505. api.add_resource(ToolBuiltinListApi, "/workspaces/current/tools/builtin")
  506. api.add_resource(ToolApiListApi, "/workspaces/current/tools/api")
  507. api.add_resource(ToolWorkflowListApi, "/workspaces/current/tools/workflow")
  508. api.add_resource(ToolLabelsApi, "/workspaces/current/tool-labels")