| """ |
| OpenEnv Client for the Shopping Agent Environment. |
| |
| Connects to the shopping environment server via WebSocket (OpenEnv protocol). |
| """ |
|
|
| from typing import Any, Dict |
|
|
| from openenv.core.env_client import EnvClient |
| from openenv.core.client_types import StepResult |
|
|
| from openenv_models import ShoppingAction, ShoppingObservation, ShoppingState |
|
|
|
|
| class ShoppingEnvClient(EnvClient[ShoppingAction, ShoppingObservation, ShoppingState]): |
| """ |
| WebSocket client for the Shopping Agent Environment. |
| |
| Usage (async): |
| async with ShoppingEnvClient(base_url="http://localhost:8000") as env: |
| result = await env.reset(query="lip balm", product_count=4) |
| result = await env.step(ShoppingAction(action_type="view_item", item_ids=["p1"])) |
| |
| Usage (sync): |
| with ShoppingEnvClient(base_url="http://localhost:8000").sync() as env: |
| result = env.reset(query="earbuds") |
| result = env.step(ShoppingAction(action_type="buy", item_ids=["p1"])) |
| """ |
|
|
| def _step_payload(self, action: ShoppingAction) -> Dict[str, Any]: |
| """Convert ShoppingAction to the JSON payload expected by the server.""" |
| return action.model_dump(exclude_none=True) |
|
|
| def _parse_result(self, payload: Dict[str, Any]) -> StepResult[ShoppingObservation]: |
| """Parse server response into StepResult[ShoppingObservation].""" |
| obs_data = payload.get("observation", payload) |
| reward = payload.get("reward") or obs_data.get("reward", 0.0) |
| done = payload.get("done", obs_data.get("done", False)) |
|
|
| observation = ShoppingObservation(**obs_data) |
| return StepResult( |
| observation=observation, |
| reward=reward, |
| done=done, |
| ) |
|
|
| def _parse_state(self, payload: Dict[str, Any]) -> ShoppingState: |
| """Parse server state response into ShoppingState.""" |
| return ShoppingState(**payload) |
|
|