| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 | 
							- import datetime
 - import enum
 - import re
 - from collections.abc import Mapping
 - from typing import Any, Optional
 - 
 - from pydantic import BaseModel, Field, model_validator
 - from werkzeug.exceptions import NotFound
 - 
 - from core.agent.plugin_entities import AgentStrategyProviderEntity
 - from core.model_runtime.entities.provider_entities import ProviderEntity
 - from core.plugin.entities.base import BasePluginEntity
 - from core.plugin.entities.endpoint import EndpointProviderDeclaration
 - from core.tools.entities.common_entities import I18nObject
 - from core.tools.entities.tool_entities import ToolProviderEntity
 - 
 - 
 - class PluginInstallationSource(enum.StrEnum):
 -     Github = "github"
 -     Marketplace = "marketplace"
 -     Package = "package"
 -     Remote = "remote"
 - 
 - 
 - class PluginResourceRequirements(BaseModel):
 -     memory: int
 - 
 -     class Permission(BaseModel):
 -         class Tool(BaseModel):
 -             enabled: Optional[bool] = Field(default=False)
 - 
 -         class Model(BaseModel):
 -             enabled: Optional[bool] = Field(default=False)
 -             llm: Optional[bool] = Field(default=False)
 -             text_embedding: Optional[bool] = Field(default=False)
 -             rerank: Optional[bool] = Field(default=False)
 -             tts: Optional[bool] = Field(default=False)
 -             speech2text: Optional[bool] = Field(default=False)
 -             moderation: Optional[bool] = Field(default=False)
 - 
 -         class Node(BaseModel):
 -             enabled: Optional[bool] = Field(default=False)
 - 
 -         class Endpoint(BaseModel):
 -             enabled: Optional[bool] = Field(default=False)
 - 
 -         class Storage(BaseModel):
 -             enabled: Optional[bool] = Field(default=False)
 -             size: int = Field(ge=1024, le=1073741824, default=1048576)
 - 
 -         tool: Optional[Tool] = Field(default=None)
 -         model: Optional[Model] = Field(default=None)
 -         node: Optional[Node] = Field(default=None)
 -         endpoint: Optional[Endpoint] = Field(default=None)
 -         storage: Optional[Storage] = Field(default=None)
 - 
 -     permission: Optional[Permission] = Field(default=None)
 - 
 - 
 - class PluginCategory(enum.StrEnum):
 -     Tool = "tool"
 -     Model = "model"
 -     Extension = "extension"
 -     AgentStrategy = "agent-strategy"
 - 
 - 
 - class PluginDeclaration(BaseModel):
 -     class Plugins(BaseModel):
 -         tools: Optional[list[str]] = Field(default_factory=list[str])
 -         models: Optional[list[str]] = Field(default_factory=list[str])
 -         endpoints: Optional[list[str]] = Field(default_factory=list[str])
 - 
 -     class Meta(BaseModel):
 -         minimum_dify_version: Optional[str] = Field(default=None, pattern=r"^\d{1,4}(\.\d{1,4}){1,3}(-\w{1,16})?$")
 -         version: Optional[str] = Field(default=None)
 - 
 -     version: str = Field(..., pattern=r"^\d{1,4}(\.\d{1,4}){1,3}(-\w{1,16})?$")
 -     author: Optional[str] = Field(..., pattern=r"^[a-zA-Z0-9_-]{1,64}$")
 -     name: str = Field(..., pattern=r"^[a-z0-9_-]{1,128}$")
 -     description: I18nObject
 -     icon: str
 -     icon_dark: Optional[str] = Field(default=None)
 -     label: I18nObject
 -     category: PluginCategory
 -     created_at: datetime.datetime
 -     resource: PluginResourceRequirements
 -     plugins: Plugins
 -     tags: list[str] = Field(default_factory=list)
 -     repo: Optional[str] = Field(default=None)
 -     verified: bool = Field(default=False)
 -     tool: Optional[ToolProviderEntity] = None
 -     model: Optional[ProviderEntity] = None
 -     endpoint: Optional[EndpointProviderDeclaration] = None
 -     agent_strategy: Optional[AgentStrategyProviderEntity] = None
 -     meta: Meta
 - 
 -     @model_validator(mode="before")
 -     @classmethod
 -     def validate_category(cls, values: dict) -> dict:
 -         # auto detect category
 -         if values.get("tool"):
 -             values["category"] = PluginCategory.Tool
 -         elif values.get("model"):
 -             values["category"] = PluginCategory.Model
 -         elif values.get("agent_strategy"):
 -             values["category"] = PluginCategory.AgentStrategy
 -         else:
 -             values["category"] = PluginCategory.Extension
 -         return values
 - 
 - 
 - class PluginInstallation(BasePluginEntity):
 -     tenant_id: str
 -     endpoints_setups: int
 -     endpoints_active: int
 -     runtime_type: str
 -     source: PluginInstallationSource
 -     meta: Mapping[str, Any]
 -     plugin_id: str
 -     plugin_unique_identifier: str
 -     version: str
 -     checksum: str
 -     declaration: PluginDeclaration
 - 
 - 
 - class PluginEntity(PluginInstallation):
 -     name: str
 -     installation_id: str
 -     version: str
 - 
 -     @model_validator(mode="after")
 -     def set_plugin_id(self):
 -         if self.declaration.tool:
 -             self.declaration.tool.plugin_id = self.plugin_id
 -         return self
 - 
 - 
 - class GenericProviderID:
 -     organization: str
 -     plugin_name: str
 -     provider_name: str
 -     is_hardcoded: bool
 - 
 -     def to_string(self) -> str:
 -         return str(self)
 - 
 -     def __str__(self) -> str:
 -         return f"{self.organization}/{self.plugin_name}/{self.provider_name}"
 - 
 -     def __init__(self, value: str, is_hardcoded: bool = False) -> None:
 -         if not value:
 -             raise NotFound("plugin not found, please add plugin")
 -         # check if the value is a valid plugin id with format: $organization/$plugin_name/$provider_name
 -         if not re.match(r"^[a-z0-9_-]+\/[a-z0-9_-]+\/[a-z0-9_-]+$", value):
 -             # check if matches [a-z0-9_-]+, if yes, append with langgenius/$value/$value
 -             if re.match(r"^[a-z0-9_-]+$", value):
 -                 value = f"langgenius/{value}/{value}"
 -             else:
 -                 raise ValueError(f"Invalid plugin id {value}")
 - 
 -         self.organization, self.plugin_name, self.provider_name = value.split("/")
 -         self.is_hardcoded = is_hardcoded
 - 
 -     def is_langgenius(self) -> bool:
 -         return self.organization == "langgenius"
 - 
 -     @property
 -     def plugin_id(self) -> str:
 -         return f"{self.organization}/{self.plugin_name}"
 - 
 - 
 - class ModelProviderID(GenericProviderID):
 -     def __init__(self, value: str, is_hardcoded: bool = False) -> None:
 -         super().__init__(value, is_hardcoded)
 -         if self.organization == "langgenius" and self.provider_name == "google":
 -             self.plugin_name = "gemini"
 - 
 - 
 - class ToolProviderID(GenericProviderID):
 -     def __init__(self, value: str, is_hardcoded: bool = False) -> None:
 -         super().__init__(value, is_hardcoded)
 -         if self.organization == "langgenius":
 -             if self.provider_name in ["jina", "siliconflow", "stepfun", "gitee_ai"]:
 -                 self.plugin_name = f"{self.provider_name}_tool"
 - 
 - 
 - class PluginDependency(BaseModel):
 -     class Type(enum.StrEnum):
 -         Github = PluginInstallationSource.Github.value
 -         Marketplace = PluginInstallationSource.Marketplace.value
 -         Package = PluginInstallationSource.Package.value
 - 
 -     class Github(BaseModel):
 -         repo: str
 -         version: str
 -         package: str
 -         github_plugin_unique_identifier: str
 - 
 -         @property
 -         def plugin_unique_identifier(self) -> str:
 -             return self.github_plugin_unique_identifier
 - 
 -     class Marketplace(BaseModel):
 -         marketplace_plugin_unique_identifier: str
 - 
 -         @property
 -         def plugin_unique_identifier(self) -> str:
 -             return self.marketplace_plugin_unique_identifier
 - 
 -     class Package(BaseModel):
 -         plugin_unique_identifier: str
 - 
 -     type: Type
 -     value: Github | Marketplace | Package
 -     current_identifier: Optional[str] = None
 - 
 - 
 - class MissingPluginDependency(BaseModel):
 -     plugin_unique_identifier: str
 -     current_identifier: Optional[str] = None
 
 
  |