Compare commits

..

1 Commits

Author SHA1 Message Date
openhands
38f1b56172 Fix issue #6940: [Bug]: Incorrect Provider Name on Advanced Setting Toggle 2025-02-25 16:53:38 +00:00
282 changed files with 8377 additions and 14464 deletions

View File

@@ -41,10 +41,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.6.0
uses: docker/setup-qemu-action@v3.4.0
with:
image: tonistiigi/binfmt:latest
- name: Login to GHCR
@@ -56,22 +54,22 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Lowercase Repository Owner
run: |
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Build and push app image
if: "!github.event.pull_request.head.repo.fork"
run: |
./containers/build.sh -i openhands -o ${{ env.REPO_OWNER }} --push
./containers/build.sh -i openhands -o ${{ github.repository_owner }} --push
- name: Build app image
if: "github.event.pull_request.head.repo.fork"
run: |
./containers/build.sh -i openhands -o ${{ env.REPO_OWNER }} --load
./containers/build.sh -i openhands -o ${{ github.repository_owner }} --load
- name: Get hash in App Image
id: get_hash_in_app_image
run: |
# Lowercase the repository owner
export REPO_OWNER=${{ github.repository_owner }}
REPO_OWNER=$(echo $REPO_OWNER | tr '[:upper:]' '[:lower:]')
# Run the build script in the app image
docker run -e SANDBOX_USER_ID=0 -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/${{ env.REPO_OWNER }}/openhands:${{ env.RELEVANT_SHA }} /bin/bash -c "mkdir -p containers/runtime; python3 openhands/runtime/utils/runtime_build.py --base_image ${{ env.BASE_IMAGE_FOR_HASH_EQUIVALENCE_TEST }} --build_folder containers/runtime --force_rebuild" 2>&1 | tee docker-outputs.txt
docker run -e SANDBOX_USER_ID=0 -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/${REPO_OWNER}/openhands:${{ env.RELEVANT_SHA }} /bin/bash -c "mkdir -p containers/runtime; python3 openhands/runtime/utils/runtime_build.py --base_image ${{ env.BASE_IMAGE_FOR_HASH_EQUIVALENCE_TEST }} --build_folder containers/runtime --force_rebuild" 2>&1 | tee docker-outputs.txt
# Get the hash from the build script
hash_from_app_image=$(cat docker-outputs.txt | grep "Hash for docker build directory" | awk -F "): " '{print $2}' | uniq | head -n1)
echo "hash_from_app_image=$hash_from_app_image" >> $GITHUB_OUTPUT
@@ -92,10 +90,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.6.0
uses: docker/setup-qemu-action@v3.4.0
with:
image: tonistiigi/binfmt:latest
- name: Login to GHCR
@@ -126,19 +122,16 @@ jobs:
run: make install-python-dependencies
- name: Create source distribution and Dockerfile
run: poetry run python3 openhands/runtime/utils/runtime_build.py --base_image ${{ matrix.base_image.image }} --build_folder containers/runtime --force_rebuild
- name: Lowercase Repository Owner
run: |
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Build and push runtime image ${{ matrix.base_image.image }}
if: github.event.pull_request.head.repo.fork != true
run: |
./containers/build.sh -i runtime -o ${{ env.REPO_OWNER }} --push -t ${{ matrix.base_image.tag }}
./containers/build.sh -i runtime -o ${{ github.repository_owner }} --push -t ${{ matrix.base_image.tag }}
# Forked repos can't push to GHCR, so we need to upload the image as an artifact
- name: Build runtime image ${{ matrix.base_image.image }} for fork
if: github.event.pull_request.head.repo.fork
uses: docker/build-push-action@v6
with:
tags: ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
tags: ghcr.io/all-hands-ai/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
outputs: type=docker,dest=/tmp/runtime-${{ matrix.base_image.tag }}.tar
context: containers/runtime
- name: Upload runtime image for fork
@@ -158,8 +151,6 @@ jobs:
base_image: ['nikolaik']
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Cache Poetry dependencies
uses: actions/cache@v4
with:
@@ -242,9 +233,6 @@ jobs:
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies
- name: Lowercase Repository Owner
run: |
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Run docker runtime tests
run: |
# We install pytest-xdist in order to run tests across CPUs
@@ -253,7 +241,8 @@ jobs:
# Install to be able to retry on failures for flaky tests
poetry run pip install pytest-rerunfailures
image_name=ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
image_name=ghcr.io/${{ github.repository_owner }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
image_name=$(echo $image_name | tr '[:upper:]' '[:lower:]')
TEST_RUNTIME=docker \
SANDBOX_USER_ID=$(id -u) \
@@ -307,9 +296,6 @@ jobs:
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies
- name: Lowercase Repository Owner
run: |
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Run runtime tests
run: |
# We install pytest-xdist in order to run tests across CPUs
@@ -318,7 +304,8 @@ jobs:
# Install to be able to retry on failures for flaky tests
poetry run pip install pytest-rerunfailures
image_name=ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
image_name=ghcr.io/${{ github.repository_owner }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
image_name=$(echo $image_name | tr '[:upper:]' '[:lower:]')
TEST_RUNTIME=docker \
SANDBOX_USER_ID=$(id -u) \

View File

@@ -40,11 +40,6 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: "poetry"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
- name: Comment on PR if 'integration-test' label is present
if: github.event_name == 'pull_request' && github.event.label.name == 'integration-test'
uses: KeisukeYamashita/create-comment@v1

View File

@@ -1,55 +0,0 @@
cff-version: 1.2.0
message: "If you use this software, please cite it using the following metadata."
title: "OpenHands: An Open Platform for AI Software Developers as Generalist Agents"
authors:
- family-names: Wang
given-names: Xingyao
- family-names: Li
given-names: Boxuan
- family-names: Song
given-names: Yufan
- family-names: Xu
given-names: Frank F.
- family-names: Tang
given-names: Xiangru
- family-names: Zhuge
given-names: Mingchen
- family-names: Pan
given-names: Jiayi
- family-names: Song
given-names: Yueqi
- family-names: Li
given-names: Bowen
- family-names: Singh
given-names: Jaskirat
- family-names: Tran
given-names: Hoang H.
- family-names: Li
given-names: Fuqiang
- family-names: Ma
given-names: Ren
- family-names: Zheng
given-names: Mingzhang
- family-names: Qian
given-names: Bill
- family-names: Shao
given-names: Yanjun
- family-names: Muennighoff
given-names: Niklas
- family-names: Zhang
given-names: Yizhe
- family-names: Hui
given-names: Binyuan
- family-names: Lin
given-names: Junyang
- family-names: Brennan
given-names: Robert
- family-names: Peng
given-names: Hao
- family-names: Ji
given-names: Heng
- family-names: Neubig
given-names: Graham
year: 2024
doi: "10.48550/arXiv.2407.16741"
url: "https://arxiv.org/abs/2407.16741"

View File

@@ -100,7 +100,7 @@ poetry run pytest ./tests/unit/test_*.py
To reduce build time (e.g., if no changes were made to the client-runtime component), you can use an existing Docker container image by
setting the SANDBOX_RUNTIME_CONTAINER_IMAGE environment variable to the desired Docker image.
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.28-nikolaik`
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.26-nikolaik`
## Develop inside Docker container

View File

@@ -2,13 +2,12 @@
These are the procedures and guidelines on how issues are triaged in this repo by the maintainers.
## General
* All issues must be tagged with **enhancement**, **bug** or **troubleshooting/help**.
* Issues may be tagged with what it relates to (**agent quality**, **frontend**, **resolver**, etc.).
* Most issues must be tagged with **enhancement** or **bug**.
* Issues may be tagged with what it relates to (**backend**, **frontend**, **agent quality**, etc.).
## Severity
* **Low**: Minor issues or affecting single user.
* **Medium**: Affecting multiple users.
* **High**: High visibility issues or affecting many users.
* **Critical**: Affecting all users or potential security issues.
## Effort
@@ -19,14 +18,8 @@ These are the procedures and guidelines on how issues are triaged in this repo b
## Not Enough Information
* User is asked to provide more information (logs, how to reproduce, etc.) when the issue is not clear.
* If an issue is unclear and the author does not provide more information or respond to a request,
the issue may be closed as **not planned** (Usually after a week).
* If an issue is unclear and the author does not provide more information or respond to a request, the issue may be closed as **not planned** (Usually after a week).
## Multiple Requests/Fixes in One Issue
* These issues will be narrowed down to one request/fix so the issue is more easily tracked and fixed.
* Issues may be broken down into multiple issues if required.
## Stale and Auto Closures
* In order to keep a maintainable backlog, issues that have no activity within 30 days are automatically marked as **Stale**.
* If issues marked as **Stale** continue to have no activity for 7 more days, they will automatically be closed as not planned.
* Issues may be reopened by maintainers if deemed important.

View File

@@ -43,17 +43,17 @@ See the [Running OpenHands](https://docs.all-hands.dev/modules/usage/installatio
system requirements and more information.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.28
docker.all-hands.dev/all-hands-ai/openhands:0.26
```
You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)!

View File

@@ -95,11 +95,6 @@ workspace_base = "./workspace"
# List of allowed file extensions for uploads
#file_uploads_allowed_extensions = [".*"]
# Whether to enable the default LLM summarizing condenser when no condenser is specified in config
# When true, a LLMSummarizingCondenserConfig will be used as the default condenser
# When false, a NoOpCondenserConfig (no summarization) will be used
#enable_default_condenser = true
#################################### LLM #####################################
# Configuration for LLM models (group name starts with 'llm')
# use 'llm' for the default LLM config
@@ -299,69 +294,6 @@ llm_config = 'gpt3'
# The security analyzer to use (For Headless / CLI only - In Web this is overridden by Session Init)
#security_analyzer = ""
#################################### Condenser #################################
# Condensers control how conversation history is managed and compressed when
# the context grows too large. Each agent uses one condenser configuration.
##############################################################################
[condenser]
# The type of condenser to use. Available options:
# - "noop": No condensing, keeps full history (default)
# - "observation_masking": Keeps full event structure but masks older observations
# - "recent": Keeps only recent events and discards older ones
# - "llm": Uses an LLM to summarize conversation history
# - "amortized": Intelligently forgets older events while preserving important context
# - "llm_attention": Uses an LLM to prioritize most relevant context
type = "noop"
# Examples for each condenser type (uncomment and modify as needed):
# 1. NoOp Condenser - No additional settings needed
#type = "noop"
# 2. Observation Masking Condenser
#type = "observation_masking"
# Number of most-recent events where observations will not be masked
#attention_window = 100
# 3. Recent Events Condenser
#type = "recent"
# Number of initial events to always keep (typically includes task description)
#keep_first = 1
# Maximum number of events to keep in history
#max_events = 100
# 4. LLM Summarizing Condenser
#type = "llm"
# Reference to an LLM config to use for summarization
#llm_config = "condenser"
# Number of initial events to always keep (typically includes task description)
#keep_first = 1
# Maximum size of history before triggering summarization
#max_size = 100
# 5. Amortized Forgetting Condenser
#type = "amortized"
# Number of initial events to always keep (typically includes task description)
#keep_first = 1
# Maximum size of history before triggering forgetting
#max_size = 100
# 6. LLM Attention Condenser
#type = "llm_attention"
# Reference to an LLM config to use for attention scoring
#llm_config = "condenser"
# Number of initial events to always keep (typically includes task description)
#keep_first = 1
# Maximum size of history before triggering attention mechanism
#max_size = 100
# Example of a custom LLM configuration for condensers that require an LLM
# If not provided, it falls back to the default LLM
#[llm.condenser]
#model = "gpt-4o"
#temperature = 0.1
#max_tokens = 1024
#################################### Eval ####################################
# Configuration for the evaluation, please refer to the specific evaluation
# plugin for the available options

View File

@@ -11,7 +11,7 @@ services:
- BACKEND_HOST=${BACKEND_HOST:-"0.0.0.0"}
- SANDBOX_API_HOSTNAME=host.docker.internal
#
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.28-nikolaik}
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.26-nikolaik}
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:

View File

@@ -7,7 +7,7 @@ services:
image: openhands:latest
container_name: openhands-app-${DATE:-}
environment:
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik}
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik}
#- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234} # enable this only if you want a specific non-root sandbox user but you will have to manually adjust permissions of openhands-state for this user
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:

View File

@@ -42,11 +42,10 @@ Créez un fichier ```config.toml``` dans le répertoire OpenHands et entrez ces
[core]
workspace_base="./workspace"
run_as_openhands=true
[sandbox]
base_container_image="image_personnalisée"
sandbox_base_container_image="image_personnalisée"
```
> Assurez-vous que ```base_container_image``` est défini sur le nom de votre image personnalisée précédente.
> Assurez-vous que ```sandbox_base_container_image``` est défini sur le nom de votre image personnalisée précédente.
## Exécution
@@ -83,15 +82,14 @@ dockerfile_content = (
## Dépannage / Erreurs
### Erreur: ```useradd: UID 1000 est non unique```
Si vous voyez cette erreur dans la sortie de la console, il s'agit du fait que OpenHands essaie de créer le utilisateur openhands dans le sandbox avec un ID d'utilisateur de 1000, cependant cet ID d'utilisateur est déjà utilisé dans l'image (pour une raison inconnue). Pour résoudre ce problème, changez la valeur du champ user_id dans le fichier config.toml en une valeur différente:
Si vous voyez cette erreur dans la sortie de la console, il s'agit du fait que OpenHands essaie de créer le utilisateur openhands dans le sandbox avec un ID d'utilisateur de 1000, cependant cet ID d'utilisateur est déjà utilisé dans l'image (pour une raison inconnue). Pour résoudre ce problème, changez la valeur du champ sandbox_user_id dans le fichier config.toml en une valeur différente:
```toml
[core]
workspace_base="./workspace"
run_as_openhands=true
[sandbox]
base_container_image="image_personnalisée"
user_id="1001"
sandbox_base_container_image="image_personnalisée"
sandbox_user_id="1001"
```
### Erreurs de port d'utilisation

View File

@@ -52,7 +52,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -61,7 +61,7 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
python -m openhands.core.cli
```

View File

@@ -44,13 +44,12 @@ Tout d'abord, assurez-vous de pouvoir exécuter OpenHands en suivant les instruc
### Spécifier l'Image de Base du Sandbox
Dans le fichier `config.toml` dans le répertoire OpenHands, définissez `base_container_image` sur l'image que vous souhaitez utiliser. Cela peut être une image que vous avez déjà extraite ou une que vous avez construite :
Dans le fichier `config.toml` dans le répertoire OpenHands, définissez `sandbox_base_container_image` sur l'image que vous souhaitez utiliser. Cela peut être une image que vous avez déjà extraite ou une que vous avez construite :
```bash
[core]
...
[sandbox]
base_container_image="custom-image"
sandbox_base_container_image="custom-image"
```
### Exécution

View File

@@ -46,7 +46,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -56,6 +56,6 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
```

View File

@@ -13,16 +13,16 @@
La façon la plus simple d'exécuter OpenHands est avec Docker.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.28
docker.all-hands.dev/all-hands-ai/openhands:0.26
```
Vous pouvez également exécuter OpenHands en mode [headless scriptable](https://docs.all-hands.dev/modules/usage/how-to/headless-mode), en tant que [CLI interactive](https://docs.all-hands.dev/modules/usage/how-to/cli-mode), ou en utilisant l'[Action GitHub OpenHands](https://docs.all-hands.dev/modules/usage/how-to/github-action).

View File

@@ -13,7 +13,7 @@ C'est le Runtime par défaut qui est utilisé lorsque vous démarrez OpenHands.
```
docker run # ...
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-v /var/run/docker.sock:/var/run/docker.sock \
# ...
```

View File

@@ -58,11 +58,10 @@ docker build -t custom_image .
[core]
workspace_base="./workspace"
run_as_openhands=true
[sandbox]
base_container_image="custom_image"
sandbox_base_container_image="custom_image"
```
对于 `base_container_image` 的值, 您可以选择以下任意一项:
对于 `sandbox_base_container_image` 的值, 您可以选择以下任意一项:
1. 在上一步中您构建的自定义镜像的名称(例如,`“custom_image”`
2. 从 Docker Hub 拉取的镜像(例如,`“node:20”`,如果你需要一个预装 `Node.js` 的沙箱环境)
@@ -84,15 +83,14 @@ base_container_image="custom_image"
### 错误:```useradd: UID 1000 is not unique```
如果在控制台输出中看到此错误,说明 OpenHands 尝试在沙箱中以 UID 1000 创建 openhands 用户,但该 UID 已经被映像中的其他部分使用(不知何故)。要解决这个问题,请更改 config.toml 文件中的 user_id 字段为不同的值:
如果在控制台输出中看到此错误,说明 OpenHands 尝试在沙箱中以 UID 1000 创建 openhands 用户,但该 UID 已经被映像中的其他部分使用(不知何故)。要解决这个问题,请更改 config.toml 文件中的 sandbox_user_id 字段为不同的值:
```
[core]
workspace_base="./workspace"
run_as_openhands=true
[sandbox]
base_container_image="custom_image"
user_id="1001"
sandbox_base_container_image="custom_image"
sandbox_user_id="1001"
```
### 端口使用错误

View File

@@ -50,7 +50,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -59,7 +59,7 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
python -m openhands.core.cli
```

View File

@@ -42,13 +42,12 @@ docker build -t custom-image .
### 指定基础沙箱镜像
在 OpenHands 目录中的 `config.toml` 文件中,将 `base_container_image` 设置为你要使用的镜像。这可以是你已经拉取的镜像或你构建的镜像:
在 OpenHands 目录中的 `config.toml` 文件中,将 `sandbox_base_container_image` 设置为你要使用的镜像。这可以是你已经拉取的镜像或你构建的镜像:
```bash
[core]
...
[sandbox]
base_container_image="custom-image"
sandbox_base_container_image="custom-image"
```
### 运行

View File

@@ -47,7 +47,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -57,6 +57,6 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
```

View File

@@ -11,16 +11,16 @@
在 Docker 中运行 OpenHands 是最简单的方式。
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.28
docker.all-hands.dev/all-hands-ai/openhands:0.26
```
你也可以在可脚本化的[无头模式](https://docs.all-hands.dev/modules/usage/how-to/headless-mode)下运行 OpenHands作为[交互式 CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode),或使用 [OpenHands GitHub Action](https://docs.all-hands.dev/modules/usage/how-to/github-action)。

View File

@@ -11,7 +11,7 @@
```
docker run # ...
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-v /var/run/docker.sock:/var/run/docker.sock \
# ...
```

View File

@@ -385,11 +385,6 @@ To use these with the docker command, pass in `-e SANDBOX_<option>`. Example: `-
- Default: `false`
- Description: Use host network
- `runtime_binding_address`
- Type: `str`
- Default: `127.0.0.1`
- Description: The binding address for the runtime ports. It specifies which network interface on the host machine Docker should bind the runtime ports to.
### Linting and Plugins
- `enable_auto_lint`
- Type: `bool`

View File

@@ -35,7 +35,7 @@ To run OpenHands in CLI mode with Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -45,7 +45,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
python -m openhands.core.cli
```

View File

@@ -60,14 +60,13 @@ First, ensure you can run OpenHands by following the instructions in [Developmen
### Specify the Base Sandbox Image
In the `config.toml` file within the OpenHands directory, set the `base_container_image` to the image you want to use.
In the `config.toml` file within the OpenHands directory, set the `sandbox_base_container_image` to the image you want to use.
This can be an image youve already pulled or one youve built:
```bash
[core]
...
[sandbox]
base_container_image="custom-image"
sandbox_base_container_image="custom-image"
```
### Additional Configuration Options

View File

@@ -32,7 +32,7 @@ To run OpenHands in Headless mode with Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -43,7 +43,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
python -m openhands.core.main -t "write a bash script that prints hi"
```

View File

@@ -58,17 +58,17 @@ A system with a modern processor and a minimum of **4GB RAM** is recommended to
The easiest way to run OpenHands is in Docker.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.28
docker.all-hands.dev/all-hands-ai/openhands:0.26
```
You'll find OpenHands running at http://localhost:3000!

View File

@@ -16,7 +16,7 @@ some flags being passed to `docker run` that make this possible:
```
docker run # ...
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
-v /var/run/docker.sock:/var/run/docker.sock \
# ...
```
@@ -84,36 +84,3 @@ docker run # ...
-e MODAL_API_TOKEN_ID="your-id" \
-e MODAL_API_TOKEN_SECRET="your-secret" \
```
## Daytona Runtime
Another option is using [Daytona](https://www.daytona.io/) as a runtime provider:
### Step 1: Retrieve Your Daytona API Key
1. Visit the [Daytona Dashboard](https://app.daytona.io/dashboard/keys).
2. Click **"Create Key"**.
3. Enter a name for your key and confirm the creation.
4. Once the key is generated, copy it.
### Step 2: Set Your API Key as an Environment Variable
Run the following command in your terminal, replacing `<your-api-key>` with the actual key you copied:
```bash
export DAYTONA_API_KEY="<your-api-key>"
```
This step ensures that OpenHands can authenticate with the Daytona platform when it runs.
### Step 3: Run OpenHands Locally Using Docker
To start the latest version of OpenHands on your machine, execute the following command in your terminal:
```bash
bash -i <(curl -sL https://get.daytona.io/openhands)
```
#### What This Command Does:
- Downloads the latest OpenHands release script.
- Runs the script in an interactive Bash session.
- Automatically pulls and runs the OpenHands container using Docker.
Once executed, OpenHands should be running locally and ready for use.
For more details and manual initialization, view the entire [README.md](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/impl/daytona/README.md)

16
docs/package-lock.json generated
View File

@@ -17,14 +17,14 @@
"prism-react-renderer": "^2.4.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
"react-icons": "^5.4.0",
"react-use": "^17.6.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.5.1",
"@docusaurus/tsconfig": "^3.7.0",
"@docusaurus/types": "^3.5.1",
"typescript": "~5.8.2"
"typescript": "~5.7.3"
},
"engines": {
"node": ">=18.0"
@@ -15680,9 +15680,9 @@
}
},
"node_modules/react-icons": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz",
"integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==",
"license": "MIT",
"peerDependencies": {
"react": "*"
@@ -17638,9 +17638,9 @@
}
},
"node_modules/typescript": {
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

View File

@@ -24,14 +24,14 @@
"prism-react-renderer": "^2.4.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
"react-icons": "^5.4.0",
"react-use": "^17.6.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.5.1",
"@docusaurus/tsconfig": "^3.7.0",
"@docusaurus/types": "^3.5.1",
"typescript": "~5.8.2"
"typescript": "~5.7.3"
},
"browserslist": {
"production": [

View File

@@ -5,6 +5,9 @@ export function Demo() {
const videoRef = React.useRef<HTMLVideoElement>(null);
return (
<div
style={{ paddingBottom: "10px", paddingTop: "10px", textAlign: "center" }}
>
<video
playsInline
autoPlay={true}
@@ -17,5 +20,6 @@ export function Demo() {
>
<source src="img/teaser.mp4" type="video/mp4"></source>
</video>
</div>
);
}

View File

@@ -1,5 +1,6 @@
.demo {
width: 100%;
padding: 30px;
max-width: 800px;
text-align: center;
border-radius: 40px;

View File

@@ -17,29 +17,6 @@ export function HomepageHeader() {
<p className="header-subtitle">{siteConfig.tagline}</p>
<div style={{
textAlign: 'center',
fontSize: '1.2rem',
maxWidth: '800px',
margin: '0 auto',
padding: '0rem 0rem 1rem'
}}>
<p style={{ margin: '0' }}>
Use AI to tackle the toil in your backlog. Our agents have all the same tools as a human developer: they can modify code, run commands, browse the web,
call APIs, and yes-even copy code snippets from StackOverflow.
<br/>
<Link to="https://docs.all-hands.dev/modules/usage/installation"
style={{
textDecoration: 'underline',
display: 'inline-block',
marginTop: '0.5rem'
}}
>
Get started with OpenHands.
</Link>
</p>
</div>
<div align="center" className="header-links">
<a href="https://github.com/All-Hands-AI/OpenHands/graphs/contributors"><img src="https://img.shields.io/github/contributors/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Contributors" /></a>
<a href="https://github.com/All-Hands-AI/OpenHands/stargazers"><img src="https://img.shields.io/github/stars/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Stargazers" /></a>
@@ -50,9 +27,12 @@ export function HomepageHeader() {
<a href="https://discord.gg/ESHStjSjD4"><img src="https://img.shields.io/badge/Discord-Join%20Us-purple?logo=discord&logoColor=white&style=for-the-badge" alt="Join our Discord community" /></a>
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/CREDITS.md"><img src="https://img.shields.io/badge/Project-Credits-blue?style=for-the-badge&color=FFE165&logo=github&logoColor=white" alt="Credits" /></a>
<br/>
<a href="https://docs.all-hands.dev/modules/usage/getting-started"><img src="https://img.shields.io/badge/Documentation-000?logo=googledocs&logoColor=FFE165&style=for-the-badge" alt="Check out the documentation" /></a>
<a href="https://arxiv.org/abs/2407.16741"><img src="https://img.shields.io/badge/Paper%20on%20Arxiv-000?logoColor=FFE165&logo=arxiv&style=for-the-badge" alt="Paper on Arxiv" /></a>
<a href="https://huggingface.co/spaces/OpenHands/evaluation"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score" /></a>
</div>
<Demo />
</div>
</div>
);

View File

@@ -1,14 +1,14 @@
/* homepageHeader.css */
.homepage-header {
padding: 1rem 0;
height: 800px;
}
.header-content {
display: flex;
flex-direction: column;
align-items: center;
padding: 1rem;
padding: 2rem;
font-weight: 300;
width: 100%;
}
@@ -25,7 +25,6 @@
.header-subtitle {
font-size: 1.5rem;
margin: 0.5rem 0;
}
.header-links {

View File

@@ -2,7 +2,15 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import { HomepageHeader } from '../components/HomepageHeader/HomepageHeader';
import { translate } from '@docusaurus/Translate';
import { Demo } from "../components/Demo/Demo";
export function Header({ title, summary }): JSX.Element {
return (
<div>
<h1>{title}</h1>
<h2 style={{ fontSize: '3rem' }}>{summary}</h2>
</div>
);
}
export default function Home(): JSX.Element {
const { siteConfig } = useDocusaurusContext();
@@ -15,14 +23,11 @@ export default function Home(): JSX.Element {
})}
>
<HomepageHeader />
<div style={{ textAlign: 'center', padding: '1rem 0' }}>
<Demo />
</div>
<div style={{ textAlign: 'center', padding: '0.5rem 2rem 1.5rem' }}>
<div style={{ textAlign: 'center', padding: '2rem' }}>
<br />
<h2>Most Popular Links</h2>
<ul style={{ listStyleType: 'none'}}>
<li><a href="/modules/usage/Installation">How to Run OpenHands</a></li>
<li><a href="/modules/usage/prompting/microagents-repo">Customizing OpenHands to a repository</a></li>
<li><a href="/modules/usage/how-to/github-action">Integrating OpenHands with Github</a></li>
<li><a href="/modules/usage/llms#model-recommendations">Recommended models to use</a></li>

View File

@@ -56,10 +56,9 @@ You can update the arguments in the script
./evaluation/benchmarks/aider_bench/scripts/run_infer.sh eval_gpt35_turbo HEAD CodeActAgent 100 1 "1,3,10"
```
### Run Inference on `RemoteRuntime`
This is in beta. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
### Run Inference on `RemoteRuntime` (experimental)
This is in limited beta. Contact Xingyao over slack if you want to try this out!
```bash
./evaluation/benchmarks/aider_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [eval-num-workers] [eval_ids]

View File

@@ -205,6 +205,7 @@ def process_instance(
runtime: Runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
initialize_runtime(runtime, instance=instance)
# Here's how you can run the agent (similar to the `main` function) and get the final task state

View File

@@ -25,7 +25,6 @@ from openhands.core.config import (
from openhands.core.logger import openhands_logger as logger
from openhands.core.main import create_runtime, run_controller
from openhands.events.action import MessageAction
from openhands.utils.async_utils import call_async_from_sync
# Only CodeActAgent can delegate to BrowsingAgent
SUPPORTED_AGENT_CLS = {'CodeActAgent'}
@@ -75,7 +74,6 @@ def process_instance(
)
runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
state: State | None = asyncio.run(
run_controller(

View File

@@ -23,10 +23,10 @@ Make sure your Docker daemon is running, and you have ample disk space (at least
When the `run_infer.sh` script is started, it will automatically pull the `lite` split in Commit0. For example, for instance ID `commit-0/minitorch`, it will try to pull our pre-build docker image `wentingzhao/minitorch` from DockerHub. This image will be used create an OpenHands runtime image where the agent will operate on.
```bash
./evaluation/benchmarks/commit0/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
# Example
./evaluation/benchmarks/commit0/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 16 100 8 wentingzhao/commit0_combined test
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 16 100 8 wentingzhao/commit0_combined test
```
where `model_config` is mandatory, and the rest are optional.
@@ -48,25 +48,26 @@ default, it is set to 1.
- `dataset`, a huggingface dataset name. e.g. `wentingzhao/commit0_combined`, specifies which dataset to evaluate on.
- `dataset_split`, split for the huggingface dataset. Notice only `test` is supported for Commit0.
Note that the `USE_INSTANCE_IMAGE` environment variable is always set to `true` for Commit0.
Let's say you'd like to run 10 instances using `llm.eval_sonnet` and CodeActAgent,
then your command would be:
```bash
./evaluation/benchmarks/commit0/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
```
### Run Inference on `RemoteRuntime`
This is in beta. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
### Run Inference on `RemoteRuntime` (experimental)
This is in limited beta. Contact Xingyao over slack if you want to try this out!
```bash
./evaluation/benchmarks/commit0/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
# Example - This runs evaluation on CodeActAgent for 10 instances on "wentingzhao/commit0_combined"'s test set, with max 30 iteration per instances, with 1 number of workers running in parallel
ALLHANDS_API_KEY="YOUR-API-KEY" RUNTIME=remote SANDBOX_REMOTE_RUNTIME_API_URL="https://runtime.eval.all-hands.dev" EVAL_DOCKER_IMAGE_PREFIX="docker.io/wentingzhao" \
./evaluation/benchmarks/commit0/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
```
To clean-up all existing runtime you've already started, run:

View File

@@ -39,6 +39,7 @@ from openhands.utils.async_utils import call_async_from_sync
from openhands.utils.shutdown_listener import sleep_if_should_continue
USE_HINT_TEXT = os.environ.get('USE_HINT_TEXT', 'false').lower() == 'true'
USE_INSTANCE_IMAGE = os.environ.get('USE_INSTANCE_IMAGE', 'false').lower() == 'true'
RUN_WITH_BROWSING = os.environ.get('RUN_WITH_BROWSING', 'false').lower() == 'true'
AGENT_CLS_TO_FAKE_USER_RESPONSE_FN = {
@@ -104,6 +105,7 @@ def get_config(
instance: pd.Series,
metadata: EvalMetadata,
) -> AppConfig:
assert USE_INSTANCE_IMAGE
repo_name = instance['repo'].split('/')[1]
base_container_image = get_instance_docker_image(repo_name)
logger.info(
@@ -301,16 +303,6 @@ def complete_runtime(
pytest_exit_code = obs.content.strip()
# logger.info(f'Pytest exit code: {pytest_exit_code}')
# Get test IDs from instance
repo_name = instance['repo'].split('/')[1]
repo_name = repo_name.replace('.', '-')
action = CmdRunAction(command=f'commit0 get-tests {repo_name}')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
# logger.info(obs, extra={'msg_type': 'OBSERVATION'})
test_ids = obs.content.strip().split('\n')
# Read the test report
action = CmdRunAction(command='cat report.json')
action.set_hard_timeout(600)
@@ -321,10 +313,18 @@ def complete_runtime(
isinstance(obs, CmdOutputObservation),
f'Failed to read test report: {str(obs)}',
)
json_report = obs.content.strip()
# Get test IDs from instance
repo_name = instance['repo'].split('/')[1]
repo_name = repo_name.replace('.', '-')
action = CmdRunAction(command=f'commit0 get-tests {repo_name}')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
# logger.info(obs, extra={'msg_type': 'OBSERVATION'})
test_ids = obs.content.strip().split('\n')
try:
report = json.loads(json_report)
report = json.loads(obs.content)
tests = {x['nodeid']: x['call'] for x in report['tests'] if 'call' in x}
# Calculate test statistics

View File

@@ -30,6 +30,11 @@ if [ -z "$MAX_ITER" ]; then
MAX_ITER=100
fi
if [ -z "$USE_INSTANCE_IMAGE" ]; then
echo "USE_INSTANCE_IMAGE not specified, use default true"
USE_INSTANCE_IMAGE=true
fi
if [ -z "$RUN_WITH_BROWSING" ]; then
echo "RUN_WITH_BROWSING not specified, use default false"
RUN_WITH_BROWSING=false
@@ -51,6 +56,8 @@ if [ -z "$SPLIT" ]; then
SPLIT="test"
fi
export USE_INSTANCE_IMAGE=$USE_INSTANCE_IMAGE
echo "USE_INSTANCE_IMAGE: $USE_INSTANCE_IMAGE"
export RUN_WITH_BROWSING=$RUN_WITH_BROWSING
echo "RUN_WITH_BROWSING: $RUN_WITH_BROWSING"
@@ -84,7 +91,7 @@ fi
function run_eval() {
local eval_note=$1
COMMAND="poetry run python evaluation/benchmarks/commit0/run_infer.py \
COMMAND="poetry run python evaluation/benchmarks/commit0_bench/run_infer.py \
--agent-cls $AGENT \
--llm-config $MODEL_CONFIG \
--max-iterations $MAX_ITER \

View File

@@ -13,7 +13,6 @@
# limitations under the License.
# This file is modified from https://github.com/ShishirPatil/gorilla/blob/main/eval/eval-scripts/ast_eval_hf.py
import tree_sitter_python as tspython
from tree_sitter import Language, Parser
@@ -40,9 +39,10 @@ def get_all_sub_trees(root_node):
# Parse the program into AST trees
def ast_parse(candidate):
LANGUAGE = Language(tspython.language())
parser = Parser(LANGUAGE)
def ast_parse(candidate, lang='python'):
LANGUAGE = Language('evaluation/gorilla/my-languages.so', lang)
parser = Parser()
parser.set_language(LANGUAGE)
candidate_tree = parser.parse(bytes(candidate, 'utf8')).root_node
return candidate_tree

View File

@@ -13,7 +13,6 @@
# limitations under the License.
# This file is modified from https://github.com/ShishirPatil/gorilla/blob/main/eval/eval-scripts/ast_eval_tf.py
import tree_sitter_python as tspython
from tree_sitter import Language, Parser
@@ -40,9 +39,10 @@ def get_all_sub_trees(root_node):
# Parse the program into AST trees
def ast_parse(candidate):
LANGUAGE = Language(tspython.language())
parser = Parser(LANGUAGE)
def ast_parse(candidate, lang='python'):
LANGUAGE = Language('evaluation/gorilla/my-languages.so', lang)
parser = Parser()
parser.set_language(LANGUAGE)
candidate_tree = parser.parse(bytes(candidate, 'utf8')).root_node
return candidate_tree

View File

@@ -13,7 +13,6 @@
# limitations under the License.
# This file is modified from https://github.com/ShishirPatil/gorilla/blob/main/eval/eval-scripts/ast_eval_th.py
import tree_sitter_python as tspython
from tree_sitter import Language, Parser
@@ -40,9 +39,10 @@ def get_all_sub_trees(root_node):
# Parse the program into AST trees
def ast_parse(candidate):
LANGUAGE = Language(tspython.language())
parser = Parser(LANGUAGE)
def ast_parse(candidate, lang='python'):
LANGUAGE = Language('evaluation/gorilla/my-languages.so', lang)
parser = Parser()
parser.set_language(LANGUAGE)
candidate_tree = parser.parse(bytes(candidate, 'utf8')).root_node
return candidate_tree

View File

@@ -71,19 +71,19 @@ def fetch_data(url, filename):
def get_data_for_hub(hub: str):
if hub == 'hf':
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/eval/eval-data/questions/huggingface/questions_huggingface_0_shot.jsonl'
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/api/huggingface_api.jsonl'
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/apibench/huggingface_eval.json'
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/eval/eval-data/questions/huggingface/questions_huggingface_0_shot.jsonl'
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/api/huggingface_api.jsonl'
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/apibench/huggingface_eval.json'
ast_eval = ast_eval_hf
elif hub == 'torch':
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/eval/eval-data/questions/torchhub/questions_torchhub_0_shot.jsonl'
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/api/torchhub_api.jsonl'
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/apibench/torchhub_eval.json'
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/eval/eval-data/questions/torchhub/questions_torchhub_0_shot.jsonl'
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/api/torchhub_api.jsonl'
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/apibench/torchhub_eval.json'
ast_eval = ast_eval_th
elif hub == 'tf':
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/eval/eval-data/questions/tensorflowhub/questions_tensorflowhub_0_shot.jsonl'
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/api/tensorflowhub_api.jsonl'
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/apibench/tensorflow_eval.json'
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/eval/eval-data/questions/tensorflowhub/questions_tensorflowhub_0_shot.jsonl'
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/api/tensorflowhub_api.jsonl'
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/apibench/tensorflow_eval.json'
ast_eval = ast_eval_tf
question_data = fetch_data(question_data, 'question_data.jsonl')

View File

@@ -19,10 +19,9 @@ Access with browser the above MiniWoB URLs and see if they load correctly.
./evaluation/benchmarks/miniwob/scripts/run_infer.sh llm.claude-35-sonnet-eval
```
### Run Inference on `RemoteRuntime`
This is in beta. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
### Run Inference on `RemoteRuntime` (experimental)
This is in limited beta. Contact Xingyao over slack if you want to try this out!
```bash
./evaluation/benchmarks/miniwob/scripts/run_infer.sh [model_config] [git-version] [agent] [note] [eval_limit] [num_workers]

View File

@@ -2,13 +2,11 @@
This folder contains the evaluation harness that we built on top of the original [SWE-Bench benchmark](https://www.swebench.com/) ([paper](https://arxiv.org/abs/2310.06770)).
**UPDATE (2/18/2025): We now support running SWE-Gym using the same evaluation harness here. For more details, checkout [this README](./SWE-Gym.md).
**UPDATE (7/1/2024): We now support the official SWE-Bench dockerized evaluation as announced [here](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md).**
The evaluation consists of three steps:
1. Environment setup: [install python environment](../../README.md#development-environment) and [configure LLM config](../../README.md#configure-openhands-and-your-llm).
1. Environment setup: [install python environment](../../README.md#development-environment), [configure LLM config](../../README.md#configure-openhands-and-your-llm), and [pull docker](#openhands-swe-bench-instance-level-docker-support).
2. [Run inference](#run-inference-on-swe-bench-instances): Generate a edit patch for each Github issue
3. [Evaluate patches using SWE-Bench docker](#evaluate-generated-patches)
@@ -16,21 +14,22 @@ The evaluation consists of three steps:
Please follow instruction [here](../../README.md#setup) to setup your local development environment and LLM.
## Run Inference (Rollout) on SWE-Bench Instances: Generate Patch from Problem Statement
## OpenHands SWE-Bench Instance-level Docker Support
### Running Locally with Docker
OpenHands now support using the [official evaluation docker](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md) for both **[inference](#run-inference-on-swe-bench-instances) and [evaluation](#evaluate-generated-patches)**.
This is now the default behavior.
Make sure your Docker daemon is running, and you have ample disk space (at least 200-500GB, depends on the SWE-Bench set you are running on) for the instance-level docker image.
## Run Inference on SWE-Bench Instances
When the `run_infer.sh` script is started, it will automatically pull the relevant SWE-Bench images.
For example, for instance ID `django_django-11011`, it will try to pull our pre-build docker image `sweb.eval.x86_64.django_s_django-11011` from DockerHub.
This image will be used create an OpenHands runtime image where the agent will operate on.
Make sure your Docker daemon is running, and you have ample disk space (at least 200-500GB, depends on the SWE-Bench set you are running on) for the [instance-level docker image](#openhands-swe-bench-instance-level-docker-support).
When the `run_infer.sh` script is started, it will automatically pull the relevant SWE-Bench images. For example, for instance ID `django_django-11011`, it will try to pull our pre-build docker image `sweb.eval.x86_64.django_s_django-11011` from DockerHub. This image will be used create an OpenHands runtime image where the agent will operate on.
```bash
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
# Example
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 500 100 1 princeton-nlp/SWE-bench_Verified test
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 300 30 1 princeton-nlp/SWE-bench_Lite test
```
where `model_config` is mandatory, and the rest are optional.
@@ -48,16 +47,14 @@ in order to use `eval_limit`, you must also set `agent`.
default, it is set to 30.
- `num_workers`, e.g. `3`, is the number of parallel workers to run the evaluation. By
default, it is set to 1.
- `dataset`, a huggingface dataset name. e.g. `princeton-nlp/SWE-bench`, `princeton-nlp/SWE-bench_Lite`, or `princeton-nlp/SWE-bench_Verified`, specifies which dataset to evaluate on.
- `dataset`, a huggingface dataset name. e.g. `princeton-nlp/SWE-bench` or `princeton-nlp/SWE-bench_Lite`, specifies which dataset to evaluate on.
- `dataset_split`, split for the huggingface dataset. e.g., `test`, `dev`. Default to `test`.
> [!CAUTION]
> Setting `num_workers` larger than 1 is not officially tested, YMMV.
There is also one optional environment variable you can set.
There are also two optional environment variables you can set.
```bash
export USE_HINT_TEXT=true # if you want to use hint text in the evaluation. Default to false. Ignore this if you are not sure.
export USE_INSTANCE_IMAGE=true # if you want to use instance-level docker images. Default to true
```
Let's say you'd like to run 10 instances using `llm.eval_gpt4_1106_preview` and CodeActAgent,
@@ -68,11 +65,9 @@ then your command would be:
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 10
```
### Running in parallel with RemoteRuntime
### Run Inference on `RemoteRuntime` (experimental)
OpenHands Remote Runtime is currently in beta (read [here](https://runtime.all-hands.dev/) for more details), it allows you to run rollout in parallel in the cloud, so you don't need a powerful machine to run evaluation.
Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
This is in limited beta. Contact Xingyao over slack if you want to try this out!
```bash
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
@@ -105,14 +100,41 @@ After running the inference, you will obtain a `output.jsonl` (by default it wil
## Evaluate Generated Patches
### Run evaluation with official SWE-Bench harness (Recommend if you have local disk space)
### Download Docker Images
**(Recommended for reproducibility)** If you have extra local space (e.g., 200GB), you can try pull the [instance-level docker images](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md#choosing-the-right-cache_level) we've prepared by running:
```bash
evaluation/benchmarks/swe_bench/scripts/docker/pull_all_eval_docker.sh instance
```
If you want to save disk space a bit (e.g., with ~50GB free disk space), while speeding up the image pre-build process, you can pull the environment-level docker images:
```bash
evaluation/benchmarks/swe_bench/scripts/docker/pull_all_eval_docker.sh env
```
If you want to evaluate on the full SWE-Bench test set:
```bash
evaluation/benchmarks/swe_bench/scripts/docker/pull_all_eval_docker.sh instance full
```
### Run evaluation
With `output.jsonl` file, you can run `eval_infer.sh` to evaluate generated patches, and produce a fine-grained report.
**This evaluation is performed using the official dockerized evaluation announced [here](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md).**
> [!NOTE]
> This process will automatically download docker images from SWE-Bench official docker hub, please make sure you have enough disk space!
> If you want to evaluate existing results, you should first run this to clone existing outputs
>
>```bash
>git clone https://huggingface.co/spaces/OpenHands/evaluation evaluation/evaluation_outputs
>```
NOTE, you should have already pulled the instance-level OR env-level docker images following [this section](#openhands-swe-bench-instance-level-docker-support).
Then you can run the following:
```bash
./evaluation/benchmarks/swe_bench/scripts/eval_infer.sh $YOUR_OUTPUT_JSONL [instance_id] [dataset_name] [split]
@@ -141,10 +163,9 @@ The final results will be saved to `evaluation/evaluation_outputs/outputs/swe_be
- `report.json`: a JSON file that contains keys like `"resolved_ids"` pointing to instance IDs that are resolved by the agent.
- `logs/`: a directory of test logs
### Run evaluation with `RemoteRuntime`
### Run evaluation with `RemoteRuntime` (experimental)
OpenHands Remote Runtime is currently in beta (read [here](https://runtime.all-hands.dev/) for more details), it allows you to run rollout in parallel in the cloud, so you don't need a powerful machine to run evaluation.
Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
This is in limited beta. Contact Xingyao over slack if you want to try this out!
```bash
./evaluation/benchmarks/swe_bench/scripts/eval_infer_remote.sh [output.jsonl filepath] [num_workers]
@@ -159,3 +180,35 @@ To clean-up all existing runtimes that you've already started, run:
```bash
ALLHANDS_API_KEY="YOUR-API-KEY" ./evaluation/utils/scripts/cleanup_remote_runtime.sh
```
## Visualize Results
First you need to clone `https://huggingface.co/spaces/OpenHands/evaluation` and add your own running results from openhands into the `outputs` of the cloned repo.
```bash
git clone https://huggingface.co/spaces/OpenHands/evaluation
```
**(optional) setup streamlit environment with conda**:
```bash
cd evaluation
conda create -n streamlit python=3.10
conda activate streamlit
pip install -r requirements.txt
```
**run the visualizer**:
Then, in a separate Python environment with `streamlit` library, you can run the following:
```bash
# Make sure you are inside the cloned `evaluation` repo
conda activate streamlit # if you follow the optional conda env setup above
streamlit run app.py --server.port 8501 --server.address 0.0.0.0
```
Then you can access the SWE-Bench trajectory visualizer at `localhost:8501`.
## Submit your evaluation results
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).

View File

@@ -1,128 +0,0 @@
<h1 align="center"> Training Software Engineering Agents and Verifiers with SWE-Gym </h1>
<p align="center">
<a href="https://www.jiayipan.com/" style="text-decoration: none;">Jiayi Pan<sup>*,1</sup></a>,
<a href="https://xwang.dev/" style="text-decoration: none;">Xingyao Wang<sup>*,2</sup></a>,
<a href="https://www.phontron.com/" style="text-decoration: none;">Graham Neubig<sup>3</sup></a>,
<a href="https://www.cs.toronto.edu/~ndjaitly/" style="text-decoration: none;">Navdeep Jaitly<sup>4</sup></a>,
<a href="https://blender.cs.illinois.edu/hengji.html" style="text-decoration: none;">Heng Ji<sup>2</sup></a>,
<a href="https://www.alanesuhr.com/" style="text-decoration: none;">Alane Suhr<sup>^,1</sup></a>,
<a href="https://dreasysnail.github.io/" style="text-decoration: none;">Yizhe Zhang<sup>^,4</sup></a>
</p>
<p align="center">
<sup>1</sup>UC Berkeley, <sup>2</sup>UIUC, <sup>3</sup>CMU, <sup>4</sup>Apple </br>
<sub><sup>*</sup>Equal contribution, <sup>^</sup>Equal supervision</sub>
</p>
<p align="center">
<a href="https://arxiv.org/abs/2412.21139">📃 Paper</a>
<a href="https://huggingface.co/SWE-Gym" >🤗 Data & Models</a>
</p>
We present **SWE-Gym**, the first environment for training real-world software engineering agents.
We use it to train strong LM agents that achieve state-of-the-art open results on SWE-Bench, with early, promising scaling characteristics as we increase training and inference-time compute.
<p align="center">
<img src="https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/teaser.jpg?raw=true" width="100%" alt="teaser">
</p>
---
# Run SWE-Gym with OpenHands
The process of running SWE-Gym is very similar to how you'd run SWE-Bench evaluation.
1. First, clone OpenHands repo `git clone https://github.com/All-Hands-AI/OpenHands.git`
2. Then setup the repo following [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)
3. Then you can simply serve your own model as an OpenAI compatible endpoint, put those info in config.toml. You can do this by following instruction [here](../../README.md#setup).
4. And then simply do the following to sample for 16x parallelism:
```bash
export ALLHANDS_API_KEY=ah-yourkey # You don't need to set this when running these in local docker container
./evaluation/benchmarks/swe_bench/scripts/rollout_swegym.sh llm.mymodel-temp05 'train-t05' 16
```
NOTE: SWE-Gym sampling with parallelism is currently only tested with AllHands RemoteRuntime (limited beta). Fill [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply for access.
5. When `rollout_swegym.sh` finishes, you will get a file called `output.with_completions.jsonl.gz`. Then you can use [`./scripts/swegym/convert_data.ipynb`](./scripts/swegym/convert_data.ipynb) to convert them into SFT data format.
---
# More info about SWE-Gym
Progress in agents for software engineering has been limited by the lack of training environments that both include rigorous verification for reinforcement learning and cover the expansive tasks encountered in real-world repository-level engineering.
We introduce SWE-Gym: An Open Environment for Training Software Engineering Agents & Verifiers.
Our baselines achieve new open SOTA - 32%/26% on SWE-Bench Verified/Lite, with promising scaling trends.
![SWE-Gym Scaling](https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/scaling.jpg?raw=true)
*SWE-Gym enables scalable improvements for software engineering agents at both training and inference time. Our current results is primarily bottlenecked by training and inference compute, rather than the size of our environment.*
## SWE-Gym Environment
We create SWE-Gym, the first environment for training SWE agents, with **2.4K real tasks from 11 Python repos** & a Lite split of 234 instances. SWE-Gym combines real-world Python tasks, repository context, executable environments, and test verification to train agents for solving software engineering problems.
![SWE-Gym Repo Distribution](https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/swe-gym.jpg?raw=true)
## SWE-Gym trains LMs as agents
When fine-tuned on less than 500 agent-environment interaction trajectories sampled from it from GPT-4o and Claude 3.5 Sonnet, we achieve **+14%** absolute gains on SWE-Bench Verified with an 32B LM-powered OpenHands agent.
![OpenHands Performance diff before and after training](https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/oh-agent.jpg?raw=true)
## SWE-Gym enables self-improvement
SWE-Gym is also effective across agent scaffolds. With rejection sampling fine-tuning and MoatlessTools scaffold, our 32B and 7B models achieve 20% and 10% respectively on SWE-Bench Lite through self-improvement.
<p align="center">
<img src="https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/ml-agent.jpg?raw=true" width="80%" alt="Moatless self-improvement">
</p>
## SWE-Gym enables inference-time scaling
SWE-Gym enables inference-time scaling through verifiers trained on agent trajectories.
These verifiers identify most promising solutions via best-of-n selection, together with our learned agents, they achieve 32%/26% on SWE-Bench Verified/Lite, a new open SoTA.
![Inference Time Scaling for Moatless Agent](https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/inference-ml.jpg?raw=true)
*Inference Time Scaling for Moatless Agent*
![Inference Time Scaling for OpenHands Agent](https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/inference-oh.jpg?raw=true)
*Inference Time Scaling for OpenHands Agent*
## Our baselines on SWE-Gym shows strong scaling trends
Lastly, our ablations reveal strong scaling trends - performance is now bottlenecked by train and inference compute, rather than the size of our dataset. Pushing and improving these scaling trends further is an exciting direction for future work.
![](https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/scaling.jpg?raw=true)
## Reproducing Results
**The Dataset**
To access SWE-Gym dataset, checkout our huggingface hub page [SWE-Gym](https://huggingface.co/SWE-Gym)
The environment constants are currently saved at [SWE-Bench-Fork](https://github.com/SWE-Gym/SWE-Bench-Fork)
We also have pre-built docker images for each instance under [xingyaoww/sweb.eval.x86_64](https://hub.docker.com/search?q=xingyaoww%2Fsweb.eval.x86_64.) prefix at docker hub.
## 📚 Citation
```bibtex
@misc{pan2024trainingsoftwareengineeringagents,
title={Training Software Engineering Agents and Verifiers with SWE-Gym},
author={Jiayi Pan and Xingyao Wang and Graham Neubig and Navdeep Jaitly and Heng Ji and Alane Suhr and Yizhe Zhang},
year={2024},
eprint={2412.21139},
archivePrefix={arXiv},
primaryClass={cs.SE},
url={https://arxiv.org/abs/2412.21139},
}
```

View File

@@ -6,6 +6,13 @@ import time
from functools import partial
import pandas as pd
from swebench.harness.grading import get_eval_report
from swebench.harness.run_evaluation import (
APPLY_PATCH_FAIL,
APPLY_PATCH_PASS,
)
from swebench.harness.test_spec import SWEbenchInstance, TestSpec, make_test_spec
from swebench.harness.utils import load_swebench_dataset
from tqdm import tqdm
from evaluation.benchmarks.swe_bench.resource.mapping import (
@@ -277,7 +284,7 @@ def process_instance(
'model_patch': model_patch,
'instance_id': instance_id,
},
test_log_path=test_output_path,
log_path=test_output_path,
include_tests_status=True,
)
report = _report[instance_id]
@@ -337,31 +344,6 @@ if __name__ == '__main__':
)
args, _ = parser.parse_known_args()
if 'SWE-Gym' in args.dataset:
from swegym.harness.grading import get_eval_report
from swegym.harness.run_evaluation import (
APPLY_PATCH_FAIL,
APPLY_PATCH_PASS,
)
from swegym.harness.test_spec import (
SWEbenchInstance,
TestSpec,
make_test_spec,
)
from swegym.harness.utils import load_swebench_dataset
else: # Newer version of SWE-Bench have different import paths
from swebench.harness.grading import get_eval_report
from swebench.harness.run_evaluation import (
APPLY_PATCH_FAIL,
APPLY_PATCH_PASS,
)
from swebench.harness.test_spec.test_spec import (
SWEbenchInstance,
TestSpec,
make_test_spec,
)
from swebench.harness.utils import load_swebench_dataset
# Load SWE-Bench dataset
full_dataset: list[SWEbenchInstance] = load_swebench_dataset(
args.dataset, args.split

View File

@@ -44,6 +44,7 @@ from openhands.utils.async_utils import call_async_from_sync
from openhands.utils.shutdown_listener import sleep_if_should_continue
USE_HINT_TEXT = os.environ.get('USE_HINT_TEXT', 'false').lower() == 'true'
USE_INSTANCE_IMAGE = os.environ.get('USE_INSTANCE_IMAGE', 'true').lower() == 'true'
RUN_WITH_BROWSING = os.environ.get('RUN_WITH_BROWSING', 'false').lower() == 'true'
@@ -58,65 +59,36 @@ def _get_swebench_workspace_dir_name(instance: pd.Series) -> str:
def get_instruction(instance: pd.Series, metadata: EvalMetadata):
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
instruction = f"""
<uploaded_files>
/workspace/{workspace_dir_name}
</uploaded_files>
# Prepare instruction
I've uploaded a python code repository in the directory {workspace_dir_name}. Consider the following issue description:
<issue_description>
{instance.problem_statement}
</issue_description>
Can you help me implement the necessary changes to the repository so that the requirements specified in the <issue_description> are met?
I've already taken care of all changes to any of the test files described in the <issue_description>. This means you DON'T have to modify the testing logic or any of the tests in any way!
Also the development Python environment is already set up for you (i.e., all dependencies already installed), so you don't need to install other packages.
Your task is to make the minimal changes to non-test files in the /workspace/{workspace_dir_name} directory to ensure the <issue_description> is satisfied.
Follow these steps to resolve the issue:
1. EXPLORATION: First, thoroughly explore the repository structure using tools like `find` and `grep`.
- Identify all files mentioned in the problem statement
- Locate where the issue occurs in the codebase
- Understand the surrounding context and dependencies
- Use `grep` to search for relevant functions, classes, or error messages
2. ANALYSIS: Based on your exploration, think carefully about the problem and propose 2-5 possible approaches to fix the issue.
- Analyze the root cause of the problem
- Consider trade-offs between different solutions
- Select the most promising approach and explain your reasoning
3. TEST CREATION: Before implementing any fix, create a script to reproduce and verify the issue.
- Look at existing test files in the repository to understand the test format/structure
- Create a minimal reproduction script that demonstrates the issue
- Run your script to confirm the error exists
4. IMPLEMENTATION: Edit the source code to implement your chosen solution.
- Make minimal, focused changes to fix the issue
5. VERIFICATION: Test your implementation thoroughly.
- Run your reproduction script to verify the fix works
- Add edge cases to your test script to ensure comprehensive coverage
- Run existing tests related to the modified code to ensure you haven't broken anything
6. FINAL REVIEW: Carefully re-read the problem description and compare your changes with the base commit {instance["base_commit"]}.
- Ensure you've fully addressed all requirements
- Run any tests in the repository related to:
* The issue you are fixing
* The files you modified
* The functions you changed
- If any tests fail, revise your implementation until all tests pass
Be thorough in your exploration, testing, and reasoning. It's fine if your thinking process is lengthy - quality and completeness are more important than brevity.
"""
# Instruction based on Anthropic's official trajectory
# https://github.com/eschluntz/swe-bench-experiments/tree/main/evaluation/verified/20241022_tools_claude-3-5-sonnet-updated/trajs
instruction = (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a python code repository in the directory {workspace_dir_name}. Consider the following issue description:\n\n"
f'<issue_description>\n'
f'{instance.problem_statement}\n'
'</issue_description>\n\n'
'Can you help me implement the necessary changes to the repository so that the requirements specified in the <issue_description> are met?\n'
"I've already taken care of all changes to any of the test files described in the <pr_description>. This means you DON'T have to modify the testing logic or any of the tests in any way!\n"
'Your task is to make the minimal changes to non-tests files in the /workspace directory to ensure the <pr_description> is satisfied.\n'
'Follow these steps to resolve the issue:\n'
'1. As a first step, it might be a good idea to explore the repo to familiarize yourself with its structure.\n'
'2. Create a script to reproduce the error and execute it with `python <filename.py>` using the BashTool, to confirm the error\n'
'3. Edit the sourcecode of the repo to resolve the issue\n'
'4. Rerun your reproduce script and confirm that the error is fixed!\n'
'5. Think about edgecases and make sure your fix handles them as well\n'
"Your thinking should be thorough and so it's fine if it's very long.\n"
)
if RUN_WITH_BROWSING:
instruction += """
<IMPORTANT!>
You SHOULD NEVER attempt to browse the web.
</IMPORTANT!>
"""
instruction += (
'<IMPORTANT!>\n'
'You SHOULD NEVER attempt to browse the web. '
'</IMPORTANT!>\n'
)
return instruction
@@ -125,19 +97,11 @@ DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/xing
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
def get_instance_docker_image(instance_id: str, official_image: bool = False) -> str:
if official_image:
# Official SWE-Bench image
# swebench/sweb.eval.x86_64.django_1776_django-11333:v1
repo, name = instance_id.split('__')
image_name = f'sweb.eval.x86_64.{repo}_1776_{name}:latest'
logger.warning(f'Using official SWE-Bench image: {image_name}')
else:
# OpenHands version of the image
image_name = 'sweb.eval.x86_64.' + instance_id
image_name = image_name.replace(
'__', '_s_'
) # to comply with docker image naming convention
def get_instance_docker_image(instance_id: str) -> str:
image_name = 'sweb.eval.x86_64.' + instance_id
image_name = image_name.replace(
'__', '_s_'
) # to comply with docker image naming convention
return (DOCKER_IMAGE_PREFIX.rstrip('/') + '/' + image_name).lower()
@@ -145,18 +109,18 @@ def get_config(
instance: pd.Series,
metadata: EvalMetadata,
) -> AppConfig:
# We use a different instance image for the each instance of swe-bench eval
use_official_image = bool(
'verified' in metadata.dataset.lower() or 'lite' in metadata.dataset.lower()
)
base_container_image = get_instance_docker_image(
instance['instance_id'], use_official_image
)
logger.info(
f'Using instance container image: {base_container_image}. '
f'Please make sure this image exists. '
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
)
SWE_BENCH_CONTAINER_IMAGE = 'ghcr.io/opendevin/eval-swe-bench:full-v1.2.1'
if USE_INSTANCE_IMAGE:
# We use a different instance image for the each instance of swe-bench eval
base_container_image = get_instance_docker_image(instance['instance_id'])
logger.info(
f'Using instance container image: {base_container_image}. '
f'Please make sure this image exists. '
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
)
else:
base_container_image = SWE_BENCH_CONTAINER_IMAGE
logger.info(f'Using swe-bench container image: {base_container_image}')
sandbox_config = get_default_sandbox_config_for_eval()
sandbox_config.base_container_image = base_container_image
@@ -228,65 +192,75 @@ def initialize_runtime(
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(obs.exit_code == 0, f'Failed to export USER: {str(obs)}')
# inject the init script
script_dir = os.path.dirname(__file__)
if USE_INSTANCE_IMAGE:
# inject the init script
script_dir = os.path.dirname(__file__)
# inject the instance info
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to create /swe_util/eval_data/instances: {str(obs)}',
)
# inject the instance info
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to create /swe_util/eval_data/instances: {str(obs)}',
)
swe_instance_json_name = 'swe-bench-instance.json'
with tempfile.TemporaryDirectory() as temp_dir:
# Construct the full path for the desired file name within the temporary directory
temp_file_path = os.path.join(temp_dir, swe_instance_json_name)
# Write to the file with the desired name within the temporary directory
with open(temp_file_path, 'w') as f:
if not isinstance(instance, dict):
json.dump([instance.to_dict()], f)
else:
json.dump([instance], f)
swe_instance_json_name = 'swe-bench-instance.json'
with tempfile.TemporaryDirectory() as temp_dir:
# Construct the full path for the desired file name within the temporary directory
temp_file_path = os.path.join(temp_dir, swe_instance_json_name)
# Write to the file with the desired name within the temporary directory
with open(temp_file_path, 'w') as f:
if not isinstance(instance, dict):
json.dump([instance.to_dict()], f)
else:
json.dump([instance], f)
# Copy the file to the desired location
runtime.copy_to(temp_file_path, '/swe_util/eval_data/instances/')
# Copy the file to the desired location
runtime.copy_to(temp_file_path, '/swe_util/eval_data/instances/')
# inject the instance swe entry
runtime.copy_to(
str(os.path.join(script_dir, 'scripts/setup/instance_swe_entry.sh')),
'/swe_util/',
)
action = CmdRunAction(command='cat ~/.bashrc')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(obs.exit_code == 0, f'Failed to cat ~/.bashrc: {str(obs)}')
action = CmdRunAction(command='cat ~/.bashrc')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(obs.exit_code == 0, f'Failed to cat ~/.bashrc: {str(obs)}')
action = CmdRunAction(command='source ~/.bashrc')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
if isinstance(obs, ErrorObservation):
logger.error(f'Failed to source ~/.bashrc: {str(obs)}')
assert_and_raise(obs.exit_code == 0, f'Failed to source ~/.bashrc: {str(obs)}')
action = CmdRunAction(command='source ~/.bashrc')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
if isinstance(obs, ErrorObservation):
logger.error(f'Failed to source ~/.bashrc: {str(obs)}')
assert_and_raise(obs.exit_code == 0, f'Failed to source ~/.bashrc: {str(obs)}')
action = CmdRunAction(command='source /swe_util/instance_swe_entry.sh')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to source /swe_util/instance_swe_entry.sh: {str(obs)}',
)
action = CmdRunAction(command='source /swe_util/instance_swe_entry.sh')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to source /swe_util/instance_swe_entry.sh: {str(obs)}',
)
else:
action = CmdRunAction(command='source /swe_util/swe_entry.sh')
action.set_hard_timeout(1800)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to source /swe_util/swe_entry.sh: {str(obs)}',
)
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
action.set_hard_timeout(600)
@@ -381,32 +355,6 @@ def complete_runtime(
f'Failed to git config --global core.pager "": {str(obs)}',
)
# First check for any git repositories in subdirectories
action = CmdRunAction(command='find . -type d -name .git -not -path "./.git"')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to find git repositories: {str(obs)}',
)
git_dirs = [p for p in obs.content.strip().split('\n') if p]
if git_dirs:
# Remove all .git directories in subdirectories
for git_dir in git_dirs:
action = CmdRunAction(command=f'rm -rf "{git_dir}"')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to remove git directory {git_dir}: {str(obs)}',
)
# add all files
action = CmdRunAction(command='git add -A')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
@@ -558,20 +506,6 @@ def filter_dataset(dataset: pd.DataFrame, filter_column: str) -> pd.DataFrame:
return dataset
# A list of instances that are known to be tricky to infer
# (will cause runtime failure even with resource factor = 8)
SWEGYM_EXCLUDE_IDS = [
'dask__dask-10422',
'pandas-dev__pandas-50548',
'pandas-dev__pandas-53672',
'pandas-dev__pandas-54174',
'pandas-dev__pandas-55518',
'pandas-dev__pandas-58383',
'pydata__xarray-6721',
'pytest-dev__pytest-10081',
'pytest-dev__pytest-7236',
]
if __name__ == '__main__':
parser = get_parser()
parser.add_argument(
@@ -595,13 +529,6 @@ if __name__ == '__main__':
logger.info(
f'Loaded dataset {args.dataset} with split {args.split}: {len(swe_bench_tests)} tasks'
)
if 'SWE-Gym' in args.dataset:
swe_bench_tests = swe_bench_tests[
~swe_bench_tests['instance_id'].isin(SWEGYM_EXCLUDE_IDS)
]
logger.info(
f'{len(swe_bench_tests)} tasks left after excluding SWE-Gym excluded tasks'
)
llm_config = None
if args.llm_config:
@@ -645,6 +572,6 @@ if __name__ == '__main__':
output_file,
args.eval_num_workers,
process_instance,
timeout_seconds=8 * 60 * 60, # 8 hour PER instance should be more than enough
timeout_seconds=120 * 60, # 2 hour PER instance should be more than enough
max_retries=5,
)

View File

@@ -1,300 +1,336 @@
swebench/sweb.eval.x86_64.astropy_1776_astropy-12907:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14182:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14365:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14995:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-6938:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-7746:latest
swebench/sweb.eval.x86_64.django_1776_django-10914:latest
swebench/sweb.eval.x86_64.django_1776_django-10924:latest
swebench/sweb.eval.x86_64.django_1776_django-11001:latest
swebench/sweb.eval.x86_64.django_1776_django-11019:latest
swebench/sweb.eval.x86_64.django_1776_django-11039:latest
swebench/sweb.eval.x86_64.django_1776_django-11049:latest
swebench/sweb.eval.x86_64.django_1776_django-11099:latest
swebench/sweb.eval.x86_64.django_1776_django-11133:latest
swebench/sweb.eval.x86_64.django_1776_django-11179:latest
swebench/sweb.eval.x86_64.django_1776_django-11283:latest
swebench/sweb.eval.x86_64.django_1776_django-11422:latest
swebench/sweb.eval.x86_64.django_1776_django-11564:latest
swebench/sweb.eval.x86_64.django_1776_django-11583:latest
swebench/sweb.eval.x86_64.django_1776_django-11620:latest
swebench/sweb.eval.x86_64.django_1776_django-11630:latest
swebench/sweb.eval.x86_64.django_1776_django-11742:latest
swebench/sweb.eval.x86_64.django_1776_django-11797:latest
swebench/sweb.eval.x86_64.django_1776_django-11815:latest
swebench/sweb.eval.x86_64.django_1776_django-11848:latest
swebench/sweb.eval.x86_64.django_1776_django-11905:latest
swebench/sweb.eval.x86_64.django_1776_django-11910:latest
swebench/sweb.eval.x86_64.django_1776_django-11964:latest
swebench/sweb.eval.x86_64.django_1776_django-11999:latest
swebench/sweb.eval.x86_64.django_1776_django-12113:latest
swebench/sweb.eval.x86_64.django_1776_django-12125:latest
swebench/sweb.eval.x86_64.django_1776_django-12184:latest
swebench/sweb.eval.x86_64.django_1776_django-12284:latest
swebench/sweb.eval.x86_64.django_1776_django-12286:latest
swebench/sweb.eval.x86_64.django_1776_django-12308:latest
swebench/sweb.eval.x86_64.django_1776_django-12453:latest
swebench/sweb.eval.x86_64.django_1776_django-12470:latest
swebench/sweb.eval.x86_64.django_1776_django-12497:latest
swebench/sweb.eval.x86_64.django_1776_django-12589:latest
swebench/sweb.eval.x86_64.django_1776_django-12700:latest
swebench/sweb.eval.x86_64.django_1776_django-12708:latest
swebench/sweb.eval.x86_64.django_1776_django-12747:latest
swebench/sweb.eval.x86_64.django_1776_django-12856:latest
swebench/sweb.eval.x86_64.django_1776_django-12908:latest
swebench/sweb.eval.x86_64.django_1776_django-12915:latest
swebench/sweb.eval.x86_64.django_1776_django-12983:latest
swebench/sweb.eval.x86_64.django_1776_django-13028:latest
swebench/sweb.eval.x86_64.django_1776_django-13033:latest
swebench/sweb.eval.x86_64.django_1776_django-13158:latest
swebench/sweb.eval.x86_64.django_1776_django-13220:latest
swebench/sweb.eval.x86_64.django_1776_django-13230:latest
swebench/sweb.eval.x86_64.django_1776_django-13265:latest
swebench/sweb.eval.x86_64.django_1776_django-13315:latest
swebench/sweb.eval.x86_64.django_1776_django-13321:latest
swebench/sweb.eval.x86_64.django_1776_django-13401:latest
swebench/sweb.eval.x86_64.django_1776_django-13447:latest
swebench/sweb.eval.x86_64.django_1776_django-13448:latest
swebench/sweb.eval.x86_64.django_1776_django-13551:latest
swebench/sweb.eval.x86_64.django_1776_django-13590:latest
swebench/sweb.eval.x86_64.django_1776_django-13658:latest
swebench/sweb.eval.x86_64.django_1776_django-13660:latest
swebench/sweb.eval.x86_64.django_1776_django-13710:latest
swebench/sweb.eval.x86_64.django_1776_django-13757:latest
swebench/sweb.eval.x86_64.django_1776_django-13768:latest
swebench/sweb.eval.x86_64.django_1776_django-13925:latest
swebench/sweb.eval.x86_64.django_1776_django-13933:latest
swebench/sweb.eval.x86_64.django_1776_django-13964:latest
swebench/sweb.eval.x86_64.django_1776_django-14016:latest
swebench/sweb.eval.x86_64.django_1776_django-14017:latest
swebench/sweb.eval.x86_64.django_1776_django-14155:latest
swebench/sweb.eval.x86_64.django_1776_django-14238:latest
swebench/sweb.eval.x86_64.django_1776_django-14382:latest
swebench/sweb.eval.x86_64.django_1776_django-14411:latest
swebench/sweb.eval.x86_64.django_1776_django-14534:latest
swebench/sweb.eval.x86_64.django_1776_django-14580:latest
swebench/sweb.eval.x86_64.django_1776_django-14608:latest
swebench/sweb.eval.x86_64.django_1776_django-14667:latest
swebench/sweb.eval.x86_64.django_1776_django-14672:latest
swebench/sweb.eval.x86_64.django_1776_django-14730:latest
swebench/sweb.eval.x86_64.django_1776_django-14752:latest
swebench/sweb.eval.x86_64.django_1776_django-14787:latest
swebench/sweb.eval.x86_64.django_1776_django-14855:latest
swebench/sweb.eval.x86_64.django_1776_django-14915:latest
swebench/sweb.eval.x86_64.django_1776_django-14997:latest
swebench/sweb.eval.x86_64.django_1776_django-14999:latest
swebench/sweb.eval.x86_64.django_1776_django-15061:latest
swebench/sweb.eval.x86_64.django_1776_django-15202:latest
swebench/sweb.eval.x86_64.django_1776_django-15213:latest
swebench/sweb.eval.x86_64.django_1776_django-15252:latest
swebench/sweb.eval.x86_64.django_1776_django-15320:latest
swebench/sweb.eval.x86_64.django_1776_django-15347:latest
swebench/sweb.eval.x86_64.django_1776_django-15388:latest
swebench/sweb.eval.x86_64.django_1776_django-15400:latest
swebench/sweb.eval.x86_64.django_1776_django-15498:latest
swebench/sweb.eval.x86_64.django_1776_django-15695:latest
swebench/sweb.eval.x86_64.django_1776_django-15738:latest
swebench/sweb.eval.x86_64.django_1776_django-15781:latest
swebench/sweb.eval.x86_64.django_1776_django-15789:latest
swebench/sweb.eval.x86_64.django_1776_django-15790:latest
swebench/sweb.eval.x86_64.django_1776_django-15814:latest
swebench/sweb.eval.x86_64.django_1776_django-15819:latest
swebench/sweb.eval.x86_64.django_1776_django-15851:latest
swebench/sweb.eval.x86_64.django_1776_django-15902:latest
swebench/sweb.eval.x86_64.django_1776_django-15996:latest
swebench/sweb.eval.x86_64.django_1776_django-16041:latest
swebench/sweb.eval.x86_64.django_1776_django-16046:latest
swebench/sweb.eval.x86_64.django_1776_django-16139:latest
swebench/sweb.eval.x86_64.django_1776_django-16229:latest
swebench/sweb.eval.x86_64.django_1776_django-16255:latest
swebench/sweb.eval.x86_64.django_1776_django-16379:latest
swebench/sweb.eval.x86_64.django_1776_django-16400:latest
swebench/sweb.eval.x86_64.django_1776_django-16408:latest
swebench/sweb.eval.x86_64.django_1776_django-16527:latest
swebench/sweb.eval.x86_64.django_1776_django-16595:latest
swebench/sweb.eval.x86_64.django_1776_django-16816:latest
swebench/sweb.eval.x86_64.django_1776_django-16820:latest
swebench/sweb.eval.x86_64.django_1776_django-16873:latest
swebench/sweb.eval.x86_64.django_1776_django-16910:latest
swebench/sweb.eval.x86_64.django_1776_django-17051:latest
swebench/sweb.eval.x86_64.django_1776_django-17087:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-18869:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22711:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22835:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23299:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23314:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23476:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23562:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23563:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23913:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23964:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23987:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24149:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24265:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24334:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24970:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25079:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25311:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25332:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25433:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25442:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25498:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26011:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26020:latest
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-2848:latest
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3010:latest
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3190:latest
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3407:latest
swebench/sweb.eval.x86_64.pallets_1776_flask-4045:latest
swebench/sweb.eval.x86_64.pallets_1776_flask-4992:latest
swebench/sweb.eval.x86_64.pallets_1776_flask-5063:latest
swebench/sweb.eval.x86_64.psf_1776_requests-1963:latest
swebench/sweb.eval.x86_64.psf_1776_requests-2148:latest
swebench/sweb.eval.x86_64.psf_1776_requests-2317:latest
swebench/sweb.eval.x86_64.psf_1776_requests-2674:latest
swebench/sweb.eval.x86_64.psf_1776_requests-3362:latest
swebench/sweb.eval.x86_64.psf_1776_requests-863:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-3364:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4094:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4248:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4493:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-5131:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-5859:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6506:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7080:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7114:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7228:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7993:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-11143:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-11148:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5103:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5221:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5227:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5413:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5495:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5692:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-6116:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7168:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7220:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7373:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7432:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7490:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-8365:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-8906:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-9359:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10297:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10508:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10949:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11040:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11281:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12471:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13142:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13241:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13439:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13496:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13497:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13584:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13779:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14087:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14092:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14894:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14983:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-15512:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-15535:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25500:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25570:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25638:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25747:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10325:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10451:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-11445:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7686:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7738:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7975:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8273:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8282:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8435:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8474:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8506:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8595:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8627:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8713:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8721:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8801:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-11400:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-11870:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-11897:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12171:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12236:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12419:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12454:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12481:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13031:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13043:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13146:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13177:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13437:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13471:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13480:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13647:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13773:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13895:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13915:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13971:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14024:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14308:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14317:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14396:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14774:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14817:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15011:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15308:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15345:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15346:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15609:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15678:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16106:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16281:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16503:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16792:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16988:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17022:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17139:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17630:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17655:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18057:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18087:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18189:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18199:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18532:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18621:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18698:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18835:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19007:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19254:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19487:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20049:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20154:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20212:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20322:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20442:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20590:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20639:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21055:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21171:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21379:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21612:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21614:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21627:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21847:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-22005:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-22714:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-22840:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23117:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23191:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23262:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24066:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24102:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24152:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24213:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24909:latest
sweb.base.x86_64:latest
sweb.env.x86_64.088a7e628bda9770f9757b:latest
sweb.env.x86_64.0d80c7dec81ee2f2f513e2:latest
sweb.env.x86_64.0f99bce2750f3109957bec:latest
sweb.env.x86_64.1b3b218535da0abf4469cb:latest
sweb.env.x86_64.1c1a6945f732f9391228c5:latest
sweb.env.x86_64.1f92e6d7cef88badc4f744:latest
sweb.env.x86_64.27dd9791e13f5c857a09f9:latest
sweb.env.x86_64.297af196949a2a635bce66:latest
sweb.env.x86_64.2baaea72acc974f6c02079:latest
sweb.env.x86_64.2e50125951bc69cddd7421:latest
sweb.env.x86_64.2f217c8b4490bfa0e2ba14:latest
sweb.env.x86_64.31244378a92e3bcce809ac:latest
sweb.env.x86_64.428468730904ff6b4232aa:latest
sweb.env.x86_64.5d1fda9d55d65d8a4e5bdb:latest
sweb.env.x86_64.6b007979cf533f0f3016e8:latest
sweb.env.x86_64.7037e8c448a4b8ebfe9b13:latest
sweb.env.x86_64.71498c7426dbf05599642f:latest
sweb.env.x86_64.756beac07713d7e8dc1129:latest
sweb.env.x86_64.78278ae2cf880e395f1337:latest
sweb.env.x86_64.8f1f7b974f0c57c7aeba39:latest
sweb.env.x86_64.934a137824256b612e9dc5:latest
sweb.env.x86_64.a0efca7a0fe6719dbf65c2:latest
sweb.env.x86_64.a18371b03f944585b4f08c:latest
sweb.env.x86_64.a33dddf55cdff5d8e23374:latest
sweb.env.x86_64.aa92880033da20ca313928:latest
sweb.env.x86_64.b649f0ff62fad147f7f073:latest
sweb.env.x86_64.b7ce4be3b3c35f68c61248:latest
sweb.env.x86_64.c70909fdac4897d1c685df:latest
sweb.env.x86_64.c795f4b88616b8462021ed:latest
sweb.env.x86_64.cc47cc71483942d0c3a15e:latest
sweb.env.x86_64.dc5ff4c0e3fe8db5afc4da:latest
sweb.env.x86_64.e3afd7f04b325a4de4982d:latest
sweb.env.x86_64.e5bb89bf78258a7d14c34b:latest
sweb.env.x86_64.e83e37f52c09532c62acfb:latest
sweb.env.x86_64.efa6065ed5bf204410fd53:latest
sweb.eval.x86_64.astropy_s_astropy-12907:latest
sweb.eval.x86_64.astropy_s_astropy-14182:latest
sweb.eval.x86_64.astropy_s_astropy-14365:latest
sweb.eval.x86_64.astropy_s_astropy-14995:latest
sweb.eval.x86_64.astropy_s_astropy-6938:latest
sweb.eval.x86_64.astropy_s_astropy-7746:latest
sweb.eval.x86_64.django_s_django-10914:latest
sweb.eval.x86_64.django_s_django-10924:latest
sweb.eval.x86_64.django_s_django-11001:latest
sweb.eval.x86_64.django_s_django-11019:latest
sweb.eval.x86_64.django_s_django-11039:latest
sweb.eval.x86_64.django_s_django-11049:latest
sweb.eval.x86_64.django_s_django-11099:latest
sweb.eval.x86_64.django_s_django-11133:latest
sweb.eval.x86_64.django_s_django-11179:latest
sweb.eval.x86_64.django_s_django-11283:latest
sweb.eval.x86_64.django_s_django-11422:latest
sweb.eval.x86_64.django_s_django-11564:latest
sweb.eval.x86_64.django_s_django-11583:latest
sweb.eval.x86_64.django_s_django-11620:latest
sweb.eval.x86_64.django_s_django-11630:latest
sweb.eval.x86_64.django_s_django-11742:latest
sweb.eval.x86_64.django_s_django-11797:latest
sweb.eval.x86_64.django_s_django-11815:latest
sweb.eval.x86_64.django_s_django-11848:latest
sweb.eval.x86_64.django_s_django-11905:latest
sweb.eval.x86_64.django_s_django-11910:latest
sweb.eval.x86_64.django_s_django-11964:latest
sweb.eval.x86_64.django_s_django-11999:latest
sweb.eval.x86_64.django_s_django-12113:latest
sweb.eval.x86_64.django_s_django-12125:latest
sweb.eval.x86_64.django_s_django-12184:latest
sweb.eval.x86_64.django_s_django-12284:latest
sweb.eval.x86_64.django_s_django-12286:latest
sweb.eval.x86_64.django_s_django-12308:latest
sweb.eval.x86_64.django_s_django-12453:latest
sweb.eval.x86_64.django_s_django-12470:latest
sweb.eval.x86_64.django_s_django-12497:latest
sweb.eval.x86_64.django_s_django-12589:latest
sweb.eval.x86_64.django_s_django-12700:latest
sweb.eval.x86_64.django_s_django-12708:latest
sweb.eval.x86_64.django_s_django-12747:latest
sweb.eval.x86_64.django_s_django-12856:latest
sweb.eval.x86_64.django_s_django-12908:latest
sweb.eval.x86_64.django_s_django-12915:latest
sweb.eval.x86_64.django_s_django-12983:latest
sweb.eval.x86_64.django_s_django-13028:latest
sweb.eval.x86_64.django_s_django-13033:latest
sweb.eval.x86_64.django_s_django-13158:latest
sweb.eval.x86_64.django_s_django-13220:latest
sweb.eval.x86_64.django_s_django-13230:latest
sweb.eval.x86_64.django_s_django-13265:latest
sweb.eval.x86_64.django_s_django-13315:latest
sweb.eval.x86_64.django_s_django-13321:latest
sweb.eval.x86_64.django_s_django-13401:latest
sweb.eval.x86_64.django_s_django-13447:latest
sweb.eval.x86_64.django_s_django-13448:latest
sweb.eval.x86_64.django_s_django-13551:latest
sweb.eval.x86_64.django_s_django-13590:latest
sweb.eval.x86_64.django_s_django-13658:latest
sweb.eval.x86_64.django_s_django-13660:latest
sweb.eval.x86_64.django_s_django-13710:latest
sweb.eval.x86_64.django_s_django-13757:latest
sweb.eval.x86_64.django_s_django-13768:latest
sweb.eval.x86_64.django_s_django-13925:latest
sweb.eval.x86_64.django_s_django-13933:latest
sweb.eval.x86_64.django_s_django-13964:latest
sweb.eval.x86_64.django_s_django-14016:latest
sweb.eval.x86_64.django_s_django-14017:latest
sweb.eval.x86_64.django_s_django-14155:latest
sweb.eval.x86_64.django_s_django-14238:latest
sweb.eval.x86_64.django_s_django-14382:latest
sweb.eval.x86_64.django_s_django-14411:latest
sweb.eval.x86_64.django_s_django-14534:latest
sweb.eval.x86_64.django_s_django-14580:latest
sweb.eval.x86_64.django_s_django-14608:latest
sweb.eval.x86_64.django_s_django-14667:latest
sweb.eval.x86_64.django_s_django-14672:latest
sweb.eval.x86_64.django_s_django-14730:latest
sweb.eval.x86_64.django_s_django-14752:latest
sweb.eval.x86_64.django_s_django-14787:latest
sweb.eval.x86_64.django_s_django-14855:latest
sweb.eval.x86_64.django_s_django-14915:latest
sweb.eval.x86_64.django_s_django-14997:latest
sweb.eval.x86_64.django_s_django-14999:latest
sweb.eval.x86_64.django_s_django-15061:latest
sweb.eval.x86_64.django_s_django-15202:latest
sweb.eval.x86_64.django_s_django-15213:latest
sweb.eval.x86_64.django_s_django-15252:latest
sweb.eval.x86_64.django_s_django-15320:latest
sweb.eval.x86_64.django_s_django-15347:latest
sweb.eval.x86_64.django_s_django-15388:latest
sweb.eval.x86_64.django_s_django-15400:latest
sweb.eval.x86_64.django_s_django-15498:latest
sweb.eval.x86_64.django_s_django-15695:latest
sweb.eval.x86_64.django_s_django-15738:latest
sweb.eval.x86_64.django_s_django-15781:latest
sweb.eval.x86_64.django_s_django-15789:latest
sweb.eval.x86_64.django_s_django-15790:latest
sweb.eval.x86_64.django_s_django-15814:latest
sweb.eval.x86_64.django_s_django-15819:latest
sweb.eval.x86_64.django_s_django-15851:latest
sweb.eval.x86_64.django_s_django-15902:latest
sweb.eval.x86_64.django_s_django-15996:latest
sweb.eval.x86_64.django_s_django-16041:latest
sweb.eval.x86_64.django_s_django-16046:latest
sweb.eval.x86_64.django_s_django-16139:latest
sweb.eval.x86_64.django_s_django-16229:latest
sweb.eval.x86_64.django_s_django-16255:latest
sweb.eval.x86_64.django_s_django-16379:latest
sweb.eval.x86_64.django_s_django-16400:latest
sweb.eval.x86_64.django_s_django-16408:latest
sweb.eval.x86_64.django_s_django-16527:latest
sweb.eval.x86_64.django_s_django-16595:latest
sweb.eval.x86_64.django_s_django-16816:latest
sweb.eval.x86_64.django_s_django-16820:latest
sweb.eval.x86_64.django_s_django-16873:latest
sweb.eval.x86_64.django_s_django-16910:latest
sweb.eval.x86_64.django_s_django-17051:latest
sweb.eval.x86_64.django_s_django-17087:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-18869:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-22711:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-22835:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23299:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23314:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23476:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23562:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23563:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23913:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23964:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-23987:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-24149:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-24265:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-24334:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-24970:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-25079:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-25311:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-25332:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-25433:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-25442:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-25498:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-26011:latest
sweb.eval.x86_64.matplotlib_s_matplotlib-26020:latest
sweb.eval.x86_64.mwaskom_s_seaborn-2848:latest
sweb.eval.x86_64.mwaskom_s_seaborn-3010:latest
sweb.eval.x86_64.mwaskom_s_seaborn-3190:latest
sweb.eval.x86_64.mwaskom_s_seaborn-3407:latest
sweb.eval.x86_64.pallets_s_flask-4045:latest
sweb.eval.x86_64.pallets_s_flask-4992:latest
sweb.eval.x86_64.pallets_s_flask-5063:latest
sweb.eval.x86_64.psf_s_requests-1963:latest
sweb.eval.x86_64.psf_s_requests-2148:latest
sweb.eval.x86_64.psf_s_requests-2317:latest
sweb.eval.x86_64.psf_s_requests-2674:latest
sweb.eval.x86_64.psf_s_requests-3362:latest
sweb.eval.x86_64.psf_s_requests-863:latest
sweb.eval.x86_64.pydata_s_xarray-3364:latest
sweb.eval.x86_64.pydata_s_xarray-4094:latest
sweb.eval.x86_64.pydata_s_xarray-4248:latest
sweb.eval.x86_64.pydata_s_xarray-4493:latest
sweb.eval.x86_64.pydata_s_xarray-5131:latest
sweb.eval.x86_64.pylint-dev_s_pylint-5859:latest
sweb.eval.x86_64.pylint-dev_s_pylint-6506:latest
sweb.eval.x86_64.pylint-dev_s_pylint-7080:latest
sweb.eval.x86_64.pylint-dev_s_pylint-7114:latest
sweb.eval.x86_64.pylint-dev_s_pylint-7228:latest
sweb.eval.x86_64.pylint-dev_s_pylint-7993:latest
sweb.eval.x86_64.pytest-dev_s_pytest-11143:latest
sweb.eval.x86_64.pytest-dev_s_pytest-11148:latest
sweb.eval.x86_64.pytest-dev_s_pytest-5103:latest
sweb.eval.x86_64.pytest-dev_s_pytest-5221:latest
sweb.eval.x86_64.pytest-dev_s_pytest-5227:latest
sweb.eval.x86_64.pytest-dev_s_pytest-5413:latest
sweb.eval.x86_64.pytest-dev_s_pytest-5495:latest
sweb.eval.x86_64.pytest-dev_s_pytest-5692:latest
sweb.eval.x86_64.pytest-dev_s_pytest-6116:latest
sweb.eval.x86_64.pytest-dev_s_pytest-7168:latest
sweb.eval.x86_64.pytest-dev_s_pytest-7220:latest
sweb.eval.x86_64.pytest-dev_s_pytest-7373:latest
sweb.eval.x86_64.pytest-dev_s_pytest-7432:latest
sweb.eval.x86_64.pytest-dev_s_pytest-7490:latest
sweb.eval.x86_64.pytest-dev_s_pytest-8365:latest
sweb.eval.x86_64.pytest-dev_s_pytest-8906:latest
sweb.eval.x86_64.pytest-dev_s_pytest-9359:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10297:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10508:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10949:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-11040:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-11281:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-12471:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13142:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13241:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13439:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13496:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13497:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13584:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13779:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14087:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14092:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14894:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14983:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-15512:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-15535:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25500:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25570:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25638:latest
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25747:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-10325:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-10451:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-11445:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-7686:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-7738:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-7975:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8273:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8282:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8435:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8474:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8506:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8595:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8627:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8713:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8721:latest
sweb.eval.x86_64.sphinx-doc_s_sphinx-8801:latest
sweb.eval.x86_64.sympy_s_sympy-11400:latest
sweb.eval.x86_64.sympy_s_sympy-11870:latest
sweb.eval.x86_64.sympy_s_sympy-11897:latest
sweb.eval.x86_64.sympy_s_sympy-12171:latest
sweb.eval.x86_64.sympy_s_sympy-12236:latest
sweb.eval.x86_64.sympy_s_sympy-12419:latest
sweb.eval.x86_64.sympy_s_sympy-12454:latest
sweb.eval.x86_64.sympy_s_sympy-12481:latest
sweb.eval.x86_64.sympy_s_sympy-13031:latest
sweb.eval.x86_64.sympy_s_sympy-13043:latest
sweb.eval.x86_64.sympy_s_sympy-13146:latest
sweb.eval.x86_64.sympy_s_sympy-13177:latest
sweb.eval.x86_64.sympy_s_sympy-13437:latest
sweb.eval.x86_64.sympy_s_sympy-13471:latest
sweb.eval.x86_64.sympy_s_sympy-13480:latest
sweb.eval.x86_64.sympy_s_sympy-13647:latest
sweb.eval.x86_64.sympy_s_sympy-13773:latest
sweb.eval.x86_64.sympy_s_sympy-13895:latest
sweb.eval.x86_64.sympy_s_sympy-13915:latest
sweb.eval.x86_64.sympy_s_sympy-13971:latest
sweb.eval.x86_64.sympy_s_sympy-14024:latest
sweb.eval.x86_64.sympy_s_sympy-14308:latest
sweb.eval.x86_64.sympy_s_sympy-14317:latest
sweb.eval.x86_64.sympy_s_sympy-14396:latest
sweb.eval.x86_64.sympy_s_sympy-14774:latest
sweb.eval.x86_64.sympy_s_sympy-14817:latest
sweb.eval.x86_64.sympy_s_sympy-15011:latest
sweb.eval.x86_64.sympy_s_sympy-15308:latest
sweb.eval.x86_64.sympy_s_sympy-15345:latest
sweb.eval.x86_64.sympy_s_sympy-15346:latest
sweb.eval.x86_64.sympy_s_sympy-15609:latest
sweb.eval.x86_64.sympy_s_sympy-15678:latest
sweb.eval.x86_64.sympy_s_sympy-16106:latest
sweb.eval.x86_64.sympy_s_sympy-16281:latest
sweb.eval.x86_64.sympy_s_sympy-16503:latest
sweb.eval.x86_64.sympy_s_sympy-16792:latest
sweb.eval.x86_64.sympy_s_sympy-16988:latest
sweb.eval.x86_64.sympy_s_sympy-17022:latest
sweb.eval.x86_64.sympy_s_sympy-17139:latest
sweb.eval.x86_64.sympy_s_sympy-17630:latest
sweb.eval.x86_64.sympy_s_sympy-17655:latest
sweb.eval.x86_64.sympy_s_sympy-18057:latest
sweb.eval.x86_64.sympy_s_sympy-18087:latest
sweb.eval.x86_64.sympy_s_sympy-18189:latest
sweb.eval.x86_64.sympy_s_sympy-18199:latest
sweb.eval.x86_64.sympy_s_sympy-18532:latest
sweb.eval.x86_64.sympy_s_sympy-18621:latest
sweb.eval.x86_64.sympy_s_sympy-18698:latest
sweb.eval.x86_64.sympy_s_sympy-18835:latest
sweb.eval.x86_64.sympy_s_sympy-19007:latest
sweb.eval.x86_64.sympy_s_sympy-19254:latest
sweb.eval.x86_64.sympy_s_sympy-19487:latest
sweb.eval.x86_64.sympy_s_sympy-20049:latest
sweb.eval.x86_64.sympy_s_sympy-20154:latest
sweb.eval.x86_64.sympy_s_sympy-20212:latest
sweb.eval.x86_64.sympy_s_sympy-20322:latest
sweb.eval.x86_64.sympy_s_sympy-20442:latest
sweb.eval.x86_64.sympy_s_sympy-20590:latest
sweb.eval.x86_64.sympy_s_sympy-20639:latest
sweb.eval.x86_64.sympy_s_sympy-21055:latest
sweb.eval.x86_64.sympy_s_sympy-21171:latest
sweb.eval.x86_64.sympy_s_sympy-21379:latest
sweb.eval.x86_64.sympy_s_sympy-21612:latest
sweb.eval.x86_64.sympy_s_sympy-21614:latest
sweb.eval.x86_64.sympy_s_sympy-21627:latest
sweb.eval.x86_64.sympy_s_sympy-21847:latest
sweb.eval.x86_64.sympy_s_sympy-22005:latest
sweb.eval.x86_64.sympy_s_sympy-22714:latest
sweb.eval.x86_64.sympy_s_sympy-22840:latest
sweb.eval.x86_64.sympy_s_sympy-23117:latest
sweb.eval.x86_64.sympy_s_sympy-23191:latest
sweb.eval.x86_64.sympy_s_sympy-23262:latest
sweb.eval.x86_64.sympy_s_sympy-24066:latest
sweb.eval.x86_64.sympy_s_sympy-24102:latest
sweb.eval.x86_64.sympy_s_sympy-24152:latest
sweb.eval.x86_64.sympy_s_sympy-24213:latest
sweb.eval.x86_64.sympy_s_sympy-24909:latest

View File

@@ -1,500 +0,0 @@
swebench/sweb.eval.x86_64.astropy_1776_astropy-12907:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-13033:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-13236:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-13398:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-13453:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-13579:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-13977:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14096:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14182:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14309:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14365:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14369:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14508:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14539:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14598:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-14995:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-7166:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-7336:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-7606:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-7671:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-8707:latest
swebench/sweb.eval.x86_64.astropy_1776_astropy-8872:latest
swebench/sweb.eval.x86_64.django_1776_django-10097:latest
swebench/sweb.eval.x86_64.django_1776_django-10554:latest
swebench/sweb.eval.x86_64.django_1776_django-10880:latest
swebench/sweb.eval.x86_64.django_1776_django-10914:latest
swebench/sweb.eval.x86_64.django_1776_django-10973:latest
swebench/sweb.eval.x86_64.django_1776_django-10999:latest
swebench/sweb.eval.x86_64.django_1776_django-11066:latest
swebench/sweb.eval.x86_64.django_1776_django-11087:latest
swebench/sweb.eval.x86_64.django_1776_django-11095:latest
swebench/sweb.eval.x86_64.django_1776_django-11099:latest
swebench/sweb.eval.x86_64.django_1776_django-11119:latest
swebench/sweb.eval.x86_64.django_1776_django-11133:latest
swebench/sweb.eval.x86_64.django_1776_django-11138:latest
swebench/sweb.eval.x86_64.django_1776_django-11141:latest
swebench/sweb.eval.x86_64.django_1776_django-11149:latest
swebench/sweb.eval.x86_64.django_1776_django-11163:latest
swebench/sweb.eval.x86_64.django_1776_django-11179:latest
swebench/sweb.eval.x86_64.django_1776_django-11206:latest
swebench/sweb.eval.x86_64.django_1776_django-11211:latest
swebench/sweb.eval.x86_64.django_1776_django-11239:latest
swebench/sweb.eval.x86_64.django_1776_django-11265:latest
swebench/sweb.eval.x86_64.django_1776_django-11276:latest
swebench/sweb.eval.x86_64.django_1776_django-11292:latest
swebench/sweb.eval.x86_64.django_1776_django-11299:latest
swebench/sweb.eval.x86_64.django_1776_django-11333:latest
swebench/sweb.eval.x86_64.django_1776_django-11400:latest
swebench/sweb.eval.x86_64.django_1776_django-11433:latest
swebench/sweb.eval.x86_64.django_1776_django-11451:latest
swebench/sweb.eval.x86_64.django_1776_django-11477:latest
swebench/sweb.eval.x86_64.django_1776_django-11490:latest
swebench/sweb.eval.x86_64.django_1776_django-11532:latest
swebench/sweb.eval.x86_64.django_1776_django-11551:latest
swebench/sweb.eval.x86_64.django_1776_django-11555:latest
swebench/sweb.eval.x86_64.django_1776_django-11603:latest
swebench/sweb.eval.x86_64.django_1776_django-11728:latest
swebench/sweb.eval.x86_64.django_1776_django-11734:latest
swebench/sweb.eval.x86_64.django_1776_django-11740:latest
swebench/sweb.eval.x86_64.django_1776_django-11749:latest
swebench/sweb.eval.x86_64.django_1776_django-11790:latest
swebench/sweb.eval.x86_64.django_1776_django-11815:latest
swebench/sweb.eval.x86_64.django_1776_django-11820:latest
swebench/sweb.eval.x86_64.django_1776_django-11848:latest
swebench/sweb.eval.x86_64.django_1776_django-11880:latest
swebench/sweb.eval.x86_64.django_1776_django-11885:latest
swebench/sweb.eval.x86_64.django_1776_django-11951:latest
swebench/sweb.eval.x86_64.django_1776_django-11964:latest
swebench/sweb.eval.x86_64.django_1776_django-11999:latest
swebench/sweb.eval.x86_64.django_1776_django-12039:latest
swebench/sweb.eval.x86_64.django_1776_django-12050:latest
swebench/sweb.eval.x86_64.django_1776_django-12125:latest
swebench/sweb.eval.x86_64.django_1776_django-12143:latest
swebench/sweb.eval.x86_64.django_1776_django-12155:latest
swebench/sweb.eval.x86_64.django_1776_django-12193:latest
swebench/sweb.eval.x86_64.django_1776_django-12209:latest
swebench/sweb.eval.x86_64.django_1776_django-12262:latest
swebench/sweb.eval.x86_64.django_1776_django-12273:latest
swebench/sweb.eval.x86_64.django_1776_django-12276:latest
swebench/sweb.eval.x86_64.django_1776_django-12304:latest
swebench/sweb.eval.x86_64.django_1776_django-12308:latest
swebench/sweb.eval.x86_64.django_1776_django-12325:latest
swebench/sweb.eval.x86_64.django_1776_django-12406:latest
swebench/sweb.eval.x86_64.django_1776_django-12419:latest
swebench/sweb.eval.x86_64.django_1776_django-12663:latest
swebench/sweb.eval.x86_64.django_1776_django-12708:latest
swebench/sweb.eval.x86_64.django_1776_django-12713:latest
swebench/sweb.eval.x86_64.django_1776_django-12741:latest
swebench/sweb.eval.x86_64.django_1776_django-12754:latest
swebench/sweb.eval.x86_64.django_1776_django-12774:latest
swebench/sweb.eval.x86_64.django_1776_django-12858:latest
swebench/sweb.eval.x86_64.django_1776_django-12965:latest
swebench/sweb.eval.x86_64.django_1776_django-13012:latest
swebench/sweb.eval.x86_64.django_1776_django-13023:latest
swebench/sweb.eval.x86_64.django_1776_django-13028:latest
swebench/sweb.eval.x86_64.django_1776_django-13033:latest
swebench/sweb.eval.x86_64.django_1776_django-13089:latest
swebench/sweb.eval.x86_64.django_1776_django-13109:latest
swebench/sweb.eval.x86_64.django_1776_django-13112:latest
swebench/sweb.eval.x86_64.django_1776_django-13121:latest
swebench/sweb.eval.x86_64.django_1776_django-13128:latest
swebench/sweb.eval.x86_64.django_1776_django-13158:latest
swebench/sweb.eval.x86_64.django_1776_django-13195:latest
swebench/sweb.eval.x86_64.django_1776_django-13212:latest
swebench/sweb.eval.x86_64.django_1776_django-13279:latest
swebench/sweb.eval.x86_64.django_1776_django-13297:latest
swebench/sweb.eval.x86_64.django_1776_django-13315:latest
swebench/sweb.eval.x86_64.django_1776_django-13343:latest
swebench/sweb.eval.x86_64.django_1776_django-13344:latest
swebench/sweb.eval.x86_64.django_1776_django-13346:latest
swebench/sweb.eval.x86_64.django_1776_django-13363:latest
swebench/sweb.eval.x86_64.django_1776_django-13401:latest
swebench/sweb.eval.x86_64.django_1776_django-13406:latest
swebench/sweb.eval.x86_64.django_1776_django-13410:latest
swebench/sweb.eval.x86_64.django_1776_django-13417:latest
swebench/sweb.eval.x86_64.django_1776_django-13449:latest
swebench/sweb.eval.x86_64.django_1776_django-13512:latest
swebench/sweb.eval.x86_64.django_1776_django-13513:latest
swebench/sweb.eval.x86_64.django_1776_django-13516:latest
swebench/sweb.eval.x86_64.django_1776_django-13551:latest
swebench/sweb.eval.x86_64.django_1776_django-13568:latest
swebench/sweb.eval.x86_64.django_1776_django-13569:latest
swebench/sweb.eval.x86_64.django_1776_django-13590:latest
swebench/sweb.eval.x86_64.django_1776_django-13658:latest
swebench/sweb.eval.x86_64.django_1776_django-13670:latest
swebench/sweb.eval.x86_64.django_1776_django-13741:latest
swebench/sweb.eval.x86_64.django_1776_django-13786:latest
swebench/sweb.eval.x86_64.django_1776_django-13794:latest
swebench/sweb.eval.x86_64.django_1776_django-13807:latest
swebench/sweb.eval.x86_64.django_1776_django-13809:latest
swebench/sweb.eval.x86_64.django_1776_django-13810:latest
swebench/sweb.eval.x86_64.django_1776_django-13820:latest
swebench/sweb.eval.x86_64.django_1776_django-13821:latest
swebench/sweb.eval.x86_64.django_1776_django-13837:latest
swebench/sweb.eval.x86_64.django_1776_django-13925:latest
swebench/sweb.eval.x86_64.django_1776_django-13933:latest
swebench/sweb.eval.x86_64.django_1776_django-13964:latest
swebench/sweb.eval.x86_64.django_1776_django-14007:latest
swebench/sweb.eval.x86_64.django_1776_django-14011:latest
swebench/sweb.eval.x86_64.django_1776_django-14017:latest
swebench/sweb.eval.x86_64.django_1776_django-14034:latest
swebench/sweb.eval.x86_64.django_1776_django-14053:latest
swebench/sweb.eval.x86_64.django_1776_django-14089:latest
swebench/sweb.eval.x86_64.django_1776_django-14122:latest
swebench/sweb.eval.x86_64.django_1776_django-14140:latest
swebench/sweb.eval.x86_64.django_1776_django-14155:latest
swebench/sweb.eval.x86_64.django_1776_django-14170:latest
swebench/sweb.eval.x86_64.django_1776_django-14238:latest
swebench/sweb.eval.x86_64.django_1776_django-14311:latest
swebench/sweb.eval.x86_64.django_1776_django-14315:latest
swebench/sweb.eval.x86_64.django_1776_django-14349:latest
swebench/sweb.eval.x86_64.django_1776_django-14351:latest
swebench/sweb.eval.x86_64.django_1776_django-14373:latest
swebench/sweb.eval.x86_64.django_1776_django-14376:latest
swebench/sweb.eval.x86_64.django_1776_django-14404:latest
swebench/sweb.eval.x86_64.django_1776_django-14434:latest
swebench/sweb.eval.x86_64.django_1776_django-14493:latest
swebench/sweb.eval.x86_64.django_1776_django-14500:latest
swebench/sweb.eval.x86_64.django_1776_django-14534:latest
swebench/sweb.eval.x86_64.django_1776_django-14539:latest
swebench/sweb.eval.x86_64.django_1776_django-14559:latest
swebench/sweb.eval.x86_64.django_1776_django-14580:latest
swebench/sweb.eval.x86_64.django_1776_django-14608:latest
swebench/sweb.eval.x86_64.django_1776_django-14631:latest
swebench/sweb.eval.x86_64.django_1776_django-14672:latest
swebench/sweb.eval.x86_64.django_1776_django-14725:latest
swebench/sweb.eval.x86_64.django_1776_django-14752:latest
swebench/sweb.eval.x86_64.django_1776_django-14765:latest
swebench/sweb.eval.x86_64.django_1776_django-14771:latest
swebench/sweb.eval.x86_64.django_1776_django-14787:latest
swebench/sweb.eval.x86_64.django_1776_django-14792:latest
swebench/sweb.eval.x86_64.django_1776_django-14855:latest
swebench/sweb.eval.x86_64.django_1776_django-14915:latest
swebench/sweb.eval.x86_64.django_1776_django-14999:latest
swebench/sweb.eval.x86_64.django_1776_django-15022:latest
swebench/sweb.eval.x86_64.django_1776_django-15037:latest
swebench/sweb.eval.x86_64.django_1776_django-15098:latest
swebench/sweb.eval.x86_64.django_1776_django-15103:latest
swebench/sweb.eval.x86_64.django_1776_django-15104:latest
swebench/sweb.eval.x86_64.django_1776_django-15127:latest
swebench/sweb.eval.x86_64.django_1776_django-15128:latest
swebench/sweb.eval.x86_64.django_1776_django-15161:latest
swebench/sweb.eval.x86_64.django_1776_django-15252:latest
swebench/sweb.eval.x86_64.django_1776_django-15268:latest
swebench/sweb.eval.x86_64.django_1776_django-15277:latest
swebench/sweb.eval.x86_64.django_1776_django-15278:latest
swebench/sweb.eval.x86_64.django_1776_django-15280:latest
swebench/sweb.eval.x86_64.django_1776_django-15315:latest
swebench/sweb.eval.x86_64.django_1776_django-15368:latest
swebench/sweb.eval.x86_64.django_1776_django-15375:latest
swebench/sweb.eval.x86_64.django_1776_django-15380:latest
swebench/sweb.eval.x86_64.django_1776_django-15382:latest
swebench/sweb.eval.x86_64.django_1776_django-15467:latest
swebench/sweb.eval.x86_64.django_1776_django-15499:latest
swebench/sweb.eval.x86_64.django_1776_django-15503:latest
swebench/sweb.eval.x86_64.django_1776_django-15525:latest
swebench/sweb.eval.x86_64.django_1776_django-15554:latest
swebench/sweb.eval.x86_64.django_1776_django-15561:latest
swebench/sweb.eval.x86_64.django_1776_django-15563:latest
swebench/sweb.eval.x86_64.django_1776_django-15569:latest
swebench/sweb.eval.x86_64.django_1776_django-15572:latest
swebench/sweb.eval.x86_64.django_1776_django-15629:latest
swebench/sweb.eval.x86_64.django_1776_django-15695:latest
swebench/sweb.eval.x86_64.django_1776_django-15731:latest
swebench/sweb.eval.x86_64.django_1776_django-15732:latest
swebench/sweb.eval.x86_64.django_1776_django-15741:latest
swebench/sweb.eval.x86_64.django_1776_django-15814:latest
swebench/sweb.eval.x86_64.django_1776_django-15851:latest
swebench/sweb.eval.x86_64.django_1776_django-15863:latest
swebench/sweb.eval.x86_64.django_1776_django-15916:latest
swebench/sweb.eval.x86_64.django_1776_django-15930:latest
swebench/sweb.eval.x86_64.django_1776_django-15957:latest
swebench/sweb.eval.x86_64.django_1776_django-15973:latest
swebench/sweb.eval.x86_64.django_1776_django-15987:latest
swebench/sweb.eval.x86_64.django_1776_django-16032:latest
swebench/sweb.eval.x86_64.django_1776_django-16082:latest
swebench/sweb.eval.x86_64.django_1776_django-16100:latest
swebench/sweb.eval.x86_64.django_1776_django-16116:latest
swebench/sweb.eval.x86_64.django_1776_django-16136:latest
swebench/sweb.eval.x86_64.django_1776_django-16139:latest
swebench/sweb.eval.x86_64.django_1776_django-16145:latest
swebench/sweb.eval.x86_64.django_1776_django-16255:latest
swebench/sweb.eval.x86_64.django_1776_django-16256:latest
swebench/sweb.eval.x86_64.django_1776_django-16263:latest
swebench/sweb.eval.x86_64.django_1776_django-16315:latest
swebench/sweb.eval.x86_64.django_1776_django-16333:latest
swebench/sweb.eval.x86_64.django_1776_django-16429:latest
swebench/sweb.eval.x86_64.django_1776_django-16454:latest
swebench/sweb.eval.x86_64.django_1776_django-16485:latest
swebench/sweb.eval.x86_64.django_1776_django-16493:latest
swebench/sweb.eval.x86_64.django_1776_django-16502:latest
swebench/sweb.eval.x86_64.django_1776_django-16527:latest
swebench/sweb.eval.x86_64.django_1776_django-16560:latest
swebench/sweb.eval.x86_64.django_1776_django-16569:latest
swebench/sweb.eval.x86_64.django_1776_django-16595:latest
swebench/sweb.eval.x86_64.django_1776_django-16612:latest
swebench/sweb.eval.x86_64.django_1776_django-16631:latest
swebench/sweb.eval.x86_64.django_1776_django-16642:latest
swebench/sweb.eval.x86_64.django_1776_django-16661:latest
swebench/sweb.eval.x86_64.django_1776_django-16662:latest
swebench/sweb.eval.x86_64.django_1776_django-16667:latest
swebench/sweb.eval.x86_64.django_1776_django-16801:latest
swebench/sweb.eval.x86_64.django_1776_django-16819:latest
swebench/sweb.eval.x86_64.django_1776_django-16877:latest
swebench/sweb.eval.x86_64.django_1776_django-16899:latest
swebench/sweb.eval.x86_64.django_1776_django-16901:latest
swebench/sweb.eval.x86_64.django_1776_django-16938:latest
swebench/sweb.eval.x86_64.django_1776_django-16950:latest
swebench/sweb.eval.x86_64.django_1776_django-17029:latest
swebench/sweb.eval.x86_64.django_1776_django-17084:latest
swebench/sweb.eval.x86_64.django_1776_django-17087:latest
swebench/sweb.eval.x86_64.django_1776_django-7530:latest
swebench/sweb.eval.x86_64.django_1776_django-9296:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-13989:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-14623:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20488:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20676:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20826:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20859:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-21568:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22719:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22865:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22871:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23299:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23314:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23412:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23476:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24026:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24149:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24177:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24570:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24627:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24637:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24870:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24970:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25122:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25287:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25311:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25332:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25479:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25775:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25960:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26113:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26208:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26291:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26342:latest
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26466:latest
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3069:latest
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3187:latest
swebench/sweb.eval.x86_64.pallets_1776_flask-5014:latest
swebench/sweb.eval.x86_64.psf_1776_requests-1142:latest
swebench/sweb.eval.x86_64.psf_1776_requests-1724:latest
swebench/sweb.eval.x86_64.psf_1776_requests-1766:latest
swebench/sweb.eval.x86_64.psf_1776_requests-1921:latest
swebench/sweb.eval.x86_64.psf_1776_requests-2317:latest
swebench/sweb.eval.x86_64.psf_1776_requests-2931:latest
swebench/sweb.eval.x86_64.psf_1776_requests-5414:latest
swebench/sweb.eval.x86_64.psf_1776_requests-6028:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-2905:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-3095:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-3151:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-3305:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-3677:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-3993:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4075:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4094:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4356:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4629:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4687:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4695:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-4966:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-6461:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-6599:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-6721:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-6744:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-6938:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-6992:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-7229:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-7233:latest
swebench/sweb.eval.x86_64.pydata_1776_xarray-7393:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4551:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4604:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4661:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4970:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6386:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6528:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6903:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7080:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7277:latest
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-8898:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-10051:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-10081:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-10356:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5262:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5631:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5787:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5809:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5840:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-6197:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-6202:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7205:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7236:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7324:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7432:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7490:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7521:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7571:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7982:latest
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-8399:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10297:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10844:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10908:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11310:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11578:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12585:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12682:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12973:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13124:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13135:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13142:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13328:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13439:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13496:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13779:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14053:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14087:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14141:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14496:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14629:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14710:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14894:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14983:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-15100:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25102:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25232:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25747:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25931:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25973:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-26194:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-26323:latest
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-9288:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10323:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10435:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10449:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10466:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10614:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10673:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-11445:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-11510:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7440:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7454:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7462:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7590:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7748:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7757:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7889:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7910:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7985:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8035:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8056:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8120:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8265:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8269:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8459:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8475:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8548:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8551:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8593:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8595:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8621:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8638:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8721:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9229:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9230:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9258:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9281:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9320:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9367:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9461:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9591:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9602:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9658:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9673:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9698:latest
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9711:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-11618:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12096:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12419:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12481:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-12489:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13031:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13091:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13372:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13480:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13551:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13615:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13647:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13757:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13798:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13852:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13877:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13878:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-13974:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14248:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14531:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14711:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-14976:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15017:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15345:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15349:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15599:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15809:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15875:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-15976:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16450:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16597:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16766:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16792:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-16886:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17139:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17318:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17630:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-17655:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18189:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18199:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18211:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18698:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-18763:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19040:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19346:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19495:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19637:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19783:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-19954:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20154:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20428:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20438:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20590:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20801:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-20916:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21379:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21596:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21612:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21847:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-21930:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-22080:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-22456:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-22714:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-22914:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23262:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23413:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23534:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23824:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-23950:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24066:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24213:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24443:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24539:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24562:latest
swebench/sweb.eval.x86_64.sympy_1776_sympy-24661:latest

View File

@@ -1,50 +0,0 @@
"""Get official docker image names for SWE-bench instances."""
import argparse
from datasets import load_dataset
parser = argparse.ArgumentParser()
parser.add_argument('--dataset', type=str, default='princeton-nlp/SWE-bench')
parser.add_argument('--split', type=str, default='test')
parser.add_argument('--output', type=str, default='swebench_images.txt')
args = parser.parse_args()
SUPPORTED_DATASET = {
'princeton-nlp/SWE-bench_Multimodal',
'princeton-nlp/SWE-bench',
'princeton-nlp/SWE-bench_Lite',
'princeton-nlp/SWE-bench_Verified',
}
assert args.dataset in SUPPORTED_DATASET, f'Dataset {args.dataset} not supported'
def swebench_instance_id_to_docker_image_name(instance_id: str) -> str:
# swebench/sweb.eval.x86_64.django_1776_django-11333:v1
repo, name = instance_id.split('__')
return f'swebench/sweb.eval.x86_64.{repo}_1776_{name}:latest'
def swebench_multimodal_instance_id_to_docker_image_name(instance_id: str) -> str:
# swebench/sweb.mm.eval.x86_64.openlayers_1776_openlayers-12172
repo, name = instance_id.split('__')
return f'swebench/sweb.mm.eval.x86_64.{repo}_1776_{name}:latest'
dataset = load_dataset(args.dataset, split=args.split)
instance_ids = dataset['instance_id']
print(f'Loading {len(instance_ids)} instances from {args.dataset} split {args.split}')
with open(args.output, 'w') as f:
for instance_id in instance_ids:
if args.dataset in [
'princeton-nlp/SWE-bench',
'princeton-nlp/SWE-bench_Lite',
'princeton-nlp/SWE-bench_Verified',
]:
f.write(swebench_instance_id_to_docker_image_name(instance_id) + '\n')
else:
f.write(
swebench_multimodal_instance_id_to_docker_image_name(instance_id) + '\n'
)
print(f'Saved {len(instance_ids)} images to {args.output}')

View File

@@ -1,36 +1,66 @@
#!/usr/bin/env bash
set -e
SET=$1
# check set is in ["full", "lite", "verified"]
if [ "$SET" != "full" ] && [ "$SET" != "lite" ] && [ "$SET" != "verified" ]; then
echo "Error: argument 1 must be one of: full, lite, verified"
LEVEL=$1
# three levels:
# - base, keyword "sweb.base"
# - env, keyword "sweb.env"
# - instance, keyword "sweb.eval"
SET=$2
if [ -z "$LEVEL" ]; then
echo "Usage: $0 <cache_level> <set>"
echo "cache_level: base, env, or instance"
echo "set: lite, full"
exit 1
fi
input_file=evaluation/benchmarks/swe_bench/scripts/docker/all-swebench-${SET}-instance-images.txt
echo "Downloading images based on ${input_file}"
# Check if the file exists
if [ ! -f "$input_file" ]; then
echo "Error: File '$input_file' not found"
exit 1
if [ -z "$SET" ]; then
echo "Usage: $0 <cache_level> <set>"
echo "cache_level: base, env, or instance"
echo "set: lite, full, default is lite"
SET="lite"
fi
# Get total number of images
total_images=$(wc -l < "${input_file}")
counter=0
# Check if namespace is provided via argument $3, otherwise default to 'xingyaoww'
NAMESPACE=${3:-xingyaoww}
echo "Starting to pull ${total_images} images"
echo "Using namespace: $NAMESPACE"
# Read the file line by line and pull each image
while IFS= read -r image; do
# Skip empty lines or comments
if [ -n "$image" ] && [[ ! "$image" =~ ^[[:space:]]*# ]]; then
counter=$((counter + 1))
echo "[${counter}/${total_images}] Pulling ${image}"
docker pull "${image}"
sleep 2
fi
done < "${input_file}"
if [ "$SET" == "lite" ]; then
IMAGE_FILE="$(dirname "$0")/all-swebench-lite-instance-images.txt"
else
IMAGE_FILE="$(dirname "$0")/all-swebench-full-instance-images.txt"
fi
echo "Finished pulling all images"
# Define a pattern based on the level
case $LEVEL in
base)
PATTERN="sweb.base"
;;
env)
PATTERN="sweb.base\|sweb.env"
;;
instance)
PATTERN="sweb.base\|sweb.env\|sweb.eval"
;;
*)
echo "Invalid cache level: $LEVEL"
echo "Valid levels are: base, env, instance"
exit 1
;;
esac
echo "Pulling docker images for [$LEVEL] level"
echo "Pattern: $PATTERN"
echo "Image file: $IMAGE_FILE"
# Read each line from the file, filter by pattern, and pull the docker image
grep "$PATTERN" "$IMAGE_FILE" | while IFS= read -r image; do
echo "Pulling $NAMESPACE/$image into $image"
docker pull $NAMESPACE/$image
# replace _s_ to __ in the image name
renamed_image=$(echo "$image" | sed 's/_s_/__/g')
docker tag $NAMESPACE/$image $renamed_image
done

View File

@@ -24,7 +24,7 @@ def load_completions(output_dir: str, instance_id: str):
# create messages
messages = result['messages']
messages.append(result['response']['choices'][0]['message'])
tools = result['kwargs'].get('tools', [])
tools = result['kwargs']['tools']
return {
'messages': messages,
'tools': tools,

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import argparse
import os
import subprocess
import pandas as pd
from termcolor import colored
@@ -36,23 +35,6 @@ if args.only_x_instances:
f'After removing instances not in X={args.input_file_1}: Y={df2.shape[0]} instances'
)
# Add summarization step for each input file
def summarize_file(file_path):
script_dir = os.path.dirname(os.path.abspath(__file__))
summarize_script = os.path.join(script_dir, 'summarize_outputs.py')
print(f'\nSummary for {file_path}:')
print('=' * 80)
subprocess.run(['python', summarize_script, file_path], check=True)
print('=' * 80)
# Generate summaries
summarize_file(args.input_file_1)
summarize_file(args.input_file_2)
# Get the intersection of the instance_ids
df = pd.merge(df1, df2, on='instance_id', how='inner')

View File

@@ -75,7 +75,7 @@ def load_completions(instance_id: str):
# create messages
messages = result['messages']
messages.append(result['response']['choices'][0]['message'])
tools = result['kwargs'].get('tools', None)
tools = result['kwargs']['tools']
return {
'messages': messages,
'tools': tools,
@@ -248,22 +248,6 @@ def write_row_to_md_file(row, instance_id_to_test_result):
completions = load_completions(instance_id)
# report file
global output_dir
report_file = os.path.join(output_dir, 'eval_outputs', instance_id, 'report.json')
if os.path.exists(report_file):
with open(report_file, 'r') as f:
report = json.load(f)
else:
report = None
test_output_file = os.path.join(
output_dir, 'eval_outputs', instance_id, 'test_output.txt'
)
if test_output is None and os.path.exists(test_output_file):
with open(test_output_file, 'r') as f:
test_output = f.read()
with open(filepath, 'w') as f:
f.write(f'# {instance_id} (resolved: {resolved})\n')
@@ -285,14 +269,8 @@ def write_row_to_md_file(row, instance_id_to_test_result):
f.write('## Model Patch\n')
f.write(f'{process_git_patch(model_patch)}\n')
if report is not None:
f.write('## Report\n')
f.write(json.dumps(report, indent=2))
f.write('\n')
f.write('## Test Output\n')
f.write(str(test_output))
f.write('\n')
instance_id_to_test_result = {}

View File

@@ -44,6 +44,7 @@ if os.path.exists(swebench_official_report_json):
f"- resolved instances: {report['resolved_instances']}\n"
f"- unresolved instances: {report['unresolved_instances']}\n"
f"- error instances: {report['error_instances']}\n"
f"- unstopped instances: {report['unstopped_instances']}\n"
)
output_md += '\n## Resolved Instances\n'

View File

@@ -1,132 +0,0 @@
#!/bin/bash
# NOTE: this script is for rolling out the SWE-Gym dataset for **TRAINING**
# For more information, please refer to
# 1. the Github Repo: https://github.com/SWE-Gym/SWE-Gym
# 2. the paper: https://arxiv.org/abs/2412.21139
MODEL=$1 # eg your llm config name in config.toml (eg: "llm.claude-3-5-sonnet-20241022-t05")
EXP_NAME=$2 # "train-t05"
N_WORKERS=${3:-64}
N_RUNS=${4:-1}
export EXP_NAME=$EXP_NAME
# use 2x resources for rollout since some codebases are pretty resource-intensive
export DEFAULT_RUNTIME_RESOURCE_FACTOR=2
echo "MODEL: $MODEL"
echo "EXP_NAME: $EXP_NAME"
DATASET="SWE-Gym/SWE-Gym" # change this to the "/SWE-Gym-Lite" if you want to rollout the lite subset
SPLIT="train"
if [ -z "$ALLHANDS_API_KEY" ]; then
echo "ALLHANDS_API_KEY is not set. Will rollout and evaluate locally using Docker. WARNING: A large value of N_WORKERS will result in a large number of Docker containers being spun up and may crash your machine."
export RUNTIME=docker
else
echo "ALLHANDS_API_KEY is set. Continuing rollout and evaluation with remote runtime..."
export RUNTIME=remote
export SANDBOX_REMOTE_RUNTIME_API_URL="https://runtime.eval.all-hands.dev"
export EVAL_DOCKER_IMAGE_PREFIX="us-central1-docker.pkg.dev/evaluation-092424/swe-bench-images"
fi
EVAL_LIMIT=3000
MAX_ITER=100
# ===== Run inference =====
source "evaluation/utils/version_control.sh"
get_openhands_version
echo "OPENHANDS_VERSION: $OPENHANDS_VERSION"
echo "MODEL_CONFIG: $MODEL_CONFIG"
echo "DATASET: $DATASET"
echo "SPLIT: $SPLIT"
# Default to NOT use Hint
export USE_INSTANCE_IMAGE=true
export USE_HINT_TEXT=false
export RUN_WITH_BROWSING=false
echo "USE_HINT_TEXT: $USE_HINT_TEXT"
EVAL_NOTE="$OPENHANDS_VERSION-no-hint-$EXP_NAME"
function run_eval() {
local eval_note=$1
COMMAND="poetry run python evaluation/benchmarks/swe_bench/run_infer.py \
--agent-cls CodeActAgent \
--llm-config $MODEL \
--max-iterations $MAX_ITER \
--eval-num-workers $N_WORKERS \
--eval-note $eval_note \
--dataset $DATASET \
--split $SPLIT"
if [ -n "$EVAL_LIMIT" ]; then
echo "EVAL_LIMIT: $EVAL_LIMIT"
COMMAND="$COMMAND --eval-n-limit $EVAL_LIMIT"
fi
# Run the command
eval $COMMAND
}
for run_idx in $(seq 1 $N_RUNS); do
while true; do
echo "### Running inference... ###"
unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
current_eval_note="$EVAL_NOTE-run_$run_idx"
echo "EVAL_NOTE: $current_eval_note"
INFER_OUTPUT=$(run_eval $current_eval_note)
INFER_STATUS=$? # Capture the exit status of run_infer.sh
echo "INFER_STATUS: $INFER_STATUS"
echo "### Cleaning up remote runtime... ###"
./evaluation/utils/scripts/cleanup_remote_runtime.sh
if [ $INFER_STATUS -eq 0 ]; then
echo "### Inference completed successfully. ###"
break
else
echo "### Inference failed with exit code $INFER_STATUS. Retrying... ###"
fi
done
# Extract the output directory using the special delimiters
OUTPUT_FILE=$(echo "$INFER_OUTPUT" | grep -o '### OUTPUT FILE:.* ###' | sed 's/### OUTPUT FILE: \(.*\) ###/\1/')
echo "Got OUTPUT_FILE: $OUTPUT_FILE"
while true; do
echo "### Evaluating on $OUTPUT_FILE ... ###"
COMMAND="poetry run python evaluation/benchmarks/swe_bench/eval_infer.py \
--eval-num-workers $((N_WORKERS * 2)) \
--input-file $OUTPUT_FILE \
--dataset $DATASET \
--split $SPLIT"
if [ -n "$EVAL_LIMIT" ]; then
echo "EVAL_LIMIT: $EVAL_LIMIT"
COMMAND="$COMMAND --eval-n-limit $EVAL_LIMIT"
fi
echo "Running command: $COMMAND"
# Run the command
eval $COMMAND
EVAL_STATUS=$?
if [ $EVAL_STATUS -eq 0 ]; then
echo "### Evaluation completed successfully. ###"
break
else
echo "### Evaluation failed with exit code $EVAL_STATUS. Retrying... ###"
fi
./evaluation/utils/scripts/cleanup_remote_runtime.sh
done
# update the output with evaluation results
echo "### Updating the output with evaluation results... ###"
poetry run python evaluation/benchmarks/swe_bench/scripts/eval/update_output_with_eval.py $OUTPUT_FILE
echo "### Combining the final completions... ###"
poetry run python evaluation/benchmarks/swe_bench/scripts/eval/combine_final_completions.py $OUTPUT_FILE
echo "### DONE for run $run_idx! ###"
echo "You can find the final output at $(dirname $OUTPUT_FILE)/$FINAL_OUTPUT_FILE"
done

View File

@@ -29,6 +29,11 @@ if [ -z "$MAX_ITER" ]; then
MAX_ITER=100
fi
if [ -z "$USE_INSTANCE_IMAGE" ]; then
echo "USE_INSTANCE_IMAGE not specified, use default true"
USE_INSTANCE_IMAGE=true
fi
if [ -z "$RUN_WITH_BROWSING" ]; then
echo "RUN_WITH_BROWSING not specified, use default false"
RUN_WITH_BROWSING=false
@@ -45,6 +50,8 @@ if [ -z "$SPLIT" ]; then
SPLIT="test"
fi
export USE_INSTANCE_IMAGE=$USE_INSTANCE_IMAGE
echo "USE_INSTANCE_IMAGE: $USE_INSTANCE_IMAGE"
export RUN_WITH_BROWSING=$RUN_WITH_BROWSING
echo "RUN_WITH_BROWSING: $RUN_WITH_BROWSING"

View File

@@ -1,287 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"import pandas as pd\n",
"from tqdm import tqdm\n",
"\n",
"tqdm.pandas()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. Load raw data and convert to training data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import gzip\n",
"import json\n",
"\n",
"from tqdm import tqdm\n",
"\n",
"FILE_PATHS = [\n",
" 'YOURPATH-no-hint-train-t05-run_1/output.with_completions.jsonl.gz',\n",
" 'YOURPATH-no-hint-train-t05-run_2/output.with_completions.jsonl.gz',\n",
"]\n",
"\n",
"# More memory efficient for large files\n",
"# Initialize lists to store the data\n",
"data = []\n",
"\n",
"\n",
"# Read file line by line\n",
"for FILE_PATH in FILE_PATHS:\n",
" with gzip.open(FILE_PATH, 'rb') as f: # Use 'rb' for gzipped files\n",
" for i, line in tqdm(\n",
" enumerate(f), desc=f\"Processing {FILE_PATH.split('/')[-1]}\"\n",
" ):\n",
" # Parse only the fields we need\n",
" raw_data = json.loads(line)\n",
" data.append(\n",
" {\n",
" 'resolved': raw_data['report']['resolved'],\n",
" 'messages': raw_data['raw_completions']['messages']\n",
" if raw_data['raw_completions'] is not None\n",
" else None,\n",
" 'git_patch': raw_data['test_result'].get('git_patch', ''),\n",
" 'tools': raw_data['raw_completions']['tools']\n",
" if raw_data['raw_completions'] is not None\n",
" and 'tools' in raw_data['raw_completions']\n",
" else None,\n",
" }\n",
" )\n",
"\n",
"# Convert to DataFrame after collecting all data\n",
"df = pd.DataFrame(data)\n",
"print(f'#total amount of data={len(df)}')\n",
"df = df[~df['messages'].isna()]\n",
"print(f'#total amount of data after removing nan={len(df)}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Filter"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def _contains_multiple_tool_calls(messages: list[dict]) -> bool:\n",
" return any(\n",
" message.get('tool_calls') and len(message['tool_calls']) > 1\n",
" for message in messages\n",
" )\n",
"\n",
"\n",
"df['contains_multiple_tool_calls'] = df['messages'].apply(_contains_multiple_tool_calls)\n",
"display(df.groupby(['contains_multiple_tool_calls'])['resolved'].sum())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import copy\n",
"\n",
"# Convert function calling messages to non-function calling messages\n",
"from openhands.llm.fn_call_converter import (\n",
" FunctionCallConversionError,\n",
" convert_fncall_messages_to_non_fncall_messages,\n",
" convert_from_multiple_tool_calls_to_single_tool_call_messages,\n",
")\n",
"\n",
"total_failed = 0\n",
"\n",
"\n",
"def _convert_messages(messages: list[dict], tools: list[dict]) -> list[dict]:\n",
" global total_failed\n",
" message_copy = copy.deepcopy(messages)\n",
" for message in message_copy:\n",
" if message['content'] is None:\n",
" message['content'] = ''\n",
" try:\n",
" return convert_fncall_messages_to_non_fncall_messages(\n",
" message_copy, tools, add_in_context_learning_example=False\n",
" )\n",
" except FunctionCallConversionError:\n",
" total_failed += 1\n",
" # print(f'Failed to convert messages: {messages}\\nTools: {tools}')\n",
" # traceback.print_exc()\n",
" return None\n",
"\n",
"\n",
"df['converted_messages'] = df.apply(\n",
" lambda row: convert_from_multiple_tool_calls_to_single_tool_call_messages(\n",
" row['messages'], ignore_final_tool_result=True\n",
" ),\n",
" axis=1,\n",
")\n",
"df['nonfncall_messages'] = df.apply(\n",
" lambda row: _convert_messages(row['converted_messages'], row['tools']), axis=1\n",
")\n",
"print('total nan', df['nonfncall_messages'].isna().sum())\n",
"df = df[~df['nonfncall_messages'].isna()]\n",
"print(f'Total failed: {total_failed}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tokenization"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pandarallel import pandarallel\n",
"from transformers import AutoTokenizer\n",
"\n",
"os.environ['TOKENIZERS_PARALLELISM'] = 'false'\n",
"pandarallel.initialize(progress_bar=True, verbose=1, nb_workers=16)\n",
"tokenizer = AutoTokenizer.from_pretrained('Qwen/Qwen2.5-7B-Instruct')\n",
"df['n_tokens'] = df['rm_conv'].parallel_apply(\n",
" lambda x: len(tokenizer.apply_chat_template(x))\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(f'BEFORE: #total={len(df)}')\n",
"df_selected = df[df['n_tokens'] < 131072]\n",
"print(f'AFTER(truncated to 128k): #total={len(df_selected)}')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_selected['n_tokens'].describe()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# ecdf of n_tokens\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"\n",
"display(df.groupby(['resolved'])['n_tokens'].describe())\n",
"sns.ecdfplot(x='n_tokens', data=df, hue='resolved')\n",
"plt.show()\n",
"\n",
"print(f'#total={len(df)}')\n",
"df_selected = df[df['n_tokens'] < 131072]\n",
"print(f'#selected={len(df_selected)}')\n",
"display(df_selected.groupby(['resolved'])['n_tokens'].describe())\n",
"sns.ecdfplot(x='n_tokens', data=df_selected, hue='resolved')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_selected[~df_selected['resolved']]['n_tokens'].describe()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_selected['resolved'].value_counts()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_selected.groupby(['resolved'])['n_tokens'].describe()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Save Resolved Messages for SFT"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_selected[df_selected['resolved']][['nonfncall_messages']].rename(\n",
" columns={'nonfncall_messages': 'messages'}\n",
").to_json(\n",
" os.path.join(\n",
" 'YOUR_OUTPUT_FOLDER',\n",
" f'policy_traj_128k_swegym_{df_selected[\"resolved\"].value_counts()[True]}i.jsonl',\n",
" ),\n",
" lines=True,\n",
" orient='records',\n",
")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "openhands-ai-CPy6G0pU-py3.12",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -7,7 +7,7 @@ import os
import re
from dataclasses import dataclass
from enum import Enum, auto
from typing import Dict, List, Union
from typing import Dict, List, Optional, Union
from openhands.core.logger import openhands_logger as logger
from openhands.events.action import BrowseInteractiveAction
@@ -133,7 +133,7 @@ def parse_content_to_elements(content: str) -> Dict[str, str]:
return elements
def find_matching_anchor(content: str, selector: str) -> str | None:
def find_matching_anchor(content: str, selector: str) -> Optional[str]:
"""Find the anchor ID that matches the given selector description"""
elements = parse_content_to_elements(content)

View File

@@ -277,6 +277,7 @@ if __name__ == '__main__':
)
runtime: Runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
init_task_env(runtime, args.server_hostname, env_llm_config)
dependencies = load_dependencies(runtime)

View File

@@ -161,7 +161,6 @@ def process_instance(
runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
task_str, goal_image_urls = initialize_runtime(runtime)
initial_user_action = MessageAction(content=task_str, image_urls=goal_image_urls)
state: State | None = asyncio.run(

View File

@@ -247,21 +247,11 @@ def prepare_dataset(
f'Starting evaluation with skipping first {skip_num} instances ({len(dataset)} instances to run).'
)
if eval_n_limit and eval_n_limit > 0:
# Use fixed random seed 42 for sampling without replacement
dataset = dataset.sample(
min(eval_n_limit, len(dataset)), random_state=42, replace=False
)
logger.info(
f'Randomly sampling {eval_n_limit} unique instances with random seed 42.'
)
dataset = dataset.head(eval_n_limit)
logger.info(f'Limiting evaluation to {eval_n_limit} instances.')
elif eval_n_limit and eval_n_limit > 0:
# Use fixed random seed 42 for sampling without replacement
dataset = dataset.sample(
min(eval_n_limit, len(dataset)), random_state=42, replace=False
)
logger.info(
f'Randomly sampling {eval_n_limit} unique instances with random seed 42.'
)
dataset = dataset.head(eval_n_limit)
logger.info(f'Limiting evaluation to first {eval_n_limit} instances.')
new_dataset = [
instance

View File

@@ -1,7 +1,6 @@
import { screen, within } from "@testing-library/react";
import { render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils";
import { TrajectoryActions } from "#/components/features/trajectory/trajectory-actions";
describe("TrajectoryActions", () => {
@@ -15,7 +14,7 @@ describe("TrajectoryActions", () => {
});
it("should render correctly", () => {
renderWithProviders(
render(
<TrajectoryActions
onPositiveFeedback={onPositiveFeedback}
onNegativeFeedback={onNegativeFeedback}
@@ -26,11 +25,10 @@ describe("TrajectoryActions", () => {
const actions = screen.getByTestId("feedback-actions");
within(actions).getByTestId("positive-feedback");
within(actions).getByTestId("negative-feedback");
within(actions).getByTestId("export-trajectory");
});
it("should call onPositiveFeedback when positive feedback is clicked", async () => {
renderWithProviders(
render(
<TrajectoryActions
onPositiveFeedback={onPositiveFeedback}
onNegativeFeedback={onNegativeFeedback}
@@ -45,7 +43,7 @@ describe("TrajectoryActions", () => {
});
it("should call onNegativeFeedback when negative feedback is clicked", async () => {
renderWithProviders(
render(
<TrajectoryActions
onPositiveFeedback={onPositiveFeedback}
onNegativeFeedback={onNegativeFeedback}
@@ -60,7 +58,7 @@ describe("TrajectoryActions", () => {
});
it("should call onExportTrajectory when negative feedback is clicked", async () => {
renderWithProviders(
render(
<TrajectoryActions
onPositiveFeedback={onPositiveFeedback}
onNegativeFeedback={onNegativeFeedback}

View File

@@ -2,7 +2,6 @@ import { render, screen } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import { Messages } from "#/components/features/chat/messages";
import type { Message } from "#/message";
import { renderWithProviders } from "test-utils";
describe("File Operations Messages", () => {
it("should show success indicator for successful file read operation", () => {
@@ -17,7 +16,7 @@ describe("File Operations Messages", () => {
},
];
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
render(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();
@@ -36,7 +35,7 @@ describe("File Operations Messages", () => {
},
];
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
render(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();
@@ -55,7 +54,7 @@ describe("File Operations Messages", () => {
},
];
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
render(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();
@@ -74,7 +73,7 @@ describe("File Operations Messages", () => {
},
];
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
render(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();

View File

@@ -36,20 +36,4 @@ describe("BrandButton", () => {
expect(screen.getByText("Test Button")).toBeDisabled();
});
it("should pass a start content", () => {
render(
<BrandButton
type="button"
variant="primary"
startContent={
<div data-testid="custom-start-content">Start Content</div>
}
>
Test Button
</BrandButton>,
);
screen.getByTestId("custom-start-content");
});
});

View File

@@ -133,4 +133,30 @@ describe("ModelSelector", () => {
expect(screen.getByLabelText("LLM Provider")).toHaveValue("Azure");
expect(screen.getByLabelText("LLM Model")).toHaveValue("ada");
});
it("should handle Mistral AI provider selection correctly", async () => {
const mistralModels = {
mistral: {
separator: "/",
models: ["mistral-tiny", "mistral-small", "mistral-medium"],
},
};
const user = userEvent.setup();
render(<ModelSelector models={mistralModels} />);
const providerSelector = screen.getByLabelText("LLM Provider");
await user.click(providerSelector);
// Select Mistral AI (display name)
const mistralOption = screen.getByText("Mistral AI");
await user.click(mistralOption);
// Verify model dropdown is enabled and shows correct models
const modelSelector = screen.getByLabelText("LLM Model");
expect(modelSelector).not.toBeDisabled();
await user.click(modelSelector);
expect(screen.getByText("mistral-tiny")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,35 @@
import { screen } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import { renderWithProviders } from "test-utils";
import { RuntimeSizeSelector } from "#/components/shared/modals/settings/runtime-size-selector";
const renderRuntimeSizeSelector = () =>
renderWithProviders(<RuntimeSizeSelector isDisabled={false} />);
describe("RuntimeSizeSelector", () => {
it("should show both runtime size options", () => {
renderRuntimeSizeSelector();
// The options are in the hidden select element
const select = screen.getByRole("combobox", { hidden: true });
expect(select).toHaveValue("1");
expect(select).toHaveDisplayValue("1x (2 core, 8G)");
expect(select.children).toHaveLength(3); // Empty option + 2 size options
});
it("should show the full description text for disabled options", async () => {
renderRuntimeSizeSelector();
// Click the button to open the dropdown
const button = screen.getByRole("button", {
name: "1x (2 core, 8G) SETTINGS_FORM$RUNTIME_SIZE_LABEL",
});
button.click();
// Wait for the dropdown to open and find the description text
const description = await screen.findByText(
"Runtime sizes over 1 are disabled by default, please contact contact@all-hands.dev to get access to larger runtimes.",
);
expect(description).toBeInTheDocument();
expect(description).toHaveClass("whitespace-normal", "break-words");
});
});

View File

@@ -2,13 +2,11 @@ import { createRoutesStub } from "react-router";
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils";
import { screen, waitFor } from "@testing-library/react";
import toast from "react-hot-toast";
import App from "#/routes/_oh.app/route";
import OpenHands from "#/api/open-hands";
import * as CustomToast from "#/utils/custom-toast-handlers";
describe("App", () => {
const errorToastSpy = vi.spyOn(CustomToast, "displayErrorToast");
const RouteStub = createRoutesStub([
{ Component: App, path: "/conversation/:conversationId" },
]);
@@ -36,19 +34,26 @@ describe("App", () => {
await screen.findByTestId("app-route");
});
it("should call endSession if the user does not have permission to view conversation", async () => {
const getConversationSpy = vi.spyOn(OpenHands, "getConversation");
it(
"should call endSession if the user does not have permission to view conversation",
async () => {
const errorToastSpy = vi.spyOn(toast, "error");
const getConversationSpy = vi.spyOn(OpenHands, "getConversation");
getConversationSpy.mockResolvedValue(null);
renderWithProviders(<RouteStub initialEntries={["/conversation/9999"]} />);
getConversationSpy.mockResolvedValue(null);
renderWithProviders(
<RouteStub initialEntries={["/conversation/9999"]} />,
);
await waitFor(() => {
expect(endSessionMock).toHaveBeenCalledOnce();
expect(errorToastSpy).toHaveBeenCalledOnce();
});
});
await waitFor(() => {
expect(endSessionMock).toHaveBeenCalledOnce();
expect(errorToastSpy).toHaveBeenCalledOnce();
});
},
);
it("should not call endSession if the user has permission", async () => {
const errorToastSpy = vi.spyOn(toast, "error");
const getConversationSpy = vi.spyOn(OpenHands, "getConversation");
getConversationSpy.mockResolvedValue({

View File

@@ -8,7 +8,6 @@ import MainApp from "#/routes/_oh/route";
import SettingsScreen from "#/routes/settings";
import Home from "#/routes/_oh._index/route";
import OpenHands from "#/api/open-hands";
import * as FeatureFlags from "#/utils/feature-flags";
const createAxiosNotFoundErrorObject = () =>
new AxiosError(
@@ -28,7 +27,6 @@ const createAxiosNotFoundErrorObject = () =>
describe("Home Screen", () => {
const getSettingsSpy = vi.spyOn(OpenHands, "getSettings");
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const RouterStub = createRoutesStub([
{
@@ -115,21 +113,5 @@ describe("Home Screen", () => {
const settingsModalAfter = screen.queryByTestId("ai-config-modal");
expect(settingsModalAfter).not.toBeInTheDocument();
});
it("should not open the settings modal if GET /settings fails but is SaaS mode", async () => {
// TODO: Remove HIDE_LLM_SETTINGS check once released
vi.spyOn(FeatureFlags, "HIDE_LLM_SETTINGS").mockReturnValue(true);
// @ts-expect-error - we only need APP_MODE for this test
getConfigSpy.mockResolvedValue({ APP_MODE: "saas" });
const error = createAxiosNotFoundErrorObject();
getSettingsSpy.mockRejectedValue(error);
renderWithProviders(<RouterStub initialEntries={["/"]} />);
// small hack to wait for the modal to not appear
await expect(
screen.findByTestId("ai-config-modal", {}, { timeout: 1000 }),
).rejects.toThrow();
});
});
});

View File

@@ -1,15 +1,6 @@
import { render, screen, waitFor, within } from "@testing-library/react";
import { createRoutesStub } from "react-router";
import {
afterEach,
beforeAll,
beforeEach,
describe,
expect,
it,
test,
vi,
} from "vitest";
import { afterEach, describe, expect, it, test, vi } from "vitest";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import userEvent, { UserEvent } from "@testing-library/user-event";
import OpenHands from "#/api/open-hands";
@@ -20,7 +11,6 @@ import { MOCK_DEFAULT_USER_SETTINGS } from "#/mocks/handlers";
import { PostApiSettings } from "#/types/settings";
import * as ConsentHandlers from "#/utils/handle-capture-consent";
import AccountSettings from "#/routes/account-settings";
import * as FeatureFlags from "#/utils/feature-flags";
const toggleAdvancedSettings = async (user: UserEvent) => {
const advancedSwitch = await screen.findByTestId("advanced-settings-switch");
@@ -39,11 +29,6 @@ describe("Settings Screen", () => {
useAppLogout: vi.fn().mockReturnValue({ handleLogout: handleLogoutMock }),
}));
beforeAll(() => {
// TODO: Remove this once we release
vi.spyOn(FeatureFlags, "HIDE_LLM_SETTINGS").mockReturnValue(true);
});
afterEach(() => {
vi.clearAllMocks();
});
@@ -82,14 +67,6 @@ describe("Settings Screen", () => {
});
describe("Account Settings", () => {
beforeEach(() => {
getConfigSpy.mockResolvedValue({
APP_MODE: "oss",
GITHUB_CLIENT_ID: "123",
POSTHOG_CLIENT_KEY: "456",
});
});
it("should render the account settings", async () => {
renderSettingsScreen();
@@ -303,14 +280,6 @@ describe("Settings Screen", () => {
});
describe("LLM Settings", () => {
beforeEach(() => {
getConfigSpy.mockResolvedValue({
APP_MODE: "oss",
GITHUB_CLIENT_ID: "123",
POSTHOG_CLIENT_KEY: "456",
});
});
it("should render the basic LLM settings by default", async () => {
renderSettingsScreen();
@@ -458,7 +427,8 @@ describe("Settings Screen", () => {
expect(input).not.toBeInTheDocument();
});
it.skip("should render the runtime settings input if SaaS mode", async () => {
it("should render the runtime settings input if SaaS mode", async () => {
const user = userEvent.setup();
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",
GITHUB_CLIENT_ID: "123",
@@ -466,10 +436,12 @@ describe("Settings Screen", () => {
});
renderSettingsScreen();
await screen.findByTestId("runtime-settings-input");
await toggleAdvancedSettings(user);
screen.getByTestId("runtime-settings-input");
});
it.skip("should set the default runtime setting set", async () => {
it("should set the default runtime setting set", async () => {
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",
GITHUB_CLIENT_ID: "123",
@@ -483,11 +455,13 @@ describe("Settings Screen", () => {
renderSettingsScreen();
await toggleAdvancedSettings(userEvent.setup());
const input = await screen.findByTestId("runtime-settings-input");
expect(input).toHaveValue("1x (2 core, 8G)");
});
it.skip("should always have the runtime input disabled", async () => {
it("should always have the runtime input disabled", async () => {
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",
GITHUB_CLIENT_ID: "123",
@@ -496,6 +470,8 @@ describe("Settings Screen", () => {
renderSettingsScreen();
await toggleAdvancedSettings(userEvent.setup());
const input = await screen.findByTestId("runtime-settings-input");
expect(input).toBeDisabled();
});
@@ -514,6 +490,8 @@ describe("Settings Screen", () => {
renderSettingsScreen();
await toggleAdvancedSettings(user);
const input = await screen.findByTestId("runtime-settings-input");
await user.click(input);
@@ -975,104 +953,4 @@ describe("Settings Screen", () => {
);
});
});
describe("SaaS mode", () => {
beforeEach(() => {
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",
GITHUB_CLIENT_ID: "123",
POSTHOG_CLIENT_KEY: "456",
});
});
it("should hide the entire LLM section", async () => {
renderSettingsScreen();
await waitFor(() => {
screen.getByTestId("account-settings-form"); // wait for the account settings form to render
const llmSection = screen.queryByTestId("llm-settings-section");
expect(llmSection).not.toBeInTheDocument();
});
});
it("should not render LLM Provider, LLM Model, and LLM API Key inputs", async () => {
renderSettingsScreen();
await waitFor(() => {
screen.getByTestId("account-settings-form"); // wait for the account settings form to render
const providerInput = screen.queryByTestId("llm-provider-input");
const modelInput = screen.queryByTestId("llm-model-input");
const apiKeyInput = screen.queryByTestId("llm-api-key-input");
const llmApiKeyHelpAnchor = screen.queryByTestId(
"llm-api-key-help-anchor",
);
const advancedSettingsSwitch = screen.queryByTestId(
"advanced-settings-switch",
);
expect(providerInput).not.toBeInTheDocument();
expect(modelInput).not.toBeInTheDocument();
expect(apiKeyInput).not.toBeInTheDocument();
expect(llmApiKeyHelpAnchor).not.toBeInTheDocument();
expect(advancedSettingsSwitch).not.toBeInTheDocument();
});
});
// We might want to bring this back if users wish to set advanced settings
it.skip("should render advanced settings by default", async () => {
renderSettingsScreen();
await waitFor(() => {
screen.getByTestId("account-settings-form"); // wait for the account settings form to render
const agentInput = screen.getByTestId("agent-input"); // this is only rendered in advanced mode
expect(agentInput).toBeInTheDocument();
// we should not allow the user to change these fields
const customModelInput = screen.queryByTestId("llm-custom-model-input");
const baseUrlInput = screen.queryByTestId("base-url-input");
expect(customModelInput).not.toBeInTheDocument();
expect(baseUrlInput).not.toBeInTheDocument();
});
});
it("should not submit the unwanted fields when saving", async () => {
const user = userEvent.setup();
renderSettingsScreen();
const saveButton = await screen.findByText("Save Changes");
await user.click(saveButton);
expect(saveSettingsSpy).toHaveBeenCalledWith(
expect.objectContaining({
llm_api_key: undefined,
llm_base_url: undefined,
llm_model: undefined,
}),
);
});
it("should not submit the unwanted fields when resetting", async () => {
const user = userEvent.setup();
renderSettingsScreen();
const resetButton = await screen.findByText("Reset to defaults");
await user.click(resetButton);
const modal = await screen.findByTestId("reset-modal");
const confirmButton = within(modal).getByText("Reset");
await user.click(confirmButton);
expect(saveSettingsSpy).toHaveBeenCalledWith(
expect.objectContaining({
llm_api_key: undefined,
llm_base_url: undefined,
llm_model: undefined,
}),
);
});
});
});

View File

@@ -1,12 +1,8 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { trackError, showErrorToast, showChatError } from "#/utils/error-handler";
import posthog from "posthog-js";
import {
trackError,
showErrorToast,
showChatError,
} from "#/utils/error-handler";
import toast from "react-hot-toast";
import * as Actions from "#/services/actions";
import * as CustomToast from "#/utils/custom-toast-handlers";
vi.mock("posthog-js", () => ({
default: {
@@ -14,6 +10,12 @@ vi.mock("posthog-js", () => ({
},
}));
vi.mock("react-hot-toast", () => ({
default: {
error: vi.fn(),
},
}));
vi.mock("#/services/actions", () => ({
handleStatusMessage: vi.fn(),
}));
@@ -36,12 +38,9 @@ describe("Error Handler", () => {
trackError(error);
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Test error"),
{
error_source: "test",
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Test error"), {
error_source: "test",
});
});
it("should include additional metadata in PostHog event", () => {
@@ -56,19 +55,15 @@ describe("Error Handler", () => {
trackError(error);
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Test error"),
{
error_source: "test",
extra: "info",
details: { foo: "bar" },
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Test error"), {
error_source: "test",
extra: "info",
details: { foo: "bar" },
});
});
});
describe("showErrorToast", () => {
const errorToastSpy = vi.spyOn(CustomToast, "displayErrorToast");
it("should log error and show toast", () => {
const error = {
message: "Toast error",
@@ -78,15 +73,12 @@ describe("Error Handler", () => {
showErrorToast(error);
// Verify PostHog logging
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Toast error"),
{
error_source: "toast-test",
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Toast error"), {
error_source: "toast-test",
});
// Verify toast was shown
expect(errorToastSpy).toHaveBeenCalled();
expect(toast.error).toHaveBeenCalled();
});
it("should include metadata in PostHog event when showing toast", () => {
@@ -98,13 +90,10 @@ describe("Error Handler", () => {
showErrorToast(error);
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Toast error"),
{
error_source: "toast-test",
context: "testing",
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Toast error"), {
error_source: "toast-test",
context: "testing",
});
});
it("should log errors from different sources with appropriate metadata", () => {
@@ -115,13 +104,10 @@ describe("Error Handler", () => {
metadata: { id: "error.agent" },
});
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Agent error"),
{
error_source: "agent-status",
id: "error.agent",
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Agent error"), {
error_source: "agent-status",
id: "error.agent",
});
showErrorToast({
message: "Server error",
@@ -129,14 +115,11 @@ describe("Error Handler", () => {
metadata: { error_code: 500, details: "Internal error" },
});
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Server error"),
{
error_source: "server",
error_code: 500,
details: "Internal error",
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Server error"), {
error_source: "server",
error_code: 500,
details: "Internal error",
});
});
it("should log feedback submission errors with conversation context", () => {
@@ -147,14 +130,11 @@ describe("Error Handler", () => {
metadata: { conversationId: "123", error },
});
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Feedback submission failed"),
{
error_source: "feedback",
conversationId: "123",
error,
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Feedback submission failed"), {
error_source: "feedback",
conversationId: "123",
error,
});
});
});
@@ -169,12 +149,9 @@ describe("Error Handler", () => {
showChatError(error);
// Verify PostHog logging
expect(posthog.captureException).toHaveBeenCalledWith(
new Error("Chat error"),
{
error_source: "chat-test",
},
);
expect(posthog.captureException).toHaveBeenCalledWith(new Error("Chat error"), {
error_source: "chat-test",
});
// Verify error message was shown in chat
expect(Actions.handleStatusMessage).toHaveBeenCalledWith({

File diff suppressed because it is too large Load Diff

View File

@@ -1,53 +1,53 @@
{
"name": "openhands-frontend",
"version": "0.28.0",
"version": "0.26.0",
"private": true,
"type": "module",
"engines": {
"node": ">=20.0.0"
},
"dependencies": {
"@heroui/react": "2.7.4",
"@heroui/react": "2.6.14",
"@monaco-editor/react": "^4.7.0-rc.0",
"@react-router/node": "^7.3.0",
"@react-router/serve": "^7.3.0",
"@react-types/shared": "^3.28.0",
"@reduxjs/toolkit": "^2.6.0",
"@stripe/react-stripe-js": "^3.3.0",
"@stripe/stripe-js": "^5.10.0",
"@tanstack/react-query": "^5.67.2",
"@react-router/node": "^7.1.5",
"@react-router/serve": "^7.1.5",
"@react-types/shared": "^3.27.0",
"@reduxjs/toolkit": "^2.5.1",
"@stripe/react-stripe-js": "^3.1.1",
"@stripe/stripe-js": "^5.5.0",
"@tanstack/react-query": "^5.66.7",
"@vitejs/plugin-react": "^4.3.2",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.4.0",
"axios": "^1.8.2",
"axios": "^1.7.9",
"clsx": "^2.1.1",
"eslint-config-airbnb-typescript": "^18.0.0",
"framer-motion": "^12.4.10",
"framer-motion": "^12.4.4",
"i18next": "^24.2.2",
"i18next-browser-languagedetector": "^8.0.4",
"i18next-browser-languagedetector": "^8.0.3",
"i18next-http-backend": "^3.0.2",
"isbot": "^5.1.23",
"jose": "^6.0.8",
"isbot": "^5.1.22",
"jose": "^5.10.0",
"monaco-editor": "^0.52.2",
"posthog-js": "^1.229.3",
"posthog-js": "^1.219.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-highlight": "^0.15.0",
"react-hot-toast": "^2.5.1",
"react-i18next": "^15.4.1",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-icons": "^5.4.0",
"react-markdown": "^9.0.3",
"react-redux": "^9.2.0",
"react-router": "^7.3.0",
"react-router": "^7.1.5",
"react-syntax-highlighter": "^15.6.1",
"react-textarea-autosize": "^8.5.7",
"remark-gfm": "^4.0.1",
"sirv-cli": "^3.0.1",
"socket.io-client": "^4.8.1",
"tailwind-merge": "^3.0.2",
"vite": "^6.2.1",
"tailwind-merge": "^3.0.1",
"vite": "^6.1.0",
"web-vitals": "^3.5.2",
"ws": "^8.18.1"
"ws": "^8.18.0"
},
"scripts": {
"dev": "npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev",
@@ -80,29 +80,29 @@
},
"devDependencies": {
"@mswjs/socket.io-binding": "^0.1.1",
"@playwright/test": "^1.51.0",
"@react-router/dev": "^7.3.0",
"@playwright/test": "^1.50.1",
"@react-router/dev": "^7.1.5",
"@tailwindcss/typography": "^0.5.16",
"@tanstack/eslint-plugin-query": "^5.67.2",
"@tanstack/eslint-plugin-query": "^5.66.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.1",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^22.13.9",
"@types/node": "^22.13.4",
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"@types/react-highlight": "^0.12.8",
"@types/react-syntax-highlighter": "^15.5.13",
"@types/ws": "^8.18.0",
"@types/ws": "^8.5.14",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitest/coverage-v8": "^3.0.8",
"@vitest/coverage-v8": "^3.0.6",
"autoprefixer": "^10.4.20",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^10.1.1",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.2.3",
@@ -113,10 +113,10 @@
"lint-staged": "^15.4.3",
"msw": "^2.6.6",
"postcss": "^8.5.2",
"prettier": "^3.5.3",
"stripe": "^17.7.0",
"prettier": "^3.5.1",
"stripe": "^17.5.0",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.2",
"typescript": "^5.7.3",
"vite-plugin-svgr": "^4.2.0",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.0.2"

View File

@@ -174,7 +174,7 @@ class OpenHands {
code: string,
): Promise<GitHubAccessTokenResponse> {
const { data } = await openHands.post<GitHubAccessTokenResponse>(
"/api/keycloak/callback",
"/api/github/callback",
{
code,
},

View File

@@ -1,5 +1,5 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M15.359 21V17.319C15.3974 16.8654 15.3314 16.4095 15.1651 15.9814C14.9989 15.5534 14.7363 15.1631 14.3949 14.8364C17.6154 14.5035 21 13.3716 21 8.17826C20.9997 6.85027 20.4489 5.57321 19.4615 4.61139C19.9291 3.44954 19.896 2.16532 19.3692 1.02548C19.3692 1.02548 18.159 0.692576 15.359 2.43321C13.0082 1.84237 10.5302 1.84237 8.17949 2.43321C5.37949 0.692576 4.16923 1.02548 4.16923 1.02548C3.64244 2.16532 3.60938 3.44954 4.07692 4.61139C3.08218 5.58034 2.53079 6.86895 2.53846 8.2068C2.53846 13.3621 5.92308 14.494 9.14359 14.865C8.80615 15.1883 8.54591 15.574 8.3798 15.9968C8.2137 16.4196 8.14544 16.8701 8.17949 17.319V21M8.17949 18.1465C3.05128 19.5732 3.05128 15.7686 1 15.293L8.17949 18.1465Z"
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" />
stroke="white" stroke-linecap="round" stroke-linejoin="round" />
</svg>

Before

Width:  |  Height:  |  Size: 896 B

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

View File

@@ -1,3 +1,4 @@
import { ModalButton } from "#/components/shared/buttons/modal-button";
import {
BaseModalTitle,
BaseModalDescription,
@@ -6,7 +7,6 @@ import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop";
import { ModalBody } from "#/components/shared/modals/modal-body";
import { useCurrentSettings } from "#/context/settings-context";
import { handleCaptureConsent } from "#/utils/handle-capture-consent";
import { BrandButton } from "../settings/brand-button";
interface AnalyticsConsentFormModalProps {
onClose: () => void;
@@ -40,7 +40,7 @@ export function AnalyticsConsentFormModal({
onSubmit={handleSubmit}
className="flex flex-col gap-2"
>
<ModalBody className="border border-tertiary">
<ModalBody>
<BaseModalTitle title="Your Privacy Preferences" />
<BaseModalDescription>
We use tools to understand how our application is used to improve
@@ -53,14 +53,12 @@ export function AnalyticsConsentFormModal({
Send anonymous usage data
</label>
<BrandButton
<ModalButton
testId="confirm-preferences"
type="submit"
variant="primary"
className="w-full"
>
Confirm Preferences
</BrandButton>
text="Confirm Preferences"
className="bg-primary text-white w-full hover:opacity-80"
/>
</ModalBody>
</form>
</ModalBackdrop>

View File

@@ -1,4 +1,5 @@
import { useDispatch, useSelector } from "react-redux";
import toast from "react-hot-toast";
import React from "react";
import posthog from "posthog-js";
import { useParams } from "react-router";
@@ -22,7 +23,6 @@ import { ScrollToBottomButton } from "#/components/shared/buttons/scroll-to-bott
import { LoadingSpinner } from "#/components/shared/loading-spinner";
import { useGetTrajectory } from "#/hooks/mutation/use-get-trajectory";
import { downloadTrajectory } from "#/utils/download-files";
import { displayErrorToast } from "#/utils/custom-toast-handlers";
function getEntryPoint(
hasRepository: boolean | null,
@@ -98,7 +98,7 @@ export function ChatInterface() {
const onClickExportTrajectoryButton = () => {
if (!params.conversationId) {
displayErrorToast("ConversationId unknown, cannot download trajectory");
toast.error("ConversationId unknown, cannot download trajectory");
return;
}
@@ -110,7 +110,7 @@ export function ChatInterface() {
);
},
onError: (error) => {
displayErrorToast(error.message);
toast.error(error.message);
},
});
};

View File

@@ -47,7 +47,7 @@ export function ChatMessage({
className={cn(
"rounded-xl relative",
"flex flex-col gap-2",
type === "user" && " max-w-[305px] p-4 bg-tertiary self-end",
type === "user" && " max-w-[305px] p-4 bg-neutral-700 self-end",
type === "assistant" && "mt-6 max-w-full bg-tranparent",
)}
>
@@ -57,19 +57,18 @@ export function ChatMessage({
onClick={handleCopyToClipboard}
mode={isCopy ? "copied" : "copy"}
/>
<div className="text-sm overflow-auto break-words">
<Markdown
components={{
code,
ul,
ol,
a: anchor,
}}
remarkPlugins={[remarkGfm]}
>
{message}
</Markdown>
</div>
<Markdown
className="text-sm overflow-auto break-words"
components={{
code,
ul,
ol,
a: anchor,
}}
remarkPlugins={[remarkGfm]}
>
{message}
</Markdown>
{children}
</article>
);

View File

@@ -13,7 +13,7 @@ export function ChatSuggestions({ onSuggestionsClick }: ChatSuggestionsProps) {
return (
<div className="flex flex-col gap-6 h-full px-4 items-center justify-center">
<div className="flex flex-col items-center p-4 bg-tertiary rounded-xl w-full">
<div className="flex flex-col items-center p-4 bg-neutral-700 rounded-xl w-full">
<BuildIt width={45} height={54} />
<span className="font-semibold text-[20px] leading-6 -tracking-[0.01em] gap-1">
{t(I18nKey.LANDING$TITLE)}

View File

@@ -2,7 +2,6 @@ import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { Link } from "react-router";
import { code } from "../markdown/code";
import { ol, ul } from "../markdown/list";
import ArrowUp from "#/icons/angle-up-solid.svg?react";
@@ -10,8 +9,6 @@ import ArrowDown from "#/icons/angle-down-solid.svg?react";
import CheckCircle from "#/icons/check-circle-solid.svg?react";
import XCircle from "#/icons/x-circle-solid.svg?react";
import { cn } from "#/utils/utils";
import { useConfig } from "#/hooks/query/use-config";
import { BILLING_SETTINGS } from "#/utils/feature-flags";
interface ExpandableMessageProps {
id?: string;
@@ -26,7 +23,6 @@ export function ExpandableMessage({
type,
success,
}: ExpandableMessageProps) {
const { data: config } = useConfig();
const { t, i18n } = useTranslation();
const [showDetails, setShowDetails] = useState(true);
const [headline, setHeadline] = useState("");
@@ -42,28 +38,6 @@ export function ExpandableMessage({
const statusIconClasses = "h-4 w-4 ml-2 inline";
if (
BILLING_SETTINGS() &&
config?.APP_MODE === "saas" &&
id === "STATUS$ERROR_LLM_OUT_OF_CREDITS"
) {
return (
<div className="flex gap-2 items-center justify-start border-l-2 pl-2 my-2 py-2 border-danger">
<div className="text-sm w-full">
<div className="font-bold text-danger">
{t("STATUS$ERROR_LLM_OUT_OF_CREDITS")}
</div>
<Link
className="mt-2 mb-2 w-full h-10 rounded flex items-center justify-center gap-2 bg-primary text-[#0D0F11]"
to="/settings/billing"
>
{t("BILLING$CLICK_TO_TOP_UP")}
</Link>
</div>
</div>
);
}
return (
<div
className={cn(
@@ -123,18 +97,17 @@ export function ExpandableMessage({
)}
</div>
{(!headline || showDetails) && (
<div className="text-sm overflow-auto">
<Markdown
components={{
code,
ul,
ol,
}}
remarkPlugins={[remarkGfm]}
>
{details}
</Markdown>
</div>
<Markdown
className="text-sm overflow-auto"
components={{
code,
ul,
ol,
}}
remarkPlugins={[remarkGfm]}
>
{details}
</Markdown>
)}
</div>
</div>

View File

@@ -59,7 +59,7 @@ export function InteractiveChatBox({
<div
className={cn(
"flex items-end gap-1",
"bg-tertiary border border-neutral-600 rounded-lg px-2",
"bg-neutral-700 border border-neutral-600 rounded-lg px-2",
"transition-colors duration-200",
"hover:border-neutral-500 focus-within:border-neutral-500",
)}

View File

@@ -1,6 +1,6 @@
export function TypingIndicator() {
return (
<div className="flex items-center space-x-1.5 bg-tertiary px-3 py-1.5 rounded-full">
<div className="flex items-center space-x-1.5 bg-neutral-700 px-3 py-1.5 rounded-full">
<span
className="w-1.5 h-1.5 bg-gray-400 rounded-full animate-[bounce_0.5s_infinite] translate-y-[-2px]"
style={{ animationDelay: "0ms" }}

View File

@@ -18,7 +18,7 @@ export function ContextMenu({
<ul
data-testid={testId}
ref={ref}
className={cn("bg-tertiary rounded-md w-[140px]", className)}
className={cn("bg-[#404040] rounded-md w-[140px]", className)}
>
{children}
</ul>

View File

@@ -9,21 +9,12 @@ import {
useWsClient,
WsClientProviderStatus,
} from "#/context/ws-client-provider";
import { useNotification } from "#/hooks/useNotification";
import { browserTab } from "#/utils/browser-tab";
const notificationStates = [
AgentState.AWAITING_USER_INPUT,
AgentState.FINISHED,
AgentState.AWAITING_USER_CONFIRMATION,
];
export function AgentStatusBar() {
const { t, i18n } = useTranslation();
const { curAgentState } = useSelector((state: RootState) => state.agent);
const { curStatusMessage } = useSelector((state: RootState) => state.status);
const { status } = useWsClient();
const { notify } = useNotification();
const [statusMessage, setStatusMessage] = React.useState<string>("");
@@ -54,40 +45,13 @@ export function AgentStatusBar() {
updateStatusMessage();
}, [curStatusMessage.id]);
// Handle window focus/blur
React.useEffect(() => {
if (typeof window === "undefined") return undefined;
const handleFocus = () => {
browserTab.stopNotification();
};
window.addEventListener("focus", handleFocus);
return () => {
window.removeEventListener("focus", handleFocus);
browserTab.stopNotification();
};
}, []);
React.useEffect(() => {
if (status === WsClientProviderStatus.DISCONNECTED) {
setStatusMessage("Connecting...");
} else {
setStatusMessage(AGENT_STATUS_MAP[curAgentState].message);
if (notificationStates.includes(curAgentState)) {
const message = t(AGENT_STATUS_MAP[curAgentState].message);
notify(t(AGENT_STATUS_MAP[curAgentState].message), {
body: t(`Agent state changed to ${curAgentState}`),
playSound: true,
});
// Update browser tab if window exists and is not focused
if (typeof document !== "undefined" && !document.hasFocus()) {
browserTab.startNotification(message);
}
}
}
}, [curAgentState, notify, t]);
}, [curAgentState]);
return (
<div className="flex flex-col items-center">

View File

@@ -1,10 +1,10 @@
import { ModalButton } from "#/components/shared/buttons/modal-button";
import {
BaseModalDescription,
BaseModalTitle,
} from "#/components/shared/modals/confirmation-modals/base-modal";
import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop";
import { ModalBody } from "#/components/shared/modals/modal-body";
import { BrandButton } from "../settings/brand-button";
interface ConfirmDeleteModalProps {
onConfirm: () => void;
@@ -17,7 +17,7 @@ export function ConfirmDeleteModal({
}: ConfirmDeleteModalProps) {
return (
<ModalBackdrop>
<ModalBody className="items-start border border-tertiary">
<ModalBody className="items-start">
<div className="flex flex-col gap-2">
<BaseModalTitle title="Are you sure you want to delete this project?" />
<BaseModalDescription description="All data associated with this project will be lost." />
@@ -26,22 +26,16 @@ export function ConfirmDeleteModal({
className="flex flex-col gap-2 w-full"
onClick={(event) => event.stopPropagation()}
>
<BrandButton
type="button"
variant="primary"
<ModalButton
onClick={onConfirm}
className="w-full"
>
Confirm
</BrandButton>
<BrandButton
type="button"
variant="secondary"
className="bg-danger font-bold"
text="Confirm"
/>
<ModalButton
onClick={onCancel}
className="w-full"
>
Cancel
</BrandButton>
className="bg-neutral-500 font-bold"
text="Cancel"
/>
</div>
</ModalBody>
</ModalBackdrop>

View File

@@ -101,11 +101,9 @@ export function ConversationCard({
"h-auto w-fit rounded-xl border border-[#525252]",
)}
>
<div className="flex items-center justify-between w-full">
<div className="flex items-center gap-2 flex-1 min-w-0 overflow-hidden mr-2">
{isActive && (
<span className="w-2 h-2 bg-blue-500 rounded-full flex-shrink-0" />
)}
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 w-full">
{isActive && <span className="w-2 h-2 bg-blue-500 rounded-full" />}
{titleMode === "edit" && (
<input
ref={inputRef}
@@ -121,8 +119,7 @@ export function ConversationCard({
{titleMode === "view" && (
<p
data-testid="conversation-card-title"
className="text-sm leading-6 font-semibold bg-transparent truncate overflow-hidden"
title={title}
className="text-sm leading-6 font-semibold bg-transparent w-full"
>
{title}
</p>

View File

@@ -25,7 +25,7 @@ export function ExitConversationModal({
<ModalButton
text="Cancel"
onClick={onClose}
className="bg-tertiary flex-1"
className="bg-neutral-700 flex-1"
/>
</div>
</ModalBody>

View File

@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { Feedback } from "#/api/open-hands.types";
import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback";
import { BrandButton } from "../settings/brand-button";
import { ModalButton } from "#/components/shared/buttons/modal-button";
const FEEDBACK_VERSION = "1.0";
const VIEWER_PAGE = "https://www.all-hands.dev/share";
@@ -121,23 +121,18 @@ export function FeedbackForm({ onClose, polarity }: FeedbackFormProps) {
</div>
<div className="flex gap-2">
<BrandButton
<ModalButton
disabled={isPending}
type="submit"
variant="primary"
className="grow"
isDisabled={isPending}
>
{t(I18nKey.FEEDBACK$SHARE_LABEL)}
</BrandButton>
<BrandButton
type="button"
variant="secondary"
className="grow"
text={t(I18nKey.FEEDBACK$SHARE_LABEL)}
className="bg-[#4465DB] grow"
/>
<ModalButton
disabled={isPending}
text={t(I18nKey.FEEDBACK$CANCEL_LABEL)}
onClick={onClose}
isDisabled={isPending}
>
{t(I18nKey.FEEDBACK$CANCEL_LABEL)}
</BrandButton>
className="bg-[#737373] grow"
/>
</div>
</form>
);

View File

@@ -21,7 +21,7 @@ export function FeedbackModal({
return (
<ModalBackdrop onClose={onClose}>
<ModalBody className="border border-tertiary">
<ModalBody>
<BaseModalTitle title="Feedback" />
<BaseModalDescription description="To help us improve, we collect feedback from your interactions to improve our prompts. By submitting this form, you consent to us collecting this data." />
<FeedbackForm onClose={onClose} polarity={polarity} />

View File

@@ -10,8 +10,7 @@ import { useListFiles } from "#/hooks/query/use-list-files";
import { cn } from "#/utils/utils";
import { FileExplorerHeader } from "./file-explorer-header";
import { useVSCodeUrl } from "#/hooks/query/use-vscode-url";
import { BrandButton } from "../settings/brand-button";
import VSCodeIcon from "#/assets/vscode-alt.svg?react";
import { OpenVSCodeButton } from "#/components/shared/buttons/open-vscode-button";
interface FileExplorerProps {
isOpen: boolean;
@@ -78,17 +77,10 @@ export function FileExplorer({ isOpen, onToggle }: FileExplorerProps) {
</div>
)}
{isOpen && (
<BrandButton
testId="open-vscode-button"
type="button"
variant="secondary"
className="w-full text-content border-content"
isDisabled={RUNTIME_INACTIVE_STATES.includes(curAgentState)}
<OpenVSCodeButton
onClick={handleOpenVSCode}
startContent={<VSCodeIcon width={20} height={20} />}
>
{t(I18nKey.VSCODE$OPEN)}
</BrandButton>
isDisabled={RUNTIME_INACTIVE_STATES.includes(curAgentState)}
/>
)}
</div>
</div>

View File

@@ -99,6 +99,7 @@ export function GitHubRepositorySelector({
<AutocompleteItem
data-testid="github-repo-item"
key={repo.id}
value={repo.id}
className="data-[selected=true]:bg-default-100"
textValue={repo.full_name}
>
@@ -113,6 +114,7 @@ export function GitHubRepositorySelector({
<AutocompleteItem
data-testid="github-repo-item"
key={repo.id}
value={repo.id}
className="data-[selected=true]:bg-default-100"
textValue={repo.full_name}
>

View File

@@ -3,14 +3,14 @@ import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router";
import { I18nKey } from "#/i18n/declaration";
import { SuggestionBox } from "#/components/features/suggestions/suggestion-box";
import GitHubLogo from "#/assets/branding/github-logo.svg?react";
import { GitHubRepositorySelector } from "./github-repo-selector";
import { ModalButton } from "#/components/shared/buttons/modal-button";
import { useAppRepositories } from "#/hooks/query/use-app-repositories";
import { useSearchRepositories } from "#/hooks/query/use-search-repositories";
import { useUserRepositories } from "#/hooks/query/use-user-repositories";
import { sanitizeQuery } from "#/utils/sanitize-query";
import { useDebounce } from "#/hooks/use-debounce";
import { BrandButton } from "../settings/brand-button";
import GitHubLogo from "#/assets/branding/github-logo.svg?react";
interface GitHubRepositoriesSuggestionBoxProps {
handleSubmit: () => void;
@@ -62,16 +62,13 @@ export function GitHubRepositoriesSuggestionBox({
userRepositories={repositories}
/>
) : (
<BrandButton
<ModalButton
testId="connect-to-github"
type="button"
variant="secondary"
className="w-full text-content border-content"
text={t(I18nKey.GITHUB$CONNECT)}
icon={<GitHubLogo width={20} height={20} />}
className="bg-[#791B80] w-full"
onClick={handleConnectToGitHub}
startContent={<GitHubLogo width={20} height={20} />}
>
{t(I18nKey.GITHUB$CONNECT)}
</BrandButton>
/>
)
}
/>

View File

@@ -7,7 +7,6 @@ interface BrandButtonProps {
isDisabled?: boolean;
className?: string;
onClick?: () => void;
startContent?: React.ReactNode;
}
export function BrandButton({
@@ -18,7 +17,6 @@ export function BrandButton({
isDisabled,
className,
onClick,
startContent,
}: React.PropsWithChildren<BrandButtonProps>) {
return (
<button
@@ -32,11 +30,9 @@ export function BrandButton({
"w-fit p-2 rounded disabled:opacity-30 disabled:cursor-not-allowed",
variant === "primary" && "bg-primary text-[#0D0F11]",
variant === "secondary" && "border border-primary text-primary",
startContent && "flex items-center justify-center gap-2",
className,
)}
>
{startContent}
{children}
</button>
);

View File

@@ -1,10 +1,9 @@
import { Autocomplete, AutocompleteItem } from "@heroui/react";
import { ReactNode } from "react";
import { OptionalTag } from "./optional-tag";
interface SettingsDropdownInputProps {
testId: string;
label: ReactNode;
label: string;
name: string;
items: { key: React.Key; label: string }[];
showOptionalTag?: boolean;
@@ -30,7 +29,7 @@ export function SettingsDropdownInput({
{showOptionalTag && <OptionalTag />}
</div>
<Autocomplete
aria-label={typeof label === "string" ? label : name}
aria-label={label}
data-testid={testId}
name={name}
defaultItems={items}

View File

@@ -2,6 +2,7 @@ import React from "react";
import { FaListUl } from "react-icons/fa";
import { useDispatch } from "react-redux";
import posthog from "posthog-js";
import toast from "react-hot-toast";
import { NavLink, useLocation } from "react-router";
import { useGitHubUser } from "#/hooks/query/use-github-user";
import { UserActions } from "./user-actions";
@@ -9,6 +10,7 @@ import { AllHandsLogoButton } from "#/components/shared/buttons/all-hands-logo-b
import { DocsButton } from "#/components/shared/buttons/docs-button";
import { ExitProjectButton } from "#/components/shared/buttons/exit-project-button";
import { SettingsButton } from "#/components/shared/buttons/settings-button";
import { LoadingSpinner } from "#/components/shared/loading-spinner";
import { SettingsModal } from "#/components/shared/modals/settings/settings-modal";
import { useCurrentSettings } from "#/context/settings-context";
import { useSettings } from "#/hooks/query/use-settings";
@@ -21,8 +23,6 @@ import { ConversationPanelWrapper } from "../conversation-panel/conversation-pan
import { useLogout } from "#/hooks/mutation/use-logout";
import { useConfig } from "#/hooks/query/use-config";
import { cn } from "#/utils/utils";
import { displayErrorToast } from "#/utils/custom-toast-handlers";
import { HIDE_LLM_SETTINGS } from "#/utils/feature-flags";
export function Sidebar() {
const location = useLocation();
@@ -43,12 +43,7 @@ export function Sidebar() {
const [conversationPanelIsOpen, setConversationPanelIsOpen] =
React.useState(false);
// TODO: Remove HIDE_LLM_SETTINGS check once released
const isSaas = HIDE_LLM_SETTINGS() && config?.APP_MODE === "saas";
React.useEffect(() => {
if (isSaas) return;
if (location.pathname === "/settings") {
setSettingsModalIsOpen(false);
} else if (
@@ -58,7 +53,7 @@ export function Sidebar() {
) {
// We don't show toast errors for settings in the global error handler
// because we have a special case for 404 errors
displayErrorToast(
toast.error(
"Something went wrong while fetching settings. Please reload the page.",
);
} else if (settingsError?.status === 404) {
@@ -116,13 +111,15 @@ export function Sidebar() {
>
<SettingsButton />
</NavLink>
<UserActions
user={
user.data ? { avatar_url: user.data.avatar_url } : undefined
}
onLogout={handleLogout}
isLoading={user.isFetching}
/>
{!user.isLoading && (
<UserActions
user={
user.data ? { avatar_url: user.data.avatar_url } : undefined
}
onLogout={handleLogout}
/>
)}
{user.isLoading && <LoadingSpinner size="small" />}
</div>
</nav>

View File

@@ -5,10 +5,9 @@ import { AccountSettingsContextMenu } from "../context-menu/account-settings-con
interface UserActionsProps {
onLogout: () => void;
user?: { avatar_url: string };
isLoading?: boolean;
}
export function UserActions({ onLogout, user, isLoading }: UserActionsProps) {
export function UserActions({ onLogout, user }: UserActionsProps) {
const [accountContextMenuIsVisible, setAccountContextMenuIsVisible] =
React.useState(false);
@@ -27,11 +26,7 @@ export function UserActions({ onLogout, user, isLoading }: UserActionsProps) {
return (
<div data-testid="user-actions" className="w-8 h-8 relative">
<UserAvatar
avatarUrl={user?.avatar_url}
onClick={toggleAccountMenu}
isLoading={isLoading}
/>
<UserAvatar avatarUrl={user?.avatar_url} onClick={toggleAccountMenu} />
{accountContextMenuIsVisible && (
<AccountSettingsContextMenu

Some files were not shown because too many files have changed in this diff Show More