Skip to content
Open
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
22 changes: 22 additions & 0 deletions environments/swe/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# swe

Any agent harness for swe tasks in a sandbox.
Run by `sandbox_agent`, scored by `anyswe` resources server.

Prepare data:

```bash
python environments/swe/prepare.py --input-jsonl <swebench_verified.jsonl> --limit 20
```

Start env:
```bash
ng_run "+config_paths=[environments/swe/config.yaml]"
```

Generate rollouts:
```bash
ng_collect_rollouts ...
```

TODO more content
97 changes: 97 additions & 0 deletions environments/swe/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
anyswe:
resources_servers:
anyswe:
entrypoint: app.py
domain: agent
verified: false
description: Grades SWE task patches in fresh sandboxes with the official SWE-bench evaluation scripts.
value: Software engineering agent capabilities.
max_pass_to_pass: 20
eval_timeout: 1800
sandbox_provider:
opensandbox:
connection:
domain: ${oc.env:OPENSANDBOX_DOMAIN}
api_key: ${oc.env:OPENSANDBOX_API_KEY}
protocol: http
use_server_proxy: true
request_timeout_s: 1800
sandbox_opencode_swe:
responses_api_agents:
sandbox_agent:
entrypoint: app.py
domain: agent
verified: false
description: opencode CLI harness solving SWE-bench tasks inside per-instance OpenSandbox images.
value: Software engineering agent capabilities with in-sandbox grading.
resources_server:
type: resources_servers
name: anyswe
model_server:
type: responses_api_models
name: policy_model
concurrency: 64
agent_module: responses_api_agents.opencode_agent.app
agent_class: OpenCodeAgent
agent_config_class: OpenCodeAgentConfig
agent_config:
resources_server:
type: resources_servers
name: anyswe
concurrency: 1
command: opencode
model: nvinf/policy_model
thinking: true
timeout: 3600
opencode_version: 1.17.8
repo_dir: /testbed
extra_args:
- --dangerously-skip-permissions
system_prompt: |
You are a software engineering agent. The repository is checked out at /testbed with the
bug already reproduced there. Investigate the issue described by the user, edit the code
under /testbed to fix it, and do not modify tests. Work only with your bash tool.
opencode_config:
permission:
bash: allow
edit: allow
webfetch: allow
provider:
nvinf:
npm: "@ai-sdk/openai-compatible"
options:
baseURL: __SANDBOX_MODEL_URL__/v1
apiKey: gym # pragma: allowlist secret
models:
policy_model:
interleaved:
field: reasoning
limit:
context: 262144
output: 262144
sandbox_provider:
opensandbox:
connection:
domain: ${oc.env:OPENSANDBOX_DOMAIN}
api_key: ${oc.env:OPENSANDBOX_API_KEY}
protocol: http
use_server_proxy: true
request_timeout_s: 1800
sandbox_image: ubuntu:24.04
sandbox_spec:
ttl_s: 7200
resources:
cpu: 2
memory_mib: 8192
disk_gib: 30
setup_commands:
- "command -v curl > /dev/null 2>&1 || (apt-get -qq update && apt-get -y -qq install curl ca-certificates > /dev/null 2>&1) || (yum -y -q install curl ca-certificates > /dev/null 2>&1) || true"
- "mkdir -p /deps && curl -fsSL https://github.com/astral-sh/python-build-standalone/releases/download/20241219/cpython-3.12.8+20241219-x86_64-unknown-linux-gnu-install_only.tar.gz | tar xz -C /deps --strip-components=1"
- "/deps/bin/python3 -m pip -q install nemo-gym"
- "curl -fsSL https://opencode.ai/install | VERSION=1.17.8 bash; command -v opencode >/dev/null 2>&1 || ln -sf $HOME/.opencode/bin/opencode /usr/local/bin/opencode"
sandbox_python: /deps/bin/python3
rollout_timeout: 4200
datasets:
- name: example
type: example
jsonl_fpath: environments/swe/data/example.jsonl
20 changes: 20 additions & 0 deletions environments/swe/data/example.jsonl

Large diffs are not rendered by default.

114 changes: 114 additions & 0 deletions environments/swe/prepare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Convert SWE-bench rows into sandbox_agent rows graded by anyswe. TODO: r2e etc"""

import argparse
import json
from pathlib import Path


def _as_list(v) -> list[str]:
if isinstance(v, str):
try:
return list(json.loads(v))
except (json.JSONDecodeError, TypeError):
return [v] if v else []
return list(v or [])


def _instance_image(container_formatter, instance_id: str) -> str:
fmt = container_formatter[0] if isinstance(container_formatter, list) else container_formatter
fmt = fmt or "swebench/sweb.eval.x86_64.{instance_id}"
if fmt.startswith("docker://"):
fmt = fmt[len("docker://") :]
tag = instance_id.replace("__", "_1776_").lower()
image = fmt.format(instance_id=tag)
if ":" not in image.rsplit("/", 1)[-1]:
image += ":latest"
return image


def _benchmark(info: dict, override: str) -> str:
if override:
return override
name = str(info.get("dataset_name") or "")
if "R2E-Gym" in name:
return "r2e-gym"
if "Multilingual" in name:
return "swe-bench-multilingual"
return "swe-bench"


def convert(row: dict, benchmark: str = "") -> dict:
info = row.get("problem_info") or row.get("verifier_metadata")
if not isinstance(info, dict):
meta = (row.get("responses_create_params") or {}).get("metadata")
info = meta if isinstance(meta, dict) else row
inst = (
json.loads(info["instance_dict"])
if isinstance(info.get("instance_dict"), str)
else dict(info["instance_dict"])
)
instance_id = info["instance_id"]
fail_to_pass = _as_list(inst.get("FAIL_TO_PASS") or inst.get("fail_to_pass"))
pass_to_pass = _as_list(inst.get("PASS_TO_PASS") or inst.get("pass_to_pass"))
if not fail_to_pass:
raise ValueError(f"no test directives for {instance_id}")
return {
"responses_create_params": {
"input": [{"role": "user", "content": inst.get("problem_statement") or info.get("problem_statement", "")}],
"metadata": {
"docker_image": _instance_image(info.get("container_formatter"), instance_id),
"patch_workdir": "/testbed",
},
},
"verifier_metadata": {
"instance_id": instance_id,
"benchmark": _benchmark(info, benchmark),
"test_patch": inst.get("test_patch", ""),
"fail_to_pass": fail_to_pass,
"pass_to_pass": pass_to_pass,
"instance_dict": inst,
},
}


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--input-jsonl", required=True)
parser.add_argument("--output-jsonl", default="environments/swe/data/example.jsonl")
parser.add_argument("--limit", type=int, default=0)
parser.add_argument("--benchmark", default="", choices=["", "swe-bench", "swe-bench-multilingual", "r2e-gym"])
args = parser.parse_args()

rows = []
for line in Path(args.input_jsonl).read_text().splitlines():
if not line.strip():
continue
try:
rows.append(convert(json.loads(line), args.benchmark))
except Exception as e:
print(f"skip: {e}")
if args.limit and len(rows) >= args.limit:
break

out = Path(args.output_jsonl)
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text("".join(json.dumps(r) + "\n" for r in rows))
print(f"wrote {len(rows)} rows to {out}")


if __name__ == "__main__":
main()
15 changes: 15 additions & 0 deletions resources_servers/anyswe/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# anyswe

Grades SWE task patches.

The agent (e.g. `sandbox_agent` with `patch_workdir: /testbed`) captures the rollout's
`git diff` into response metadata as `model_patch`. This verifier rebuilds the task's
instance container in a fresh sandbox, applies the patch, and runs the official SWE-bench
evaluation scripts (`swebench` package, `make_test_spec` + log parsers) via
`verify_task`. Reward is 1.0 when the instance is resolved.

Dataset rows need `verifier_metadata` with `instance_id`, `test_patch`, `fail_to_pass`,
`pass_to_pass`, and `instance_dict` (the raw SWE-bench instance row), plus
`responses_create_params.metadata.docker_image` naming the instance image.

See `environments/swe` for a full wiring with the sandboxed opencode harness.
Loading
Loading