openenv 0.2.3__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openenv-0.2.3/src/openenv.egg-info → openenv-0.3.0}/PKG-INFO +27 -17
- {openenv-0.2.3 → openenv-0.3.0}/README.md +22 -12
- {openenv-0.2.3 → openenv-0.3.0}/pyproject.toml +5 -5
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/__init__.py +1 -1
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/auto/_discovery.py +2 -2
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/__main__.py +14 -1
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/_validation.py +81 -9
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/build.py +16 -7
- openenv-0.3.0/src/openenv/cli/commands/collect.py +443 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/push.py +211 -26
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/skills.py +12 -5
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/server/app.py +1 -1
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/http_server.py +50 -6
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/interfaces.py +2 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/web_interface.py +39 -6
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/evals/inspect_harness.py +13 -1
- openenv-0.3.0/src/openenv/core/harness/__init__.py +723 -0
- openenv-0.3.0/src/openenv/core/harness/collect.py +586 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/llm_client.py +32 -8
- {openenv-0.2.3 → openenv-0.3.0/src/openenv.egg-info}/PKG-INFO +27 -17
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv.egg-info/SOURCES.txt +3 -1
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv.egg-info/requires.txt +4 -4
- {openenv-0.2.3 → openenv-0.3.0}/LICENSE +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/MANIFEST.in +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/setup.cfg +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/auto/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/auto/auto_action.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/auto/auto_env.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/_cli_utils.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/fork.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/init.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/serve.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/commands/validate.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/README.md +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/client.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/models.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/openenv.yaml +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/pyproject.toml +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/server/Dockerfile +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/server/__ENV_NAME___environment.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/server/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/cli/templates/openenv_env/server/requirements.txt +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/client_types.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/containers/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/containers/runtime/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/containers/runtime/daytona_provider.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/containers/runtime/providers.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/containers/runtime/uv_provider.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/containers/test_local_docker_provider.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_client.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/base_transforms.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/exceptions.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/gradio_theme.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/gradio_ui.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/mcp_environment.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/mcp_types.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/route_config.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/serialization.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/env_server/types.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/evals/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/evals/base.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/evals/types.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/generic_client.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/mcp_client.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/rubrics/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/rubrics/base.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/rubrics/containers.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/rubrics/llm_judge.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/rubrics/trajectory.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/sync_client.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/tools/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/tools/git_server_client.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/tools/local_python_executor.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv/core/utils.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv.egg-info/dependency_links.txt +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv.egg-info/entry_points.txt +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv.egg-info/top_level.txt +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/src/openenv_core/__init__.py +0 -0
- {openenv-0.2.3 → openenv-0.3.0}/tests/test_line_endings.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openenv
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A unified framework for reinforcement learning environments
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -37,13 +37,13 @@ Requires-Dist: tomli-w>=1.2.0; extra == "cli"
|
|
|
37
37
|
Provides-Extra: docs
|
|
38
38
|
Requires-Dist: sphinx==7.2.6; extra == "docs"
|
|
39
39
|
Requires-Dist: pytorch-sphinx-theme2; extra == "docs"
|
|
40
|
-
Requires-Dist: sphinxcontrib.katex==0.9.
|
|
41
|
-
Requires-Dist: docutils<0.
|
|
40
|
+
Requires-Dist: sphinxcontrib.katex==0.9.11; extra == "docs"
|
|
41
|
+
Requires-Dist: docutils<0.23,>=0.18.1; extra == "docs"
|
|
42
42
|
Requires-Dist: sphinx-design==0.6.1; extra == "docs"
|
|
43
|
-
Requires-Dist: sphinxcontrib-mermaid==
|
|
43
|
+
Requires-Dist: sphinxcontrib-mermaid==2.0.2; extra == "docs"
|
|
44
44
|
Requires-Dist: myst-parser; extra == "docs"
|
|
45
45
|
Requires-Dist: sphinxext-opengraph; extra == "docs"
|
|
46
|
-
Requires-Dist: sphinx-sitemap==2.
|
|
46
|
+
Requires-Dist: sphinx-sitemap==2.9.0; extra == "docs"
|
|
47
47
|
Requires-Dist: sphinx-gallery>=0.14.0; extra == "docs"
|
|
48
48
|
Requires-Dist: matplotlib; extra == "docs"
|
|
49
49
|
Requires-Dist: nest-asyncio; extra == "docs"
|
|
@@ -75,7 +75,7 @@ An e2e framework for creating, deploying and using isolated execution environmen
|
|
|
75
75
|
|
|
76
76
|
## Quick Start
|
|
77
77
|
|
|
78
|
-
Install the OpenEnv
|
|
78
|
+
Install the OpenEnv package:
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
81
|
pip install openenv
|
|
@@ -91,7 +91,7 @@ Then use the environment:
|
|
|
91
91
|
|
|
92
92
|
```python
|
|
93
93
|
import asyncio
|
|
94
|
-
from echo_env import
|
|
94
|
+
from echo_env import CallToolAction, EchoEnv
|
|
95
95
|
|
|
96
96
|
async def main():
|
|
97
97
|
# Connect to a running Space (async context manager)
|
|
@@ -101,9 +101,14 @@ async def main():
|
|
|
101
101
|
print(result.observation.echoed_message) # "Echo environment ready!"
|
|
102
102
|
|
|
103
103
|
# Send messages
|
|
104
|
-
result = await client.step(
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
result = await client.step(
|
|
105
|
+
CallToolAction(
|
|
106
|
+
tool_name="echo_message",
|
|
107
|
+
arguments={"message": "Hello, World!"},
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
print(result.observation.result) # "Hello, World!"
|
|
111
|
+
print(result.reward)
|
|
107
112
|
|
|
108
113
|
asyncio.run(main())
|
|
109
114
|
```
|
|
@@ -111,16 +116,21 @@ asyncio.run(main())
|
|
|
111
116
|
**Synchronous usage** is also supported via the `.sync()` wrapper:
|
|
112
117
|
|
|
113
118
|
```python
|
|
114
|
-
from echo_env import
|
|
119
|
+
from echo_env import CallToolAction, EchoEnv
|
|
115
120
|
|
|
116
121
|
# Use .sync() for synchronous context manager
|
|
117
122
|
with EchoEnv(base_url="https://openenv-echo-env.hf.space").sync() as client:
|
|
118
123
|
result = client.reset()
|
|
119
|
-
result = client.step(
|
|
120
|
-
|
|
124
|
+
result = client.step(
|
|
125
|
+
CallToolAction(
|
|
126
|
+
tool_name="echo_message",
|
|
127
|
+
arguments={"message": "Hello, World!"},
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
print(result.observation.result)
|
|
121
131
|
```
|
|
122
132
|
|
|
123
|
-
For a detailed quick start, check out the [docs page](https://meta-pytorch.org/OpenEnv/
|
|
133
|
+
For a detailed quick start, check out the [docs page](https://meta-pytorch.org/OpenEnv/auto_getting_started/index.html).
|
|
124
134
|
|
|
125
135
|
## OpenEnv on partner platforms:
|
|
126
136
|
|
|
@@ -299,7 +309,7 @@ See [`envs/README.md`](envs/README.md) for a complete guide on building environm
|
|
|
299
309
|
|
|
300
310
|
To use an environment:
|
|
301
311
|
1. Install the client: `pip install git+https://huggingface.co/spaces/openenv/echo-env`
|
|
302
|
-
2. Import: `from echo_env import
|
|
312
|
+
2. Import: `from echo_env import CallToolAction, EchoEnv`
|
|
303
313
|
3. Use async (recommended) or sync API:
|
|
304
314
|
|
|
305
315
|
**Async (recommended):**
|
|
@@ -427,12 +437,12 @@ See the [Oumi example](https://github.com/oumi-ai/oumi/blob/main/notebooks/Oumi%
|
|
|
427
437
|
| [Atari Environment](envs/atari_env/README.md) | Classic Arcade Learning Environment tasks for RL benchmarking. |
|
|
428
438
|
| [FinRL Environment](envs/finrl_env/README.md) | Financial market simulations for algorithmic trading experiments. |
|
|
429
439
|
|
|
430
|
-
> Browse the full catalog of community environments at [meta-pytorch.org/OpenEnv/environments](https://meta-pytorch.org/OpenEnv/environments
|
|
440
|
+
> Browse the full catalog of community environments at [meta-pytorch.org/OpenEnv/environments](https://meta-pytorch.org/OpenEnv/environments.html).
|
|
431
441
|
|
|
432
442
|
## Community Support & Acknowledgments
|
|
433
443
|
This is an open and community-centric project. If you would like to add your name here, please put up a pull request and tag @jspisak for review. Ty!!
|
|
434
444
|
|
|
435
|
-
Supporters include: Meta-PyTorch, Hugging Face, [Scaler AI Labs](https://scalerailabs.com), [Patronus AI](https://patronus.ai), [Surge AI](https://surgehq.ai), [LastMile AI](https://www.lastmileai.dev), Unsloth AI, Reflection AI, vLLM, SkyRL (UC-Berkeley), LightningAI, Axolotl AI, Stanford Scaling Intelligence Lab, Mithril, [OpenMined](https://openmined.org/), [Fleet AI](https://fleetai.com), [Halluminate](https://halluminate.ai/), [Turing](https://www.turing.com/), [Scale AI](https://scale.com/) ..
|
|
445
|
+
Supporters include: Meta-PyTorch, Hugging Face, [Scaler AI Labs](https://scalerailabs.com), [Patronus AI](https://patronus.ai), [Surge AI](https://surgehq.ai), [LastMile AI](https://www.lastmileai.dev), Unsloth AI, Reflection AI, vLLM, SkyRL (UC-Berkeley), LightningAI, Axolotl AI, Stanford Scaling Intelligence Lab, Mithril, [OpenMined](https://openmined.org/), [Fleet AI](https://fleetai.com), [Halluminate](https://halluminate.ai/), [Turing](https://www.turing.com/), [Scale AI](https://scale.com/), [Scorecard](https://www.scorecard.io/) ..
|
|
436
446
|
|
|
437
447
|
And we'd also like to acknowledge the team at Farama Foundation as the OpenEnv API was heavily inspired by the work you all have done on Gymnasium. Cheers!
|
|
438
448
|
|
|
@@ -15,7 +15,7 @@ An e2e framework for creating, deploying and using isolated execution environmen
|
|
|
15
15
|
|
|
16
16
|
## Quick Start
|
|
17
17
|
|
|
18
|
-
Install the OpenEnv
|
|
18
|
+
Install the OpenEnv package:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
pip install openenv
|
|
@@ -31,7 +31,7 @@ Then use the environment:
|
|
|
31
31
|
|
|
32
32
|
```python
|
|
33
33
|
import asyncio
|
|
34
|
-
from echo_env import
|
|
34
|
+
from echo_env import CallToolAction, EchoEnv
|
|
35
35
|
|
|
36
36
|
async def main():
|
|
37
37
|
# Connect to a running Space (async context manager)
|
|
@@ -41,9 +41,14 @@ async def main():
|
|
|
41
41
|
print(result.observation.echoed_message) # "Echo environment ready!"
|
|
42
42
|
|
|
43
43
|
# Send messages
|
|
44
|
-
result = await client.step(
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
result = await client.step(
|
|
45
|
+
CallToolAction(
|
|
46
|
+
tool_name="echo_message",
|
|
47
|
+
arguments={"message": "Hello, World!"},
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
print(result.observation.result) # "Hello, World!"
|
|
51
|
+
print(result.reward)
|
|
47
52
|
|
|
48
53
|
asyncio.run(main())
|
|
49
54
|
```
|
|
@@ -51,16 +56,21 @@ asyncio.run(main())
|
|
|
51
56
|
**Synchronous usage** is also supported via the `.sync()` wrapper:
|
|
52
57
|
|
|
53
58
|
```python
|
|
54
|
-
from echo_env import
|
|
59
|
+
from echo_env import CallToolAction, EchoEnv
|
|
55
60
|
|
|
56
61
|
# Use .sync() for synchronous context manager
|
|
57
62
|
with EchoEnv(base_url="https://openenv-echo-env.hf.space").sync() as client:
|
|
58
63
|
result = client.reset()
|
|
59
|
-
result = client.step(
|
|
60
|
-
|
|
64
|
+
result = client.step(
|
|
65
|
+
CallToolAction(
|
|
66
|
+
tool_name="echo_message",
|
|
67
|
+
arguments={"message": "Hello, World!"},
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
print(result.observation.result)
|
|
61
71
|
```
|
|
62
72
|
|
|
63
|
-
For a detailed quick start, check out the [docs page](https://meta-pytorch.org/OpenEnv/
|
|
73
|
+
For a detailed quick start, check out the [docs page](https://meta-pytorch.org/OpenEnv/auto_getting_started/index.html).
|
|
64
74
|
|
|
65
75
|
## OpenEnv on partner platforms:
|
|
66
76
|
|
|
@@ -239,7 +249,7 @@ See [`envs/README.md`](envs/README.md) for a complete guide on building environm
|
|
|
239
249
|
|
|
240
250
|
To use an environment:
|
|
241
251
|
1. Install the client: `pip install git+https://huggingface.co/spaces/openenv/echo-env`
|
|
242
|
-
2. Import: `from echo_env import
|
|
252
|
+
2. Import: `from echo_env import CallToolAction, EchoEnv`
|
|
243
253
|
3. Use async (recommended) or sync API:
|
|
244
254
|
|
|
245
255
|
**Async (recommended):**
|
|
@@ -367,12 +377,12 @@ See the [Oumi example](https://github.com/oumi-ai/oumi/blob/main/notebooks/Oumi%
|
|
|
367
377
|
| [Atari Environment](envs/atari_env/README.md) | Classic Arcade Learning Environment tasks for RL benchmarking. |
|
|
368
378
|
| [FinRL Environment](envs/finrl_env/README.md) | Financial market simulations for algorithmic trading experiments. |
|
|
369
379
|
|
|
370
|
-
> Browse the full catalog of community environments at [meta-pytorch.org/OpenEnv/environments](https://meta-pytorch.org/OpenEnv/environments
|
|
380
|
+
> Browse the full catalog of community environments at [meta-pytorch.org/OpenEnv/environments](https://meta-pytorch.org/OpenEnv/environments.html).
|
|
371
381
|
|
|
372
382
|
## Community Support & Acknowledgments
|
|
373
383
|
This is an open and community-centric project. If you would like to add your name here, please put up a pull request and tag @jspisak for review. Ty!!
|
|
374
384
|
|
|
375
|
-
Supporters include: Meta-PyTorch, Hugging Face, [Scaler AI Labs](https://scalerailabs.com), [Patronus AI](https://patronus.ai), [Surge AI](https://surgehq.ai), [LastMile AI](https://www.lastmileai.dev), Unsloth AI, Reflection AI, vLLM, SkyRL (UC-Berkeley), LightningAI, Axolotl AI, Stanford Scaling Intelligence Lab, Mithril, [OpenMined](https://openmined.org/), [Fleet AI](https://fleetai.com), [Halluminate](https://halluminate.ai/), [Turing](https://www.turing.com/), [Scale AI](https://scale.com/) ..
|
|
385
|
+
Supporters include: Meta-PyTorch, Hugging Face, [Scaler AI Labs](https://scalerailabs.com), [Patronus AI](https://patronus.ai), [Surge AI](https://surgehq.ai), [LastMile AI](https://www.lastmileai.dev), Unsloth AI, Reflection AI, vLLM, SkyRL (UC-Berkeley), LightningAI, Axolotl AI, Stanford Scaling Intelligence Lab, Mithril, [OpenMined](https://openmined.org/), [Fleet AI](https://fleetai.com), [Halluminate](https://halluminate.ai/), [Turing](https://www.turing.com/), [Scale AI](https://scale.com/), [Scorecard](https://www.scorecard.io/) ..
|
|
376
386
|
|
|
377
387
|
And we'd also like to acknowledge the team at Farama Foundation as the OpenEnv API was heavily inspired by the work you all have done on Gymnasium. Cheers!
|
|
378
388
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openenv"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "A unified framework for reinforcement learning environments"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -52,13 +52,13 @@ cli = [
|
|
|
52
52
|
docs = [
|
|
53
53
|
"sphinx==7.2.6",
|
|
54
54
|
"pytorch-sphinx-theme2",
|
|
55
|
-
"sphinxcontrib.katex==0.9.
|
|
56
|
-
"docutils>=0.18.1,<0.
|
|
55
|
+
"sphinxcontrib.katex==0.9.11",
|
|
56
|
+
"docutils>=0.18.1,<0.23",
|
|
57
57
|
"sphinx-design==0.6.1",
|
|
58
|
-
"sphinxcontrib-mermaid==
|
|
58
|
+
"sphinxcontrib-mermaid==2.0.2",
|
|
59
59
|
"myst-parser",
|
|
60
60
|
"sphinxext-opengraph",
|
|
61
|
-
"sphinx-sitemap==2.
|
|
61
|
+
"sphinx-sitemap==2.9.0",
|
|
62
62
|
"sphinx-gallery>=0.14.0",
|
|
63
63
|
"matplotlib",
|
|
64
64
|
"nest-asyncio",
|
|
@@ -17,7 +17,7 @@ __all__ = [
|
|
|
17
17
|
|
|
18
18
|
def _load_package_version() -> str:
|
|
19
19
|
"""Resolve the installed distribution version for the OpenEnv package."""
|
|
20
|
-
for distribution_name in ("openenv", "openenv"):
|
|
20
|
+
for distribution_name in ("openenv", "openenv-core"):
|
|
21
21
|
try:
|
|
22
22
|
return metadata.version(distribution_name)
|
|
23
23
|
except metadata.PackageNotFoundError:
|
|
@@ -369,14 +369,14 @@ class EnvironmentDiscovery:
|
|
|
369
369
|
logger.warning(f"Failed to get installed packages: {e}")
|
|
370
370
|
return environments
|
|
371
371
|
|
|
372
|
-
# Filter for openenv-* packages
|
|
372
|
+
# Filter for openenv-* environment packages; ignore the legacy core wheel.
|
|
373
373
|
for dist in distributions:
|
|
374
374
|
package_name = dist.metadata["Name"]
|
|
375
375
|
|
|
376
376
|
if not package_name.startswith("openenv-"):
|
|
377
377
|
continue
|
|
378
378
|
|
|
379
|
-
if package_name == "openenv":
|
|
379
|
+
if package_name == "openenv-core":
|
|
380
380
|
continue
|
|
381
381
|
|
|
382
382
|
# Get module name (e.g., "openenv-echo_env" → "echo_env")
|
|
@@ -14,7 +14,16 @@ following the Hugging Face CLI pattern.
|
|
|
14
14
|
import sys
|
|
15
15
|
|
|
16
16
|
import typer
|
|
17
|
-
from openenv.cli.commands import
|
|
17
|
+
from openenv.cli.commands import (
|
|
18
|
+
build,
|
|
19
|
+
collect,
|
|
20
|
+
fork,
|
|
21
|
+
init,
|
|
22
|
+
push,
|
|
23
|
+
serve,
|
|
24
|
+
skills,
|
|
25
|
+
validate,
|
|
26
|
+
)
|
|
18
27
|
|
|
19
28
|
# Create the main CLI app
|
|
20
29
|
app = typer.Typer(
|
|
@@ -47,6 +56,10 @@ app.add_typer(
|
|
|
47
56
|
name="skills",
|
|
48
57
|
help="Manage OpenEnv skills for AI assistants",
|
|
49
58
|
)
|
|
59
|
+
app.command(
|
|
60
|
+
name="collect",
|
|
61
|
+
help="Collect rollouts from a deployed OpenEnv environment",
|
|
62
|
+
)(collect.collect)
|
|
50
63
|
|
|
51
64
|
|
|
52
65
|
# Entry point for setuptools
|
|
@@ -11,6 +11,8 @@ This module provides functions to check if environments are properly
|
|
|
11
11
|
configured for multi-mode deployment (Docker, direct Python, notebooks, clusters).
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
+
import ast
|
|
15
|
+
import re
|
|
14
16
|
from pathlib import Path
|
|
15
17
|
from typing import Any
|
|
16
18
|
from urllib.parse import urlparse
|
|
@@ -426,6 +428,79 @@ def validate_running_environment(
|
|
|
426
428
|
return report
|
|
427
429
|
|
|
428
430
|
|
|
431
|
+
def _has_main_guard_call(app_content: str) -> bool:
|
|
432
|
+
"""Return True when the module calls main() under a __main__ guard."""
|
|
433
|
+
try:
|
|
434
|
+
tree = ast.parse(app_content)
|
|
435
|
+
except SyntaxError:
|
|
436
|
+
return (
|
|
437
|
+
"__name__" in app_content
|
|
438
|
+
and "__main__" in app_content
|
|
439
|
+
and "main(" in app_content
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
for node in ast.iter_child_nodes(tree):
|
|
443
|
+
if not isinstance(node, ast.If):
|
|
444
|
+
continue
|
|
445
|
+
|
|
446
|
+
test = node.test
|
|
447
|
+
if not (
|
|
448
|
+
isinstance(test, ast.Compare)
|
|
449
|
+
and isinstance(test.left, ast.Name)
|
|
450
|
+
and test.left.id == "__name__"
|
|
451
|
+
and len(test.ops) == 1
|
|
452
|
+
and isinstance(test.ops[0], ast.Eq)
|
|
453
|
+
and len(test.comparators) == 1
|
|
454
|
+
and isinstance(test.comparators[0], ast.Constant)
|
|
455
|
+
and test.comparators[0].value == "__main__"
|
|
456
|
+
):
|
|
457
|
+
continue
|
|
458
|
+
|
|
459
|
+
for guarded_node in node.body:
|
|
460
|
+
for candidate in ast.walk(guarded_node):
|
|
461
|
+
if isinstance(candidate, ast.Call):
|
|
462
|
+
func = candidate.func
|
|
463
|
+
if isinstance(func, ast.Name) and func.id == "main":
|
|
464
|
+
return True
|
|
465
|
+
|
|
466
|
+
return False
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
_OPENENV_RUNTIME_DEP_RE = re.compile(r"^openenv(?:\s*(?:$|[<>=!~@;])|\[)")
|
|
470
|
+
_LEGACY_OPENENV_CORE_DEP_RE = re.compile(r"^openenv-core(?:\s*(?:$|[<>=!~@;])|\[)")
|
|
471
|
+
_OPENENV_DOCKER_INSTALL_RE = re.compile(
|
|
472
|
+
r"(?<![a-z0-9_.-])openenv(?:\s*(?:$|[<>=!~@;])|\[)"
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def _dockerfile_installs_openenv_runtime(env_path: Path) -> bool:
|
|
477
|
+
"""Return True when a Docker deployment installs OpenEnv outside pyproject."""
|
|
478
|
+
for dockerfile_path in (
|
|
479
|
+
env_path / "server" / "Dockerfile",
|
|
480
|
+
env_path / "Dockerfile",
|
|
481
|
+
):
|
|
482
|
+
if not dockerfile_path.exists():
|
|
483
|
+
continue
|
|
484
|
+
|
|
485
|
+
try:
|
|
486
|
+
dockerfile = dockerfile_path.read_text(encoding="utf-8")
|
|
487
|
+
except OSError:
|
|
488
|
+
continue
|
|
489
|
+
|
|
490
|
+
for line in dockerfile.splitlines():
|
|
491
|
+
stripped = line.strip().lower()
|
|
492
|
+
if not stripped or stripped.startswith("#"):
|
|
493
|
+
continue
|
|
494
|
+
if _OPENENV_DOCKER_INSTALL_RE.search(stripped):
|
|
495
|
+
return True
|
|
496
|
+
if "openenv-core" in stripped:
|
|
497
|
+
return True
|
|
498
|
+
if "git+https://github.com/meta-pytorch/openenv" in stripped:
|
|
499
|
+
return True
|
|
500
|
+
|
|
501
|
+
return False
|
|
502
|
+
|
|
503
|
+
|
|
429
504
|
def validate_multi_mode_deployment(env_path: Path) -> tuple[bool, list[str]]:
|
|
430
505
|
"""
|
|
431
506
|
Validate that an environment is ready for multi-mode deployment.
|
|
@@ -475,15 +550,12 @@ def validate_multi_mode_deployment(env_path: Path) -> tuple[bool, list[str]]:
|
|
|
475
550
|
|
|
476
551
|
# Check required dependencies
|
|
477
552
|
deps = [dep.lower() for dep in pyproject.get("project", {}).get("dependencies", [])]
|
|
478
|
-
has_openenv = any(
|
|
479
|
-
|
|
480
|
-
)
|
|
481
|
-
has_legacy_core = any(dep.startswith("openenv") for dep in deps)
|
|
553
|
+
has_openenv = any(_OPENENV_RUNTIME_DEP_RE.match(dep) for dep in deps)
|
|
554
|
+
has_legacy_core = any(_LEGACY_OPENENV_CORE_DEP_RE.match(dep) for dep in deps)
|
|
555
|
+
has_dockerfile_core = _dockerfile_installs_openenv_runtime(env_path)
|
|
482
556
|
|
|
483
|
-
if not (has_openenv or has_legacy_core):
|
|
484
|
-
issues.append(
|
|
485
|
-
"Missing required dependency: openenv>=0.2.0 (or openenv>=0.2.0)"
|
|
486
|
-
)
|
|
557
|
+
if not (has_openenv or has_legacy_core or has_dockerfile_core):
|
|
558
|
+
issues.append("Missing required dependency: openenv>=0.2.0")
|
|
487
559
|
|
|
488
560
|
# Check server/app.py exists
|
|
489
561
|
server_app = env_path / "server" / "app.py"
|
|
@@ -496,7 +568,7 @@ def validate_multi_mode_deployment(env_path: Path) -> tuple[bool, list[str]]:
|
|
|
496
568
|
issues.append("server/app.py missing main() function")
|
|
497
569
|
|
|
498
570
|
# Check if main() is callable
|
|
499
|
-
if
|
|
571
|
+
if not _has_main_guard_call(app_content):
|
|
500
572
|
issues.append(
|
|
501
573
|
"server/app.py main() function not callable (missing if __name__ == '__main__')"
|
|
502
574
|
)
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
import re
|
|
11
12
|
import shutil
|
|
12
13
|
import subprocess
|
|
13
14
|
import sys
|
|
@@ -21,6 +22,18 @@ from .._cli_utils import console
|
|
|
21
22
|
|
|
22
23
|
app = typer.Typer(help="Build Docker images for OpenEnv environments")
|
|
23
24
|
|
|
25
|
+
_OPENENV_RUNTIME_DEP_RE = re.compile(r"^openenv(?:\s*(?:$|[<>=!~@;])|\[)")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _is_openenv_runtime_dependency(dep: str) -> bool:
|
|
29
|
+
"""Return True for the OpenEnv runtime distribution, not openenv-* envs."""
|
|
30
|
+
normalized = dep.strip().lower()
|
|
31
|
+
return (
|
|
32
|
+
_OPENENV_RUNTIME_DEP_RE.match(normalized) is not None
|
|
33
|
+
or normalized.startswith("openenv-core")
|
|
34
|
+
or normalized.startswith("openenv_core")
|
|
35
|
+
)
|
|
36
|
+
|
|
24
37
|
|
|
25
38
|
def _detect_build_context(env_path: Path) -> tuple[str, Path, Path | None]:
|
|
26
39
|
"""
|
|
@@ -156,19 +169,15 @@ def _prepare_inrepo_build(env_path: Path, repo_root: Path, temp_dir: Path) -> Pa
|
|
|
156
169
|
pyproject = tomli.load(f)
|
|
157
170
|
deps = pyproject.get("project", {}).get("dependencies", [])
|
|
158
171
|
|
|
159
|
-
# Replace
|
|
172
|
+
# Replace OpenEnv package references with local source.
|
|
160
173
|
new_deps = []
|
|
161
174
|
for dep in deps:
|
|
162
|
-
if (
|
|
163
|
-
dep.startswith("openenv")
|
|
164
|
-
or dep.startswith("openenv_core")
|
|
165
|
-
or dep.startswith("openenv")
|
|
166
|
-
):
|
|
175
|
+
if _is_openenv_runtime_dependency(dep):
|
|
167
176
|
# Skip - we'll use local core
|
|
168
177
|
continue
|
|
169
178
|
new_deps.append(dep)
|
|
170
179
|
|
|
171
|
-
# Write back with local
|
|
180
|
+
# Write back with local OpenEnv reference
|
|
172
181
|
pyproject["project"]["dependencies"] = new_deps + [
|
|
173
182
|
"openenv @ file:///app/env/openenv"
|
|
174
183
|
]
|