mirror of
https://github.com/langgenius/dify.git
synced 2025-11-07 15:07:09 +00:00
Signed-off-by: -LAN- <laipz8200@outlook.com> Co-authored-by: twwu <twwu@dify.ai> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: jyong <718720800@qq.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com> Co-authored-by: lyzno1 <yuanyouhuilyz@gmail.com> Co-authored-by: quicksand <quicksandzn@gmail.com> Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com> Co-authored-by: lyzno1 <92089059+lyzno1@users.noreply.github.com> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: Yongtao Huang <yongtaoh2022@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: nite-knite <nkCoding@gmail.com> Co-authored-by: Hanqing Zhao <sherry9277@gmail.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Harry <xh001x@hotmail.com>
138 lines
5.6 KiB
Python
138 lines
5.6 KiB
Python
import re
|
|
|
|
from configs import dify_config
|
|
from core.helper import marketplace
|
|
from core.plugin.entities.plugin import PluginDependency, PluginInstallationSource
|
|
from core.plugin.impl.plugin import PluginInstaller
|
|
from models.provider_ids import ModelProviderID, ToolProviderID
|
|
|
|
# Compile regex pattern for version extraction at module level for better performance
|
|
_VERSION_REGEX = re.compile(r":(?P<version>[0-9]+(?:\.[0-9]+){2}(?:[+-][0-9A-Za-z.-]+)?)(?:@|$)")
|
|
|
|
|
|
class DependenciesAnalysisService:
|
|
@classmethod
|
|
def analyze_tool_dependency(cls, tool_id: str) -> str:
|
|
"""
|
|
Analyze the dependency of a tool.
|
|
|
|
Convert the tool id to the plugin_id
|
|
"""
|
|
try:
|
|
return ToolProviderID(tool_id).plugin_id
|
|
except Exception as e:
|
|
raise e
|
|
|
|
@classmethod
|
|
def analyze_model_provider_dependency(cls, model_provider_id: str) -> str:
|
|
"""
|
|
Analyze the dependency of a model provider.
|
|
|
|
Convert the model provider id to the plugin_id
|
|
"""
|
|
try:
|
|
return ModelProviderID(model_provider_id).plugin_id
|
|
except Exception as e:
|
|
raise e
|
|
|
|
@classmethod
|
|
def get_leaked_dependencies(cls, tenant_id: str, dependencies: list[PluginDependency]) -> list[PluginDependency]:
|
|
"""
|
|
Check dependencies, returns the leaked dependencies in current workspace
|
|
"""
|
|
required_plugin_unique_identifiers = []
|
|
for dependency in dependencies:
|
|
required_plugin_unique_identifiers.append(dependency.value.plugin_unique_identifier)
|
|
|
|
manager = PluginInstaller()
|
|
|
|
# get leaked dependencies
|
|
missing_plugins = manager.fetch_missing_dependencies(tenant_id, required_plugin_unique_identifiers)
|
|
missing_plugin_unique_identifiers = {plugin.plugin_unique_identifier: plugin for plugin in missing_plugins}
|
|
|
|
leaked_dependencies = []
|
|
for dependency in dependencies:
|
|
unique_identifier = dependency.value.plugin_unique_identifier
|
|
if unique_identifier in missing_plugin_unique_identifiers:
|
|
# Extract version for Marketplace dependencies
|
|
if dependency.type == PluginDependency.Type.Marketplace:
|
|
version_match = _VERSION_REGEX.search(unique_identifier)
|
|
if version_match:
|
|
dependency.value.version = version_match.group("version")
|
|
|
|
# Create and append the dependency (same for all types)
|
|
leaked_dependencies.append(
|
|
PluginDependency(
|
|
type=dependency.type,
|
|
value=dependency.value,
|
|
current_identifier=missing_plugin_unique_identifiers[unique_identifier].current_identifier,
|
|
)
|
|
)
|
|
|
|
return leaked_dependencies
|
|
|
|
@classmethod
|
|
def generate_dependencies(cls, tenant_id: str, dependencies: list[str]) -> list[PluginDependency]:
|
|
"""
|
|
Generate dependencies through the list of plugin ids
|
|
"""
|
|
dependencies = list(set(dependencies))
|
|
manager = PluginInstaller()
|
|
plugins = manager.fetch_plugin_installation_by_ids(tenant_id, dependencies)
|
|
result = []
|
|
for plugin in plugins:
|
|
if plugin.source == PluginInstallationSource.Github:
|
|
result.append(
|
|
PluginDependency(
|
|
type=PluginDependency.Type.Github,
|
|
value=PluginDependency.Github(
|
|
repo=plugin.meta["repo"],
|
|
version=plugin.meta["version"],
|
|
package=plugin.meta["package"],
|
|
github_plugin_unique_identifier=plugin.plugin_unique_identifier,
|
|
),
|
|
)
|
|
)
|
|
elif plugin.source == PluginInstallationSource.Marketplace:
|
|
result.append(
|
|
PluginDependency(
|
|
type=PluginDependency.Type.Marketplace,
|
|
value=PluginDependency.Marketplace(
|
|
marketplace_plugin_unique_identifier=plugin.plugin_unique_identifier
|
|
),
|
|
)
|
|
)
|
|
elif plugin.source == PluginInstallationSource.Package:
|
|
result.append(
|
|
PluginDependency(
|
|
type=PluginDependency.Type.Package,
|
|
value=PluginDependency.Package(plugin_unique_identifier=plugin.plugin_unique_identifier),
|
|
)
|
|
)
|
|
elif plugin.source == PluginInstallationSource.Remote:
|
|
raise ValueError(
|
|
f"You used a remote plugin: {plugin.plugin_unique_identifier} in the app, please remove it first"
|
|
" if you want to export the DSL."
|
|
)
|
|
else:
|
|
raise ValueError(f"Unknown plugin source: {plugin.source}")
|
|
|
|
return result
|
|
|
|
@classmethod
|
|
def generate_latest_dependencies(cls, dependencies: list[str]) -> list[PluginDependency]:
|
|
"""
|
|
Generate the latest version of dependencies
|
|
"""
|
|
dependencies = list(set(dependencies))
|
|
if not dify_config.MARKETPLACE_ENABLED:
|
|
return []
|
|
deps = marketplace.batch_fetch_plugin_manifests(dependencies)
|
|
return [
|
|
PluginDependency(
|
|
type=PluginDependency.Type.Marketplace,
|
|
value=PluginDependency.Marketplace(marketplace_plugin_unique_identifier=dep.latest_package_identifier),
|
|
)
|
|
for dep in deps
|
|
]
|