plugin.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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_plugin_installation_task_item(self, tenant_id: str, task_id: str, identifier: str) -> bool:
  116. """
  117. Delete a plugin installation task item.
  118. """
  119. return self._request_with_plugin_daemon_response(
  120. "POST",
  121. f"plugin/{tenant_id}/management/install/tasks/{task_id}/delete/{identifier}",
  122. bool,
  123. )
  124. def fetch_plugin_manifest(self, tenant_id: str, plugin_unique_identifier: str) -> PluginDeclaration:
  125. """
  126. Fetch a plugin manifest.
  127. """
  128. class PluginDeclarationResponse(BaseModel):
  129. declaration: PluginDeclaration
  130. return self._request_with_plugin_daemon_response(
  131. "GET",
  132. f"plugin/{tenant_id}/management/fetch/manifest",
  133. PluginDeclarationResponse,
  134. params={"plugin_unique_identifier": plugin_unique_identifier},
  135. ).declaration
  136. def fetch_plugin_installation_by_ids(
  137. self, tenant_id: str, plugin_ids: Sequence[str]
  138. ) -> Sequence[PluginInstallation]:
  139. """
  140. Fetch plugin installations by ids.
  141. """
  142. return self._request_with_plugin_daemon_response(
  143. "POST",
  144. f"plugin/{tenant_id}/management/installation/fetch/batch",
  145. list[PluginInstallation],
  146. data={"plugin_ids": plugin_ids},
  147. headers={"Content-Type": "application/json"},
  148. )
  149. def fetch_missing_dependencies(self, tenant_id: str, plugin_unique_identifiers: list[str]) -> list[str]:
  150. """
  151. Fetch missing dependencies
  152. """
  153. return self._request_with_plugin_daemon_response(
  154. "POST",
  155. f"plugin/{tenant_id}/management/installation/missing",
  156. list[str],
  157. data={"plugin_unique_identifiers": plugin_unique_identifiers},
  158. headers={"Content-Type": "application/json"},
  159. )
  160. def uninstall(self, tenant_id: str, plugin_installation_id: str) -> bool:
  161. """
  162. Uninstall a plugin.
  163. """
  164. return self._request_with_plugin_daemon_response(
  165. "POST",
  166. f"plugin/{tenant_id}/management/uninstall",
  167. bool,
  168. data={
  169. "plugin_installation_id": plugin_installation_id,
  170. },
  171. headers={"Content-Type": "application/json"},
  172. )
  173. def upgrade_plugin(
  174. self,
  175. tenant_id: str,
  176. original_plugin_unique_identifier: str,
  177. new_plugin_unique_identifier: str,
  178. source: PluginInstallationSource,
  179. meta: dict,
  180. ) -> PluginInstallTaskStartResponse:
  181. """
  182. Upgrade a plugin.
  183. """
  184. return self._request_with_plugin_daemon_response(
  185. "POST",
  186. f"plugin/{tenant_id}/management/install/upgrade",
  187. PluginInstallTaskStartResponse,
  188. data={
  189. "original_plugin_unique_identifier": original_plugin_unique_identifier,
  190. "new_plugin_unique_identifier": new_plugin_unique_identifier,
  191. "source": source,
  192. "meta": meta,
  193. },
  194. headers={"Content-Type": "application/json"},
  195. )