Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docs/source/environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,48 @@ Secure sandbox with filesystem access and evaluation hooks for executing generat
```
````

````{grid-item-card} Jupyter
:class-card: sd-border-1

Notebook-style coding environment backed by E2B with setup/verify hooks and a web UI for interactive runs.

+++
```{button-link} environments/jupyter.html
:color: primary
:outline:

{octicon}`file;1em` Docs
```
````

````{grid-item-card} Terminus
:class-card: sd-border-1

Terminal-first coding environment with high-contrast shell output and session controls for execute/verify/close flows.

+++
```{button-link} environments/terminus.html
:color: primary
:outline:

{octicon}`file;1em` Docs
```
````

````{grid-item-card} Coding Tools
:class-card: sd-border-1

SETA-style multi-tool coding environment with shell, file editing, search, todos, and submit verification.

+++
```{button-link} environments/coding_tools.html
:color: primary
:outline:

{octicon}`file;1em` Docs
```
````

````{grid-item-card} Chat
:class-card: sd-border-1

Expand Down Expand Up @@ -546,6 +588,9 @@ A suite of 400 environments that procedurally generate reasoning problems for LM

environments/echo
environments/coding
environments/jupyter
environments/terminus
environments/coding_tools
environments/chat
environments/atari
environments/openspiel
Expand Down
2 changes: 2 additions & 0 deletions docs/source/environments/coding_tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```{include} ../../../envs/coding_tools_env/README.md
```
2 changes: 2 additions & 0 deletions docs/source/environments/jupyter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```{include} ../../../envs/jupyter_env/README.md
```
2 changes: 2 additions & 0 deletions docs/source/environments/terminus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```{include} ../../../envs/terminus_env/README.md
```
15 changes: 15 additions & 0 deletions envs/coding_tools_env/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.venv
.git
.gitignore
.env
__pycache__/
*.pyc
*.pyo
*.pyd
*.pyw
*.pyz
*.pywz
*.pyzw
*.pyzwz


73 changes: 73 additions & 0 deletions envs/coding_tools_env/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: Coding Tools Environment Server
emoji: 🧰
colorFrom: green
colorTo: gray
sdk: docker
pinned: false
app_port: 8000
base_path: /web
tags:
- openenv
- coding
- tools
- e2b
short_description: SETA-style multi-tool coding environment backed by E2B
---

# Coding Tools Environment

`coding_tools_env` is an E2B-backed multi-tool coding environment with explicit
filesystem and shell tools. The tool surface is modeled after
[SETA](https://github.com/EnvCommons/SETA).

Each episode creates a fresh E2B sandbox. Reset accepts setup and verify
commands. Verify commands are used by `submit_solution`.

## Tools

- `bash(command, timeout=30)`
- `read(file_path, offset=None, limit=None)`
- `write(file_path, content)`
- `edit(file_path, old_string, new_string, replace_all=False)`
- `multi_edit(file_path, edits)`
- `glob(pattern, path=None)`
- `grep(pattern, path=None, include=None)`
- `ls(path=".", ignore=None)`
- `todo_write(todos)`
- `submit_solution()`

## Quick Start

```python
from coding_tools_env import CodingToolsEnv

with CodingToolsEnv(base_url="http://localhost:8000").sync() as env:
env.reset(
setup=["mkdir -p /home/user/work"],
verify=["test -f /home/user/work/answer.txt"],
)
print(env.call_tool("write", file_path="/home/user/work/answer.txt", content="done\n"))
print(env.call_tool("submit_solution"))
```

## Local Server

```bash
cd envs/coding_tools_env
E2B_API_KEY=e2b_... uv run --project . server
```

## Docker

```bash
cd envs/coding_tools_env
openenv build -t coding-tools-env
docker run -p 8000:8000 -e E2B_API_KEY=e2b_... coding-tools-env
```

## Configuration

- `E2B_API_KEY`: required when resetting an episode.
- `MAX_CONCURRENT_ENVS`: max concurrent sessions (default `4`).

22 changes: 22 additions & 0 deletions envs/coding_tools_env/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

"""Coding Tools Environment for OpenEnv."""

from openenv.core.env_server.mcp_types import CallToolAction, ListToolsAction

from .client import CodingToolsEnv
from .models import CodingToolsState, CommandResult, EditSpec, TodoItem

__all__ = [
"CodingToolsEnv",
"CodingToolsState",
"CommandResult",
"TodoItem",
"EditSpec",
"CallToolAction",
"ListToolsAction",
]
15 changes: 15 additions & 0 deletions envs/coding_tools_env/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

"""Client for coding_tools_env."""

from openenv.core.mcp_client import MCPToolClient


class CodingToolsEnv(MCPToolClient):
"""MCP client for coding_tools_env."""

pass
55 changes: 55 additions & 0 deletions envs/coding_tools_env/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

"""Models for coding_tools_env."""

from __future__ import annotations

from typing import Any

from openenv.core.env_server.types import State
from pydantic import BaseModel, Field


class CommandResult(BaseModel):
"""Normalized result for one tool execution."""

tool: str
ok: bool
output: str = ""
error: str | None = None
metadata: dict[str, Any] = Field(default_factory=dict)


class TodoItem(BaseModel):
"""Todo item tracked by todo_write."""

id: str
content: str
status: str
priority: str


class CodingToolsState(State):
"""Per-session state for coding_tools_env."""

sandbox_id: str | None = None
setup_results: list[CommandResult] = Field(default_factory=list)
verify_commands: list[str] = Field(default_factory=list)
verify_results: list[CommandResult] = Field(default_factory=list)
todos: list[TodoItem] = Field(default_factory=list)
tool_history: list[CommandResult] = Field(default_factory=list)
submitted: bool = False
last_reward: float | None = None
last_error: str | None = None


class EditSpec(BaseModel):
"""One edit operation for multi_edit."""

old_string: str
new_string: str
replace_all: bool = False
7 changes: 7 additions & 0 deletions envs/coding_tools_env/openenv.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spec_version: 1
name: coding_tools_env
type: space
runtime: fastapi
app: server.app:app
port: 8000

42 changes: 42 additions & 0 deletions envs/coding_tools_env/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

[build-system]
requires = ["setuptools>=45", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "openenv-coding_tools_env"
version = "0.1.0"
description = "SETA-style coding tools environment for OpenEnv backed by E2B"
requires-python = ">=3.10"
dependencies = [
"openenv-core[core]>=0.2.2",
"e2b-code-interpreter>=1.0.0",
"fastapi>=0.115.0",
"fastmcp>=3.0.0",
"gradio>=4.0.0",
"pydantic>=2.0.0",
"requests>=2.31.0",
"uvicorn>=0.24.0",
]

[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"pytest-cov>=4.0.0",
]

[project.scripts]
server = "coding_tools_env.server.app:main"

[tool.setuptools]
include-package-data = true
packages = ["coding_tools_env", "coding_tools_env.server"]
package-dir = { "coding_tools_env" = ".", "coding_tools_env.server" = "server" }

[tool.setuptools.package-data]
coding_tools_env = ["**/*.txt", "**/*.yaml"]
81 changes: 81 additions & 0 deletions envs/coding_tools_env/server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# Multi-stage build using openenv-base
# This Dockerfile is flexible and works for both:
# - In-repo environments (with local OpenEnv sources)
# - Standalone environments (with openenv from PyPI/Git)
# The build script (openenv build) handles context detection and sets appropriate build args.

ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest
FROM ${BASE_IMAGE} AS builder

WORKDIR /app

# Ensure git is available (required for installing dependencies from VCS)
RUN apt-get update && \
apt-get install -y --no-install-recommends git && \
rm -rf /var/lib/apt/lists/*

# Build argument to control whether we're building standalone or in-repo
ARG BUILD_MODE=in-repo
ARG ENV_NAME=coding_tools_env

# Copy environment code (always at root of build context)
COPY . /app/env

# For in-repo builds, openenv is already vendored in the build context
# For standalone builds, openenv will be installed via pyproject.toml
WORKDIR /app/env

# Ensure uv is available (for local builds where base image lacks it)
RUN if ! command -v uv >/dev/null 2>&1; then \
curl -LsSf https://astral.sh/uv/install.sh | sh && \
mv /root/.local/bin/uv /usr/local/bin/uv && \
mv /root/.local/bin/uvx /usr/local/bin/uvx; \
fi

# Install dependencies using uv sync
# If uv.lock exists, use it; otherwise resolve on the fly
RUN --mount=type=cache,target=/root/.cache/uv \
if [ -f uv.lock ]; then \
uv sync --frozen --no-install-project --no-editable; \
else \
uv sync --no-install-project --no-editable; \
fi

RUN --mount=type=cache,target=/root/.cache/uv \
if [ -f uv.lock ]; then \
uv sync --frozen --no-editable; \
else \
uv sync --no-editable; \
fi

# Final runtime stage
FROM ${BASE_IMAGE}

WORKDIR /app

# Copy the virtual environment from builder
COPY --from=builder /app/env/.venv /app/.venv

# Copy the environment code
COPY --from=builder /app/env /app/env

# Set PATH to use the virtual environment
ENV PATH="/app/.venv/bin:$PATH"

# Set PYTHONPATH so imports work correctly
ENV PYTHONPATH="/app/env:$PYTHONPATH"
ENV ENABLE_WEB_INTERFACE=true

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=2).read()" || exit 1

# Run the FastAPI server
# The module path is constructed to work with the /app/env structure
CMD ["sh", "-c", "cd /app/env && uvicorn server.app:app --host 0.0.0.0 --port 8000"]
11 changes: 11 additions & 0 deletions envs/coding_tools_env/server/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

"""Coding Tools Env environment server components."""

from .coding_tools_env_environment import CodingToolsEnvironment

__all__ = ["CodingToolsEnvironment"]
Loading