from typing import Any, Dict, List, Optional from openenv.core.env_server.types import Action, Observation from pydantic import Field, PrivateAttr class CadforgeAction(Action): action_type: str = Field( ..., description="One of: read_docs | execute_cadquery | submit | render_object", ) params: Dict[str, Any] = Field( default_factory=dict, description="Parameters for the action", ) class CadforgeObservation(Observation): task: Optional[str] = Field( default=None, description="Task prompt provided on reset", ) step_count: int = Field( default=0, description="Number of steps taken so far", ) docs_results: Optional[List[str]] = Field( default=None, description="Documentation paragraphs returned by read_docs", ) code_executed: Optional[bool] = Field( default=None, description="True if code ran successfully, False if errored, None if no code run", ) code_error: Optional[str] = Field( default=None, description="Exception message if code_executed is False", ) object_id: Optional[str] = Field( default=None, description="Unique identifier for the shape produced by execute_cadquery", ) object_properties: Optional[Dict[str, Any]] = Field( default=None, description="Geometric properties of the shape produced by execute_cadquery", ) artifacts: Optional[List[Dict[str, Any]]] = Field( default=None, description="Registry of all shapes created so far: [{object_id, step_path}]", ) last_executed: Optional[str] = Field( default=None, description="Object ID of the most recently executed shape", ) image_path: Optional[str] = Field( default=None, description="Path to rendered PNG (Phase 2 only)", ) _raw_data: Optional[Dict[str, Any]] = PrivateAttr(default=None)