Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| import json | |
| import pytest | |
| from world_simulator.config import apply_runtime_env_overrides, load_game_config, parse_game_config | |
| def test_parse_game_config() -> None: | |
| config = parse_game_config( | |
| { | |
| "world": {"width": 80, "depth": 60, "terrain": "plain_green", "seed": 7}, | |
| "npcs": {"count": 3}, | |
| "simulation": {"tick_ms": 500}, | |
| "server": {"host": "127.0.0.1", "port": 8000}, | |
| } | |
| ) | |
| assert config.world.width == 80 | |
| assert config.world.depth == 60 | |
| assert config.npcs.count == 3 | |
| assert config.world.seed == 7 | |
| assert config.connector.type == "deterministic" | |
| def test_parse_openai_compatible_connector() -> None: | |
| config = parse_game_config( | |
| { | |
| "world": {"width": 80, "depth": 60, "terrain": "plain_green", "seed": 7}, | |
| "npcs": {"count": 3}, | |
| "simulation": {"tick_ms": 500}, | |
| "server": {"host": "127.0.0.1", "port": 8000}, | |
| "connector": { | |
| "type": "openai_compatible", | |
| "base_url": "http://llm.local/v1", | |
| "model": "test-model", | |
| "max_tokens": 256, | |
| "temperature": 0.6, | |
| "top_p": 0.95, | |
| "tool_choice": "required", | |
| "max_parallel_npc_calls": 3, | |
| }, | |
| "god_console": { | |
| "type": "openai_compatible", | |
| "base_url": "https://georgij-sawin--world-simulator-qwen36-27b-h100-serve.modal.run/v1", | |
| "model": "qwen3.6-27b-h100-fp8", | |
| "max_tokens": 1200, | |
| "tool_choice": "required", | |
| }, | |
| } | |
| ) | |
| assert config.connector.type == "openai_compatible" | |
| assert config.connector.base_url == "http://llm.local/v1" | |
| assert config.connector.model == "test-model" | |
| assert config.connector.max_tokens == 256 | |
| assert config.connector.temperature == 0.6 | |
| assert config.connector.top_p == 0.95 | |
| assert config.connector.tool_choice == "required" | |
| assert config.connector.max_parallel_npc_calls == 3 | |
| assert config.god_console is not None | |
| assert ( | |
| config.god_console.base_url | |
| == "https://georgij-sawin--world-simulator-qwen36-27b-h100-serve.modal.run/v1" | |
| ) | |
| assert config.god_console.model == "qwen3.6-27b-h100-fp8" | |
| assert config.god_console.max_tokens == 1200 | |
| assert config.god_console.tool_choice == "required" | |
| def test_rejects_negative_npc_count() -> None: | |
| with pytest.raises(ValueError, match="count"): | |
| parse_game_config( | |
| { | |
| "world": {"width": 80, "depth": 60, "terrain": "plain_green", "seed": 7}, | |
| "npcs": {"count": -1}, | |
| "simulation": {"tick_ms": 500}, | |
| "server": {"host": "127.0.0.1", "port": 8000}, | |
| } | |
| ) | |
| def test_load_game_config_reads_dotenv(tmp_path, monkeypatch: pytest.MonkeyPatch) -> None: | |
| monkeypatch.chdir(tmp_path) | |
| config_dir = tmp_path / "config" | |
| config_dir.mkdir() | |
| config_path = config_dir / "game.json" | |
| config_path.write_text( | |
| json.dumps( | |
| { | |
| "world": {"width": 80, "depth": 60, "terrain": "plain_green", "seed": 7}, | |
| "npcs": {"count": 3}, | |
| "simulation": {"tick_ms": 500}, | |
| "server": {"host": "127.0.0.1", "port": 8000}, | |
| "connector": { | |
| "type": "openai_compatible", | |
| "base_url_env": "TEST_OPENAI_BASE_URL", | |
| "model_env": "TEST_OPENAI_MODEL", | |
| "api_key_env": "TEST_OPENAI_API_KEY", | |
| }, | |
| } | |
| ), | |
| encoding="utf-8", | |
| ) | |
| (tmp_path / ".env").write_text( | |
| "\n".join( | |
| [ | |
| "TEST_OPENAI_BASE_URL=https://api.openai.com/v1", | |
| "TEST_OPENAI_MODEL=your-tool-capable-model", | |
| "TEST_OPENAI_API_KEY=test-key", | |
| ] | |
| ), | |
| encoding="utf-8", | |
| ) | |
| config = load_game_config(config_path) | |
| assert config.connector.base_url == "https://api.openai.com/v1" | |
| assert config.connector.model == "your-tool-capable-model" | |
| assert config.connector.api_key_env == "TEST_OPENAI_API_KEY" | |
| def test_load_game_config_does_not_override_existing_env( | |
| tmp_path, | |
| monkeypatch: pytest.MonkeyPatch, | |
| ) -> None: | |
| monkeypatch.chdir(tmp_path) | |
| monkeypatch.setenv("TEST_OPENAI_BASE_URL", "https://already-set.example/v1") | |
| config_path = tmp_path / "game.json" | |
| config_path.write_text( | |
| json.dumps( | |
| { | |
| "world": {"width": 80, "depth": 60, "terrain": "plain_green", "seed": 7}, | |
| "npcs": {"count": 3}, | |
| "simulation": {"tick_ms": 500}, | |
| "server": {"host": "127.0.0.1", "port": 8000}, | |
| "connector": { | |
| "type": "openai_compatible", | |
| "base_url_env": "TEST_OPENAI_BASE_URL", | |
| "model": "test-model", | |
| }, | |
| } | |
| ), | |
| encoding="utf-8", | |
| ) | |
| (tmp_path / ".env").write_text( | |
| "TEST_OPENAI_BASE_URL=https://from-dotenv.example/v1", | |
| encoding="utf-8", | |
| ) | |
| config = load_game_config(config_path) | |
| assert config.connector.base_url == "https://already-set.example/v1" | |
| def test_force_deterministic_env_overrides_runtime_connectors( | |
| monkeypatch: pytest.MonkeyPatch, | |
| ) -> None: | |
| monkeypatch.setenv("WORLD_SIMULATOR_FORCE_DETERMINISTIC", "1") | |
| config = parse_game_config( | |
| { | |
| "world": {"width": 80, "depth": 60, "terrain": "plain_green", "seed": 7}, | |
| "npcs": {"count": 3}, | |
| "simulation": {"tick_ms": 500}, | |
| "server": {"host": "127.0.0.1", "port": 8000}, | |
| "connector": { | |
| "type": "openai_compatible", | |
| "base_url": "https://workspace--npc-serve.modal.run/v1", | |
| "model": "npc-model", | |
| }, | |
| "god_console": { | |
| "type": "openai_compatible", | |
| "base_url": "https://workspace--god-serve.modal.run/v1", | |
| "model": "god-model", | |
| }, | |
| "overseer": { | |
| "mode": "autopilot", | |
| "connector": { | |
| "type": "openai_compatible", | |
| "base_url": "https://workspace--overseer-serve.modal.run/v1", | |
| "model": "overseer-model", | |
| }, | |
| }, | |
| } | |
| ) | |
| config = apply_runtime_env_overrides(config) | |
| assert config.connector.type == "deterministic" | |
| assert config.god_console is None | |
| assert config.overseer.mode == "autopilot" | |
| assert config.overseer.connector.type == "deterministic" | |