mirror of
https://github.com/langgenius/dify.git
synced 2026-11-11 22:02:23 +08:00
Add revision-scoped stable saved-model inventory and source plugin admission. Preserve independent and BYOK owners, frozen contracts, actual schema RPC boundaries and non-secret source protocol facts.
220 lines
8.9 KiB
Python
220 lines
8.9 KiB
Python
"""Legacy daemon mechanics behind the admitted plugin installation use case.
|
|
|
|
These five operations preserve existing download, signature/source-policy and
|
|
cache invalidation behavior. Application admission runs before this adapter;
|
|
there is deliberately no Kernel-to-application composition-root backedge.
|
|
"""
|
|
|
|
from collections.abc import Sequence
|
|
|
|
from configs import dify_config
|
|
from core.helper import marketplace
|
|
from core.helper.marketplace import download_plugin_pkg
|
|
from core.plugin.entities.plugin import PluginInstallationSource
|
|
from core.plugin.entities.plugin_daemon import PluginInstallTaskStartResponse
|
|
from core.plugin.impl.plugin import PluginInstaller
|
|
from core.plugin.plugin_service import PluginService
|
|
from services.plugin.installation_service import PluginInstallationOperation, PluginInstallationResult
|
|
|
|
|
|
def _result(value: PluginInstallTaskStartResponse) -> PluginInstallationResult:
|
|
return PluginInstallationResult(
|
|
all_installed=value.all_installed,
|
|
task_id=value.task_id,
|
|
task=value.task.model_dump(mode="json") if value.task is not None else None,
|
|
)
|
|
|
|
|
|
class LegacyPluginInstallationGateway:
|
|
@staticmethod
|
|
def assert_available(
|
|
operation: PluginInstallationOperation, original_uid: str | None, candidate_uid: str | None
|
|
) -> None:
|
|
if operation in {"marketplace", "upgrade_marketplace"}:
|
|
if not dify_config.MARKETPLACE_ENABLED:
|
|
raise ValueError("marketplace is not enabled")
|
|
if operation == "upgrade_marketplace" and original_uid == candidate_uid:
|
|
raise ValueError("you should not upgrade plugin with the same plugin")
|
|
PluginService._get_plugin_installation_permission()
|
|
else:
|
|
PluginService._check_marketplace_only_permission()
|
|
|
|
@staticmethod
|
|
def upgrade_plugin_with_marketplace(
|
|
tenant_id: str, original_plugin_unique_identifier: str, new_plugin_unique_identifier: str
|
|
) -> PluginInstallationResult:
|
|
"""
|
|
Upgrade plugin with marketplace
|
|
"""
|
|
if not dify_config.MARKETPLACE_ENABLED:
|
|
raise ValueError("marketplace is not enabled")
|
|
|
|
if original_plugin_unique_identifier == new_plugin_unique_identifier:
|
|
raise ValueError("you should not upgrade plugin with the same plugin")
|
|
|
|
# check if plugin pkg is already downloaded
|
|
manager = PluginInstaller()
|
|
|
|
permission = PluginService._get_plugin_installation_permission()
|
|
|
|
try:
|
|
manager.fetch_plugin_manifest(tenant_id, new_plugin_unique_identifier)
|
|
except Exception:
|
|
# plugin not downloaded yet, download and upload pkg
|
|
pkg = download_plugin_pkg(new_plugin_unique_identifier)
|
|
response = manager.upload_pkg(
|
|
tenant_id,
|
|
pkg,
|
|
verify_signature=permission.restrict_to_marketplace_only,
|
|
)
|
|
|
|
# check if the plugin is available to install
|
|
PluginService._check_plugin_installation_scope(response.verification)
|
|
else:
|
|
# already downloaded, the cached pkg still has to satisfy the installation scope
|
|
decode_response = manager.decode_plugin_from_identifier(tenant_id, new_plugin_unique_identifier)
|
|
PluginService._check_plugin_installation_scope(decode_response.verification)
|
|
marketplace.record_install_plugin_event(new_plugin_unique_identifier)
|
|
|
|
result = manager.upgrade_plugin(
|
|
tenant_id,
|
|
original_plugin_unique_identifier,
|
|
new_plugin_unique_identifier,
|
|
PluginInstallationSource.Marketplace,
|
|
{
|
|
"plugin_unique_identifier": new_plugin_unique_identifier,
|
|
},
|
|
)
|
|
PluginService.invalidate_plugin_model_providers_cache(tenant_id)
|
|
return _result(result)
|
|
|
|
@staticmethod
|
|
def upgrade_plugin_with_github(
|
|
tenant_id: str,
|
|
original_plugin_unique_identifier: str,
|
|
new_plugin_unique_identifier: str,
|
|
repo: str,
|
|
version: str,
|
|
package: str,
|
|
) -> PluginInstallationResult:
|
|
"""
|
|
Upgrade plugin with github
|
|
"""
|
|
PluginService._check_marketplace_only_permission()
|
|
manager = PluginInstaller()
|
|
result = manager.upgrade_plugin(
|
|
tenant_id,
|
|
original_plugin_unique_identifier,
|
|
new_plugin_unique_identifier,
|
|
PluginInstallationSource.Github,
|
|
{
|
|
"repo": repo,
|
|
"version": version,
|
|
"package": package,
|
|
},
|
|
)
|
|
PluginService.invalidate_plugin_model_providers_cache(tenant_id)
|
|
return _result(result)
|
|
|
|
@staticmethod
|
|
def install_from_local_pkg(tenant_id: str, plugin_unique_identifiers: Sequence[str]) -> PluginInstallationResult:
|
|
PluginService._check_marketplace_only_permission()
|
|
|
|
manager = PluginInstaller()
|
|
|
|
for plugin_unique_identifier in plugin_unique_identifiers:
|
|
resp = manager.decode_plugin_from_identifier(tenant_id, plugin_unique_identifier)
|
|
PluginService._check_plugin_installation_scope(resp.verification)
|
|
|
|
result = manager.install_from_identifiers(
|
|
tenant_id,
|
|
plugin_unique_identifiers,
|
|
PluginInstallationSource.Package,
|
|
[
|
|
{"plugin_unique_identifier": plugin_unique_identifier}
|
|
for plugin_unique_identifier in plugin_unique_identifiers
|
|
],
|
|
)
|
|
PluginService.invalidate_plugin_model_providers_cache(tenant_id)
|
|
return _result(result)
|
|
|
|
@staticmethod
|
|
def install_from_github(
|
|
tenant_id: str, plugin_unique_identifier: str, repo: str, version: str, package: str
|
|
) -> PluginInstallationResult:
|
|
"""
|
|
Install plugin from github release package files,
|
|
returns plugin_unique_identifier
|
|
"""
|
|
PluginService._check_marketplace_only_permission()
|
|
|
|
manager = PluginInstaller()
|
|
plugin_decode_response = manager.decode_plugin_from_identifier(tenant_id, plugin_unique_identifier)
|
|
PluginService._check_plugin_installation_scope(plugin_decode_response.verification)
|
|
|
|
result = manager.install_from_identifiers(
|
|
tenant_id,
|
|
[plugin_unique_identifier],
|
|
PluginInstallationSource.Github,
|
|
[
|
|
{
|
|
"repo": repo,
|
|
"version": version,
|
|
"package": package,
|
|
}
|
|
],
|
|
)
|
|
PluginService.invalidate_plugin_model_providers_cache(tenant_id)
|
|
return _result(result)
|
|
|
|
@staticmethod
|
|
def install_from_marketplace_pkg(
|
|
tenant_id: str, plugin_unique_identifiers: Sequence[str]
|
|
) -> PluginInstallationResult:
|
|
"""
|
|
Install plugin from marketplace package files,
|
|
returns installation task id
|
|
"""
|
|
if not dify_config.MARKETPLACE_ENABLED:
|
|
raise ValueError("marketplace is not enabled")
|
|
|
|
manager = PluginInstaller()
|
|
|
|
# collect actual plugin_unique_identifiers
|
|
actual_plugin_unique_identifiers = []
|
|
metas = []
|
|
permission = PluginService._get_plugin_installation_permission()
|
|
|
|
# check if already downloaded
|
|
for plugin_unique_identifier in plugin_unique_identifiers:
|
|
try:
|
|
manager.fetch_plugin_manifest(tenant_id, plugin_unique_identifier)
|
|
except Exception:
|
|
# plugin not downloaded yet, download and upload pkg
|
|
pkg = download_plugin_pkg(plugin_unique_identifier)
|
|
response = manager.upload_pkg(
|
|
tenant_id,
|
|
pkg,
|
|
verify_signature=permission.restrict_to_marketplace_only,
|
|
)
|
|
# check if the plugin is available to install
|
|
PluginService._check_plugin_installation_scope(response.verification)
|
|
# use response plugin_unique_identifier
|
|
actual_plugin_unique_identifiers.append(response.unique_identifier)
|
|
metas.append({"plugin_unique_identifier": response.unique_identifier})
|
|
else:
|
|
# already downloaded, the cached pkg still has to satisfy the installation scope
|
|
plugin_decode_response = manager.decode_plugin_from_identifier(tenant_id, plugin_unique_identifier)
|
|
PluginService._check_plugin_installation_scope(plugin_decode_response.verification)
|
|
actual_plugin_unique_identifiers.append(plugin_unique_identifier)
|
|
metas.append({"plugin_unique_identifier": plugin_unique_identifier})
|
|
|
|
result = manager.install_from_identifiers(
|
|
tenant_id,
|
|
actual_plugin_unique_identifiers,
|
|
PluginInstallationSource.Marketplace,
|
|
metas,
|
|
)
|
|
PluginService.invalidate_plugin_model_providers_cache(tenant_id)
|
|
return _result(result)
|