plugin.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. from collections.abc import Sequence
  2. from pydantic import BaseModel
  3. from core.plugin.entities.bundle import PluginBundleDependency
  4. from core.plugin.entities.plugin import (
  5. PluginDeclaration,
  6. PluginEntity,
  7. PluginInstallation,
  8. PluginInstallationSource,
  9. )
  10. from core.plugin.entities.plugin_daemon import PluginInstallTask, PluginInstallTaskStartResponse, PluginUploadResponse
  11. from core.plugin.manager.base import BasePluginManager
  12. class PluginInstallationManager(BasePluginManager):
  13. def fetch_plugin_by_identifier(
  14. self,
  15. tenant_id: str,
  16. identifier: str,
  17. ) -> bool:
  18. return self._request_with_plugin_daemon_response(
  19. "GET",
  20. f"plugin/{tenant_id}/management/fetch/identifier",
  21. bool,
  22. params={"plugin_unique_identifier": identifier},
  23. )
  24. def list_plugins(self, tenant_id: str) -> list[PluginEntity]:
  25. return self._request_with_plugin_daemon_response(
  26. "GET",
  27. f"plugin/{tenant_id}/management/list",
  28. list[PluginEntity],
  29. params={"page": 1, "page_size": 256},
  30. )
  31. def upload_pkg(
  32. self,
  33. tenant_id: str,
  34. pkg: bytes,
  35. verify_signature: bool = False,
  36. ) -> PluginUploadResponse:
  37. """
  38. Upload a plugin package and return the plugin unique identifier.
  39. """
  40. body = {
  41. "dify_pkg": ("dify_pkg", pkg, "application/octet-stream"),
  42. }
  43. data = {
  44. "verify_signature": "true" if verify_signature else "false",
  45. }
  46. return self._request_with_plugin_daemon_response(
  47. "POST",
  48. f"plugin/{tenant_id}/management/install/upload/package",
  49. PluginUploadResponse,
  50. files=body,
  51. data=data,
  52. )
  53. def upload_bundle(
  54. self,
  55. tenant_id: str,
  56. bundle: bytes,
  57. verify_signature: bool = False,
  58. ) -> Sequence[PluginBundleDependency]:
  59. """
  60. Upload a plugin bundle and return the dependencies.
  61. """
  62. return self._request_with_plugin_daemon_response(
  63. "POST",
  64. f"plugin/{tenant_id}/management/install/upload/bundle",
  65. list[PluginBundleDependency],
  66. files={"dify_bundle": ("dify_bundle", bundle, "application/octet-stream")},
  67. data={"verify_signature": "true" if verify_signature else "false"},
  68. )
  69. def install_from_identifiers(
  70. self, tenant_id: str, identifiers: Sequence[str], source: PluginInstallationSource, meta: dict
  71. ) -> PluginInstallTaskStartResponse:
  72. """
  73. Install a plugin from an identifier.
  74. """
  75. # exception will be raised if the request failed
  76. return self._request_with_plugin_daemon_response(
  77. "POST",
  78. f"plugin/{tenant_id}/management/install/identifiers",
  79. PluginInstallTaskStartResponse,
  80. data={
  81. "plugin_unique_identifiers": identifiers,
  82. "source": source,
  83. "meta": meta,
  84. },
  85. headers={"Content-Type": "application/json"},
  86. )
  87. def fetch_plugin_installation_tasks(self, tenant_id: str, page: int, page_size: int) -> Sequence[PluginInstallTask]:
  88. """
  89. Fetch plugin installation tasks.
  90. """
  91. return self._request_with_plugin_daemon_response(
  92. "GET",
  93. f"plugin/{tenant_id}/management/install/tasks",
  94. list[PluginInstallTask],
  95. params={"page": page, "page_size": page_size},
  96. )
  97. def fetch_plugin_installation_task(self, tenant_id: str, task_id: str) -> PluginInstallTask:
  98. """
  99. Fetch a plugin installation task.
  100. """
  101. return self._request_with_plugin_daemon_response(
  102. "GET",
  103. f"plugin/{tenant_id}/management/install/tasks/{task_id}",
  104. PluginInstallTask,
  105. )
  106. def delete_plugin_installation_task(self, tenant_id: str, task_id: str) -> bool:
  107. """
  108. Delete a plugin installation task.
  109. """
  110. return self._request_with_plugin_daemon_response(
  111. "POST",
  112. f"plugin/{tenant_id}/management/install/tasks/{task_id}/delete",
  113. bool,
  114. )
  115. def delete_all_plugin_installation_task_items(self, tenant_id: str) -> bool:
  116. """
  117. Delete all plugin installation task items.
  118. """
  119. return self._request_with_plugin_daemon_response(
  120. "POST",
  121. f"plugin/{tenant_id}/management/install/tasks/delete_all",
  122. bool,
  123. )
  124. def delete_plugin_installation_task_item(self, tenant_id: str, task_id: str, identifier: str) -> bool:
  125. """
  126. Delete a plugin installation task item.
  127. """
  128. return self._request_with_plugin_daemon_response(
  129. "POST",
  130. f"plugin/{tenant_id}/management/install/tasks/{task_id}/delete/{identifier}",
  131. bool,
  132. )
  133. def fetch_plugin_manifest(self, tenant_id: str, plugin_unique_identifier: str) -> PluginDeclaration:
  134. """
  135. Fetch a plugin manifest.
  136. """
  137. class PluginDeclarationResponse(BaseModel):
  138. declaration: PluginDeclaration
  139. return self._request_with_plugin_daemon_response(
  140. "GET",
  141. f"plugin/{tenant_id}/management/fetch/manifest",
  142. PluginDeclarationResponse,
  143. params={"plugin_unique_identifier": plugin_unique_identifier},
  144. ).declaration
  145. def fetch_plugin_installation_by_ids(
  146. self, tenant_id: str, plugin_ids: Sequence[str]
  147. ) -> Sequence[PluginInstallation]:
  148. """
  149. Fetch plugin installations by ids.
  150. """
  151. return self._request_with_plugin_daemon_response(
  152. "POST",
  153. f"plugin/{tenant_id}/management/installation/fetch/batch",
  154. list[PluginInstallation],
  155. data={"plugin_ids": plugin_ids},
  156. headers={"Content-Type": "application/json"},
  157. )
  158. def fetch_missing_dependencies(self, tenant_id: str, plugin_unique_identifiers: list[str]) -> list[str]:
  159. """
  160. Fetch missing dependencies
  161. """
  162. return self._request_with_plugin_daemon_response(
  163. "POST",
  164. f"plugin/{tenant_id}/management/installation/missing",
  165. list[str],
  166. data={"plugin_unique_identifiers": plugin_unique_identifiers},
  167. headers={"Content-Type": "application/json"},
  168. )
  169. def uninstall(self, tenant_id: str, plugin_installation_id: str) -> bool:
  170. """
  171. Uninstall a plugin.
  172. """
  173. return self._request_with_plugin_daemon_response(
  174. "POST",
  175. f"plugin/{tenant_id}/management/uninstall",
  176. bool,
  177. data={
  178. "plugin_installation_id": plugin_installation_id,
  179. },
  180. headers={"Content-Type": "application/json"},
  181. )
  182. def upgrade_plugin(
  183. self,
  184. tenant_id: str,
  185. original_plugin_unique_identifier: str,
  186. new_plugin_unique_identifier: str,
  187. source: PluginInstallationSource,
  188. meta: dict,
  189. ) -> PluginInstallTaskStartResponse:
  190. """
  191. Upgrade a plugin.
  192. """
  193. return self._request_with_plugin_daemon_response(
  194. "POST",
  195. f"plugin/{tenant_id}/management/install/upgrade",
  196. PluginInstallTaskStartResponse,
  197. data={
  198. "original_plugin_unique_identifier": original_plugin_unique_identifier,
  199. "new_plugin_unique_identifier": new_plugin_unique_identifier,
  200. "source": source,
  201. "meta": meta,
  202. },
  203. headers={"Content-Type": "application/json"},
  204. )