You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

plugin.py 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import datetime
  2. import enum
  3. from collections.abc import Mapping
  4. from typing import Any, Optional
  5. from packaging.version import InvalidVersion, Version
  6. from pydantic import BaseModel, Field, field_validator, model_validator
  7. from core.agent.plugin_entities import AgentStrategyProviderEntity
  8. from core.model_runtime.entities.provider_entities import ProviderEntity
  9. from core.plugin.entities.base import BasePluginEntity
  10. from core.plugin.entities.endpoint import EndpointProviderDeclaration
  11. from core.tools.entities.common_entities import I18nObject
  12. from core.tools.entities.tool_entities import ToolProviderEntity
  13. class PluginInstallationSource(enum.StrEnum):
  14. Github = "github"
  15. Marketplace = "marketplace"
  16. Package = "package"
  17. Remote = "remote"
  18. class PluginResourceRequirements(BaseModel):
  19. memory: int
  20. class Permission(BaseModel):
  21. class Tool(BaseModel):
  22. enabled: Optional[bool] = Field(default=False)
  23. class Model(BaseModel):
  24. enabled: Optional[bool] = Field(default=False)
  25. llm: Optional[bool] = Field(default=False)
  26. text_embedding: Optional[bool] = Field(default=False)
  27. rerank: Optional[bool] = Field(default=False)
  28. tts: Optional[bool] = Field(default=False)
  29. speech2text: Optional[bool] = Field(default=False)
  30. moderation: Optional[bool] = Field(default=False)
  31. class Node(BaseModel):
  32. enabled: Optional[bool] = Field(default=False)
  33. class Endpoint(BaseModel):
  34. enabled: Optional[bool] = Field(default=False)
  35. class Storage(BaseModel):
  36. enabled: Optional[bool] = Field(default=False)
  37. size: int = Field(ge=1024, le=1073741824, default=1048576)
  38. tool: Optional[Tool] = Field(default=None)
  39. model: Optional[Model] = Field(default=None)
  40. node: Optional[Node] = Field(default=None)
  41. endpoint: Optional[Endpoint] = Field(default=None)
  42. storage: Optional[Storage] = Field(default=None)
  43. permission: Optional[Permission] = Field(default=None)
  44. class PluginCategory(enum.StrEnum):
  45. Tool = "tool"
  46. Model = "model"
  47. Extension = "extension"
  48. AgentStrategy = "agent-strategy"
  49. class PluginDeclaration(BaseModel):
  50. class Plugins(BaseModel):
  51. tools: Optional[list[str]] = Field(default_factory=list[str])
  52. models: Optional[list[str]] = Field(default_factory=list[str])
  53. endpoints: Optional[list[str]] = Field(default_factory=list[str])
  54. class Meta(BaseModel):
  55. minimum_dify_version: Optional[str] = Field(default=None)
  56. version: Optional[str] = Field(default=None)
  57. @field_validator("minimum_dify_version")
  58. @classmethod
  59. def validate_minimum_dify_version(cls, v: Optional[str]) -> Optional[str]:
  60. if v is None:
  61. return v
  62. try:
  63. Version(v)
  64. return v
  65. except InvalidVersion as e:
  66. raise ValueError(f"Invalid version format: {v}") from e
  67. version: str = Field(...)
  68. author: Optional[str] = Field(..., pattern=r"^[a-zA-Z0-9_-]{1,64}$")
  69. name: str = Field(..., pattern=r"^[a-z0-9_-]{1,128}$")
  70. description: I18nObject
  71. icon: str
  72. icon_dark: Optional[str] = Field(default=None)
  73. label: I18nObject
  74. category: PluginCategory
  75. created_at: datetime.datetime
  76. resource: PluginResourceRequirements
  77. plugins: Plugins
  78. tags: list[str] = Field(default_factory=list)
  79. repo: Optional[str] = Field(default=None)
  80. verified: bool = Field(default=False)
  81. tool: Optional[ToolProviderEntity] = None
  82. model: Optional[ProviderEntity] = None
  83. endpoint: Optional[EndpointProviderDeclaration] = None
  84. agent_strategy: Optional[AgentStrategyProviderEntity] = None
  85. meta: Meta
  86. @field_validator("version")
  87. @classmethod
  88. def validate_version(cls, v: str) -> str:
  89. try:
  90. Version(v)
  91. return v
  92. except InvalidVersion as e:
  93. raise ValueError(f"Invalid version format: {v}") from e
  94. @model_validator(mode="before")
  95. @classmethod
  96. def validate_category(cls, values: dict):
  97. # auto detect category
  98. if values.get("tool"):
  99. values["category"] = PluginCategory.Tool
  100. elif values.get("model"):
  101. values["category"] = PluginCategory.Model
  102. elif values.get("agent_strategy"):
  103. values["category"] = PluginCategory.AgentStrategy
  104. else:
  105. values["category"] = PluginCategory.Extension
  106. return values
  107. class PluginInstallation(BasePluginEntity):
  108. tenant_id: str
  109. endpoints_setups: int
  110. endpoints_active: int
  111. runtime_type: str
  112. source: PluginInstallationSource
  113. meta: Mapping[str, Any]
  114. plugin_id: str
  115. plugin_unique_identifier: str
  116. version: str
  117. checksum: str
  118. declaration: PluginDeclaration
  119. class PluginEntity(PluginInstallation):
  120. name: str
  121. installation_id: str
  122. version: str
  123. @model_validator(mode="after")
  124. def set_plugin_id(self):
  125. if self.declaration.tool:
  126. self.declaration.tool.plugin_id = self.plugin_id
  127. return self
  128. class PluginDependency(BaseModel):
  129. class Type(enum.StrEnum):
  130. Github = PluginInstallationSource.Github.value
  131. Marketplace = PluginInstallationSource.Marketplace.value
  132. Package = PluginInstallationSource.Package.value
  133. class Github(BaseModel):
  134. repo: str
  135. version: str
  136. package: str
  137. github_plugin_unique_identifier: str
  138. @property
  139. def plugin_unique_identifier(self) -> str:
  140. return self.github_plugin_unique_identifier
  141. class Marketplace(BaseModel):
  142. marketplace_plugin_unique_identifier: str
  143. @property
  144. def plugin_unique_identifier(self) -> str:
  145. return self.marketplace_plugin_unique_identifier
  146. class Package(BaseModel):
  147. plugin_unique_identifier: str
  148. type: Type
  149. value: Github | Marketplace | Package
  150. current_identifier: Optional[str] = None
  151. class MissingPluginDependency(BaseModel):
  152. plugin_unique_identifier: str
  153. current_identifier: Optional[str] = None