Phase 1a: Extract Pydantic models into models/requests.py + models/responses.py (#7)
This commit is contained in:
1 parent
312d13949d
commit
eadf54c670
4 files changed
+222
-141
No files matched your search
@@ -0,0 +1,47 @@
|
|||||||
|
"""Pydantic models for Commander AI Lab API."""
|
||||||
|
|
||||||
|
from models.requests import (
|
||||||
|
StartRequest,
|
||||||
|
ImportUrlRequest,
|
||||||
|
ImportTextRequest,
|
||||||
|
MetaFetchRequest,
|
||||||
|
CreateDeckRequest,
|
||||||
|
UpdateDeckRequest,
|
||||||
|
AddDeckCardRequest,
|
||||||
|
PatchDeckCardRequest,
|
||||||
|
BulkAddRequest,
|
||||||
|
BulkAddRecommendedRequest,
|
||||||
|
DeckGenerationSourceConfig,
|
||||||
|
DeckGenerationRequest,
|
||||||
|
DeckGenV3Request,
|
||||||
|
DeckGenV3SubstituteRequest,
|
||||||
|
)
|
||||||
|
from models.responses import (
|
||||||
|
StartResponse,
|
||||||
|
StatusResponse,
|
||||||
|
DeckInfo,
|
||||||
|
GeneratedDeckCard,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
# Requests
|
||||||
|
"StartRequest",
|
||||||
|
"ImportUrlRequest",
|
||||||
|
"ImportTextRequest",
|
||||||
|
"MetaFetchRequest",
|
||||||
|
"CreateDeckRequest",
|
||||||
|
"UpdateDeckRequest",
|
||||||
|
"AddDeckCardRequest",
|
||||||
|
"PatchDeckCardRequest",
|
||||||
|
"BulkAddRequest",
|
||||||
|
"BulkAddRecommendedRequest",
|
||||||
|
"DeckGenerationSourceConfig",
|
||||||
|
"DeckGenerationRequest",
|
||||||
|
"DeckGenV3Request",
|
||||||
|
"DeckGenV3SubstituteRequest",
|
||||||
|
# Responses
|
||||||
|
"StartResponse",
|
||||||
|
"StatusResponse",
|
||||||
|
"DeckInfo",
|
||||||
|
"GeneratedDeckCard",
|
||||||
|
]
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
"""Pydantic request models for Commander AI Lab API."""
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Optional
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class StartRequest(BaseModel):
|
||||||
|
decks: list[str]
|
||||||
|
numGames: int = 100
|
||||||
|
threads: int = 4
|
||||||
|
seed: Optional[int] = None
|
||||||
|
clock: int = 120
|
||||||
|
deckSources: Optional[list[Optional[dict]]] = None
|
||||||
|
useLearnedPolicy: bool = False
|
||||||
|
policyStyle: str = "midrange"
|
||||||
|
policyGreedy: bool = False
|
||||||
|
aiSimplified: bool = False
|
||||||
|
aiThinkTimeMs: int = -1
|
||||||
|
maxQueueDepth: int = -1
|
||||||
|
|
||||||
|
|
||||||
|
class ImportUrlRequest(BaseModel):
|
||||||
|
url: str
|
||||||
|
|
||||||
|
|
||||||
|
class ImportTextRequest(BaseModel):
|
||||||
|
text: str
|
||||||
|
commander: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class MetaFetchRequest(BaseModel):
|
||||||
|
commander: str
|
||||||
|
|
||||||
|
|
||||||
|
class CreateDeckRequest(BaseModel):
|
||||||
|
name: str
|
||||||
|
commander_scryfall_id: Optional[str] = ""
|
||||||
|
commander_name: Optional[str] = ""
|
||||||
|
color_identity: Optional[list] = []
|
||||||
|
strategy_tag: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateDeckRequest(BaseModel):
|
||||||
|
name: Optional[str] = None
|
||||||
|
commander_scryfall_id: Optional[str] = None
|
||||||
|
commander_name: Optional[str] = None
|
||||||
|
color_identity: Optional[list] = None
|
||||||
|
strategy_tag: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class AddDeckCardRequest(BaseModel):
|
||||||
|
scryfall_id: str
|
||||||
|
card_name: Optional[str] = ""
|
||||||
|
quantity: Optional[int] = 1
|
||||||
|
is_commander: Optional[int] = 0
|
||||||
|
role_tag: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
|
class PatchDeckCardRequest(BaseModel):
|
||||||
|
quantity: Optional[int] = None
|
||||||
|
role_tag: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class BulkAddRequest(BaseModel):
|
||||||
|
cards: list[dict]
|
||||||
|
respect_ratios: Optional[bool] = False
|
||||||
|
|
||||||
|
|
||||||
|
class BulkAddRecommendedRequest(BaseModel):
|
||||||
|
source: str = "collection"
|
||||||
|
only_owned: Optional[bool] = True
|
||||||
|
respect_ratios: Optional[bool] = False
|
||||||
|
types: Optional[list[str]] = None
|
||||||
|
roles: Optional[list[str]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class DeckGenerationSourceConfig(BaseModel):
|
||||||
|
use_archidekt: bool = True
|
||||||
|
use_edhrec: bool = True
|
||||||
|
use_moxfield: bool = False
|
||||||
|
use_mtggoldfish: bool = False
|
||||||
|
archidekt_url: Optional[str] = ""
|
||||||
|
moxfield_url: Optional[str] = ""
|
||||||
|
mtggoldfish_url: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
|
class DeckGenerationRequest(BaseModel):
|
||||||
|
commander_name: Optional[str] = ""
|
||||||
|
commander_scryfall_id: Optional[str] = ""
|
||||||
|
color_identity: Optional[list[str]] = None
|
||||||
|
sources: Optional[DeckGenerationSourceConfig] = None
|
||||||
|
target_land_count: int = 37
|
||||||
|
target_instant_count: int = 10
|
||||||
|
target_sorcery_count: int = 8
|
||||||
|
target_artifact_count: int = 10
|
||||||
|
target_enchantment_count: int = 8
|
||||||
|
target_creature_count: int = 25
|
||||||
|
target_planeswalker_count: int = 2
|
||||||
|
only_cards_in_collection: bool = False
|
||||||
|
allow_proxies: bool = True
|
||||||
|
deck_name: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
|
class DeckGenV3Request(BaseModel):
|
||||||
|
commander_name: str = ""
|
||||||
|
strategy: str = ""
|
||||||
|
target_bracket: int = 3
|
||||||
|
budget_usd: Optional[float] = None
|
||||||
|
budget_mode: str = "total"
|
||||||
|
omit_cards: list[str] = []
|
||||||
|
use_collection: bool = True
|
||||||
|
run_substitution: bool = True
|
||||||
|
model: Optional[str] = None
|
||||||
|
deck_name: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
|
class DeckGenV3SubstituteRequest(BaseModel):
|
||||||
|
card_name: str
|
||||||
|
substitute_name: str
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
"""Pydantic response models for Commander AI Lab API."""
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Optional
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class StartResponse(BaseModel):
|
||||||
|
batchId: str
|
||||||
|
status: str = "started"
|
||||||
|
message: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class StatusResponse(BaseModel):
|
||||||
|
batchId: str = ""
|
||||||
|
running: bool = False
|
||||||
|
completed: int = 0
|
||||||
|
total: int = 0
|
||||||
|
threads: int = 0
|
||||||
|
elapsedMs: int = 0
|
||||||
|
error: Optional[str] = None
|
||||||
|
simsPerSec: float = 0.0
|
||||||
|
run_id: str = ""
|
||||||
|
games_completed: int = 0
|
||||||
|
total_games: int = 0
|
||||||
|
current_decks: list = []
|
||||||
|
|
||||||
|
|
||||||
|
class DeckInfo(BaseModel):
|
||||||
|
name: str
|
||||||
|
filename: str
|
||||||
|
|
||||||
|
|
||||||
|
class GeneratedDeckCard(BaseModel):
|
||||||
|
scryfall_id: str = ""
|
||||||
|
name: str = ""
|
||||||
|
type_line: str = ""
|
||||||
|
mana_cost: str = ""
|
||||||
|
cmc: float = 0
|
||||||
|
card_type: str = ""
|
||||||
|
roles: list[str] = []
|
||||||
|
source: str = "collection"
|
||||||
|
quantity: int = 1
|
||||||
|
image_url: str = ""
|
||||||
|
owned_qty: int = 0
|
||||||
|
is_proxy: bool = False
|
||||||
+11
-141
@@ -183,147 +183,17 @@ def load_commander_meta() -> None:
|
|||||||
log.info(f" Meta: {len(COMMANDER_META)} built-in commanders")
|
log.info(f" Meta: {len(COMMANDER_META)} built-in commanders")
|
||||||
|
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════════════
|
# Pydantic Models (imported from models/)
|
||||||
# Pydantic Models
|
from models.requests import (
|
||||||
# ══════════════════════════════════════════════════════════════
|
StartRequest, ImportUrlRequest, ImportTextRequest, MetaFetchRequest,
|
||||||
|
CreateDeckRequest, UpdateDeckRequest, AddDeckCardRequest,
|
||||||
class StartRequest(BaseModel):
|
PatchDeckCardRequest, BulkAddRequest, BulkAddRecommendedRequest,
|
||||||
decks: list[str]
|
DeckGenerationSourceConfig, DeckGenerationRequest,
|
||||||
numGames: int = 100
|
DeckGenV3Request, DeckGenV3SubstituteRequest,
|
||||||
threads: int = 4
|
)
|
||||||
seed: Optional[int] = None
|
from models.responses import (
|
||||||
clock: int = 120
|
StartResponse, StatusResponse, DeckInfo, GeneratedDeckCard,
|
||||||
deckSources: Optional[list[Optional[dict]]] = None
|
)
|
||||||
useLearnedPolicy: bool = False
|
|
||||||
policyStyle: str = "midrange"
|
|
||||||
policyGreedy: bool = False
|
|
||||||
aiSimplified: bool = False
|
|
||||||
aiThinkTimeMs: int = -1
|
|
||||||
maxQueueDepth: int = -1
|
|
||||||
|
|
||||||
class StartResponse(BaseModel):
|
|
||||||
batchId: str
|
|
||||||
status: str = "started"
|
|
||||||
message: str = ""
|
|
||||||
|
|
||||||
class StatusResponse(BaseModel):
|
|
||||||
batchId: str = ""
|
|
||||||
running: bool = False
|
|
||||||
completed: int = 0
|
|
||||||
total: int = 0
|
|
||||||
threads: int = 0
|
|
||||||
elapsedMs: int = 0
|
|
||||||
error: Optional[str] = None
|
|
||||||
simsPerSec: float = 0.0
|
|
||||||
run_id: str = ""
|
|
||||||
games_completed: int = 0
|
|
||||||
total_games: int = 0
|
|
||||||
current_decks: list = []
|
|
||||||
|
|
||||||
class DeckInfo(BaseModel):
|
|
||||||
name: str
|
|
||||||
filename: str
|
|
||||||
|
|
||||||
class ImportUrlRequest(BaseModel):
|
|
||||||
url: str
|
|
||||||
|
|
||||||
class ImportTextRequest(BaseModel):
|
|
||||||
text: str
|
|
||||||
commander: Optional[str] = None
|
|
||||||
|
|
||||||
class MetaFetchRequest(BaseModel):
|
|
||||||
commander: str
|
|
||||||
|
|
||||||
class CreateDeckRequest(BaseModel):
|
|
||||||
name: str
|
|
||||||
commander_scryfall_id: Optional[str] = ""
|
|
||||||
commander_name: Optional[str] = ""
|
|
||||||
color_identity: Optional[list] = []
|
|
||||||
strategy_tag: Optional[str] = ""
|
|
||||||
|
|
||||||
class UpdateDeckRequest(BaseModel):
|
|
||||||
name: Optional[str] = None
|
|
||||||
commander_scryfall_id: Optional[str] = None
|
|
||||||
commander_name: Optional[str] = None
|
|
||||||
color_identity: Optional[list] = None
|
|
||||||
strategy_tag: Optional[str] = None
|
|
||||||
|
|
||||||
class AddDeckCardRequest(BaseModel):
|
|
||||||
scryfall_id: str
|
|
||||||
card_name: Optional[str] = ""
|
|
||||||
quantity: Optional[int] = 1
|
|
||||||
is_commander: Optional[int] = 0
|
|
||||||
role_tag: Optional[str] = ""
|
|
||||||
|
|
||||||
class PatchDeckCardRequest(BaseModel):
|
|
||||||
quantity: Optional[int] = None
|
|
||||||
role_tag: Optional[str] = None
|
|
||||||
|
|
||||||
class BulkAddRequest(BaseModel):
|
|
||||||
cards: list[dict]
|
|
||||||
respect_ratios: Optional[bool] = False
|
|
||||||
|
|
||||||
class BulkAddRecommendedRequest(BaseModel):
|
|
||||||
source: str = "collection"
|
|
||||||
only_owned: Optional[bool] = True
|
|
||||||
respect_ratios: Optional[bool] = False
|
|
||||||
types: Optional[list[str]] = None
|
|
||||||
roles: Optional[list[str]] = None
|
|
||||||
|
|
||||||
class DeckGenerationSourceConfig(BaseModel):
|
|
||||||
use_archidekt: bool = True
|
|
||||||
use_edhrec: bool = True
|
|
||||||
use_moxfield: bool = False
|
|
||||||
use_mtggoldfish: bool = False
|
|
||||||
archidekt_url: Optional[str] = ""
|
|
||||||
moxfield_url: Optional[str] = ""
|
|
||||||
mtggoldfish_url: Optional[str] = ""
|
|
||||||
|
|
||||||
class DeckGenerationRequest(BaseModel):
|
|
||||||
commander_name: Optional[str] = ""
|
|
||||||
commander_scryfall_id: Optional[str] = ""
|
|
||||||
color_identity: Optional[list[str]] = None
|
|
||||||
sources: Optional[DeckGenerationSourceConfig] = None
|
|
||||||
target_land_count: int = 37
|
|
||||||
target_instant_count: int = 10
|
|
||||||
target_sorcery_count: int = 8
|
|
||||||
target_artifact_count: int = 10
|
|
||||||
target_enchantment_count: int = 8
|
|
||||||
target_creature_count: int = 25
|
|
||||||
target_planeswalker_count: int = 2
|
|
||||||
only_cards_in_collection: bool = False
|
|
||||||
allow_proxies: bool = True
|
|
||||||
deck_name: Optional[str] = ""
|
|
||||||
|
|
||||||
class GeneratedDeckCard(BaseModel):
|
|
||||||
scryfall_id: str = ""
|
|
||||||
name: str = ""
|
|
||||||
type_line: str = ""
|
|
||||||
mana_cost: str = ""
|
|
||||||
cmc: float = 0
|
|
||||||
card_type: str = ""
|
|
||||||
roles: list[str] = []
|
|
||||||
source: str = "collection"
|
|
||||||
quantity: int = 1
|
|
||||||
image_url: str = ""
|
|
||||||
owned_qty: int = 0
|
|
||||||
is_proxy: bool = False
|
|
||||||
|
|
||||||
class DeckGenV3Request(BaseModel):
|
|
||||||
commander_name: str = ""
|
|
||||||
strategy: str = ""
|
|
||||||
target_bracket: int = 3
|
|
||||||
budget_usd: Optional[float] = None
|
|
||||||
budget_mode: str = "total"
|
|
||||||
omit_cards: list[str] = []
|
|
||||||
use_collection: bool = True
|
|
||||||
run_substitution: bool = True
|
|
||||||
model: Optional[str] = None
|
|
||||||
deck_name: Optional[str] = ""
|
|
||||||
|
|
||||||
class DeckGenV3SubstituteRequest(BaseModel):
|
|
||||||
card_name: str
|
|
||||||
substitute_name: str
|
|
||||||
|
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════
|
||||||
|
|||||||
Reference in new issue
Block a user