refactor: plugin installation

This commit is contained in:
Yeuoly
2024-10-14 17:52:29 +08:00
parent 8e1cf3233c
commit 276701e1b7
5 changed files with 277 additions and 128 deletions

View File

@ -6,9 +6,10 @@ from pydantic import BaseModel, ConfigDict, Field
from core.model_runtime.entities.model_entities import AIModelEntity
from core.model_runtime.entities.provider_entities import ProviderEntity
from core.plugin.entities.base import BasePluginEntity
from core.tools.entities.tool_entities import ToolProviderEntityWithPlugin
T = TypeVar("T", bound=(BaseModel | dict | list | bool))
T = TypeVar("T", bound=(BaseModel | dict | list | bool | str))
class PluginDaemonBasicResponse(BaseModel, Generic[T]):
@ -106,3 +107,24 @@ class PluginDaemonInnerError(Exception):
def __init__(self, code: int, message: str):
self.code = code
self.message = message
class PluginInstallTaskStatus(str, Enum):
Pending = "pending"
Running = "running"
Success = "success"
Failed = "failed"
class PluginInstallTaskPluginStatus(BaseModel):
plugin_unique_identifier: str = Field(description="The plugin unique identifier of the install task.")
plugin_id: str = Field(description="The plugin ID of the install task.")
status: PluginInstallTaskStatus = Field(description="The status of the install task.")
message: str = Field(description="The message of the install task.")
class PluginInstallTask(BasePluginEntity):
status: PluginInstallTaskStatus = Field(description="The status of the install task.")
total_plugins: int = Field(description="The total number of plugins to be installed.")
completed_plugins: int = Field(description="The number of plugins that have been installed.")
plugins: list[PluginInstallTaskPluginStatus] = Field(description="The status of the plugins.")

View File

@ -19,7 +19,7 @@ from core.plugin.entities.plugin_daemon import PluginDaemonBasicResponse, Plugin
plugin_daemon_inner_api_baseurl = dify_config.PLUGIN_API_URL
plugin_daemon_inner_api_key = dify_config.PLUGIN_API_KEY
T = TypeVar("T", bound=(BaseModel | dict | list | bool))
T = TypeVar("T", bound=(BaseModel | dict | list | bool | str))
class BasePluginManager:

View File

@ -1,16 +1,16 @@
import json
from collections.abc import Generator, Mapping
from typing import Any
from collections.abc import Sequence
from core.plugin.entities.plugin import PluginEntity, PluginInstallationSource
from core.plugin.entities.plugin_daemon import InstallPluginMessage
from core.plugin.entities.plugin import PluginDeclaration, PluginEntity, PluginInstallationSource
from core.plugin.entities.plugin_daemon import PluginInstallTask
from core.plugin.manager.base import BasePluginManager
class PluginInstallationManager(BasePluginManager):
def fetch_plugin_by_identifier(self, tenant_id: str, identifier: str) -> bool:
# urlencode the identifier
def fetch_plugin_by_identifier(
self,
tenant_id: str,
identifier: str,
) -> bool:
return self._request_with_plugin_daemon_response(
"GET",
f"plugin/{tenant_id}/management/fetch/identifier",
@ -26,37 +26,34 @@ class PluginInstallationManager(BasePluginManager):
params={"page": 1, "page_size": 256},
)
def install_from_pkg(
def upload_pkg(
self,
tenant_id: str,
pkg: bytes,
source: PluginInstallationSource,
meta: Mapping[str, Any],
verify_signature: bool = False,
) -> Generator[InstallPluginMessage, None, None]:
) -> str:
"""
Install a plugin from a package.
Upload a plugin package and return the plugin unique identifier.
"""
# using multipart/form-data to encode body
body = {
"dify_pkg": ("dify_pkg", pkg, "application/octet-stream"),
}
data = {
"verify_signature": "true" if verify_signature else "false",
"source": source.value,
"meta": json.dumps(meta),
}
return self._request_with_plugin_daemon_response_stream(
return self._request_with_plugin_daemon_response(
"POST",
f"plugin/{tenant_id}/management/install/pkg",
InstallPluginMessage,
f"plugin/{tenant_id}/management/install/upload",
str,
files=body,
data=data,
)
def install_from_identifier(self, tenant_id: str, identifier: str) -> bool:
def install_from_identifiers(
self, tenant_id: str, identifiers: Sequence[str], source: PluginInstallationSource, meta: dict
) -> str:
"""
Install a plugin from an identifier.
"""
@ -64,13 +61,45 @@ class PluginInstallationManager(BasePluginManager):
return self._request_with_plugin_daemon_response(
"POST",
f"plugin/{tenant_id}/management/install/identifier",
bool,
str,
data={
"plugin_unique_identifier": identifier,
"plugin_unique_identifiers": identifiers,
"source": source,
"meta": meta,
},
headers={"Content-Type": "application/json"},
)
def fetch_plugin_installation_tasks(self, tenant_id: str) -> Sequence[PluginInstallTask]:
"""
Fetch plugin installation tasks.
"""
return self._request_with_plugin_daemon_response(
"GET",
f"plugin/{tenant_id}/management/install/tasks",
list[PluginInstallTask],
)
def fetch_plugin_installation_task(self, tenant_id: str, task_id: str) -> PluginInstallTask:
"""
Fetch a plugin installation task.
"""
return self._request_with_plugin_daemon_response(
"GET",
f"plugin/{tenant_id}/management/install/tasks/{task_id}",
PluginInstallTask,
)
def fetch_plugin_manifest(self, tenant_id: str, plugin_unique_identifier: str) -> PluginDeclaration:
"""
Fetch a plugin manifest.
"""
return self._request_with_plugin_daemon_response(
"GET",
f"plugin/{tenant_id}/management/fetch/identifier",
PluginDeclaration,
)
def uninstall(self, tenant_id: str, plugin_installation_id: str) -> bool:
"""
Uninstall a plugin.