mirror of
https://github.com/langgenius/dify.git
synced 2026-08-29 02:16:23 +08:00
Signed-off-by: kenwoodjw <blackxin55+@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: 起岚 <155608604+xiaoyaoqilan@users.noreply.github.com> Co-authored-by: Parman Mohammadalizadeh <prmma23@gmail.com> Co-authored-by: Escape0707 <tothesong@gmail.com> Co-authored-by: Xin Zhang <zhangxin@dify.ai> Co-authored-by: iridescentWen <66297467+iridescentWen@users.noreply.github.com> Co-authored-by: Bond Zhu <37842169+MRZHUH@users.noreply.github.com> Co-authored-by: KVOJJJin <jzongcode@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: Chester <superdiao6@gmail.com> Co-authored-by: WH-2099 <wh2099@pm.me> Co-authored-by: Jony <619963502@qq.com> Co-authored-by: Jony <13896935+zyz619963502zyz@users.noreply.github.com> Co-authored-by: Harsh Kashyap <harsh.kashyap2001@gmail.com> Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com> Co-authored-by: kenwoodjw <blackxin55+@gmail.com> Co-authored-by: csurong <csurong1@gmail.com> Co-authored-by: caosurong <surong.cao@thinkingdata.cn> Co-authored-by: Taranum Wasu <81034301+Taranum01@users.noreply.github.com> Co-authored-by: Taranum01 <50813317+Taranum01@users.noreply.github.com> Co-authored-by: Pranav Agarwal <agarwalpranav0711@gmail.com> Co-authored-by: Stephen Zhou <hi@hyoban.cc> Co-authored-by: zl86790 <marshal_li_b@163.com> Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com> Co-authored-by: yunlu.wen <yunlu.wen@dify.ai> Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
200 lines
7.8 KiB
Python
200 lines
7.8 KiB
Python
"""Workspace-level Skill Management models.
|
|
|
|
These tables are the source of truth for reusable workspace Skills. Agent Soul
|
|
``config_skills`` and Agent Drive skill rows remain per-agent runtime/config
|
|
assets; they may consume a published Skill snapshot but do not own the Skill's
|
|
draft, metadata, version history, or Agent binding priority.
|
|
"""
|
|
|
|
from enum import StrEnum
|
|
|
|
import sqlalchemy as sa
|
|
from pydantic import BaseModel, ConfigDict
|
|
from sqlalchemy import Index, UniqueConstraint
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from models.base import Base, DefaultFieldsMixin
|
|
from models.types import EnumText, JSONModelColumn, LongText, StringUUID
|
|
|
|
|
|
class SkillFileKind(StrEnum):
|
|
"""Draft file entry kind."""
|
|
|
|
FILE = "file"
|
|
DIRECTORY = "directory"
|
|
|
|
|
|
class SkillFileStorage(StrEnum):
|
|
"""How a draft file's content is stored."""
|
|
|
|
TEXT = "text"
|
|
TOOL_FILE = "tool_file"
|
|
|
|
|
|
class SkillVersionManifestFile(BaseModel):
|
|
"""One file entry captured in a published Skill snapshot manifest."""
|
|
|
|
path: str
|
|
mime_type: str | None = None
|
|
size: int
|
|
hash: str
|
|
|
|
model_config = ConfigDict(extra="forbid")
|
|
|
|
|
|
class SkillVersionManifest(BaseModel):
|
|
"""Published Skill snapshot file index."""
|
|
|
|
files: list[SkillVersionManifestFile]
|
|
name: str | None = None
|
|
display_name: str | None = None
|
|
description: str | None = None
|
|
|
|
model_config = ConfigDict(extra="forbid")
|
|
|
|
|
|
class Skill(DefaultFieldsMixin, Base):
|
|
"""Workspace-level reusable Skill metadata and draft status."""
|
|
|
|
__tablename__ = "skills"
|
|
__table_args__ = (
|
|
sa.PrimaryKeyConstraint("id", name="skill_pkey"),
|
|
UniqueConstraint("tenant_id", "name", name="skill_tenant_name_unique"),
|
|
Index("skills_tenant_updated_at_idx", "tenant_id", "updated_at"),
|
|
)
|
|
|
|
tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
name: Mapped[str] = mapped_column(sa.String(64), nullable=False)
|
|
display_name: Mapped[str] = mapped_column(sa.String(128), nullable=False)
|
|
icon: Mapped[str] = mapped_column(sa.String(16), nullable=False, default="📄", server_default="📄")
|
|
description: Mapped[str] = mapped_column(sa.String(1024), nullable=False, default="", server_default="")
|
|
name_manually_edited: Mapped[bool] = mapped_column(
|
|
sa.Boolean,
|
|
nullable=False,
|
|
default=False,
|
|
server_default=sa.false(),
|
|
)
|
|
visibility: Mapped[str] = mapped_column(
|
|
sa.String(32),
|
|
nullable=False,
|
|
default="workspace",
|
|
server_default="workspace",
|
|
)
|
|
latest_published_version_id: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
|
created_by: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
|
updated_by: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
|
|
|
|
|
class SkillDraftFile(DefaultFieldsMixin, Base):
|
|
"""One draft file or directory in a workspace Skill."""
|
|
|
|
__tablename__ = "skill_draft_files"
|
|
__table_args__ = (
|
|
sa.PrimaryKeyConstraint("id", name="skill_draft_file_pkey"),
|
|
UniqueConstraint("skill_id", "path", name="skill_draft_file_skill_path_unique"),
|
|
Index("skill_draft_files_skill_path_idx", "skill_id", "path"),
|
|
)
|
|
|
|
skill_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
path: Mapped[str] = mapped_column(sa.String(512), nullable=False)
|
|
kind: Mapped[SkillFileKind] = mapped_column(EnumText(SkillFileKind, length=32), nullable=False)
|
|
storage: Mapped[SkillFileStorage | None] = mapped_column(EnumText(SkillFileStorage, length=32), nullable=True)
|
|
mime_type: Mapped[str | None] = mapped_column(sa.String(255), nullable=True)
|
|
content_text: Mapped[str | None] = mapped_column(LongText, nullable=True)
|
|
tool_file_id: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
|
size: Mapped[int | None] = mapped_column(sa.BigInteger, nullable=True)
|
|
hash: Mapped[str | None] = mapped_column(sa.String(255), nullable=True)
|
|
|
|
|
|
class SkillVersion(DefaultFieldsMixin, Base):
|
|
"""Immutable published Skill snapshot.
|
|
|
|
``hash_code`` uniquely identifies a published version for downstream
|
|
execution audit. It includes Skill identity, version number, and archive
|
|
content digest instead of being only the archive content hash.
|
|
"""
|
|
|
|
__tablename__ = "skill_versions"
|
|
__table_args__ = (
|
|
sa.PrimaryKeyConstraint("id", name="skill_version_pkey"),
|
|
UniqueConstraint("skill_id", "version_number", name="skill_version_skill_number_unique"),
|
|
Index("skill_versions_skill_created_at_idx", "skill_id", "created_at"),
|
|
)
|
|
|
|
skill_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
version_number: Mapped[int] = mapped_column(sa.Integer, nullable=False)
|
|
version_name: Mapped[str] = mapped_column(sa.String(128), nullable=False, default="", server_default="")
|
|
publish_note: Mapped[str] = mapped_column(sa.String(1024), nullable=False, default="", server_default="")
|
|
manifest: Mapped[SkillVersionManifest] = mapped_column(JSONModelColumn(SkillVersionManifest), nullable=False)
|
|
archive_tool_file_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
hash_code: Mapped[str] = mapped_column(sa.String(255), nullable=False)
|
|
archive_size: Mapped[int] = mapped_column(sa.BigInteger, nullable=False)
|
|
published_by: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
|
|
|
|
|
class AgentSkillBinding(DefaultFieldsMixin, Base):
|
|
"""Direct Agent-to-workspace-Skill binding.
|
|
|
|
``priority`` is retained as an internal ordering column for the current
|
|
schema constraints. Runtime Skill selection is Agent-driven and must not
|
|
treat it as a matching priority.
|
|
"""
|
|
|
|
__tablename__ = "agent_skill_bindings"
|
|
__table_args__ = (
|
|
sa.PrimaryKeyConstraint("id", name="agent_skill_binding_pkey"),
|
|
UniqueConstraint("tenant_id", "agent_id", "skill_id", name="agent_skill_binding_unique"),
|
|
UniqueConstraint("tenant_id", "agent_id", "priority", name="agent_skill_binding_priority_unique"),
|
|
Index("agent_skill_bindings_skill_idx", "tenant_id", "skill_id"),
|
|
)
|
|
|
|
tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
agent_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
skill_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
priority: Mapped[int] = mapped_column(sa.Integer, nullable=False)
|
|
created_by: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
|
|
|
|
|
class AgentSkillBindingSnapshot(DefaultFieldsMixin, Base):
|
|
"""Published Agent-to-workspace-Skill bindings for one Agent snapshot."""
|
|
|
|
__tablename__ = "agent_skill_binding_snapshots"
|
|
__table_args__ = (
|
|
sa.PrimaryKeyConstraint("id", name="agent_skill_binding_snapshot_pkey"),
|
|
UniqueConstraint(
|
|
"tenant_id",
|
|
"agent_id",
|
|
"config_snapshot_id",
|
|
"skill_id",
|
|
name="agent_skill_binding_snapshot_skill_unique",
|
|
),
|
|
UniqueConstraint(
|
|
"tenant_id",
|
|
"agent_id",
|
|
"config_snapshot_id",
|
|
"priority",
|
|
name="agent_skill_binding_snapshot_priority_unique",
|
|
),
|
|
Index("agent_skill_binding_snapshots_agent_snapshot_idx", "tenant_id", "agent_id", "config_snapshot_id"),
|
|
)
|
|
|
|
tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
agent_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
config_snapshot_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
skill_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
priority: Mapped[int] = mapped_column(sa.Integer, nullable=False)
|
|
created_by: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
|
|
|
|
|
__all__ = [
|
|
"AgentSkillBinding",
|
|
"AgentSkillBindingSnapshot",
|
|
"Skill",
|
|
"SkillDraftFile",
|
|
"SkillFileKind",
|
|
"SkillFileStorage",
|
|
"SkillVersion",
|
|
"SkillVersionManifest",
|
|
"SkillVersionManifestFile",
|
|
]
|