from __future__ import annotations from typing import Literal from pydantic import BaseModel, ConfigDict, Field class PreferenceEntry(BaseModel): model_config = ConfigDict(extra="forbid") enabled: bool | None = None forced: bool = False order: int | None = Field(default=None, ge=0, le=100_000) class ProfileUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") base_revision: int = Field(ge=1) category_preferences: dict[str, PreferenceEntry] = Field(default_factory=dict) tool_preferences: dict[str, PreferenceEntry] = Field(default_factory=dict) class ProfileResponse(BaseModel): scope_type: Literal["system", "tenant", "user"] tenant_id: str | None = None scope_id: str | None = None revision: int etag: str category_preferences: dict[str, PreferenceEntry] tool_preferences: dict[str, PreferenceEntry] stale_category_ids: list[str] = Field(default_factory=list) stale_tool_ids: list[str] = Field(default_factory=list) class CatalogueCategoryResponse(BaseModel): id: str label: str description: str icon: str order: int class CatalogueToolResponse(BaseModel): contract_version: str id: str module_id: str category_id: str label: str description: str | None = None icon: str surface_id: str full_page_path: str | None = None required_all: list[str] required_any: list[str] order: int default_enabled: bool modes: list[str] availability: str accepted_reference_kinds: list[str] returned_reference_kinds: list[str] help_context_id: str | None = None class CatalogueResponse(BaseModel): categories: list[CatalogueCategoryResponse] tools: list[CatalogueToolResponse] class EffectiveToolResponse(CatalogueToolResponse): enabled: bool forced: bool locked_by: str | None = None availability_state: Literal["available", "forced", "blocked"] availability_source: Literal["module", "system", "tenant", "user"] order_source: Literal["module", "system", "tenant", "user"] class EffectiveCategoryResponse(CatalogueCategoryResponse): enabled: bool forced: bool locked_by: str | None = None availability_state: Literal["available", "forced", "blocked"] availability_source: Literal["module", "system", "tenant", "user"] order_source: Literal["module", "system", "tenant", "user"] tools: list[EffectiveToolResponse] class EffectiveStalePreferenceResponse(BaseModel): id: str kind: Literal["category", "tool"] source: Literal["system", "tenant", "user"] class EffectiveQuickAccessResponse(BaseModel): categories: list[EffectiveCategoryResponse] stale_preferences: list[EffectiveStalePreferenceResponse] = Field(default_factory=list) diagnostics: list[str] = Field(default_factory=list) __all__ = [ "CatalogueResponse", "EffectiveQuickAccessResponse", "PreferenceEntry", "ProfileResponse", "ProfileUpdateRequest", ]