| """OpenEnv client for connecting to a deployed SENTINEL Space."""
|
| from __future__ import annotations
|
|
|
| from dataclasses import dataclass
|
| from typing import Generic, TypeVar
|
|
|
| try:
|
| from openenv.core.client_types import StepResult
|
| from openenv.core.env_client import EnvClient
|
| except ModuleNotFoundError:
|
| ActionT = TypeVar("ActionT")
|
| ObservationT = TypeVar("ObservationT")
|
| StateT = TypeVar("StateT")
|
|
|
| @dataclass
|
| class StepResult(Generic[ObservationT]):
|
| observation: ObservationT
|
| reward: float | None
|
| done: bool
|
| info: dict
|
|
|
| class EnvClient(Generic[ActionT, ObservationT, StateT]):
|
| """Local fallback when openenv-core is unavailable."""
|
|
|
| def __init__(self, *_args, **_kwargs) -> None:
|
| raise ModuleNotFoundError("openenv-core is required to use SentinelEnvClient.")
|
|
|
| from models import SentinelAction, SentinelObservation, SentinelState
|
|
|
|
|
| class SentinelEnvClient(EnvClient[SentinelAction, SentinelObservation, SentinelState]):
|
| """Typed OpenEnv client for SENTINEL."""
|
|
|
| def _step_payload(self, action: SentinelAction) -> dict:
|
| return action.model_dump()
|
|
|
| def _parse_result(self, payload: dict) -> StepResult[SentinelObservation]:
|
| observation = SentinelObservation(**payload.get("observation", {}))
|
| return StepResult(
|
| observation=observation,
|
| reward=payload.get("reward"),
|
| done=payload.get("done", False),
|
| info=payload.get("info", {}),
|
| )
|
|
|
| def _parse_state(self, payload: dict) -> SentinelState:
|
| return SentinelState(**payload)
|
|
|