|
|
from __future__ import annotations |
|
|
|
|
|
from typing import Optional, List, Literal |
|
|
from pydantic import BaseModel, Field, ConfigDict |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Health(BaseModel): |
|
|
score: Optional[float] = None |
|
|
status: Optional[str] = None |
|
|
last_checked: Optional[str] = None |
|
|
|
|
|
|
|
|
class RecentCheck(BaseModel): |
|
|
check: str |
|
|
result: str |
|
|
latency_ms: Optional[float] = None |
|
|
ts: Optional[str] = None |
|
|
|
|
|
|
|
|
class PlanContext(BaseModel): |
|
|
""" |
|
|
Context is permissive: accept any extra keys from Guardian (or future sources). |
|
|
Known fields are typed below; unknown fields pass through. |
|
|
""" |
|
|
model_config = ConfigDict(extra="allow") |
|
|
|
|
|
|
|
|
app_id: Optional[str] = None |
|
|
entity_uid: Optional[str] = None |
|
|
|
|
|
|
|
|
symptoms: Optional[List[str]] = None |
|
|
lkg: Optional[str] = None |
|
|
lkg_version: Optional[str] = None |
|
|
health: Optional[Health] = None |
|
|
recent_checks: Optional[List[RecentCheck]] = None |
|
|
|
|
|
|
|
|
class PlanConstraints(BaseModel): |
|
|
max_steps: int = Field(default=3, ge=1, le=10) |
|
|
risk: Literal["low", "medium", "high"] = "low" |
|
|
|
|
|
|
|
|
class PlanRequest(BaseModel): |
|
|
|
|
|
mode: Literal["plan"] = "plan" |
|
|
context: PlanContext |
|
|
constraints: PlanConstraints = Field(default_factory=PlanConstraints) |
|
|
|
|
|
|
|
|
class PlanResponse(BaseModel): |
|
|
plan_id: str |
|
|
steps: List[str] |
|
|
risk: str |
|
|
explanation: str |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ChatRequest(BaseModel): |
|
|
question: str = Field(..., min_length=3, max_length=512) |
|
|
|
|
|
|
|
|
class ChatResponse(BaseModel): |
|
|
answer: str |
|
|
sources: List[str] = Field(default_factory=list) |
|
|
|