File size: 4,007 Bytes
816634a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15503f9
816634a
 
 
 
f0dcfd3
 
 
 
 
 
e28941b
f0dcfd3
e28941b
f0dcfd3
84ba78e
f0dcfd3
e28941b
84ba78e
e28941b
 
 
 
84ba78e
e28941b
84ba78e
e28941b
 
 
 
 
 
 
 
f0dcfd3
e28941b
f0dcfd3
e28941b
f0dcfd3
e28941b
 
 
84ba78e
e28941b
84ba78e
e28941b
f0dcfd3
e28941b
f0dcfd3
e28941b
 
 
84ba78e
 
 
e28941b
84ba78e
 
f0dcfd3
 
 
 
 
 
e28941b
84ba78e
 
 
 
 
 
f0dcfd3
e28941b
f0dcfd3
 
816634a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15503f9
 
 
 
 
 
 
816634a
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""
FastAPI application entrypoint for the Visual Memory environment.

Uses OpenEnv's create_app() factory which auto-generates:
  - POST /reset, POST /step, GET /state, GET /health
  - WebSocket /ws for persistent connections
  - /web interface (when ENABLE_WEB_INTERFACE=true on HF Spaces)
"""

from __future__ import annotations

import os
import sys
from pathlib import Path

from dotenv import load_dotenv
from fastapi.middleware.cors import CORSMiddleware
from openenv.core.env_server.http_server import create_app

load_dotenv(os.path.join(os.path.dirname(__file__), "..", ".env"))

# Override the generic Quick Start with gym-specific content
import openenv.core.env_server.web_interface as _wi  # noqa: E402

_wi.DEFAULT_QUICK_START_MARKDOWN = """
### How to use this environment

**Visual Memory (Phantom Grid)** β€” a hidden-state reasoning gym. Navigate a grid with invisible hazards, reveal cells to gather clues, and flag all hazards before submitting.

Use the **Playground** on the right. Type a **Tool Name** and **Arguments Json**, then click **Step**.

---

#### 1. Start a session

1. Click **Reset**
2. `list_tools` β†’ `{}` β€” discover all tools & params
3. `list_scenarios` β†’ `{}` β€” see all 10 scenarios
4. `load_scenario` β†’ `{"scenario_id": "directional_trap_8x8"}`

#### 2. Explore the board

- `get_board_view` β†’ `{}` β€” render SVG board
- `get_status` β†’ `{}` β€” score, flags, steps
- `reveal_cell` β†’ `{"row": 0, "col": 0}` β€” uncover a cell *(costs 1 step)*
- `inspect_region` β†’ `{"center_row": 3, "center_col": 3, "radius": 1}` β€” peek without revealing *(costs 1 step)*
- `recall_log` β†’ `{}` β€” signals found so far
- `get_action_history` β†’ `{}` β€” full action log
- `get_progress_stats` β†’ `{}` β€” % revealed, steps left
- `move_viewport` β†’ `{"row": 5, "col": 5}` β€” move camera *(fog scenarios only)*

> **Note:** `inspect_region` uses **center_row** / **center_col**, not row/col.

#### 3. Flag hazards & submit

- `flag_cell` β†’ `{"row": 1, "col": 1}` β€” mark hazardous
- `unflag_cell` β†’ `{"row": 1, "col": 1}` β€” remove flag
- `submit_solution` β†’ `{"flagged_positions": "[[0,1],[2,3]]"}` β€” submit & end game

> `submit_solution` also accepts optional `safe_positions`.

#### 4. Trap tools (avoid!)

These always fail with **-0.1 reward penalty**:

- `auto_solve` β†’ `{}`
- `peek_hidden_cell` β†’ `{"row": 2, "col": 2}`
- `undo_last_action` β†’ `{}`

---

#### Scenarios (10)

`directional_trap_8x8` Β· `ambiguous_cluster_10x10` Β· `partial_intel_9x9` Β· `cascading_deduction_11x11` Β· `safe_zone_identification_9x9` Β· `flash_fade_minefield_7x7` Β· `delayed_recall_keys_8x8` Β· `fog_labyrinth_10x10` Β· `fog_key_hunt_8x8` Β· `decoy_minefield_8x10`

#### Connect from Python

```python
from visual_memory import VisualMemoryAction, VisualMemoryEnv

env = VisualMemoryEnv(base_url="http://localhost:8000")
obs = env.reset()
obs = await env.step(VisualMemoryAction(
    tool_name="load_scenario",
    arguments_json='{"scenario_id": "directional_trap_8x8"}'
))
```

For more, see the [OpenEnv documentation](https://meta-pytorch.org/OpenEnv/).
"""

try:
    from visual_memory.models import VisualMemoryAction, VisualMemoryObservation
    from visual_memory.server.memory_environment import MemoryEnvironment
except ImportError:
    sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
    from models import VisualMemoryAction, VisualMemoryObservation
    from server.memory_environment import MemoryEnvironment


MAX_CONCURRENT_ENVS = int(os.getenv("MAX_CONCURRENT_ENVS", "8"))

app = create_app(
    MemoryEnvironment,
    VisualMemoryAction,
    VisualMemoryObservation,
    env_name="visual_memory",
    max_concurrent_envs=MAX_CONCURRENT_ENVS,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)


def main(host: str = "0.0.0.0", port: int = 8000):
    import uvicorn
    uvicorn.run(app, host=host, port=port)


if __name__ == "__main__":
    main()