| from sqlalchemy import String, Enum as SQLAlchemyEnum | |
| from sqlalchemy.orm import Mapped, mapped_column, relationship | |
| from typing import TYPE_CHECKING | |
| from ..database.db import Base, TimestampMixin | |
| from ..lib.enum import ServiceType | |
| if TYPE_CHECKING: | |
| from .resource_catalog import ResourceCatalog | |
| class ServiceCatalog(Base, TimestampMixin): | |
| """ | |
| Service Catalog table where admins define which services users can add API keys for. | |
| The slug field is used as the key in UserSettings.api_keys dictionary. | |
| When users add API keys, they select from available services and the key is stored | |
| with the service slug as the identifier. | |
| Examples: | |
| - Tavily (web search) - slug: "tavily" | |
| - LangSearch (web search) - slug: "langsearch" | |
| - Firecrawl (web scrape) - slug: "firecrawl" | |
| - Groq (LLM) - slug: "groq" | |
| - OpenAI (LLM, embedding) - slug: "openai" | |
| - Cohere (LLM, embedding, rerank) - slug: "cohere" | |
| - Pinecone (vector store) - slug: "pinecone" | |
| - Gemini (LLM) - slug: "gemini" | |
| """ | |
| __tablename__ = "service_catalog" | |
| id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) | |
| name: Mapped[str] = mapped_column(String(100), nullable=False, unique=True) | |
| slug: Mapped[str] = mapped_column( | |
| String(100), nullable=False, unique=True, index=True | |
| ) | |
| service_type: Mapped[ServiceType] = mapped_column( | |
| SQLAlchemyEnum(ServiceType, native_enum=False, length=50), | |
| nullable=False, | |
| index=True, | |
| ) | |
| description: Mapped[str | None] = mapped_column(String(500), nullable=True) | |
| is_active: Mapped[bool] = mapped_column(default=True, nullable=False) | |
| resources: Mapped[list["ResourceCatalog"]] = relationship( | |
| "ResourceCatalog", back_populates="service", cascade="all, delete-orphan" | |
| ) | |
| def __repr__(self) -> str: | |
| return f"ServiceCatalog(id={self.id}, name={self.name}, slug={self.slug}, type={self.service_type})" | |
| def to_dict(self) -> dict: | |
| """Convert model to dictionary.""" | |
| return { | |
| "id": self.id, | |
| "name": self.name, | |
| "slug": self.slug, | |
| "service_type": self.service_type.value, | |
| "description": self.description, | |
| "is_active": self.is_active, | |
| "created_at": self.created_at.isoformat() if self.created_at else None, | |
| "updated_at": self.updated_at.isoformat() if self.updated_at else None, | |
| } | |