from typing import List, Optional, Dict, Literal, Any
from pydantic import BaseModel, Field
# --- Input Models ---
class Node(BaseModel):
id: str
type: Literal["Start", "Speak", "Ask", "SetVar", "Condition", "Transfer", "End"]
prompt: Optional[str] = None
vars_defined: Optional[List[str]] = Field(default_factory=list)
vars_used: Optional[List[str]] = Field(default_factory=list)
meta: Optional[Dict[str, Any]] = Field(default_factory=dict)
class Edge(BaseModel):
from_node: str = Field(alias="from")
to_node: str = Field(alias="to")
label: Optional[str] = None
condition: Optional[str] = None
is_fallback: bool = False
class Config:
populate_by_name = True
class FlowInput(BaseModel):
schema_version: str = "0.1"
flow_id: Optional[str] = None
nodes: List[Node]
edges: List[Edge]
# --- Output Models ---
class Finding(BaseModel):
code: str
node_id: Optional[str] = None
message: str
fix: Optional[str] = None
severity: Literal["error", "warning"]
class QuickFix(BaseModel):
node_id: str
patch_type: Literal["json_patch", "instructions"]
patch: str
class FlowMeta(BaseModel):
nodes: int
edges: int
unreachable_count: int
dead_end_count: int
created_at: str
class LintResult(BaseModel):
schema_version: str = "0.1"
flow_hash: str
score: int
errors: List[Finding]
warnings: List[Finding]
quick_fixes: List[QuickFix]
flow_meta: FlowMeta
class MCPResponse(BaseModel):
data: LintResult
ui: Dict[str, Any]