from typing import Any, Dict, List, Literal, Optional from pydantic import BaseModel, Field, HttpUrl class ProxmoxServerConfig(BaseModel): name: str url: HttpUrl token_name: str token_value: str = Field(repr=False) class ServerInfo(BaseModel): name: str url: str configured: bool = True class ServerScanStatus(BaseModel): name: str url: str ok: bool vm_count: int = 0 errors: List[str] = Field(default_factory=list) class VmRecord(BaseModel): id: str server: str node: str vmid: int type: Literal["qemu", "lxc"] name: str status: Optional[str] = None cpu: Optional[float] = None mem: Optional[int] = None maxmem: Optional[int] = None disk: Optional[int] = None maxdisk: Optional[int] = None uptime: Optional[int] = None tags: Optional[str] = None duplicate_id: Optional[int] = None description_available: bool = False raw: Dict[str, Any] = Field(default_factory=dict) class DuplicateGroup(BaseModel): id: str label: str reason: Literal["name", "metadata"] count: int items: List[VmRecord] class ScanResponse(BaseModel): servers: List[ServerScanStatus] items: List[VmRecord] duplicates: List[DuplicateGroup] class AiVmSummary(BaseModel): server: str node: str vmid: int type: Literal["qemu", "lxc"] name: str status: Optional[str] = None tags: Optional[str] = None duplicate_id: Optional[int] = None class AiDuplicateSummary(BaseModel): label: str reason: Literal["name", "metadata"] count: int vmids: List[str] class AiInventoryStats(BaseModel): total: int running: int stopped: int qemu: int lxc: int duplicate_groups: int class AiContextResponse(BaseModel): generated_at: str purpose: str stats: AiInventoryStats servers: List[ServerScanStatus] duplicates: List[AiDuplicateSummary] inventory: List[AiVmSummary] notes: List[str] = Field(default_factory=list)