"""Shared pydantic schemas for the scheduling agent. The model is constrained to emit an ActionPlan (see server/agent.py); these types are also the contract used by the UI and the calendar outputs. """ from __future__ import annotations from typing import Optional from pydantic import BaseModel, Field class Event(BaseModel): title: str start: str # ISO 8601, e.g. 2026-06-10T13:00:00 end: Optional[str] = None location: Optional[str] = None attendees: list[str] = Field(default_factory=list) reminder_minutes: Optional[int] = None notes: Optional[str] = None class Conflict(BaseModel): event_index: int = Field(description="index into ActionPlan.events") clashes_with: str = Field(description="summary of the existing event it clashes with") severity: str = Field(description='one of: "overlap", "adjacent", "tight"') class ActionPlan(BaseModel): """Everything the agent decides for one thread, in one constrained object.""" reasoning: Optional[str] = Field( default=None, description="brief chain of thought shown to the user" ) events: list[Event] = Field(default_factory=list) conflicts: list[Conflict] = Field(default_factory=list) proposed_times: list[str] = Field( default_factory=list, description="ISO 8601 alternatives when there is a conflict" ) reply_draft: str = Field(default="", description="suggested reply to send back") needs_clarification: Optional[str] = Field( default=None, description="a question to ask if the plan is ambiguous" )