Spaces:
Sleeping
Sleeping
| """Spreadsheet Environment Client. | |
| Connects to a running Spreadsheet OpenEnv server over HTTP/WebSocket. | |
| Agents interact via MCP tools (read_range, write_cell, submit_workbook, etc.). | |
| """ | |
| from __future__ import annotations | |
| from typing import Any, Dict | |
| from openenv.core.client_types import StepResult | |
| from openenv.core.env_client import EnvClient | |
| from openenv.core.env_server.mcp_types import CallToolAction, ListToolsAction, Tool | |
| from .models import SpreadsheetAction, SpreadsheetObservation, SpreadsheetState | |
| class SpreadsheetEnv( | |
| EnvClient[SpreadsheetAction, SpreadsheetObservation, SpreadsheetState] | |
| ): | |
| """Client for the Spreadsheet Environment. | |
| Example: | |
| >>> with SpreadsheetEnv(base_url="http://localhost:8000") as client: | |
| ... result = client.reset() | |
| ... result = client.step( | |
| ... SpreadsheetAction(tool_name="list_scenarios", arguments_json="{}") | |
| ... ) | |
| ... result = client.step( | |
| ... SpreadsheetAction( | |
| ... tool_name="read_range", | |
| ... arguments_json='{"sheet":"Summary","range":"A1:D10"}' | |
| ... ) | |
| ... ) | |
| """ | |
| def list_tools(self, use_cache: bool = True): | |
| if use_cache and hasattr(self, "_tools_cache") and self._tools_cache: | |
| return self._tools_cache | |
| import requests | |
| http_base = ( | |
| self._ws_url | |
| .replace("ws://", "http://") | |
| .replace("wss://", "https://") | |
| .rstrip("/ws") | |
| ) | |
| resp = requests.post( | |
| f"{http_base}/step", | |
| json={"action": {"type": "list_tools"}}, | |
| ) | |
| data = resp.json() | |
| raw_tools = data.get("observation", {}).get("tools", []) | |
| tools = [ | |
| Tool( | |
| name=t["name"], | |
| description=t.get("description", ""), | |
| input_schema=t.get("input_schema", {}), | |
| ) | |
| for t in raw_tools | |
| ] | |
| self._tools_cache = tools | |
| return tools | |
| def _step_payload(self, action: Any) -> Dict: | |
| if hasattr(action, "to_mcp_action"): | |
| action = action.to_mcp_action() | |
| if isinstance(action, ListToolsAction): | |
| return {"type": "list_tools"} | |
| if isinstance(action, CallToolAction): | |
| return { | |
| "type": "call_tool", | |
| "tool_name": action.tool_name, | |
| "arguments": action.arguments or {}, | |
| } | |
| if hasattr(action, "model_dump"): | |
| return action.model_dump() | |
| return {"tool_name": getattr(action, "tool_name", ""), "arguments": {}} | |
| def _parse_result(self, payload: Dict) -> StepResult[SpreadsheetObservation]: | |
| obs_data = payload.get("observation", payload) | |
| observation = SpreadsheetObservation( | |
| tool_name=obs_data.get("tool_name", ""), | |
| result=obs_data.get("result"), | |
| error=obs_data.get("error"), | |
| done=payload.get("done", False), | |
| reward=payload.get("reward"), | |
| metadata=obs_data.get("metadata", {}), | |
| ) | |
| return StepResult( | |
| observation=observation, | |
| reward=payload.get("reward"), | |
| done=payload.get("done", False), | |
| ) | |
| def _parse_state(self, payload: Dict[str, Any]) -> SpreadsheetState: | |
| return SpreadsheetState( | |
| episode_id=payload.get("episode_id"), | |
| step_count=payload.get("step_count", 0), | |
| ) | |