import uuid from datetime import datetime from typing import TYPE_CHECKING from sqlalchemy import DateTime, ForeignKey, Integer, JSON, String from sqlalchemy import Uuid as UUID from sqlalchemy.orm import Mapped, mapped_column, relationship from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin if TYPE_CHECKING: from src.models.config_profile import ConfigProfile from src.models.git_repository import GitRepository from src.models.project import Project from src.models.tool_type import ToolType from src.models.user import User from src.models.workspace import Workspace class ToolInstance(UUIDPrimaryKeyMixin, TimestampMixin, Base): __tablename__ = "tool_instances" name: Mapped[str] = mapped_column(String(255), nullable=False) display_name: Mapped[str] = mapped_column(String(255), nullable=False) tool_type_id: Mapped[uuid.UUID] = mapped_column( UUID(), ForeignKey("tool_types.id"), nullable=False ) repository_id: Mapped[uuid.UUID] = mapped_column( UUID(), ForeignKey("git_repositories.id"), nullable=False ) project_id: Mapped[uuid.UUID] = mapped_column( UUID(), ForeignKey("projects.id"), nullable=False ) owner_id: Mapped[uuid.UUID] = mapped_column( UUID(), ForeignKey("users.id"), nullable=False ) status: Mapped[str] = mapped_column(String(50), nullable=False, default="pending") container_id: Mapped[str | None] = mapped_column(String(255), nullable=True) container_name: Mapped[str | None] = mapped_column(String(255), nullable=True) compose_path: Mapped[str | None] = mapped_column(String(1024), nullable=True) url: Mapped[str | None] = mapped_column(String(1024), nullable=True) public_url: Mapped[str | None] = mapped_column(String(1024), nullable=True) tunnel_id: Mapped[str | None] = mapped_column(String(255), nullable=True) port: Mapped[int | None] = mapped_column(Integer, nullable=True) last_started_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) last_stopped_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) manifest_compiled_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) image_tag: Mapped[str | None] = mapped_column(String(256), nullable=True) probe_result: Mapped[dict | None] = mapped_column(JSON, nullable=True) clone_mode: Mapped[str] = mapped_column(String(20), nullable=False, default="mount") branch: Mapped[str | None] = mapped_column( String(255), nullable=True, default="main" ) selected_config_profile_id: Mapped[uuid.UUID | None] = mapped_column( UUID(), ForeignKey("config_profiles.id", ondelete="SET NULL"), nullable=True ) ssh_key_ids: Mapped[list[str] | None] = mapped_column(JSON, nullable=True) workspace_id: Mapped[uuid.UUID | None] = mapped_column( UUID(), ForeignKey("workspaces.id", ondelete="SET NULL"), nullable=True ) tool_type: Mapped["ToolType"] = relationship() workspace: Mapped["Workspace | None"] = relationship() repository: Mapped["GitRepository"] = relationship() project: Mapped["Project"] = relationship() owner: Mapped["User"] = relationship() selected_config_profile: Mapped["ConfigProfile | None"] = relationship()