"""Pydantic 数据模型 -- API 请求/响应 + 数据库行映射""" from __future__ import annotations from datetime import datetime from enum import Enum from typing import Any from pydantic import BaseModel, Field # ── 枚举 ────────────────────────────────────────────── class RefreshType(str, Enum): FIXED_INTERVAL = "fixed_interval" CALENDAR_CYCLE = "calendar_cycle" MANUAL = "manual" API_SYNC = "api_sync" class TaskStatus(str, Enum): PENDING = "pending" RUNNING = "running" COMPLETED = "completed" FAILED = "failed" CANCELLED = "cancelled" # ── Plan ────────────────────────────────────────────── class PlanBase(BaseModel): name: str provider_name: str api_base: str = "" plan_type: str = "coding" supported_models: list[str] = Field(default_factory=list) extra_headers: dict[str, str] = Field(default_factory=dict) extra_config: dict[str, Any] = Field(default_factory=dict) enabled: bool = True class PlanCreate(PlanBase): api_key: str = "" class PlanUpdate(BaseModel): name: str | None = None api_key: str | None = None api_base: str | None = None plan_type: str | None = None supported_models: list[str] | None = None extra_headers: dict[str, str] | None = None extra_config: dict[str, Any] | None = None enabled: bool | None = None class PlanOut(PlanBase): id: str created_at: datetime updated_at: datetime # ── QuotaRule ───────────────────────────────────────── class QuotaRuleBase(BaseModel): rule_name: str quota_total: int quota_unit: str = "requests" refresh_type: RefreshType = RefreshType.CALENDAR_CYCLE interval_hours: float | None = None calendar_unit: str | None = None calendar_anchor: dict[str, Any] | None = None enabled: bool = True class QuotaRuleCreate(QuotaRuleBase): plan_id: str class QuotaRuleUpdate(BaseModel): rule_name: str | None = None quota_total: int | None = None quota_unit: str | None = None refresh_type: RefreshType | None = None interval_hours: float | None = None calendar_unit: str | None = None calendar_anchor: dict[str, Any] | None = None enabled: bool | None = None class QuotaRuleOut(QuotaRuleBase): id: str plan_id: str quota_used: int = 0 last_refresh_at: datetime | None = None next_refresh_at: datetime | None = None # ── QuotaSnapshot ───────────────────────────────────── class QuotaSnapshotOut(BaseModel): id: str rule_id: str quota_used: int quota_remaining: int checked_at: datetime # ── Model Route ─────────────────────────────────────── class ModelRouteBase(BaseModel): model_name: str plan_id: str priority: int = 0 class ModelRouteOut(ModelRouteBase): id: str # ── Task Queue ──────────────────────────────────────── class TaskCreate(BaseModel): plan_id: str | None = None task_type: str request_payload: dict[str, Any] = Field(default_factory=dict) priority: int = 0 max_retries: int = 3 callback_url: str | None = None class TaskOut(BaseModel): id: str plan_id: str | None task_type: str status: TaskStatus request_payload: dict[str, Any] response_payload: dict[str, Any] | None = None result_file_path: str | None = None result_mime_type: str | None = None priority: int retry_count: int max_retries: int callback_url: str | None = None created_at: datetime started_at: datetime | None = None completed_at: datetime | None = None # ── 聚合视图 ────────────────────────────────────────── class PlanWithRules(PlanOut): """Plan + 所有 QuotaRule 的聚合返回""" quota_rules: list[QuotaRuleOut] = Field(default_factory=list) class DashboardPlan(BaseModel): """仪表盘用的精简视图""" id: str name: str provider_name: str plan_type: str enabled: bool quota_rules: list[QuotaRuleOut] all_available: bool = True # 所有 Rule 均有余量