"""StabilizerForge environment client (sync + async via openenv core).""" from __future__ import annotations from typing import Any from openenv.core import EnvClient from openenv.core.client_types import StepResult from openenv.core.env_server.types import State from .models import StabilizerAction, StabilizerObservation class StabilizerForgeEnv(EnvClient[StabilizerAction, StabilizerObservation, State]): """Client for the StabilizerForge environment server. Example: with StabilizerForgeEnv(base_url="http://localhost:8000") as client: result = client.reset(task_id="steane_7_1_3") result = client.step(StabilizerAction(op="H", qubits=[0])) ... result = client.step(StabilizerAction(op="FINALIZE")) """ def _step_payload(self, action: StabilizerAction) -> dict[str, Any]: return {"op": action.op, "qubits": list(action.qubits)} def _parse_result( self, payload: dict[str, Any] ) -> StepResult[StabilizerObservation]: obs_data = payload.get("observation", {}) observation = StabilizerObservation(**obs_data) if obs_data else StabilizerObservation() # Top-level done/reward override what's inside observation if present if "done" in payload: observation.done = bool(payload.get("done")) if "reward" in payload: observation.reward = payload.get("reward") return StepResult( observation=observation, reward=payload.get("reward"), done=payload.get("done", False), ) def _parse_state(self, payload: dict[str, Any]) -> State: return State( episode_id=payload.get("episode_id"), step_count=payload.get("step_count", 0), )