From c440fcc835e5f8b10f9a7043d2a8866fb07a556e Mon Sep 17 00:00:00 2001 From: sergiopaniego Date: Wed, 28 Oct 2026 13:53:24 +0100 Subject: [PATCH] Parse TEXTARENA_KW_* values as JSON so numeric kwargs keep their type TEXTARENA_KW_CLUES=65 reached Sudoku as the string "65" and crashed on reset (int > str in _remove_cells). Values that are not JSON stay strings. --- docs/source/environments/textarena.md | 2 +- envs/textarena_env/README.md | 2 +- envs/textarena_env/server/app.py | 17 +++++++++++++---- tests/envs/test_textarena_environment.py | 22 ++++++++++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/docs/source/environments/textarena.md b/docs/source/environments/textarena.md index d84b0998e..edfe7b9dc 100644 --- a/docs/source/environments/textarena.md +++ b/docs/source/environments/textarena.md @@ -180,7 +180,7 @@ The server supports configuration via environment variables: - `TEXTARENA_NUM_PLAYERS` - Number of players (default: 1) - `TEXTARENA_MAX_TURNS` - Maximum turns per episode - `TEXTARENA_DOWNLOAD_NLTK` - Download NLTK data (default: "1") -- `TEXTARENA_KW_*` - Pass additional kwargs to TextArena (e.g., `TEXTARENA_KW_difficulty=hard`) +- `TEXTARENA_KW_*` - Pass additional kwargs to TextArena. Values are read as JSON, so numbers and booleans keep their type (e.g., `TEXTARENA_KW_CLUES=65` for Sudoku, `TEXTARENA_KW_difficulty=hard`) ## Development & Testing diff --git a/envs/textarena_env/README.md b/envs/textarena_env/README.md index 681ce7db3..71859af4b 100644 --- a/envs/textarena_env/README.md +++ b/envs/textarena_env/README.md @@ -192,7 +192,7 @@ The server supports configuration via environment variables: - `TEXTARENA_NUM_PLAYERS` - Number of players (default: 1) - `TEXTARENA_MAX_TURNS` - Maximum turns per episode - `TEXTARENA_DOWNLOAD_NLTK` - Download NLTK data (default: "1") -- `TEXTARENA_KW_*` - Pass additional kwargs to TextArena (e.g., `TEXTARENA_KW_difficulty=hard`) +- `TEXTARENA_KW_*` - Pass additional kwargs to TextArena. Values are read as JSON, so numbers and booleans keep their type (e.g., `TEXTARENA_KW_CLUES=65` for Sudoku, `TEXTARENA_KW_difficulty=hard`) ## Development & Testing diff --git a/envs/textarena_env/server/app.py b/envs/textarena_env/server/app.py index dd8450f46..2dca57bc3 100644 --- a/envs/textarena_env/server/app.py +++ b/envs/textarena_env/server/app.py @@ -9,8 +9,10 @@ from __future__ import annotations import inspect +import json import logging import os +from typing import Any from openenv.core.env_server.http_server import create_app @@ -31,14 +33,21 @@ from .gradio_ui import build_textarena_gradio_app -def _parse_env_kwargs(prefix: str = "TEXTARENA_KW_") -> dict[str, str]: - """Collect arbitrary environment kwargs from the process environment.""" +def _parse_env_kwargs(prefix: str = "TEXTARENA_KW_") -> dict[str, Any]: + """Collect arbitrary environment kwargs from the process environment. - env_kwargs: dict[str, str] = {} + Values are read as JSON, so `TEXTARENA_KW_CLUES=65` passes the integer 65. Values that are not JSON, like + `TEXTARENA_KW_DIFFICULTY=hard`, are passed as strings. + """ + + env_kwargs: dict[str, Any] = {} for key, value in os.environ.items(): if key.startswith(prefix): env_key = key[len(prefix) :].lower() - env_kwargs[env_key] = value + try: + env_kwargs[env_key] = json.loads(value) + except json.JSONDecodeError: + env_kwargs[env_key] = value return env_kwargs diff --git a/tests/envs/test_textarena_environment.py b/tests/envs/test_textarena_environment.py index 8ea50ed03..3806f6c90 100644 --- a/tests/envs/test_textarena_environment.py +++ b/tests/envs/test_textarena_environment.py @@ -536,3 +536,25 @@ def test_bandit_seeded_trajectory_is_reproducible_across_sessions(): assert sum(len(v) for v in _bandit_history(first).values()) == len(actions) assert _bandit_history(first) == _bandit_history(second) + + +def test_env_kwargs_are_parsed_as_json(monkeypatch): + pytest.importorskip("textarena", reason="textarena not installed") + from textarena_env.server.app import _parse_env_kwargs + + monkeypatch.setenv("TEXTARENA_KW_CLUES", "65") + monkeypatch.setenv("TEXTARENA_KW_DIFFICULTY", "hard") + monkeypatch.setenv("TEXTARENA_KW_HARDCORE", "true") + + assert _parse_env_kwargs() == {"clues": 65, "difficulty": "hard", "hardcore": True} + + +def test_sudoku_clues_from_env_kwargs(monkeypatch): + pytest.importorskip("textarena", reason="textarena not installed") + from textarena_env.server.app import _parse_env_kwargs + + monkeypatch.setenv("TEXTARENA_KW_CLUES", "65") + env = TextArenaEnvironment(env_id="Sudoku-v0", env_kwargs=_parse_env_kwargs()) + board = env.reset().messages[0].content.split("Game Board:")[-1] + + assert board.count(".") <= 81 - 65