mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 08:57:28 +08:00
Resolve the full dependency chain to enable all previously disabled controllers: Enabled routes: - sandbox_files: sandbox file browser API - sandbox_providers: sandbox provider management API - app_asset: app asset management API - skills: skill extraction API - CLI API blueprint: DifyCli callback endpoints (/cli/api/*) Dependencies extracted (64 files, ~8000 lines): - models/sandbox.py, models/app_asset.py: DB models - core/zip_sandbox/: zip-based sandbox execution - core/session/: CLI API session management - core/memory/: base memory + node token buffer - core/helper/creators.py: helper utilities - core/llm_generator/: context models, output models, utils - core/workflow/nodes/command/: command node type - core/workflow/nodes/file_upload/: file upload node type - core/app/entities/: app_asset_entities, app_bundle_entities, llm_generation_entities - services/: asset_content, skill, workflow_collaboration, workflow_comment - controllers/console/app/error.py: AppAsset error classes - core/tools/utils/system_encryption.py Import fixes: - dify_graph.enums -> graphon.enums in skill_service.py - get_signed_file_url_for_plugin -> get_signed_file_url in cli_api.py All 5 controllers verified: import OK, Flask starts successfully. 46 existing tests still pass. Made-with: Cursor
90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
from datetime import datetime
|
|
from uuid import uuid4
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy import DateTime, Integer, String, func
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from core.app.entities.app_asset_entities import AppAssetFileTree
|
|
|
|
from .base import Base
|
|
from .types import LongText, StringUUID
|
|
|
|
|
|
class AppAssets(Base):
|
|
__tablename__ = "app_assets"
|
|
__table_args__ = (
|
|
sa.PrimaryKeyConstraint("id", name="app_assets_pkey"),
|
|
sa.Index("app_assets_version_idx", "tenant_id", "app_id", "version"),
|
|
)
|
|
|
|
VERSION_DRAFT = "draft"
|
|
VERSION_PUBLISHED = "published"
|
|
|
|
id: Mapped[str] = mapped_column(StringUUID, default=lambda: str(uuid4()))
|
|
tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
app_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
version: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
_asset_tree: Mapped[str] = mapped_column("asset_tree", LongText, nullable=False, default='{"nodes":[]}')
|
|
created_by: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, server_default=func.current_timestamp())
|
|
updated_by: Mapped[str | None] = mapped_column(StringUUID)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime,
|
|
nullable=False,
|
|
default=func.current_timestamp(),
|
|
server_default=func.current_timestamp(),
|
|
onupdate=func.current_timestamp(),
|
|
)
|
|
|
|
@property
|
|
def asset_tree(self) -> AppAssetFileTree:
|
|
if not self._asset_tree:
|
|
return AppAssetFileTree()
|
|
return AppAssetFileTree.model_validate_json(self._asset_tree)
|
|
|
|
@asset_tree.setter
|
|
def asset_tree(self, value: AppAssetFileTree) -> None:
|
|
self._asset_tree = value.model_dump_json()
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<AppAssets(id={self.id}, app_id={self.app_id}, version={self.version})>"
|
|
|
|
|
|
class AppAssetContent(Base):
|
|
"""Inline content cache for app asset draft files.
|
|
|
|
Acts as a read-through cache for S3: text-like asset content is dual-written
|
|
here on save and read from DB first (falling back to S3 on miss with sync backfill).
|
|
Keyed by (tenant_id, app_id, node_id) — stores only the current draft content,
|
|
not published snapshots.
|
|
|
|
See core/app_assets/content_accessor.py for the accessor abstraction that
|
|
manages the DB/S3 read-through and dual-write logic.
|
|
"""
|
|
|
|
__tablename__ = "app_asset_contents"
|
|
__table_args__ = (
|
|
sa.PrimaryKeyConstraint("id", name="app_asset_contents_pkey"),
|
|
sa.UniqueConstraint("tenant_id", "app_id", "node_id", name="uq_asset_content_node"),
|
|
sa.Index("idx_asset_content_app", "tenant_id", "app_id"),
|
|
)
|
|
|
|
id: Mapped[str] = mapped_column(StringUUID, default=lambda: str(uuid4()))
|
|
tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
app_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
node_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
|
content: Mapped[str] = mapped_column(LongText, nullable=False, default="")
|
|
size: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, server_default=func.current_timestamp())
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime,
|
|
nullable=False,
|
|
default=func.current_timestamp(),
|
|
server_default=func.current_timestamp(),
|
|
onupdate=func.current_timestamp(),
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<AppAssetContent(id={self.id}, node_id={self.node_id})>"
|