Prithvigg commited on
Commit
e8b86e7
·
1 Parent(s): c57b5d0

fix: clean up file structure

Browse files
Files changed (3) hide show
  1. echo_environment.py +0 -196
  2. server/Dockerfile +0 -80
  3. server/__init__.py +0 -11
echo_environment.py DELETED
@@ -1,196 +0,0 @@
1
- # Copyright (c) Meta Platforms, Inc. and affiliates.
2
- # All rights reserved.
3
- #
4
- # This source code is licensed under the BSD-style license found in the
5
- # LICENSE file in the root directory of this source tree.
6
-
7
- """
8
- Echo Environment Implementation.
9
-
10
- A pure MCP environment that echoes back messages sent to it.
11
- This demonstrates how to build an MCPEnvironment with inline FastMCP tools.
12
-
13
- All interactions happen through MCP tools:
14
- - `echo_message(message)`: Echo back the provided message
15
- - `echo_with_length(message)`: Echo back the message with its length
16
-
17
- Example:
18
- >>> from openenv.core.env_server.mcp_types import ListToolsAction, CallToolAction
19
- >>> env = EchoEnvironment()
20
- >>> env.reset()
21
- >>>
22
- >>> # List available tools
23
- >>> obs = env.step(ListToolsAction())
24
- >>> print([t.name for t in obs.tools]) # ["echo_message", "echo_with_length"]
25
- >>>
26
- >>> # Call a tool
27
- >>> obs = env.step(CallToolAction(tool_name="echo_message", arguments={"message": "Hi!"}))
28
- >>> print(obs.result) # "Hi!"
29
- """
30
-
31
- from typing import Any, Optional
32
- from uuid import uuid4
33
-
34
- # Support both in-repo and standalone imports
35
- try:
36
- # In-repo imports (when running from OpenEnv repository)
37
- from openenv.core.env_server.mcp_environment import MCPEnvironment
38
- from openenv.core.env_server.types import Action, Observation, State
39
- except ImportError:
40
- # Standalone imports (when environment is standalone with openenv from pip)
41
- from openenv.core.env_server.mcp_environment import MCPEnvironment
42
- from openenv.core.env_server.types import Action, Observation, State
43
-
44
- from fastmcp import FastMCP
45
-
46
-
47
- class EchoEnvironment(MCPEnvironment):
48
- """
49
- A pure MCP echo environment that echoes back messages.
50
-
51
- This environment exposes all functionality through MCP tools:
52
- - `echo_message`: Echo back the provided message
53
- - `echo_with_length`: Echo back the message with its length
54
-
55
- The environment inherits MCP support (ListToolsAction, CallToolAction)
56
- from the MCPEnvironment base class. No legacy action types are supported.
57
-
58
- Example using MCPToolClient:
59
- >>> from openenv.core.mcp_client import MCPToolClient
60
- >>>
61
- >>> with MCPToolClient(base_url="http://localhost:8000") as env:
62
- ... env.reset()
63
- ... tools = env.list_tools()
64
- ... print([t.name for t in tools])
65
- ... result = env.call_tool("echo_message", message="Hello!")
66
- ... print(result)
67
- """
68
-
69
- def __init__(self):
70
- """Initialize the echo environment with MCP server and tools."""
71
- # Create MCP server and define tools inline
72
- mcp = FastMCP("echo_env")
73
-
74
- @mcp.tool
75
- def echo_message(message: str) -> str:
76
- """
77
- Echo back the provided message.
78
-
79
- Args:
80
- message: The message to echo back
81
-
82
- Returns:
83
- The same message that was provided
84
- """
85
- return message
86
-
87
- @mcp.tool
88
- def echo_with_length(message: str) -> dict:
89
- """
90
- Echo back the message with its length.
91
-
92
- Args:
93
- message: The message to echo back
94
-
95
- Returns:
96
- Dictionary with the message and its length
97
- """
98
- return {"message": message, "length": len(message)}
99
-
100
- # Pass the MCP server to the base class
101
- super().__init__(mcp)
102
- self._state = State(episode_id=str(uuid4()), step_count=0)
103
- self._reset_count = 0
104
-
105
- def reset(
106
- self,
107
- seed: Optional[int] = None,
108
- episode_id: Optional[str] = None,
109
- **kwargs: Any,
110
- ) -> Observation:
111
- """
112
- Reset the environment.
113
-
114
- Args:
115
- seed: Optional random seed (unused in echo env)
116
- episode_id: Optional episode ID to use
117
- **kwargs: Additional reset options
118
-
119
- Returns:
120
- Observation indicating the environment is ready
121
- """
122
- self._state = State(
123
- episode_id=episode_id or str(uuid4()),
124
- step_count=0,
125
- )
126
- self._reset_count += 1
127
-
128
- return Observation(
129
- done=False,
130
- reward=0.0,
131
- metadata={"status": "ready", "message": "Echo environment ready!"},
132
- )
133
-
134
- def _step_impl(
135
- self,
136
- action: Action,
137
- timeout_s: Optional[float] = None,
138
- **kwargs: Any,
139
- ) -> Observation:
140
- """
141
- Handle non-MCP actions.
142
-
143
- This environment only supports MCP actions (ListToolsAction, CallToolAction).
144
- Any other action type returns an error observation.
145
-
146
- Args:
147
- action: The action to execute
148
- timeout_s: Optional timeout (unused)
149
- **kwargs: Additional arguments
150
-
151
- Returns:
152
- Observation with error for unknown action types
153
- """
154
- return Observation(
155
- done=False,
156
- reward=0.0,
157
- metadata={
158
- "error": f"Unknown action type: {type(action).__name__}. "
159
- "Use ListToolsAction or CallToolAction for MCP interactions."
160
- },
161
- )
162
-
163
- def step(
164
- self,
165
- action: Action,
166
- timeout_s: Optional[float] = None,
167
- **kwargs: Any,
168
- ) -> Observation:
169
- """
170
- Execute a step in the environment.
171
-
172
- Delegates to base class for MCP actions. Increments step count for all actions.
173
-
174
- Args:
175
- action: The MCP action to execute (ListToolsAction or CallToolAction)
176
- timeout_s: Optional timeout for the action
177
- **kwargs: Additional arguments
178
-
179
- Returns:
180
- Observation from the action execution
181
- """
182
- # Increment step count for all actions
183
- self._state.step_count += 1
184
-
185
- # Let the base class handle MCP actions and non-MCP routing
186
- return super().step(action, timeout_s=timeout_s, **kwargs)
187
-
188
- @property
189
- def state(self) -> State:
190
- """
191
- Get the current environment state.
192
-
193
- Returns:
194
- Current State with episode_id and step_count
195
- """
196
- return self._state
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
server/Dockerfile DELETED
@@ -1,80 +0,0 @@
1
- # Copyright (c) Meta Platforms, Inc. and affiliates.
2
- # All rights reserved.
3
- #
4
- # This source code is licensed under the BSD-style license found in the
5
- # LICENSE file in the root directory of this source tree.
6
-
7
- # Multi-stage build using openenv-base
8
- # This Dockerfile is flexible and works for both:
9
- # - In-repo environments (with local src/core)
10
- # - Standalone environments (with openenv-core from pip)
11
- # The build script (openenv build) handles context detection and sets appropriate build args.
12
-
13
- ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest
14
- FROM ${BASE_IMAGE} AS builder
15
-
16
- WORKDIR /app
17
-
18
- # Build argument to control whether we're building standalone or in-repo
19
- ARG BUILD_MODE=in-repo
20
-
21
- # Copy environment code (always at root of build context)
22
- COPY . /app/env
23
-
24
- # For in-repo builds, openenv-core is already in the pyproject.toml dependencies
25
- # For standalone builds, openenv-core will be installed from pip via pyproject.toml
26
- WORKDIR /app/env
27
-
28
- # Ensure uv is available (for local builds where base image lacks it)
29
- RUN if ! command -v uv >/dev/null 2>&1; then \
30
- curl -LsSf https://astral.sh/uv/install.sh | sh && \
31
- mv /root/.local/bin/uv /usr/local/bin/uv && \
32
- mv /root/.local/bin/uvx /usr/local/bin/uvx; \
33
- fi
34
-
35
- # Install git for building from git repos (build-time only)
36
- RUN apt-get update && apt-get install -y --no-install-recommends \
37
- git \
38
- && rm -rf /var/lib/apt/lists/*
39
-
40
- # Install dependencies using uv sync
41
- # First pass: install dependencies without the project (for better caching)
42
- # Second pass: install the project itself
43
- RUN --mount=type=cache,target=/root/.cache/uv \
44
- if [ -f uv.lock ]; then \
45
- uv sync --frozen --no-install-project --no-editable; \
46
- else \
47
- uv sync --no-install-project --no-editable; \
48
- fi
49
-
50
- RUN --mount=type=cache,target=/root/.cache/uv \
51
- if [ -f uv.lock ]; then \
52
- uv sync --frozen --no-editable; \
53
- else \
54
- uv sync --no-editable; \
55
- fi
56
-
57
- # Final runtime stage
58
- FROM ${BASE_IMAGE}
59
-
60
- WORKDIR /app
61
-
62
- # Copy the virtual environment from builder
63
- COPY --from=builder /app/env/.venv /app/.venv
64
-
65
- # Copy the environment code
66
- COPY --from=builder /app/env /app/env
67
-
68
- # Set PATH to use the virtual environment
69
- ENV PATH="/app/.venv/bin:$PATH"
70
-
71
- # Set PYTHONPATH so imports work correctly
72
- ENV PYTHONPATH="/app/env:$PYTHONPATH"
73
-
74
- # Health check using Python (more portable than curl/wget)
75
- HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
76
- CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
77
-
78
- # Run the FastAPI server
79
- # The module path is constructed to work with the /app/env structure
80
- CMD ["sh", "-c", "cd /app/env && uvicorn server.app:app --host 0.0.0.0 --port 8000"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
server/__init__.py DELETED
@@ -1,11 +0,0 @@
1
- # Copyright (c) Meta Platforms, Inc. and affiliates.
2
- # All rights reserved.
3
- #
4
- # This source code is licensed under the BSD-style license found in the
5
- # LICENSE file in the root directory of this source tree.
6
-
7
- """Echo environment server components."""
8
-
9
- from .echo_environment import EchoEnvironment
10
-
11
- __all__ = ["EchoEnvironment"]