Jayant2304/commitment-os
0
1"""API-facing Pydantic models — the public contract of CommitmentOS."""2 3from __future__ import annotations4 5from typing import Any, Dict, List6 7from pydantic import Field8from openenv.core.env_server import Action, Observation, State9 10 11class CommitmentAction(Action):12 """Agent's tool call submitted via POST /step.13 14 Each step is one tool invocation. The agent fills ``action_type`` and15 the relevant subset of optional parameters for that tool.16 """17 18 action_type: str = Field(19 ...,20 description=(21 "Tool to invoke: 'view_calendar' | 'check_availability' | "22 "'search_restaurants' | 'schedule_meeting' | 'reschedule_event' | "23 "'cancel_event' | 'send_email' | 'submit_plan'"24 ),25 )26 27 # calendar operations28 date: str = Field("", description="ISO date for calendar queries (yyyy-mm-dd)")29 event_id: str = Field("", description="Event ID for reschedule / cancel")30 new_time: str = Field("", description="New start time HH:MM for reschedule")31 title: str = Field("", description="Title for new meetings")32 participants: List[str] = Field(default_factory=list, description="Attendee names")33 time: str = Field("", description="Start time HH:MM for new meetings")34 duration_min: int = Field(60, description="Meeting duration in minutes")35 location: str = Field("", description="Room or location")36 37 # contact queries38 person: str = Field("", description="Contact name for availability check")39 40 # restaurant search41 cuisine: str = Field("", description="Cuisine filter")42 max_price: int = Field(0, description="Max price per person (0 = no limit)")43 dietary: str = Field("", description="Dietary requirement filter")44 max_distance_miles: float = Field(0.0, description="Max distance (0 = no limit)")45 near_airport: bool = Field(False, description="Filter for airport proximity")46 restaurant_name: str = Field("", description="Specific restaurant to book")47 48 # email49 to: str = Field("", description="Recipient name for send_email")50 subject: str = Field("", description="Email subject line")51 body: str = Field("", description="Email body text")52 53 54class CommitmentObservation(Observation):55 """Observation from reset() and step(). Inherits ``done``, ``reward``."""56 57 scenario_id: str = Field(default="", description="Current scenario identifier")58 difficulty: str = Field(default="", description="easy | medium | hard")59 briefing: str = Field(default="", description="Scenario description shown on reset")60 tool_result: str = Field(default="", description="Output of the last tool call")61 calendar_snapshot: List[Dict[str, Any]] = Field(62 default_factory=list, description="Current calendar events",63 )64 inbox: List[Dict[str, Any]] = Field(65 default_factory=list, description="Unread inbox emails",66 )67 pending_commitments: int = Field(0, description="Number of active commitments in ledger")68 step_number: int = Field(0, description="Current step within this episode")69 max_steps: int = Field(15, description="Maximum steps before forced submission")70 reward_breakdown: Dict[str, float] = Field(71 default_factory=dict, description="Per-component reward scores",72 )73 feedback: str = Field(default="", description="Human-readable grader feedback")74 75 76class CommitmentState(State):77 """Episode metadata from GET /state."""78 79 scenario_id: str = Field(default="", description="Current scenario identifier")80 difficulty: str = Field(default="", description="Current difficulty level")81 completed: bool = Field(default=False, description="Whether episode is finished")82 cumulative_reward: float = Field(default=0.0, description="Sum of rewards this episode")83 commitment_count: int = Field(default=0, description="Total commitments created")84 violation_count: int = Field(default=0, description="Silent commitment violations")85 available_tasks: List[str] = Field(86 default_factory=list, description="All scenario IDs in the dataset",87 )88 