mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-04-29 03:00:45 -04:00
Compare commits
289 Commits
fix/utils-
...
delegates-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
497fd4a02c | ||
|
|
7fac7d6dd0 | ||
|
|
4155b8f801 | ||
|
|
e712b013f9 | ||
|
|
29b137e9b1 | ||
|
|
1292f0c2ea | ||
|
|
da8c946078 | ||
|
|
43cef1f969 | ||
|
|
722711db3b | ||
|
|
ab661b485b | ||
|
|
9632914bf0 | ||
|
|
f45f398d81 | ||
|
|
3db780ef93 | ||
|
|
43c16516e8 | ||
|
|
0bab3b62f2 | ||
|
|
ae990d3cb1 | ||
|
|
9babd756e5 | ||
|
|
985e20d529 | ||
|
|
98cb2e24ee | ||
|
|
de175dcc87 | ||
|
|
976019ce11 | ||
|
|
709b6ff39a | ||
|
|
767d092f8f | ||
|
|
7244e5df9f | ||
|
|
dfbb968ea0 | ||
|
|
e4c3bbbc08 | ||
|
|
6e0fbfeeda | ||
|
|
03aa5d7456 | ||
|
|
6032d2620d | ||
|
|
0fc86b4063 | ||
|
|
e39d904a1f | ||
|
|
9887813b41 | ||
|
|
d36cde5060 | ||
|
|
fc4ad2f8c3 | ||
|
|
9e97ea2dd7 | ||
|
|
1ffaae17ff | ||
|
|
3edea7c710 | ||
|
|
08171eaf59 | ||
|
|
5376a54800 | ||
|
|
14d7449514 | ||
|
|
735ac72351 | ||
|
|
e5f25726c0 | ||
|
|
59fc0fe9db | ||
|
|
7ae3494ccc | ||
|
|
3d22520992 | ||
|
|
cfae2a3607 | ||
|
|
906823f898 | ||
|
|
4dcceacc9e | ||
|
|
9f05237b0d | ||
|
|
467ee52b05 | ||
|
|
0d5dbbfa84 | ||
|
|
9b128f6168 | ||
|
|
760a14482e | ||
|
|
b5338c69d6 | ||
|
|
c99f031cdb | ||
|
|
bcc28a12fe | ||
|
|
c82b3378a6 | ||
|
|
a6d3db3ce7 | ||
|
|
4cbbfd799c | ||
|
|
0b728c0c79 | ||
|
|
e35c8ee173 | ||
|
|
9a9b143620 | ||
|
|
38578bd5f5 | ||
|
|
7b2c88ae6b | ||
|
|
0cbf3987f8 | ||
|
|
d18edc8b30 | ||
|
|
42eb355a68 | ||
|
|
5fa01ed278 | ||
|
|
1f747232cf | ||
|
|
4b1ed30e97 | ||
|
|
998de564cd | ||
|
|
06ce12eff4 | ||
|
|
88fc26d9b0 | ||
|
|
99233ec153 | ||
|
|
ae9573a503 | ||
|
|
f2725eeb3d | ||
|
|
1b63633030 | ||
|
|
107789b5a8 | ||
|
|
04bdea5faf | ||
|
|
2bad4ea3d2 | ||
|
|
1c4c477b3f | ||
|
|
391ba1d988 | ||
|
|
70f469b0c1 | ||
|
|
8a5c6d3bef | ||
|
|
998e04e51b | ||
|
|
da7041b5e9 | ||
|
|
e4b7b31f48 | ||
|
|
587c53f115 | ||
|
|
4d76f31610 | ||
|
|
c25a96825c | ||
|
|
16137942eb | ||
|
|
cf07b151dc | ||
|
|
ea3787c2ba | ||
|
|
956d278138 | ||
|
|
fa186fc433 | ||
|
|
4ef9c72da1 | ||
|
|
c5245a622d | ||
|
|
9b1aaa53fe | ||
|
|
4deffa3907 | ||
|
|
a47c6f3ed1 | ||
|
|
90ece3f8e1 | ||
|
|
a948b0fef3 | ||
|
|
52848cd3db | ||
|
|
62f015370a | ||
|
|
7109b057b6 | ||
|
|
e694fc2d58 | ||
|
|
50baf3fd18 | ||
|
|
dc37f039bf | ||
|
|
91fff77ffe | ||
|
|
db01cd39d5 | ||
|
|
00865fbb8a | ||
|
|
356cd9ff9f | ||
|
|
78d82408b7 | ||
|
|
3c4ebc3d8a | ||
|
|
964478c22f | ||
|
|
00c449d447 | ||
|
|
bfd75a1355 | ||
|
|
dc91cb263b | ||
|
|
fa559ace86 | ||
|
|
1fd26d196a | ||
|
|
5de62d85fd | ||
|
|
5d749aeba7 | ||
|
|
693c72d670 | ||
|
|
62557d44f2 | ||
|
|
89f8e162da | ||
|
|
b0a9938e6c | ||
|
|
039fe295a4 | ||
|
|
8f3ff1210e | ||
|
|
5e1e685493 | ||
|
|
e9f2b72ea5 | ||
|
|
986b90be0a | ||
|
|
bf9f2aa7a5 | ||
|
|
b3bd3924a0 | ||
|
|
0de50153a0 | ||
|
|
a04024a239 | ||
|
|
1e509a70d4 | ||
|
|
300a59853b | ||
|
|
2514b200c5 | ||
|
|
52d881c98d | ||
|
|
6ac23aea80 | ||
|
|
0412949018 | ||
|
|
5b5adc5c7b | ||
|
|
0b40f6fac8 | ||
|
|
44d488b718 | ||
|
|
4f9120ffc6 | ||
|
|
50426edaa1 | ||
|
|
a792f84a83 | ||
|
|
cd9d96766c | ||
|
|
14564b25d6 | ||
|
|
0637b5b912 | ||
|
|
20bf48b693 | ||
|
|
5b3270be2d | ||
|
|
ae43744052 | ||
|
|
b5d7e428d1 | ||
|
|
d65ea313e8 | ||
|
|
a09ecadba6 | ||
|
|
358166feb2 | ||
|
|
85e2b73eb4 | ||
|
|
c18475ddc2 | ||
|
|
06fcf54475 | ||
|
|
f751f8ab37 | ||
|
|
523c6d03c1 | ||
|
|
0e0f043e59 | ||
|
|
91c691d526 | ||
|
|
c6092291ce | ||
|
|
a2c55cfdef | ||
|
|
76cad626ed | ||
|
|
7c23993344 | ||
|
|
b669715416 | ||
|
|
7292122b72 | ||
|
|
992ae15c78 | ||
|
|
f2b4772ac2 | ||
|
|
9b9b1291fc | ||
|
|
6171395ef9 | ||
|
|
d270476d6c | ||
|
|
f1f7dca009 | ||
|
|
45f572f268 | ||
|
|
4b124d5906 | ||
|
|
988d4aa679 | ||
|
|
b452fe273c | ||
|
|
9544b37c8a | ||
|
|
0491357fef | ||
|
|
fedd517a71 | ||
|
|
9cbed8802f | ||
|
|
c2e1babd76 | ||
|
|
cc8b677f3e | ||
|
|
78e3f82de1 | ||
|
|
20ca2cd8b9 | ||
|
|
ea0fcd6002 | ||
|
|
6bcebd4b9d | ||
|
|
93e9db3206 | ||
|
|
caf34d83bd | ||
|
|
49d3cd0863 | ||
|
|
34989f8e96 | ||
|
|
9274664302 | ||
|
|
437f0a0154 | ||
|
|
9d79bf5fff | ||
|
|
4c62b1d428 | ||
|
|
b2a4b4ed90 | ||
|
|
9262babc3b | ||
|
|
1c80ded753 | ||
|
|
4de8c4d6b1 | ||
|
|
91f2254039 | ||
|
|
66fd156c65 | ||
|
|
4ec16f3c2e | ||
|
|
628003abef | ||
|
|
07e400b73d | ||
|
|
7e14a512e0 | ||
|
|
d7e8f843ad | ||
|
|
e69ae81ad2 | ||
|
|
03c5db32e6 | ||
|
|
5e5bf23f9c | ||
|
|
e0fcd7a61e | ||
|
|
e9989d1085 | ||
|
|
49c515b252 | ||
|
|
2d05578c21 | ||
|
|
d05a6f30e1 | ||
|
|
10c81c39fb | ||
|
|
2d599349ef | ||
|
|
33caf5c6ca | ||
|
|
a9850766a7 | ||
|
|
77e2416def | ||
|
|
02af9865ec | ||
|
|
75ca2aa6b1 | ||
|
|
d820661592 | ||
|
|
1ff351a4f1 | ||
|
|
78b8e58561 | ||
|
|
fddbfce51a | ||
|
|
20d3766451 | ||
|
|
72b5e18898 | ||
|
|
03b8b8c19a | ||
|
|
7c2f1b075e | ||
|
|
883da1b28c | ||
|
|
bb98d94b35 | ||
|
|
d114c45135 | ||
|
|
36e092e0ac | ||
|
|
e2bb69908a | ||
|
|
cd33c5eac7 | ||
|
|
0f8a139fb5 | ||
|
|
ced4ee3038 | ||
|
|
cc19dac939 | ||
|
|
4c7c73a6f2 | ||
|
|
0493fea9fc | ||
|
|
1c2db9f468 | ||
|
|
c210230802 | ||
|
|
9b12989a36 | ||
|
|
f1bcd72cd8 | ||
|
|
a5c57fbd3a | ||
|
|
513f7ab7e7 | ||
|
|
53c0c5a07b | ||
|
|
d924e7cea5 | ||
|
|
7910a90522 | ||
|
|
35d49f6941 | ||
|
|
e359a4affa | ||
|
|
159f79f9d8 | ||
|
|
827c19ccd9 | ||
|
|
588b9f34be | ||
|
|
fb02fefaca | ||
|
|
856d5ff976 | ||
|
|
eb4aeb3922 | ||
|
|
4b47e5215b | ||
|
|
0087082643 | ||
|
|
e698a393b2 | ||
|
|
d48e2a4cf1 | ||
|
|
749a903de5 | ||
|
|
0a6321246a | ||
|
|
ddda30d9b7 | ||
|
|
d1851cc3ee | ||
|
|
883bf5847b | ||
|
|
1c8ab4d835 | ||
|
|
255e209886 | ||
|
|
c8904e4672 | ||
|
|
dcfc2da428 | ||
|
|
84e28234e5 | ||
|
|
60e8b5841c | ||
|
|
dd03d9adce | ||
|
|
9fa211bc27 | ||
|
|
22cf5144cc | ||
|
|
99e493b3a4 | ||
|
|
e4d92d6f56 | ||
|
|
a9d08852db | ||
|
|
408ad1ff2b | ||
|
|
69d4a8df7c | ||
|
|
02f92164de | ||
|
|
1549927fa3 | ||
|
|
e951da7a25 | ||
|
|
f830d5814c | ||
|
|
0519e9e3c2 | ||
|
|
9b8a628395 |
5
.github/ISSUE_TEMPLATE/bug_template.yml
vendored
5
.github/ISSUE_TEMPLATE/bug_template.yml
vendored
@@ -5,11 +5,12 @@ labels: ['bug']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thank you for taking the time to fill out this bug report. Please provide as much information as possible to help us understand and address the issue effectively.
|
||||
value: Thank you for taking the time to fill out this bug report. Please provide as much information as possible
|
||||
to help us understand and address the issue effectively.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for the same bug?
|
||||
label: Is there an existing issue for the same bug? (If one exists, thumbs up or comment on the issue instead).
|
||||
description: Please check if an issue already exists for the bug you encountered.
|
||||
options:
|
||||
- label: I have checked the existing issues.
|
||||
|
||||
13
.github/ISSUE_TEMPLATE/feature_request.md
vendored
13
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for OpenHands features
|
||||
name: Feature Request or Enhancement
|
||||
about: Suggest an idea for an OpenHands feature or enhancement
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
assignees: ''
|
||||
@@ -9,10 +9,9 @@ assignees: ''
|
||||
|
||||
**What problem or use case are you trying to solve?**
|
||||
|
||||
**Describe the UX of the solution you'd like**
|
||||
|
||||
**Do you have thoughts on the technical implementation?**
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
**Describe the UX or technical implementation you have in mind**
|
||||
|
||||
**Additional context**
|
||||
|
||||
|
||||
### If you find this feature request or enhancement useful, make sure to add a 👍 to the issue
|
||||
|
||||
18
.github/ISSUE_TEMPLATE/technical_proposal.md
vendored
18
.github/ISSUE_TEMPLATE/technical_proposal.md
vendored
@@ -1,18 +0,0 @@
|
||||
---
|
||||
name: Technical Proposal
|
||||
about: Propose a new architecture or technology
|
||||
title: ''
|
||||
labels: 'proposal'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Summary**
|
||||
|
||||
**Motivation**
|
||||
|
||||
**Technical Design**
|
||||
|
||||
**Alternatives to Consider**
|
||||
|
||||
**Additional context**
|
||||
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
@@ -1,12 +1,12 @@
|
||||
- [ ] This change is worth documenting at https://docs.all-hands.dev/
|
||||
- [ ] Include this change in the Release Notes. If checked, you **must** provide an **end-user friendly** description for your change below
|
||||
|
||||
**End-user friendly description of the problem this fixes or functionality that this introduces.**
|
||||
**End-user friendly description of the problem this fixes or functionality this introduces.**
|
||||
|
||||
|
||||
---
|
||||
**Give a summary of what the PR does, explaining any non-trivial design decisions.**
|
||||
**Summarize what the PR does, explaining any non-trivial design decisions.**
|
||||
|
||||
|
||||
---
|
||||
**Link of any specific issues this addresses.**
|
||||
**Link of any specific issues this addresses:**
|
||||
|
||||
53
.github/workflows/dummy-agent-test.yml
vendored
53
.github/workflows/dummy-agent-test.yml
vendored
@@ -1,53 +0,0 @@
|
||||
# Workflow that uses the DummyAgent to run a simple task
|
||||
name: Run E2E test with dummy agent
|
||||
|
||||
# Always run on "main"
|
||||
# Always run on PRs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
# If triggered by a PR, it will be in the same group. However, each commit on main will be in its own unique group
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Install tmux
|
||||
run: sudo apt-get update && sudo apt-get install -y tmux
|
||||
- name: Setup Node.js
|
||||
uses: useblacksmith/setup-node@v5
|
||||
with:
|
||||
node-version: '22.x'
|
||||
- name: Install poetry via pipx
|
||||
run: pipx install poetry
|
||||
- name: Set up Python
|
||||
uses: useblacksmith/setup-python@v6
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'poetry'
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: poetry install --without evaluation
|
||||
- name: Build Environment
|
||||
run: make build
|
||||
- name: Run tests
|
||||
run: |
|
||||
set -e
|
||||
SANDBOX_FORCE_REBUILD_RUNTIME=True poetry run python3 openhands/core/main.py -t "do a flip" -d ./workspace/ -c DummyAgent
|
||||
- name: Check exit code
|
||||
run: |
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Test failed"
|
||||
exit 1
|
||||
else
|
||||
echo "Test passed"
|
||||
fi
|
||||
146
.github/workflows/ghcr-build.yml
vendored
146
.github/workflows/ghcr-build.yml
vendored
@@ -25,10 +25,31 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
BASE_IMAGE_FOR_HASH_EQUIVALENCE_TEST: nikolaik/python-nodejs:python3.12-nodejs22
|
||||
RELEVANT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
jobs:
|
||||
define-matrix:
|
||||
runs-on: blacksmith
|
||||
outputs:
|
||||
base_image: ${{ steps.define-base-images.outputs.base_image }}
|
||||
steps:
|
||||
- name: Define base images
|
||||
shell: bash
|
||||
id: define-base-images
|
||||
run: |
|
||||
# Only build nikolaik on PRs, otherwise build both nikolaik and ubuntu.
|
||||
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
|
||||
json=$(jq -n -c '[
|
||||
{ image: "nikolaik/python-nodejs:python3.12-nodejs22", tag: "nikolaik" }
|
||||
]')
|
||||
else
|
||||
json=$(jq -n -c '[
|
||||
{ image: "nikolaik/python-nodejs:python3.12-nodejs22", tag: "nikolaik" },
|
||||
{ image: "ubuntu:24.04", tag: "ubuntu" }
|
||||
]')
|
||||
fi
|
||||
echo "base_image=$json" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Builds the OpenHands Docker images
|
||||
ghcr_build_app:
|
||||
name: Build App Image
|
||||
@@ -37,6 +58,7 @@ jobs:
|
||||
contents: read
|
||||
packages: write
|
||||
outputs:
|
||||
# Since this job uses outputs it cannot use matrix
|
||||
hash_from_app_image: ${{ steps.get_hash_in_app_image.outputs.hash_from_app_image }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -84,11 +106,10 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
needs: define-matrix
|
||||
strategy:
|
||||
matrix:
|
||||
base_image:
|
||||
- image: 'nikolaik/python-nodejs:python3.12-nodejs22'
|
||||
tag: nikolaik
|
||||
base_image: ${{ fromJson(needs.define-matrix.outputs.base_image) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -118,35 +139,54 @@ jobs:
|
||||
~/.cache/pypoetry
|
||||
~/.virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
# This is the one that saves the cache, the others set 'lookup-only: true'
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
- name: Install poetry via pipx
|
||||
run: pipx install poetry
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: make install-python-dependencies
|
||||
run: make install-python-dependencies POETRY_GROUP=main INSTALL_PLAYWRIGHT=0
|
||||
- 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: Short SHA
|
||||
run: |
|
||||
echo SHORT_SHA=$(git rev-parse --short "$RELEVANT_SHA") >> $GITHUB_ENV
|
||||
- name: Determine docker build params
|
||||
if: github.event.pull_request.head.repo.fork != true
|
||||
shell: bash
|
||||
run: |
|
||||
./containers/build.sh -i runtime -o ${{ env.REPO_OWNER }} -t ${{ matrix.base_image.tag }} --dry
|
||||
|
||||
DOCKER_BUILD_JSON=$(jq -c . < docker-build-dry.json)
|
||||
echo "DOCKER_TAGS=$(echo "$DOCKER_BUILD_JSON" | jq -r '.tags | join(",")')" >> $GITHUB_ENV
|
||||
echo "DOCKER_PLATFORM=$(echo "$DOCKER_BUILD_JSON" | jq -r '.platform')" >> $GITHUB_ENV
|
||||
echo "DOCKER_BUILD_ARGS=$(echo "$DOCKER_BUILD_JSON" | jq -r '.build_args | join(",")')" >> $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 }}
|
||||
# Forked repos can't push to GHCR, so we need to upload the image as an artifact
|
||||
uses: useblacksmith/build-push-action@v1
|
||||
with:
|
||||
push: true
|
||||
tags: ${{ env.DOCKER_TAGS }}
|
||||
platforms: ${{ env.DOCKER_PLATFORM }}
|
||||
build-args: ${{ env.DOCKER_BUILD_ARGS }}
|
||||
context: containers/runtime
|
||||
provenance: false
|
||||
# Forked repos can't push to GHCR, so we just build in order to populate the cache for rebuilding
|
||||
- name: Build runtime image ${{ matrix.base_image.image }} for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
uses: docker/build-push-action@v6
|
||||
uses: useblacksmith/build-push-action@v1
|
||||
with:
|
||||
tags: ghcr.io/${{ env.REPO_OWNER }}/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
|
||||
- name: Upload runtime source for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: runtime-${{ matrix.base_image.tag }}
|
||||
path: /tmp/runtime-${{ matrix.base_image.tag }}.tar
|
||||
name: runtime-src-${{ matrix.base_image.tag }}
|
||||
path: containers/runtime
|
||||
|
||||
verify_hash_equivalence_in_runtime_and_app:
|
||||
name: Verify Hash Equivalence in Runtime and Docker images
|
||||
@@ -156,6 +196,8 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
base_image: ['nikolaik']
|
||||
env:
|
||||
BASE_IMAGE_FOR_HASH_EQUIVALENCE_TEST: nikolaik/python-nodejs:python3.12-nodejs22
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -167,6 +209,7 @@ jobs:
|
||||
~/.cache/pypoetry
|
||||
~/.virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
lookup-only: true
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
- name: Set up Python
|
||||
@@ -176,7 +219,7 @@ jobs:
|
||||
- name: Install poetry via pipx
|
||||
run: pipx install poetry
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: make install-python-dependencies
|
||||
run: make install-python-dependencies POETRY_GROUP=main INSTALL_PLAYWRIGHT=0
|
||||
- name: Get hash in App Image
|
||||
run: |
|
||||
echo "Hash from app image: ${{ needs.ghcr_build_app.outputs.hash_from_app_image }}"
|
||||
@@ -203,28 +246,34 @@ jobs:
|
||||
# Run unit tests with the Docker runtime Docker images as root
|
||||
test_runtime_root:
|
||||
name: RT Unit Tests (Root)
|
||||
needs: [ghcr_build_runtime]
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
||||
needs: [ghcr_build_runtime, define-matrix]
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2204
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
base_image: ['nikolaik']
|
||||
base_image: ${{ fromJson(needs.define-matrix.outputs.base_image) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
# Forked repos can't push to GHCR, so we need to download the image as an artifact
|
||||
- name: Download runtime image for fork
|
||||
- name: Download runtime source for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: runtime-${{ matrix.base_image }}
|
||||
path: /tmp
|
||||
- name: Load runtime image for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
name: runtime-src-${{ matrix.base_image.tag }}
|
||||
path: containers/runtime
|
||||
- name: Lowercase Repository Owner
|
||||
run: |
|
||||
docker load --input /tmp/runtime-${{ matrix.base_image }}.tar
|
||||
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
# Forked repos can't push to GHCR, so we need to rebuild using cache
|
||||
- name: Build runtime image ${{ matrix.base_image.image }} for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
uses: useblacksmith/build-push-action@v1
|
||||
with:
|
||||
load: true
|
||||
tags: ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
|
||||
context: containers/runtime
|
||||
- name: Cache Poetry dependencies
|
||||
uses: useblacksmith/cache@v5
|
||||
with:
|
||||
@@ -232,6 +281,7 @@ jobs:
|
||||
~/.cache/pypoetry
|
||||
~/.virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
lookup-only: true
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
- name: Set up Python
|
||||
@@ -241,10 +291,7 @@ jobs:
|
||||
- name: Install poetry via pipx
|
||||
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
|
||||
run: make install-python-dependencies POETRY_GROUP=main,test,runtime INSTALL_PLAYWRIGHT=0
|
||||
- name: Run docker runtime tests
|
||||
run: |
|
||||
# We install pytest-xdist in order to run tests across CPUs
|
||||
@@ -253,14 +300,17 @@ 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/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
|
||||
|
||||
# Setting RUN_AS_OPENHANDS to false means use root.
|
||||
# That should mean SANDBOX_USER_ID is ignored but some tests do not check for RUN_AS_OPENHANDS.
|
||||
|
||||
TEST_RUNTIME=docker \
|
||||
SANDBOX_USER_ID=$(id -u) \
|
||||
SANDBOX_RUNTIME_CONTAINER_IMAGE=$image_name \
|
||||
TEST_IN_CI=true \
|
||||
RUN_AS_OPENHANDS=false \
|
||||
poetry run pytest -n 3 -raRs --reruns 2 --reruns-delay 5 --cov=openhands --cov-report=xml -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py
|
||||
poetry run pytest -n 7 -raRs --reruns 2 --reruns-delay 5 --cov=openhands --cov-report=xml -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py --durations=10
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
env:
|
||||
@@ -269,27 +319,33 @@ jobs:
|
||||
# Run unit tests with the Docker runtime Docker images as openhands user
|
||||
test_runtime_oh:
|
||||
name: RT Unit Tests (openhands)
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
||||
needs: [ghcr_build_runtime]
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2204
|
||||
needs: [ghcr_build_runtime, define-matrix]
|
||||
strategy:
|
||||
matrix:
|
||||
base_image: ['nikolaik']
|
||||
base_image: ${{ fromJson(needs.define-matrix.outputs.base_image) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
# Forked repos can't push to GHCR, so we need to download the image as an artifact
|
||||
- name: Download runtime image for fork
|
||||
- name: Download runtime source for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: runtime-${{ matrix.base_image }}
|
||||
path: /tmp
|
||||
- name: Load runtime image for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
name: runtime-src-${{ matrix.base_image.tag }}
|
||||
path: containers/runtime
|
||||
- name: Lowercase Repository Owner
|
||||
run: |
|
||||
docker load --input /tmp/runtime-${{ matrix.base_image }}.tar
|
||||
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
# Forked repos can't push to GHCR, so we need to rebuild using cache
|
||||
- name: Build runtime image ${{ matrix.base_image.image }} for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
uses: useblacksmith/build-push-action@v1
|
||||
with:
|
||||
load: true
|
||||
tags: ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
|
||||
context: containers/runtime
|
||||
- name: Cache Poetry dependencies
|
||||
uses: useblacksmith/cache@v5
|
||||
with:
|
||||
@@ -297,6 +353,7 @@ jobs:
|
||||
~/.cache/pypoetry
|
||||
~/.virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
lookup-only: true
|
||||
restore-keys: |
|
||||
${{ runner.os }}-poetry-
|
||||
- name: Set up Python
|
||||
@@ -306,10 +363,7 @@ jobs:
|
||||
- name: Install poetry via pipx
|
||||
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
|
||||
run: make install-python-dependencies POETRY_GROUP=main,test,runtime INSTALL_PLAYWRIGHT=0
|
||||
- name: Run runtime tests
|
||||
run: |
|
||||
# We install pytest-xdist in order to run tests across CPUs
|
||||
@@ -318,14 +372,14 @@ 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/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
|
||||
|
||||
TEST_RUNTIME=docker \
|
||||
SANDBOX_USER_ID=$(id -u) \
|
||||
SANDBOX_RUNTIME_CONTAINER_IMAGE=$image_name \
|
||||
TEST_IN_CI=true \
|
||||
RUN_AS_OPENHANDS=true \
|
||||
poetry run pytest -n 3 -raRs --reruns 2 --reruns-delay 5 --cov=openhands --cov-report=xml -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py
|
||||
poetry run pytest -n 7 -raRs --reruns 2 --reruns-delay 5 --cov=openhands --cov-report=xml -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py --durations=10
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
env:
|
||||
|
||||
13
.github/workflows/openhands-resolver.yml
vendored
13
.github/workflows/openhands-resolver.yml
vendored
@@ -16,10 +16,15 @@ on:
|
||||
type: string
|
||||
default: "main"
|
||||
description: "Target branch to pull and create PR against"
|
||||
pr_type:
|
||||
required: false
|
||||
type: string
|
||||
default: "draft"
|
||||
description: "The PR type that is going to be created (draft, ready)"
|
||||
LLM_MODEL:
|
||||
required: false
|
||||
type: string
|
||||
default: "anthropic/claude-3-5-sonnet-20241022"
|
||||
default: "anthropic/claude-3-7-sonnet-20250219"
|
||||
LLM_API_VERSION:
|
||||
required: false
|
||||
type: string
|
||||
@@ -174,7 +179,7 @@ jobs:
|
||||
|
||||
echo "MAX_ITERATIONS=${{ inputs.max_iterations || 50 }}" >> $GITHUB_ENV
|
||||
echo "SANDBOX_ENV_GITHUB_TOKEN=${{ secrets.PAT_TOKEN || github.token }}" >> $GITHUB_ENV
|
||||
echo "SANDBOX_ENV_BASE_CONTAINER_IMAGE=${{ inputs.base_container_image }}" >> $GITHUB_ENV
|
||||
echo "SANDBOX_BASE_CONTAINER_IMAGE=${{ inputs.base_container_image }}" >> $GITHUB_ENV
|
||||
|
||||
# Set branch variables
|
||||
echo "TARGET_BRANCH=${{ inputs.target_branch || 'main' }}" >> $GITHUB_ENV
|
||||
@@ -280,9 +285,9 @@ jobs:
|
||||
cd /tmp && python -m openhands.resolver.send_pull_request \
|
||||
--issue-number ${{ env.ISSUE_NUMBER }} \
|
||||
--target-branch ${{ env.TARGET_BRANCH }} \
|
||||
--pr-type draft \
|
||||
--pr-type ${{ inputs.pr_type || 'draft' }} \
|
||||
--reviewer ${{ github.actor }} | tee pr_result.txt && \
|
||||
grep "draft created" pr_result.txt | sed 's/.*\///g' > pr_number.txt
|
||||
grep "PR created" pr_result.txt | sed 's/.*\///g' > pr_number.txt
|
||||
else
|
||||
cd /tmp && python -m openhands.resolver.send_pull_request \
|
||||
--issue-number ${{ env.ISSUE_NUMBER }} \
|
||||
|
||||
@@ -54,3 +54,20 @@ Frontend:
|
||||
## Template for Github Pull Request
|
||||
|
||||
If you are starting a pull request (PR), please follow the template in `.github/pull_request_template.md`.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
These details may or may not be useful for your current task.
|
||||
|
||||
### Frontend
|
||||
|
||||
#### Action Handling:
|
||||
- Actions are defined in `frontend/src/types/action-type.ts`
|
||||
- The `HANDLED_ACTIONS` array in `frontend/src/state/chat-slice.ts` determines which actions are displayed as collapsible UI elements
|
||||
- To add a new action type to the UI:
|
||||
1. Add the action type to the `HANDLED_ACTIONS` array
|
||||
2. Implement the action handling in `addAssistantAction` function in chat-slice.ts
|
||||
3. Add a translation key in the format `ACTION_MESSAGE$ACTION_NAME` to the i18n files
|
||||
- Actions with `thought` property are displayed in the UI based on their action type:
|
||||
- Regular actions (like "run", "edit") display the thought as a separate message
|
||||
- Special actions (like "think") are displayed as collapsible elements only
|
||||
|
||||
@@ -118,7 +118,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.31-nikolaik`
|
||||
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.36-nikolaik`
|
||||
|
||||
## Develop inside Docker container
|
||||
|
||||
|
||||
48
Makefile
48
Makefile
@@ -39,6 +39,7 @@ ifeq ($(INSTALL_DOCKER),)
|
||||
@$(MAKE) -s check-docker
|
||||
endif
|
||||
@$(MAKE) -s check-poetry
|
||||
@$(MAKE) -s check-tmux
|
||||
@echo "$(GREEN)Dependencies checked successfully.$(RESET)"
|
||||
|
||||
check-system:
|
||||
@@ -101,6 +102,18 @@ check-docker:
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
check-tmux:
|
||||
@echo "$(YELLOW)Checking tmux installation...$(RESET)"
|
||||
@if command -v tmux > /dev/null; then \
|
||||
echo "$(BLUE)$(shell tmux -V) is already installed.$(RESET)"; \
|
||||
else \
|
||||
echo "$(YELLOW)╔════════════════════════════════════════════════════════════════════════════╗$(RESET)"; \
|
||||
echo "$(YELLOW)║ OPTIONAL: tmux is not installed. ║$(RESET)"; \
|
||||
echo "$(YELLOW)║ Some advanced terminal features may not work without tmux. ║$(RESET)"; \
|
||||
echo "$(YELLOW)║ You can install it if needed, but it's not required for development. ║$(RESET)"; \
|
||||
echo "$(YELLOW)╚════════════════════════════════════════════════════════════════════════════╝$(RESET)"; \
|
||||
fi
|
||||
|
||||
check-poetry:
|
||||
@echo "$(YELLOW)Checking Poetry installation...$(RESET)"
|
||||
@if command -v poetry > /dev/null; then \
|
||||
@@ -133,20 +146,29 @@ install-python-dependencies:
|
||||
export HNSWLIB_NO_NATIVE=1; \
|
||||
poetry run pip install chroma-hnswlib; \
|
||||
fi
|
||||
@poetry install
|
||||
@if [ -f "/etc/manjaro-release" ]; then \
|
||||
echo "$(BLUE)Detected Manjaro Linux. Installing Playwright dependencies...$(RESET)"; \
|
||||
poetry run pip install playwright; \
|
||||
poetry run playwright install chromium; \
|
||||
@if [ -n "${POETRY_GROUP}" ]; then \
|
||||
echo "Installing only POETRY_GROUP=${POETRY_GROUP}"; \
|
||||
poetry install --only $${POETRY_GROUP}; \
|
||||
else \
|
||||
if [ ! -f cache/playwright_chromium_is_installed.txt ]; then \
|
||||
echo "Running playwright install --with-deps chromium..."; \
|
||||
poetry run playwright install --with-deps chromium; \
|
||||
mkdir -p cache; \
|
||||
touch cache/playwright_chromium_is_installed.txt; \
|
||||
poetry install; \
|
||||
fi
|
||||
@if [ "${INSTALL_PLAYWRIGHT}" != "false" ] && [ "${INSTALL_PLAYWRIGHT}" != "0" ]; then \
|
||||
if [ -f "/etc/manjaro-release" ]; then \
|
||||
echo "$(BLUE)Detected Manjaro Linux. Installing Playwright dependencies...$(RESET)"; \
|
||||
poetry run pip install playwright; \
|
||||
poetry run playwright install chromium; \
|
||||
else \
|
||||
echo "Setup already done. Skipping playwright installation."; \
|
||||
if [ ! -f cache/playwright_chromium_is_installed.txt ]; then \
|
||||
echo "Running playwright install --with-deps chromium..."; \
|
||||
poetry run playwright install --with-deps chromium; \
|
||||
mkdir -p cache; \
|
||||
touch cache/playwright_chromium_is_installed.txt; \
|
||||
else \
|
||||
echo "Setup already done. Skipping playwright installation."; \
|
||||
fi \
|
||||
fi \
|
||||
else \
|
||||
echo "Skipping Playwright installation (INSTALL_PLAYWRIGHT=${INSTALL_PLAYWRIGHT})."; \
|
||||
fi
|
||||
@echo "$(GREEN)Python dependencies installed successfully.$(RESET)"
|
||||
|
||||
@@ -166,7 +188,7 @@ install-pre-commit-hooks:
|
||||
|
||||
lint-backend:
|
||||
@echo "$(YELLOW)Running linters...$(RESET)"
|
||||
@poetry run pre-commit run --files openhands/**/* agenthub/**/* evaluation/**/* --show-diff-on-failure --config $(PRE_COMMIT_CONFIG_PATH)
|
||||
@poetry run pre-commit run --files openhands/**/* evaluation/**/* tests/**/* --show-diff-on-failure --config $(PRE_COMMIT_CONFIG_PATH)
|
||||
|
||||
lint-frontend:
|
||||
@echo "$(YELLOW)Running linters for frontend...$(RESET)"
|
||||
@@ -185,7 +207,7 @@ test:
|
||||
|
||||
build-frontend:
|
||||
@echo "$(YELLOW)Building frontend...$(RESET)"
|
||||
@cd frontend && npm run build
|
||||
@cd frontend && npm run prepare && npm run build
|
||||
|
||||
# Start backend
|
||||
start-backend:
|
||||
|
||||
50
README.md
50
README.md
@@ -9,7 +9,6 @@
|
||||
<div align="center">
|
||||
<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>
|
||||
<a href="https://codecov.io/github/All-Hands-AI/OpenHands?branch=main"><img alt="CodeCov" src="https://img.shields.io/codecov/c/github/All-Hands-AI/OpenHands?style=for-the-badge&color=blue"></a>
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE"><img src="https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="MIT License"></a>
|
||||
<br/>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community"></a>
|
||||
@@ -18,7 +17,7 @@
|
||||
<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>
|
||||
<a href="https://docs.google.com/spreadsheets/d/1wOUdFCMyY6Nt0AIqF705KN4JKOWgeI4wUGUP60krXXs/edit?gid=0#gid=0"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score"></a>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +26,7 @@ Welcome to OpenHands (formerly OpenDevin), a platform for software development a
|
||||
OpenHands agents can do anything a human developer can: modify code, run commands, browse the web,
|
||||
call APIs, and yes—even copy code snippets from StackOverflow.
|
||||
|
||||
Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or jump to the [Quick Start](#-quick-start).
|
||||
Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or [sign up for OpenHands Cloud](https://app.all-hands.dev) to get started.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Using OpenHands for work? We'd love to chat! Fill out
|
||||
@@ -36,37 +35,50 @@ Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or jump to the [
|
||||
|
||||

|
||||
|
||||
## ⚡ Quick Start
|
||||
## ☁️ OpenHands Cloud
|
||||
The easiest way to get started with OpenHands is on [OpenHands Cloud](https://app.all-hands.dev),
|
||||
which comes with $50 in free credits for new users.
|
||||
|
||||
The easiest way to run OpenHands is in Docker.
|
||||
## 💻 Running OpenHands Locally
|
||||
|
||||
OpenHands can also run on your local system using Docker.
|
||||
See the [Running OpenHands](https://docs.all-hands.dev/modules/usage/installation) guide for
|
||||
system requirements and more information.
|
||||
|
||||
> [!WARNING]
|
||||
> On a public network? See our [Hardened Docker Installation Guide](https://docs.all-hands.dev/modules/usage/runtimes/docker#hardened-docker-installation)
|
||||
> to secure your deployment by restricting network binding and implementing additional security measures.
|
||||
|
||||
|
||||
```bash
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> On a public network? See our [Hardened Docker Installation](https://docs.all-hands.dev/modules/usage/runtimes/docker#hardened-docker-installation) guide
|
||||
> to secure your deployment by restricting network binding and implementing additional security measures.
|
||||
|
||||
You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)!
|
||||
|
||||
Finally, you'll need a model provider and API key.
|
||||
[Anthropic's Claude 3.5 Sonnet](https://www.anthropic.com/api) (`anthropic/claude-3-5-sonnet-20241022`)
|
||||
When you open the application, you'll be asked to choose an LLM provider and add an API key.
|
||||
[Anthropic's Claude 3.7 Sonnet](https://www.anthropic.com/api) (`anthropic/claude-3-7-sonnet-20250219`)
|
||||
works best, but you have [many options](https://docs.all-hands.dev/modules/usage/llms).
|
||||
|
||||
---
|
||||
## 💡 Other ways to run OpenHands
|
||||
|
||||
> [!CAUTION]
|
||||
> OpenHands is meant to be run by a single user on their local workstation.
|
||||
> It is not appropriate for multi-tenant deployments where multiple users share the same instance. There is no built-in authentication, isolation, or scalability.
|
||||
>
|
||||
> If you're interested in running OpenHands in a multi-tenant environment, please
|
||||
> [get in touch with us](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
|
||||
> for advanced deployment options.
|
||||
|
||||
You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem),
|
||||
run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/modules/usage/how-to/headless-mode),
|
||||
@@ -75,14 +87,6 @@ or run it on tagged issues with [a github action](https://docs.all-hands.dev/mod
|
||||
|
||||
Visit [Running OpenHands](https://docs.all-hands.dev/modules/usage/installation) for more information and setup instructions.
|
||||
|
||||
> [!CAUTION]
|
||||
> OpenHands is meant to be run by a single user on their local workstation.
|
||||
> It is not appropriate for multi-tenant deployments where multiple users share the same instance. There is no built-in isolation or scalability.
|
||||
>
|
||||
> If you're interested in running OpenHands in a multi-tenant environment, please
|
||||
> [get in touch with us](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
|
||||
> for advanced deployment options.
|
||||
|
||||
If you want to modify the OpenHands source code, check out [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
|
||||
|
||||
Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting) can help.
|
||||
|
||||
@@ -216,13 +216,26 @@ model = "gpt-4o"
|
||||
[agent]
|
||||
|
||||
# Whether the browsing tool is enabled
|
||||
codeact_enable_browsing = true
|
||||
enable_browsing = true
|
||||
|
||||
# Whether the LLM draft editor is enabled
|
||||
codeact_enable_llm_editor = false
|
||||
enable_llm_editor = false
|
||||
|
||||
# Whether the standard editor tool (str_replace_editor) is enabled
|
||||
# Only has an effect if enable_llm_editor is False
|
||||
enable_editor = true
|
||||
|
||||
# Whether the IPython tool is enabled
|
||||
codeact_enable_jupyter = true
|
||||
enable_jupyter = true
|
||||
|
||||
# Whether the command tool is enabled
|
||||
enable_cmd = true
|
||||
|
||||
# Whether the think tool is enabled
|
||||
enable_think = true
|
||||
|
||||
# Whether the finish tool is enabled
|
||||
enable_finish = true
|
||||
|
||||
# LLM config group to use
|
||||
#llm_config = 'your-llm-config-group'
|
||||
@@ -378,7 +391,7 @@ type = "noop"
|
||||
#[llm.condenser]
|
||||
#model = "gpt-4o"
|
||||
#temperature = 0.1
|
||||
#max_tokens = 1024
|
||||
#max_input_tokens = 1024
|
||||
|
||||
#################################### Eval ####################################
|
||||
# Configuration for the evaluation, please refer to the specific evaluation
|
||||
|
||||
@@ -7,15 +7,17 @@ org_name=""
|
||||
push=0
|
||||
load=0
|
||||
tag_suffix=""
|
||||
dry_run=0
|
||||
|
||||
# Function to display usage information
|
||||
usage() {
|
||||
echo "Usage: $0 -i <image_name> [-o <org_name>] [--push] [--load] [-t <tag_suffix>]"
|
||||
echo "Usage: $0 -i <image_name> [-o <org_name>] [--push] [--load] [-t <tag_suffix>] [--dry]"
|
||||
echo " -i: Image name (required)"
|
||||
echo " -o: Organization name"
|
||||
echo " --push: Push the image"
|
||||
echo " --load: Load the image"
|
||||
echo " -t: Tag suffix"
|
||||
echo " --dry: Don't build, only create build-args.json"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -27,6 +29,7 @@ while [[ $# -gt 0 ]]; do
|
||||
--push) push=1; shift ;;
|
||||
--load) load=1; shift ;;
|
||||
-t) tag_suffix="$2"; shift 2 ;;
|
||||
--dry) dry_run=1; shift ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
@@ -113,10 +116,13 @@ echo "Repo: $DOCKER_REPOSITORY"
|
||||
echo "Base dir: $DOCKER_BASE_DIR"
|
||||
|
||||
args=""
|
||||
full_tags=()
|
||||
for tag in "${tags[@]}"; do
|
||||
args+=" -t $DOCKER_REPOSITORY:$tag"
|
||||
full_tags+=("$DOCKER_REPOSITORY:$tag")
|
||||
done
|
||||
|
||||
|
||||
if [[ $push -eq 1 ]]; then
|
||||
args+=" --push"
|
||||
args+=" --cache-to=type=registry,ref=$DOCKER_REPOSITORY:$cache_tag,mode=max"
|
||||
@@ -136,6 +142,26 @@ else
|
||||
# For push or without load, build for multiple platforms
|
||||
platform="linux/amd64,linux/arm64"
|
||||
fi
|
||||
if [[ $dry_run -eq 1 ]]; then
|
||||
echo "Dry Run is enabled. Writing build config to docker-build-dry.json"
|
||||
jq -n \
|
||||
--argjson tags "$(printf '%s\n' "${full_tags[@]}" | jq -R . | jq -s .)" \
|
||||
--arg platform "$platform" \
|
||||
--arg openhands_build_version "$OPENHANDS_BUILD_VERSION" \
|
||||
--arg dockerfile "$dir/Dockerfile" \
|
||||
'{
|
||||
tags: $tags,
|
||||
platform: $platform,
|
||||
build_args: [
|
||||
"OPENHANDS_BUILD_VERSION=" + $openhands_build_version
|
||||
],
|
||||
dockerfile: $dockerfile
|
||||
}' > docker-build-dry.json
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "Building for platform(s): $platform"
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ RUN add-apt-repository ppa:deadsnakes/ppa \
|
||||
&& apt-get install -y python3.12 python3.12-venv python3.12-dev python3-pip \
|
||||
&& ln -s /usr/bin/python3.12 /usr/bin/python
|
||||
|
||||
# NodeJS >= 18.17.1
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
|
||||
# NodeJS >= 22.x
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||
&& apt-get install -y nodejs
|
||||
|
||||
# Poetry >= 1.8
|
||||
@@ -108,7 +108,7 @@ WORKDIR /app
|
||||
|
||||
# cache build dependencies
|
||||
RUN \
|
||||
--mount=type=bind,source=./,target=/app/ \
|
||||
--mount=type=bind,source=./,target=/app/,rw \
|
||||
<<EOF
|
||||
#!/bin/bash
|
||||
make -s clean
|
||||
|
||||
@@ -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.31-nikolaik}
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.36-nikolaik}
|
||||
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
|
||||
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
|
||||
ports:
|
||||
|
||||
@@ -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.31-nikolaik}
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.all-hands.dev/all-hands-ai/runtime:0.36-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:
|
||||
|
||||
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
|
||||
# Production
|
||||
/build
|
||||
/static/swagger-ui
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
|
||||
@@ -32,6 +32,8 @@ For instructions or processes that need to be followed in a specific order, use
|
||||
|
||||
Example:
|
||||
1. Step one: Do this.
|
||||
- First this sub step.
|
||||
- Then this sub step.
|
||||
2. Step two: Complete this action.
|
||||
3. Step three: Verify the result.
|
||||
|
||||
@@ -47,6 +49,14 @@ docker run -it \
|
||||
...
|
||||
```
|
||||
|
||||
### Use of Note and Warning
|
||||
|
||||
When adding a note or warning, use the built-in note and warning syntax.
|
||||
|
||||
Example:
|
||||
:::note
|
||||
This section is for advanced users only.
|
||||
:::
|
||||
|
||||
### Referring to UI Elements
|
||||
|
||||
|
||||
@@ -36,6 +36,14 @@ const config: Config = {
|
||||
mermaid: true,
|
||||
},
|
||||
themes: ['@docusaurus/theme-mermaid'],
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('docusaurus-lunr-search'),
|
||||
{
|
||||
languages: ['en', 'zh', 'fr', 'ja', 'pt']
|
||||
}
|
||||
]
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
@@ -75,10 +83,19 @@ const config: Config = {
|
||||
position: 'left',
|
||||
label: 'User Guides',
|
||||
},
|
||||
{
|
||||
href: 'https://docs.all-hands.dev/swagger-ui/', // FIXME: this should be a relative path, but docusarus steals the click
|
||||
label: 'API',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
type: 'localeDropdown',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
type: 'search',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
href: 'https://all-hands.dev',
|
||||
label: 'Company',
|
||||
|
||||
102
docs/generate-swagger-ui.js
Normal file
102
docs/generate-swagger-ui.js
Normal file
@@ -0,0 +1,102 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const swaggerUiDist = require('swagger-ui-dist');
|
||||
|
||||
/**
|
||||
* This script manually sets up Swagger UI for the Docusaurus documentation.
|
||||
*
|
||||
* Why we need this approach:
|
||||
* 1. Docusaurus doesn't have a built-in way to integrate Swagger UI
|
||||
* 2. We need to copy the necessary files from swagger-ui-dist to our static directory
|
||||
* 3. We need to create a custom index.html file that points to our OpenAPI spec
|
||||
* 4. This approach allows us to customize the Swagger UI to match our documentation style
|
||||
*/
|
||||
|
||||
// Get the absolute path to the swagger-ui-dist package
|
||||
const swaggerUiDistPath = swaggerUiDist.getAbsoluteFSPath();
|
||||
|
||||
// Create the target directory if it doesn't exist
|
||||
const targetDir = path.join(__dirname, 'static', 'swagger-ui');
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy all files from swagger-ui-dist to our target directory
|
||||
const files = fs.readdirSync(swaggerUiDistPath);
|
||||
files.forEach(file => {
|
||||
const sourcePath = path.join(swaggerUiDistPath, file);
|
||||
const targetPath = path.join(targetDir, file);
|
||||
|
||||
// Skip directories and non-essential files
|
||||
if (fs.statSync(sourcePath).isDirectory() ||
|
||||
file === 'package.json' ||
|
||||
file === 'README.md' ||
|
||||
file.endsWith('.map')) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
});
|
||||
|
||||
// Create a custom index.html file that points to our OpenAPI spec
|
||||
const indexHtml = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>OpenHands API Documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "/openapi.json",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
});
|
||||
// End Swagger UI call region
|
||||
window.ui = ui;
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
fs.writeFileSync(path.join(targetDir, 'index.html'), indexHtml);
|
||||
|
||||
console.log('Swagger UI files generated successfully in static/swagger-ui/');
|
||||
@@ -354,12 +354,12 @@ Les options de configuration de l'agent sont définies dans les sections `[agent
|
||||
- Valeur par défaut : `true`
|
||||
- Description : Si l'appel de fonction est activé
|
||||
|
||||
- `codeact_enable_browsing`
|
||||
- `enable_browsing`
|
||||
- Type : `bool`
|
||||
- Valeur par défaut : `false`
|
||||
- Description : Si le délégué de navigation est activé dans l'espace d'action (fonctionne uniquement avec l'appel de fonction)
|
||||
|
||||
- `codeact_enable_llm_editor`
|
||||
- `enable_llm_editor`
|
||||
- Type : `bool`
|
||||
- Valeur par défaut : `false`
|
||||
- Description : Si l'éditeur LLM est activé dans l'espace d'action (fonctionne uniquement avec l'appel de fonction)
|
||||
|
||||
@@ -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.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
|
||||
@@ -21,14 +21,18 @@ OpenHands fournit un mode Interface Graphique (GUI) convivial pour interagir ave
|
||||
3. Entrez la `Clé API` correspondante pour le fournisseur choisi.
|
||||
4. Cliquez sur "Enregistrer" pour appliquer les paramètres.
|
||||
|
||||
### Configuration du Jeton GitHub
|
||||
### Jetons de Contrôle de Version
|
||||
|
||||
OpenHands prend en charge plusieurs fournisseurs de contrôle de version. Vous pouvez configurer des jetons pour plusieurs fournisseurs simultanément.
|
||||
|
||||
#### Configuration du Jeton GitHub
|
||||
|
||||
OpenHands exporte automatiquement un `GITHUB_TOKEN` vers l'environnement shell s'il est disponible. Cela peut se produire de deux manières :
|
||||
|
||||
1. **Localement (OSS)** : L'utilisateur saisit directement son jeton GitHub
|
||||
2. **En ligne (SaaS)** : Le jeton est obtenu via l'authentification OAuth GitHub
|
||||
|
||||
#### Configuration d'un Jeton GitHub Local
|
||||
##### Configuration d'un Jeton GitHub Local
|
||||
|
||||
1. **Générer un Personal Access Token (PAT)** :
|
||||
- Allez dans Paramètres GitHub > Paramètres développeur > Personal Access Tokens > Tokens (classique)
|
||||
@@ -40,11 +44,11 @@ OpenHands exporte automatiquement un `GITHUB_TOKEN` vers l'environnement shell s
|
||||
|
||||
2. **Entrer le Jeton dans OpenHands** :
|
||||
- Cliquez sur le bouton Paramètres (icône d'engrenage) en haut à droite
|
||||
- Accédez à la section "GitHub"
|
||||
- Accédez à la section "Git Provider Settings"
|
||||
- Collez votre jeton dans le champ "Jeton GitHub"
|
||||
- Cliquez sur "Enregistrer" pour appliquer les modifications
|
||||
|
||||
#### Politiques de Jetons Organisationnels
|
||||
##### Politiques de Jetons Organisationnels
|
||||
|
||||
Si vous travaillez avec des dépôts organisationnels, une configuration supplémentaire peut être nécessaire :
|
||||
|
||||
@@ -59,7 +63,7 @@ Si vous travaillez avec des dépôts organisationnels, une configuration supplé
|
||||
- Si nécessaire, cliquez sur "Activer SSO" à côté de votre organisation
|
||||
- Terminez le processus d'autorisation SSO
|
||||
|
||||
#### Authentification OAuth (Mode En Ligne)
|
||||
##### Authentification OAuth (Mode En Ligne)
|
||||
|
||||
Lorsque vous utilisez OpenHands en mode en ligne, le flux OAuth GitHub :
|
||||
|
||||
@@ -74,7 +78,7 @@ Lorsque vous utilisez OpenHands en mode en ligne, le flux OAuth GitHub :
|
||||
- Autorisez OpenHands à accéder à votre compte GitHub
|
||||
- Si vous utilisez une organisation, autorisez l'accès à l'organisation si vous y êtes invité
|
||||
|
||||
#### Dépannage
|
||||
##### Dépannage
|
||||
|
||||
Problèmes courants et solutions :
|
||||
|
||||
@@ -95,6 +99,43 @@ Problèmes courants et solutions :
|
||||
- Vérifiez la console du navigateur pour tout message d'erreur
|
||||
- Utilisez le bouton "Tester la connexion" dans les paramètres s'il est disponible
|
||||
|
||||
#### Configuration du Jeton GitLab
|
||||
|
||||
OpenHands exporte automatiquement un `GITLAB_TOKEN` vers l'environnement shell, uniquement pour les installations locales, s'il est disponible.
|
||||
|
||||
##### Configuration d'un Jeton GitLab
|
||||
|
||||
1. **Générer un Personal Access Token (PAT)** :
|
||||
- Sur GitLab, allez dans Paramètres utilisateur > Jetons d'accès
|
||||
- Créez un nouveau jeton avec les portées suivantes :
|
||||
- `api` (Accès API)
|
||||
- `read_user` (Lecture des informations utilisateur)
|
||||
- `read_repository` (Lecture du dépôt)
|
||||
- `write_repository` (Écriture du dépôt)
|
||||
- Définissez une date d'expiration ou laissez vide pour un jeton sans expiration
|
||||
|
||||
2. **Entrer le Jeton dans OpenHands** :
|
||||
- Cliquez sur le bouton Paramètres (icône d'engrenage)
|
||||
- Accédez à la section `Git Provider Settings`
|
||||
- Collez votre jeton dans le champ `Jeton GitLab`
|
||||
- Si vous utilisez GitLab auto-hébergé, entrez l'URL de votre instance GitLab
|
||||
- Cliquez sur `Enregistrer les modifications` pour appliquer les changements
|
||||
|
||||
##### Dépannage
|
||||
|
||||
Problèmes courants et solutions :
|
||||
|
||||
1. **Jeton Non Reconnu** :
|
||||
- Assurez-vous que le jeton est correctement enregistré dans les paramètres
|
||||
- Vérifiez que le jeton n'a pas expiré
|
||||
- Vérifiez que le jeton a les portées requises
|
||||
- Pour les instances auto-hébergées, vérifiez l'URL correcte de l'instance
|
||||
|
||||
2. **Accès Refusé** :
|
||||
- Vérifiez les permissions d'accès au projet
|
||||
- Vérifiez si le jeton possède les portées nécessaires
|
||||
- Pour les dépôts de groupe/organisation, assurez-vous d'avoir les accès appropriés
|
||||
|
||||
### Paramètres Avancés
|
||||
|
||||
1. Basculez sur `Options Avancées` pour accéder aux paramètres supplémentaires.
|
||||
|
||||
@@ -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.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
|
||||
```
|
||||
|
||||
@@ -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.31-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36
|
||||
```
|
||||
|
||||
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).
|
||||
|
||||
@@ -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.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
# ...
|
||||
```
|
||||
|
||||
@@ -348,12 +348,12 @@ dockerコマンドで使用する場合は、`-e LLM_<option>`として渡しま
|
||||
- デフォルト値: `true`
|
||||
- 説明: 関数呼び出しが有効かどうか
|
||||
|
||||
- `codeact_enable_browsing`
|
||||
- `enable_browsing`
|
||||
- 型: `bool`
|
||||
- デフォルト値: `false`
|
||||
- 説明: アクションスペースでブラウジングデリゲートが有効かどうか(関数呼び出しでのみ機能)
|
||||
|
||||
- `codeact_enable_llm_editor`
|
||||
- `enable_llm_editor`
|
||||
- 型: `bool`
|
||||
- デフォルト値: `false`
|
||||
- 説明: アクションスペースでLLMエディタが有効かどうか(関数呼び出しでのみ機能)
|
||||
|
||||
@@ -34,7 +34,7 @@ Docker で OpenHands を CLI モードで実行するには:
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -44,7 +44,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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
|
||||
@@ -16,7 +16,11 @@ OpenHandsは、AI アシスタントとやり取りするためのグラフィ
|
||||
3. 選択したプロバイダーに対応する`API Key`を入力します。
|
||||
4. `Save Changes`をクリックして設定を適用します。
|
||||
|
||||
### GitHubトークンの設定
|
||||
### バージョン管理トークン
|
||||
|
||||
OpenHandsは複数のバージョン管理プロバイダーをサポートしています。複数のプロバイダーのトークンを同時に設定できます。
|
||||
|
||||
#### GitHubトークンの設定
|
||||
|
||||
OpenHandsは、利用可能な場合、自動的に`GITHUB_TOKEN`をシェル環境にエクスポートします。これは2つの方法で行われます。
|
||||
|
||||
@@ -34,7 +38,7 @@ OpenHandsは、利用可能な場合、自動的に`GITHUB_TOKEN`をシェル環
|
||||
- Minimal Permissions(検索用に**Meta Data = Read-only**を選択し、ブランチ作成用に**Pull Requests = Read and Write**、**Content = Read and Write**を選択します)
|
||||
2. **OpenHandsにトークンを入力**:
|
||||
- 設定ボタン(歯車アイコン)をクリックします。
|
||||
- `GitHub Settings`セクションに移動します。
|
||||
- `Git Provider Settings`セクションに移動します。
|
||||
- `GitHub Token`フィールドにトークンを貼り付けます。
|
||||
- `Save Changes`をクリックして変更を適用します。
|
||||
</details>
|
||||
@@ -94,6 +98,46 @@ OpenHandsは、利用可能な場合、自動的に`GITHUB_TOKEN`をシェル環
|
||||
- 組織を使用している場合は、プロンプトが表示されたら組織へのアクセスを承認します。
|
||||
</details>
|
||||
|
||||
#### GitLabトークンの設定
|
||||
|
||||
OpenHandsは、利用可能な場合、ローカルインストールのみ、自動的に`GITLAB_TOKEN`をシェル環境にエクスポートします。
|
||||
|
||||
<details>
|
||||
<summary>GitLabトークンの設定</summary>
|
||||
|
||||
1. **Personal Access Token(PAT)の生成**:
|
||||
- GitLabで、User Settings > Access Tokensに移動します。
|
||||
- 以下のスコープを持つ新しいトークンを作成します:
|
||||
- `api`(APIアクセス)
|
||||
- `read_user`(ユーザー情報の読み取り)
|
||||
- `read_repository`(リポジトリ読み取り)
|
||||
- `write_repository`(リポジトリ書き込み)
|
||||
- 有効期限を設定するか、無期限トークンの場合は空白のままにします。
|
||||
2. **OpenHandsにトークンを入力**:
|
||||
- 設定ボタン(歯車アイコン)をクリックします。
|
||||
- `Git Provider Settings`セクションに移動します。
|
||||
- `GitLab Token`フィールドにトークンを貼り付けます。
|
||||
- セルフホスト型GitLabを使用している場合は、GitLabインスタンスのURLを入力します。
|
||||
- `Save Changes`をクリックして変更を適用します。
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>トラブルシューティング</summary>
|
||||
|
||||
一般的な問題と解決策:
|
||||
|
||||
- **トークンが認識されない**:
|
||||
- トークンが設定に正しく保存されていることを確認します。
|
||||
- トークンの有効期限が切れていないことを確認します。
|
||||
- トークンに必要なスコープがあることを確認します。
|
||||
- セルフホスト型インスタンスの場合は、正しいインスタンスURLを確認します。
|
||||
|
||||
- **アクセスが拒否された**:
|
||||
- プロジェクトのアクセス権限を確認します。
|
||||
- トークンに必要なスコープがあるかどうかを確認します。
|
||||
- グループ/組織のリポジトリの場合は、適切なアクセス権があることを確認します。
|
||||
</details>
|
||||
|
||||
### 高度な設定
|
||||
|
||||
1. 設定ページ内で、`Advanced`オプションを切り替えて追加の設定にアクセスします。
|
||||
|
||||
@@ -31,7 +31,7 @@ DockerでOpenHandsをヘッドレスモードで実行するには:
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -42,7 +42,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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.main -t "write a bash script that prints hi"
|
||||
```
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ OpenHandsがリポジトリで動作する際:
|
||||
|
||||
1. リポジトリに`.openhands/microagents/`が存在する場合、そこからリポジトリ固有の指示を読み込みます。
|
||||
2. 会話のキーワードによってトリガーされる一般的なガイドラインを読み込みます。
|
||||
現在の[パブリックMicroagents](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)を参照してください。
|
||||
現在の[パブリックMicroagents](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)を参照してください。
|
||||
|
||||
## Microagentのフォーマット
|
||||
|
||||
@@ -21,8 +21,8 @@ OpenHandsがリポジトリで動作する際:
|
||||
```
|
||||
---
|
||||
name: <Microagentの名前>
|
||||
type: <MicroAgentのタイプ>
|
||||
version: <MicroAgentのバージョン>
|
||||
type: <Microagentのタイプ>
|
||||
version: <Microagentのバージョン>
|
||||
agent: <エージェントのタイプ (通常はCodeActAgent)>
|
||||
triggers:
|
||||
- <オプション: microagentをトリガーするキーワード。トリガーを削除すると、常に含まれるようになります>
|
||||
|
||||
@@ -88,4 +88,4 @@ triggers:
|
||||
- ビルド時間とイメージサイズを最適化
|
||||
```
|
||||
|
||||
より多くの例については、[現在のパブリックマイクロエージェント](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)をご覧ください。
|
||||
より多くの例については、[現在のパブリックマイクロエージェント](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)をご覧ください。
|
||||
|
||||
@@ -25,7 +25,7 @@ nikolaik の `SANDBOX_RUNTIME_CONTAINER_IMAGE` は、ランタイムサーバー
|
||||
|
||||
```bash
|
||||
docker run # ...
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-v $WORKSPACE_BASE:/opt/workspace_base \
|
||||
@@ -82,5 +82,5 @@ docker network create openhands-network
|
||||
# 分離されたネットワークで OpenHands を実行
|
||||
docker run # ... \
|
||||
--network openhands-network \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.31
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36
|
||||
```
|
||||
|
||||
@@ -7,7 +7,7 @@ O GitHub Cloud Resolver automatiza correções de código e fornece assistência
|
||||
## Configuração
|
||||
|
||||
O Resolvedor do GitHub na Nuvem está disponível automaticamente quando você
|
||||
[concede acesso ao repositório do OpenHands Cloud](./openhands-cloud.md#adding-repository-access).
|
||||
[concede acesso ao repositório do OpenHands Cloud](./openhands-cloud#adding-repository-access).
|
||||
|
||||
## Uso
|
||||
|
||||
|
||||
@@ -292,17 +292,17 @@ As opções de configuração do agente são definidas nas seções `[agent]` e
|
||||
- Padrão: `true`
|
||||
- Descrição: Se a chamada de função está habilitada
|
||||
|
||||
- `codeact_enable_browsing`
|
||||
- `enable_browsing`
|
||||
- Tipo: `bool`
|
||||
- Padrão: `false`
|
||||
- Descrição: Se o delegado de navegação está habilitado no espaço de ação (funciona apenas com chamada de função)
|
||||
|
||||
- `codeact_enable_llm_editor`
|
||||
- `enable_llm_editor`
|
||||
- Tipo: `bool`
|
||||
- Padrão: `false`
|
||||
- Descrição: Se o editor LLM está habilitado no espaço de ação (funciona apenas com chamada de função)
|
||||
|
||||
- `codeact_enable_jupyter`
|
||||
- `enable_jupyter`
|
||||
- Tipo: `bool`
|
||||
- Padrão: `false`
|
||||
- Descrição: Se o Jupyter está habilitado no espaço de ação
|
||||
|
||||
@@ -35,7 +35,7 @@ Para executar o OpenHands no modo CLI com Docker:
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
|
||||
@@ -17,7 +17,11 @@ O OpenHands fornece um modo de Interface Gráfica do Usuário (GUI) para interag
|
||||
3. Insira a `Chave de API` correspondente para o provedor escolhido.
|
||||
4. Clique em `Salvar Alterações` para aplicar as configurações.
|
||||
|
||||
### Configuração do Token do GitHub
|
||||
### Tokens de Controle de Versão
|
||||
|
||||
O OpenHands suporta múltiplos provedores de controle de versão. Você pode configurar tokens para vários provedores simultaneamente.
|
||||
|
||||
#### Configuração do Token do GitHub
|
||||
|
||||
O OpenHands exporta automaticamente um `GITHUB_TOKEN` para o ambiente shell se ele estiver disponível. Isso pode acontecer de duas maneiras:
|
||||
|
||||
@@ -35,7 +39,7 @@ O OpenHands exporta automaticamente um `GITHUB_TOKEN` para o ambiente shell se e
|
||||
- Minimal Permissions (Selecione **Meta Data = Read-only** para pesquisa, **Pull Requests = Read and Write**, **Content = Read and Write** para criação de branches)
|
||||
2. **Insira o Token no OpenHands**:
|
||||
- Clique no botão Settings (ícone de engrenagem).
|
||||
- Navegue até a seção `GitHub Settings`.
|
||||
- Navegue até a seção `Git Provider Settings`.
|
||||
- Cole seu token no campo `GitHub Token`.
|
||||
- Clique em `Save Changes` para aplicar as alterações.
|
||||
</details>
|
||||
@@ -95,6 +99,46 @@ O OpenHands exporta automaticamente um `GITHUB_TOKEN` para o ambiente shell se e
|
||||
- Se estiver usando uma organização, autorize o acesso à organização se solicitado.
|
||||
</details>
|
||||
|
||||
#### Configuração do Token do GitLab
|
||||
|
||||
O OpenHands exporta automaticamente um `GITLAB_TOKEN` para o ambiente shell, apenas para instalações locais, se ele estiver disponível.
|
||||
|
||||
<details>
|
||||
<summary>Configurando um Token do GitLab</summary>
|
||||
|
||||
1. **Gere um Personal Access Token (PAT)**:
|
||||
- No GitLab, vá para User Settings > Access Tokens.
|
||||
- Crie um novo token com os seguintes escopos:
|
||||
- `api` (Acesso à API)
|
||||
- `read_user` (Leitura de informações do usuário)
|
||||
- `read_repository` (Leitura do repositório)
|
||||
- `write_repository` (Escrita no repositório)
|
||||
- Defina uma data de expiração ou deixe em branco para um token sem expiração.
|
||||
2. **Insira o Token no OpenHands**:
|
||||
- Clique no botão Settings (ícone de engrenagem).
|
||||
- Navegue até a seção `Git Provider Settings`.
|
||||
- Cole seu token no campo `GitLab Token`.
|
||||
- Se estiver usando GitLab auto-hospedado, insira a URL da sua instância GitLab.
|
||||
- Clique em `Save Changes` para aplicar as alterações.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Solução de Problemas</summary>
|
||||
|
||||
Problemas comuns e soluções:
|
||||
|
||||
- **Token Não Reconhecido**:
|
||||
- Certifique-se de que o token esteja salvo corretamente nas configurações.
|
||||
- Verifique se o token não expirou.
|
||||
- Verifique se o token possui os escopos necessários.
|
||||
- Para instâncias auto-hospedadas, verifique a URL correta da instância.
|
||||
|
||||
- **Acesso Negado**:
|
||||
- Verifique as permissões de acesso ao projeto.
|
||||
- Verifique se o token possui os escopos necessários.
|
||||
- Para repositórios de grupo/organização, certifique-se de ter o acesso adequado.
|
||||
</details>
|
||||
|
||||
### Configurações Avançadas
|
||||
|
||||
1. Dentro da página Settings, ative as opções `Advanced` para acessar configurações adicionais.
|
||||
|
||||
@@ -32,7 +32,7 @@ Para executar o OpenHands no modo Headless com Docker:
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.main -t "escreva um script bash que imprima oi"
|
||||
```
|
||||
|
||||
|
||||
@@ -58,17 +58,17 @@
|
||||
A maneira mais fácil de executar o OpenHands é no Docker.
|
||||
|
||||
```bash
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36
|
||||
```
|
||||
|
||||
Você encontrará o OpenHands em execução em http://localhost:3000!
|
||||
|
||||
@@ -13,7 +13,7 @@ Quando o OpenHands trabalha com um repositório, ele:
|
||||
|
||||
1. Carrega instruções específicas do repositório de `.openhands/microagents/`, se presentes no repositório.
|
||||
2. Carrega diretrizes gerais acionadas por palavras-chave nas conversas.
|
||||
Veja os [Microagentes Públicos](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) atuais.
|
||||
Veja os [Microagentes Públicos](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents) atuais.
|
||||
|
||||
## Formato do Microagente
|
||||
|
||||
@@ -21,8 +21,8 @@ Todos os microagentes usam arquivos markdown com frontmatter YAML que possuem in
|
||||
```
|
||||
---
|
||||
name: <Nome do microagente>
|
||||
type: <Tipo do MicroAgent>
|
||||
version: <Versão do MicroAgent>
|
||||
type: <Tipo do Microagent>
|
||||
version: <Versão do Microagent>
|
||||
agent: <O tipo de agente (normalmente CodeActAgent)>
|
||||
triggers:
|
||||
- <Palavras-chave opcionais que acionam o microagente. Se os gatilhos forem removidos, ele sempre será incluído>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Microagentes públicos são diretrizes especializadas acionadas por palavras-chave para todos os usuários do OpenHands.
|
||||
Eles são definidos em arquivos markdown no diretório
|
||||
[`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge).
|
||||
[`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents).
|
||||
|
||||
Microagentes públicos:
|
||||
- Monitoram comandos recebidos em busca de suas palavras-chave de acionamento.
|
||||
@@ -15,7 +15,7 @@ Microagentes públicos:
|
||||
## Microagentes Públicos Atuais
|
||||
|
||||
Para mais informações sobre microagentes específicos, consulte seus arquivos de documentação individuais no
|
||||
diretório [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge/).
|
||||
diretório [`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/).
|
||||
|
||||
### Agente GitHub
|
||||
**Arquivo**: `github.md`
|
||||
@@ -59,7 +59,7 @@ yes | npm install package-name
|
||||
## Contribuindo com um Microagente Público
|
||||
|
||||
Você pode criar seus próprios microagentes públicos adicionando novos arquivos markdown ao
|
||||
diretório [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge/).
|
||||
diretório [`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/).
|
||||
|
||||
### Melhores Práticas para Microagentes Públicos
|
||||
|
||||
@@ -81,7 +81,7 @@ Antes de criar um microagente público, considere:
|
||||
|
||||
#### 2. Crie o Arquivo
|
||||
|
||||
Crie um novo arquivo markdown em [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge/)
|
||||
Crie um novo arquivo markdown em [`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/)
|
||||
com um nome descritivo (por exemplo, `docker.md` para um agente focado em Docker).
|
||||
|
||||
Atualize o arquivo com o frontmatter necessário [de acordo com o formato exigido](./microagents-overview#microagent-format)
|
||||
@@ -149,5 +149,5 @@ Lembre-se de:
|
||||
- Otimizar para tempo de build e tamanho da imagem
|
||||
```
|
||||
|
||||
Veja os [microagentes públicos atuais](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) para
|
||||
Veja os [microagentes públicos atuais](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents) para
|
||||
mais exemplos.
|
||||
|
||||
@@ -13,7 +13,7 @@ Este é o Runtime padrão que é usado quando você inicia o OpenHands. Você po
|
||||
|
||||
```
|
||||
docker run # ...
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
# ...
|
||||
```
|
||||
|
||||
@@ -349,17 +349,17 @@ Agent 配置选项在 `config.toml` 文件的 `[agent]` 和 `[agent.<agent_name>
|
||||
- 默认值: `true`
|
||||
- 描述: 是否启用函数调用
|
||||
|
||||
- `codeact_enable_browsing`
|
||||
- `enable_browsing`
|
||||
- 类型: `bool`
|
||||
- 默认值: `false`
|
||||
- 描述: 是否在 action space 中启用浏览代理(仅适用于函数调用)
|
||||
|
||||
- `codeact_enable_llm_editor`
|
||||
- `enable_llm_editor`
|
||||
- 类型: `bool`
|
||||
- 默认值: `false`
|
||||
- 描述: 是否在 action space 中启用 LLM 编辑器(仅适用于函数调用)
|
||||
|
||||
- `codeact_enable_jupyter`
|
||||
- `enable_jupyter`
|
||||
- 类型: `bool`
|
||||
- 默认值: `false`
|
||||
- 描述: 是否在 action space 中启用 Jupyter
|
||||
|
||||
@@ -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.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
|
||||
@@ -19,14 +19,18 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
|
||||
3. 输入所选提供商对应的 `API Key`。
|
||||
4. 点击"保存"应用设置。
|
||||
|
||||
### GitHub Token 设置
|
||||
### 版本控制令牌
|
||||
|
||||
OpenHands 支持多个版本控制提供商。您可以同时配置多个提供商的令牌。
|
||||
|
||||
#### GitHub Token 设置
|
||||
|
||||
如果可用,OpenHands 会自动将 `GITHUB_TOKEN` 导出到 shell 环境中。这可以通过两种方式实现:
|
||||
|
||||
1. **本地(OSS)**:用户直接输入他们的 GitHub token
|
||||
2. **在线(SaaS)**:通过 GitHub OAuth 身份验证获取 token
|
||||
|
||||
#### 设置本地 GitHub Token
|
||||
##### 设置本地 GitHub Token
|
||||
|
||||
1. **生成个人访问令牌(PAT)**:
|
||||
- 转到 GitHub 设置 > 开发者设置 > 个人访问令牌 > 令牌(经典)
|
||||
@@ -38,11 +42,11 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
|
||||
|
||||
2. **在 OpenHands 中输入令牌**:
|
||||
- 点击右上角的设置按钮(齿轮图标)
|
||||
- 导航到"GitHub"部分
|
||||
- 导航到"Git Provider Settings"部分
|
||||
- 将令牌粘贴到"GitHub Token"字段中
|
||||
- 点击"保存"应用更改
|
||||
|
||||
#### 组织令牌策略
|
||||
##### 组织令牌策略
|
||||
|
||||
如果您使用组织仓库,可能需要额外的设置:
|
||||
|
||||
@@ -57,7 +61,7 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
|
||||
- 如果需要,点击组织旁边的"启用 SSO"
|
||||
- 完成 SSO 授权过程
|
||||
|
||||
#### OAuth 身份验证(在线模式)
|
||||
##### OAuth 身份验证(在线模式)
|
||||
|
||||
在在线模式下使用 OpenHands 时,GitHub OAuth 流程:
|
||||
|
||||
@@ -72,7 +76,7 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
|
||||
- 授权 OpenHands 访问您的 GitHub 帐户
|
||||
- 如果使用组织,在出现提示时授权组织访问
|
||||
|
||||
#### 故障排除
|
||||
##### 故障排除
|
||||
|
||||
常见问题和解决方案:
|
||||
|
||||
@@ -93,6 +97,43 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
|
||||
- 检查浏览器控制台中是否有任何错误消息
|
||||
- 如果可用,使用设置中的"测试连接"按钮
|
||||
|
||||
#### GitLab Token 设置
|
||||
|
||||
OpenHands 会自动将 `GITLAB_TOKEN` 导出到 shell 环境中,仅适用于本地安装,如果它可用的话。
|
||||
|
||||
##### 设置 GitLab Token
|
||||
|
||||
1. **生成个人访问令牌(PAT)**:
|
||||
- 在 GitLab 中,转到用户设置 > 访问令牌
|
||||
- 创建具有以下范围的新令牌:
|
||||
- `api`(API 访问)
|
||||
- `read_user`(读取用户信息)
|
||||
- `read_repository`(读取仓库)
|
||||
- `write_repository`(写入仓库)
|
||||
- 设置过期日期或留空以获取永不过期的令牌
|
||||
|
||||
2. **在 OpenHands 中输入令牌**:
|
||||
- 点击设置按钮(齿轮图标)
|
||||
- 导航到 `Git Provider Settings` 部分
|
||||
- 将令牌粘贴到 `GitLab Token` 字段中
|
||||
- 如果使用自托管 GitLab,请输入您的 GitLab 实例 URL
|
||||
- 点击 `Save Changes` 应用更改
|
||||
|
||||
##### 故障排除
|
||||
|
||||
常见问题和解决方案:
|
||||
|
||||
1. **令牌无法识别**:
|
||||
- 确保令牌已正确保存在设置中
|
||||
- 检查令牌是否已过期
|
||||
- 验证令牌是否具有所需的范围
|
||||
- 对于自托管实例,验证正确的实例 URL
|
||||
|
||||
2. **访问被拒绝**:
|
||||
- 验证项目访问权限
|
||||
- 检查令牌是否具有必要的范围
|
||||
- 对于组/组织仓库,确保您拥有适当的访问权限
|
||||
|
||||
### 高级设置
|
||||
|
||||
1. 切换`高级选项`以访问其他设置。
|
||||
|
||||
@@ -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.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
|
||||
```
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
在 Docker 中运行 OpenHands 是最简单的方式。
|
||||
|
||||
```bash
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36
|
||||
```
|
||||
|
||||
你也可以在可脚本化的[无头模式](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)。
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
```
|
||||
docker run # ...
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
# ...
|
||||
```
|
||||
|
||||
8
docs/modules/usage/cloud/_category_.json
Normal file
8
docs/modules/usage/cloud/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "OpenHands Cloud",
|
||||
"position": 9,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Documentation for OpenHands Cloud features and services."
|
||||
}
|
||||
}
|
||||
177
docs/modules/usage/cloud/cloud-api.md
Normal file
177
docs/modules/usage/cloud/cloud-api.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# OpenHands Cloud API
|
||||
|
||||
OpenHands Cloud provides a REST API that allows you to programmatically interact with the service. This is useful if you easily want to kick off your own jobs from your programs in a flexible way.
|
||||
|
||||
This guide explains how to obtain an API key and use the API to start conversations.
|
||||
For more detailed information about the API, refer to the [OpenHands API Reference](https://docs.all-hands.dev/swagger-ui/).
|
||||
|
||||
## Obtaining an API Key
|
||||
|
||||
To use the OpenHands Cloud API, you'll need to generate an API key:
|
||||
|
||||
1. Log in to your [OpenHands Cloud](https://app.all-hands.dev) account
|
||||
2. Navigate to the [Settings page](https://app.all-hands.dev/settings)
|
||||
3. Locate the "API Keys" section
|
||||
4. Click "Generate New Key"
|
||||
5. Give your key a descriptive name (e.g., "Development", "Production")
|
||||
6. Copy the generated API key and store it securely - it will only be shown once
|
||||
|
||||

|
||||
|
||||
## API Usage
|
||||
|
||||
### Starting a New Conversation
|
||||
|
||||
To start a new conversation with OpenHands performing a task, you'll need to make a POST request to the conversation endpoint.
|
||||
|
||||
#### Request Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `initial_user_msg` | string | Yes | The initial message to start the conversation |
|
||||
| `repository` | string | No | Git repository name to provide context in the format `owner/repo`. You must have access to the repo. |
|
||||
|
||||
#### Examples
|
||||
|
||||
<details>
|
||||
<summary>cURL</summary>
|
||||
|
||||
```bash
|
||||
curl -X POST "https://app.all-hands.dev/api/conversations" \
|
||||
-H "Authorization: Bearer YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"initial_user_msg": "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so.",
|
||||
"repository": "yourusername/your-repo"
|
||||
}'
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Python (with requests)</summary>
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
api_key = "YOUR_API_KEY"
|
||||
url = "https://app.all-hands.dev/api/conversations"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
data = {
|
||||
"initial_user_msg": "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so.",
|
||||
"repository": "yourusername/your-repo"
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
conversation = response.json()
|
||||
|
||||
print(f"Conversation Link: https://app.all-hands.dev/conversations/{conversation['id']}")
|
||||
print(f"Status: {conversation['status']}")
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>TypeScript/JavaScript (with fetch)</summary>
|
||||
|
||||
```typescript
|
||||
const apiKey = "YOUR_API_KEY";
|
||||
const url = "https://app.all-hands.dev/api/conversations";
|
||||
|
||||
const headers = {
|
||||
"Authorization": `Bearer ${apiKey}`,
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
|
||||
const data = {
|
||||
initial_user_msg: "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so.",
|
||||
repository: "yourusername/your-repo"
|
||||
};
|
||||
|
||||
async function startConversation() {
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const conversation = await response.json();
|
||||
|
||||
console.log(`Conversation Link: https://app.all-hands.dev/conversations/${conversation.id}`);
|
||||
console.log(`Status: ${conversation.status}`);
|
||||
|
||||
return conversation;
|
||||
} catch (error) {
|
||||
console.error("Error starting conversation:", error);
|
||||
}
|
||||
}
|
||||
|
||||
startConversation();
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Response
|
||||
|
||||
The API will return a JSON object with details about the created conversation:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"conversation_id": "abc1234",
|
||||
}
|
||||
```
|
||||
|
||||
You may also receive an `AuthenticationError` if:
|
||||
|
||||
1. You provided an invalid API key
|
||||
2. You provided the wrong repo name
|
||||
3. You don't have access to the repo
|
||||
|
||||
|
||||
### Retrieving Conversation Status
|
||||
|
||||
You can check the status of a conversation by making a GET request to the conversation endpoint.
|
||||
|
||||
#### Endpoint
|
||||
|
||||
```
|
||||
GET https://app.all-hands.dev/api/conversations/{conversation_id}
|
||||
```
|
||||
|
||||
#### Example
|
||||
|
||||
<details>
|
||||
<summary>cURL</summary>
|
||||
|
||||
```bash
|
||||
curl -X GET "https://app.all-hands.dev/api/conversations/{conversation_id}" \
|
||||
-H "Authorization: Bearer YOUR_API_KEY"
|
||||
```
|
||||
</details>
|
||||
|
||||
#### Response
|
||||
|
||||
The response is formatted as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"conversation_id":"abc1234",
|
||||
"title":"Update README.md",
|
||||
"created_at":"2025-04-29T15:13:51.370706Z",
|
||||
"last_updated_at":"2025-04-29T15:13:57.199210Z",
|
||||
"status":"RUNNING",
|
||||
"selected_repository":"yourusername/your-repo",
|
||||
"trigger":"gui"
|
||||
}
|
||||
```
|
||||
|
||||
## Rate Limits
|
||||
|
||||
The API has a limit of 10 simultaneous conversations per account. If you need a higher limit for your use case, please contact us at [contact@all-hands.dev](mailto:contact@all-hands.dev).
|
||||
|
||||
If you exceed this limit, the API will return a 429 Too Many Requests response.
|
||||
@@ -5,7 +5,7 @@ The GitHub Resolver automates code fixes and provides intelligent assistance for
|
||||
## Setup
|
||||
|
||||
The Cloud GitHub Resolver is available automatically when you
|
||||
[grant OpenHands Cloud repository access](./openhands-cloud.md#adding-repository-access).
|
||||
[grant OpenHands Cloud repository access](./openhands-cloud#adding-repository-access).
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
# Openhands Cloud
|
||||
|
||||
OpenHands Cloud is the cloud hosted version of OpenHands by All Hands AI.
|
||||
|
||||
## Accessing OpenHands Cloud
|
||||
|
||||
Currently, users are being admitted to access OpenHands Cloud in waves. To sign up,
|
||||
[join the waitlist](https://www.all-hands.dev/join-waitlist). Once you are approved, you will get an email with
|
||||
instructions on how to access it.
|
||||
|
||||
## Getting Started
|
||||
|
||||
After visiting OpenHands Cloud, you will be asked to connect with your GitHub account:
|
||||
1. After reading and accepting the terms of service, click `Connect to GitHub`.
|
||||
2. Review the permissions requested by OpenHands and then click `Authorize OpenHands AI`.
|
||||
- OpenHands will require some permissions from your GitHub account. To read more about these permissions,
|
||||
you can click the `Learn more` link on the GitHub authorize page.
|
||||
|
||||
## Repository Access
|
||||
|
||||
### Adding Repository Access
|
||||
|
||||
You can grant OpenHands specific repository access:
|
||||
1. Click the `Select a GitHub project` dropdown, select `Add more repositories...`.
|
||||
2. Select the organization, then choose the specific repositories to grant OpenHands access to.
|
||||
- Openhands requests short-lived tokens (8-hour expiry) with these permissions:
|
||||
- Actions: Read and write
|
||||
- Administration: Read-only
|
||||
- Commit statuses: Read and write
|
||||
- Contents: Read and write
|
||||
- Issues: Read and write
|
||||
- Metadata: Read-only
|
||||
- Pull requests: Read and write
|
||||
- Webhooks: Read and write
|
||||
- Workflows: Read and write
|
||||
- Repository access for a user is granted based on:
|
||||
- Granted permission for the repository.
|
||||
- User's GitHub permissions (owner/collaborator).
|
||||
3. Click on `Install & Authorize`.
|
||||
|
||||
### Modifying Repository Access
|
||||
|
||||
You can modify repository access at any time by:
|
||||
* Using the same `Select a GitHub project > Add more repositories` workflow, or
|
||||
* Visiting the Settings page and selecting `Configure GitHub Repositories` under the `GitHub Settings` section.
|
||||
65
docs/modules/usage/cloud/openhands-cloud.mdx
Normal file
65
docs/modules/usage/cloud/openhands-cloud.mdx
Normal file
@@ -0,0 +1,65 @@
|
||||
# Openhands Cloud
|
||||
|
||||
OpenHands Cloud is the cloud hosted version of OpenHands by All Hands AI.
|
||||
|
||||
## Accessing OpenHands Cloud
|
||||
|
||||
OpenHands Cloud can be accessed at https://app.all-hands.dev/.
|
||||
|
||||
You can also interact with OpenHands Cloud programmatically using the [API](./cloud-api).
|
||||
|
||||
## Getting Started
|
||||
|
||||
After visiting OpenHands Cloud, you will be asked to connect with your GitHub or GitLab account:
|
||||
|
||||
1. After reading and accepting the terms of service, click `Log in with GitHub` or `Log in with GitLab`.
|
||||
2. Review the permissions requested by OpenHands and then click `Authorize OpenHands AI`.
|
||||
- OpenHands will require some permissions from your GitHub or GitLab account. To read more about these permissions:
|
||||
- GitHub: You can click the `Learn more` link on the GitHub authorize page.
|
||||
- GitLab: You can expand each permission request on the GitLab authorize page.
|
||||
|
||||
## Repository Access
|
||||
|
||||
### GitHub
|
||||
|
||||
#### Adding Repository Access
|
||||
|
||||
You can grant OpenHands specific repository access:
|
||||
1. Click `Add GitHub repos` on the Home page.
|
||||
2. Select the organization, then choose the specific repositories to grant OpenHands access to.
|
||||
<details>
|
||||
<summary>Permission Details for Repository Access</summary>
|
||||
|
||||
Openhands requests short-lived tokens (8-hour expiry) with these permissions:
|
||||
- Actions: Read and write
|
||||
- Administration: Read-only
|
||||
- Commit statuses: Read and write
|
||||
- Contents: Read and write
|
||||
- Issues: Read and write
|
||||
- Metadata: Read-only
|
||||
- Pull requests: Read and write
|
||||
- Webhooks: Read and write
|
||||
- Workflows: Read and write
|
||||
|
||||
Repository access for a user is granted based on:
|
||||
- Granted permission for the repository.
|
||||
- User's GitHub permissions (owner/collaborator).
|
||||
</details>
|
||||
|
||||
3. Click on `Install & Authorize`.
|
||||
|
||||
#### Modifying Repository Access
|
||||
|
||||
You can modify GitHub repository access at any time by:
|
||||
* Using the same `Add GitHub repos` workflow, or
|
||||
* Visiting the Settings page and selecting `Configure GitHub Repositories` under the `Git Settings` section.
|
||||
|
||||
### GitLab
|
||||
|
||||
When using your GitLab account, OpenHands will automatically have access to your repositories.
|
||||
|
||||
## Conversation Persistence
|
||||
|
||||
- Conversations List – Displays only the 10 most recent conversations initiated within the past 10 days.
|
||||
- Workspaces – Conversation workspaces are retained for 14 days.
|
||||
- Runtimes – Runtimes remain active ("warm") for 30 minutes. After this period, resuming a conversation may take 1–2 minutes.
|
||||
@@ -1,10 +1,8 @@
|
||||
# Configuration Options
|
||||
|
||||
This guide details all configuration options available for OpenHands, helping you customize its behavior and integrate it with other services.
|
||||
|
||||
:::note
|
||||
If you are running in [GUI Mode](https://docs.all-hands.dev/modules/usage/how-to/gui-mode), the settings available in the Settings UI will always
|
||||
take precedence.
|
||||
This page outlines all available configuration options for OpenHands, allowing you to customize its behavior and
|
||||
integrate it with other services. In GUI Mode, any settings applied through the Settings UI will take precedence.
|
||||
:::
|
||||
|
||||
## Core Configuration
|
||||
@@ -293,17 +291,17 @@ The agent configuration options are defined in the `[agent]` and `[agent.<agent_
|
||||
- Default: `true`
|
||||
- Description: Whether function calling is enabled
|
||||
|
||||
- `codeact_enable_browsing`
|
||||
- `enable_browsing`
|
||||
- Type: `bool`
|
||||
- Default: `false`
|
||||
- Description: Whether browsing delegate is enabled in the action space (only works with function calling)
|
||||
|
||||
- `codeact_enable_llm_editor`
|
||||
- `enable_llm_editor`
|
||||
- Type: `bool`
|
||||
- Default: `false`
|
||||
- Description: Whether LLM editor is enabled in the action space (only works with function calling)
|
||||
|
||||
- `codeact_enable_jupyter`
|
||||
- `enable_jupyter`
|
||||
- Type: `bool`
|
||||
- Default: `false`
|
||||
- Description: Whether Jupyter is enabled in the action space
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
# Repository Customization
|
||||
|
||||
You can customize how OpenHands works with your repository by creating a
|
||||
You can customize how OpenHands interacts with your repository by creating a
|
||||
`.openhands` directory at the root level.
|
||||
|
||||
## Microagents
|
||||
You can use microagents to extend the OpenHands prompts with information
|
||||
about your project and how you want OpenHands to work. See
|
||||
[Repository Microagents](../prompting/microagents-repo) for more information.
|
||||
|
||||
Microagents allow you to extend OpenHands prompts with information specific to your project and define how OpenHands
|
||||
should function. See [Microagents Overview](../prompting/microagents-overview) for more information.
|
||||
|
||||
|
||||
## Setup Script
|
||||
You can add `.openhands/setup.sh`, which will be run every time OpenHands begins
|
||||
working with your repository. This is a good place to install dependencies, set
|
||||
environment variables, etc.
|
||||
You can add a `.openhands/setup.sh` file, which will run every time OpenHands begins working with your repository.
|
||||
This is an ideal location for installing dependencies, setting environment variables, and performing other setup tasks.
|
||||
|
||||
For example:
|
||||
```bash
|
||||
|
||||
@@ -3,109 +3,97 @@
|
||||
So you've [run OpenHands](./installation) and have
|
||||
[set up your LLM](./installation#setup). Now what?
|
||||
|
||||
OpenHands can help you tackle a wide variety of engineering tasks. But the technology
|
||||
is still new, and we're a long way off from having agents that can take on large, complicated
|
||||
engineering tasks without any guidance. So it's important to get a feel for what the agent
|
||||
does well, and where it might need some help.
|
||||
OpenHands can assist with a range of engineering tasks. However, the technology is still new, and we’re far from having
|
||||
agents that can handle complex tasks independently. It’s important to understand what the agent does well and where it
|
||||
needs support.
|
||||
|
||||
## Hello World
|
||||
|
||||
The first thing you might want to try is a simple "hello world" example.
|
||||
This can be more complicated than it sounds!
|
||||
Start with a simple "hello world" example. It might be trickier than it seems!
|
||||
|
||||
Try prompting the agent with:
|
||||
> Please write a bash script hello.sh that prints "hello world!"
|
||||
Prompt the agent with:
|
||||
> Write a bash script hello.sh that prints "hello world!"
|
||||
|
||||
You should see that the agent not only writes the script, it sets the correct
|
||||
permissions and runs the script to check the output.
|
||||
The agent will write the script, set the correct permissions, and run it to check the output.
|
||||
|
||||
You can continue prompting the agent to refine your code. This is a great way to
|
||||
work with agents. Start simple, and iterate.
|
||||
|
||||
> Please modify hello.sh so that it accepts a name as the first argument, but defaults to "world"
|
||||
> Modify hello.sh so that it accepts a name as the first argument, but defaults to "world"
|
||||
|
||||
You can also work in any language you need, though the agent might need to spend some
|
||||
time setting up its environment!
|
||||
You can also use any language you need. The agent may need time to set up the environment.
|
||||
|
||||
> Please convert hello.sh to a Ruby script, and run it
|
||||
|
||||
## Building From Scratch
|
||||
|
||||
Agents do exceptionally well at "greenfield" tasks (tasks where they don't need
|
||||
any context about an existing codebase) and they can just start from scratch.
|
||||
|
||||
It's best to start with a simple task, and then iterate on it. It's also best to be
|
||||
as specific as possible about what you want, what the tech stack should be, etc.
|
||||
Agents excel at "greenfield" tasks, where they don’t need context about existing code and
|
||||
they can start from scratch.
|
||||
Begin with a simple task and iterate from there. Be specific about what you want and the tech stack.
|
||||
|
||||
For example, we might build a TODO app:
|
||||
|
||||
> Please build a basic TODO list app in React. It should be frontend-only, and all state
|
||||
> should be kept in localStorage.
|
||||
> Build a frontend-only TODO app in React. All state should be stored in localStorage.
|
||||
|
||||
We can keep iterating on the app once the skeleton is there:
|
||||
Once the basic structure is in place, continue refining:
|
||||
|
||||
> Please allow adding an optional due date to every task.
|
||||
> Allow adding an optional due date to each task.
|
||||
|
||||
Just like with normal development, it's good to commit and push your code frequently.
|
||||
Just like normal development, commit and push your code often.
|
||||
This way you can always revert back to an old state if the agent goes off track.
|
||||
You can ask the agent to commit and push for you:
|
||||
|
||||
> Please commit the changes and push them to a new branch called "feature/due-dates"
|
||||
|
||||
> Commit the changes and push them to a new branch called "feature/due-dates"
|
||||
|
||||
## Adding New Code
|
||||
|
||||
OpenHands can also do a great job adding new code to an existing code base.
|
||||
OpenHands is great at adding new code to an existing codebase.
|
||||
|
||||
For example, you can ask OpenHands to add a new GitHub action to your project
|
||||
which lints your code. OpenHands may take a peek at your codebase to see what language
|
||||
it should use and then drop a new file into `./github/workflows/lint.yml`.
|
||||
For instance, you can ask OpenHands to add a GitHub action that lints your code. It might check your codebase to
|
||||
determine the language, then create a new file in `./github/workflows/lint.yml`.
|
||||
|
||||
> Please add a GitHub action that lints the code in this repository.
|
||||
> Add a GitHub action that lints the code in this repository.
|
||||
|
||||
Some tasks might require a bit more context. While OpenHands can use `ls` and `grep`
|
||||
to search through your codebase, providing context up front allows it to move faster,
|
||||
and more accurately. And it'll cost you fewer tokens!
|
||||
Some tasks need more context. While OpenHands can use commands like ls and grep to search, providing context upfront
|
||||
speeds things up and reduces token usage.
|
||||
|
||||
> Please modify ./backend/api/routes.js to add a new route that returns a list of all tasks.
|
||||
> Modify ./backend/api/routes.js to add a new route that returns a list of all tasks.
|
||||
|
||||
> Please add a new React component that displays a list of Widgets to the ./frontend/components
|
||||
> directory. It should use the existing Widget component.
|
||||
> Add a new React component to the ./frontend/components directory to display a list of Widgets.
|
||||
> It should use the existing Widget component.
|
||||
|
||||
## Refactoring
|
||||
|
||||
OpenHands does great at refactoring existing code, especially in small chunks.
|
||||
You probably don't want to try rearchitecting your whole codebase, but breaking up
|
||||
long files and functions, renaming variables, etc. tend to work very well.
|
||||
OpenHands does great at refactoring code in small chunks. Rather than rearchitecting the entire codebase,
|
||||
it's more effective to break up long files and functions or rename variables.
|
||||
|
||||
> Please rename all the single-letter variables in ./app.go.
|
||||
> Rename all the single-letter variables in ./app.go.
|
||||
|
||||
> Please break the function `build_and_deploy_widgets` into two functions, `build_widgets` and `deploy_widgets` in widget.php.
|
||||
> Split the `build_and_deploy_widgets` function into two functions, `build_widgets` and `deploy_widgets` in widget.php.
|
||||
|
||||
> Please break ./api/routes.js into separate files for each route.
|
||||
> Break ./api/routes.js into separate files for each route.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
OpenHands can also help you track down and fix bugs in your code. But as any
|
||||
developer knows, bug fixing can be extremely tricky, and often OpenHands will need more context.
|
||||
It helps if you've diagnosed the bug, but want OpenHands to figure out the logic.
|
||||
OpenHands can help track down and fix bugs, but bug fixing can be tricky and often requires more context.
|
||||
It’s helpful if you’ve already diagnosed the issue and just need OpenHands to handle the logic.
|
||||
|
||||
> Currently the email field in the `/subscribe` endpoint is rejecting .io domains. Please fix this.
|
||||
> The email field in the `/subscribe` endpoint is rejecting .io domains. Fix this.
|
||||
|
||||
> The `search_widgets` function in ./app.py is doing a case-sensitive search. Please make it case-insensitive.
|
||||
> The `search_widgets` function in ./app.py is doing a case-sensitive search. Make it case-insensitive.
|
||||
|
||||
It often helps to do test-driven development when bug fixing with an agent.
|
||||
You can ask the agent to write a new test, and then iterate until it fixes the bug:
|
||||
For bug fixing, test-driven development can be really useful. You can ask the agent to write a new test and iterate
|
||||
until the bug is fixed:
|
||||
|
||||
> The `hello` function crashes on the empty string. Please write a test that reproduces this bug, then fix the code so it passes.
|
||||
> The `hello` function crashes on the empty string. Write a test that reproduces this bug, then fix the code so it passes.
|
||||
|
||||
## More
|
||||
|
||||
OpenHands is capable of helping out on just about any coding task but it takes some practice
|
||||
to get the most out of it. Remember to:
|
||||
OpenHands can assist with nearly any coding task, but it takes some practice to get the best results.
|
||||
Keep these tips in mind:
|
||||
* Keep your tasks small.
|
||||
* Be as specific as possible.
|
||||
* Provide as much context as possible.
|
||||
* Be specific.
|
||||
* Provide plenty of context.
|
||||
* Commit and push frequently.
|
||||
|
||||
See [Prompting Best Practices](./prompting/prompting-best-practices) for more tips on how to get the most out of OpenHands.
|
||||
|
||||
@@ -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.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -45,52 +45,11 @@ 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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
This command will start an interactive session in Docker where you can input tasks and receive responses from OpenHands.
|
||||
|
||||
## Examples of CLI Commands and Expected Outputs
|
||||
|
||||
Here are some examples of CLI commands and their expected outputs:
|
||||
|
||||
### Example 1: Simple Task
|
||||
|
||||
```bash
|
||||
>> Write a Python script that prints "Hello, World!"
|
||||
```
|
||||
|
||||
Expected Output:
|
||||
|
||||
```bash
|
||||
🤖 Sure! Here is a Python script that prints "Hello, World!":
|
||||
|
||||
❯ print("Hello, World!")
|
||||
```
|
||||
|
||||
### Example 2: Bash Command
|
||||
|
||||
```bash
|
||||
>> Create a directory named "test_dir"
|
||||
```
|
||||
|
||||
Expected Output:
|
||||
|
||||
```bash
|
||||
🤖 Creating a directory named "test_dir":
|
||||
|
||||
❯ mkdir test_dir
|
||||
```
|
||||
|
||||
### Example 3: Error Handling
|
||||
|
||||
```bash
|
||||
>> Delete a non-existent file
|
||||
```
|
||||
|
||||
Expected Output:
|
||||
|
||||
```bash
|
||||
🤖 An error occurred. Please try again.
|
||||
```
|
||||
The `-e SANDBOX_USER_ID=$(id -u)` is passed to the Docker command to ensure the sandbox user matches the host user’s
|
||||
permissions. This prevents the agent from creating root-owned files in the mounted workspace.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Custom Sandbox
|
||||
|
||||
:::note
|
||||
This guide is for users that would like to use their own custom Docker image for the runtime. For example
|
||||
with certain tools or programming languages pre-installed.
|
||||
:::
|
||||
|
||||
The sandbox is where the agent performs its tasks. Instead of running commands directly on your computer
|
||||
(which could be risky), the agent runs them inside a Docker container.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Using the OpenHands GitHub Action
|
||||
|
||||
This guide explains how to use the OpenHands GitHub Action, both within the OpenHands repository and in your own projects.
|
||||
This guide explains how to use the OpenHands GitHub Action in your own projects.
|
||||
|
||||
## Using the Action in the OpenHands Repository
|
||||
|
||||
|
||||
@@ -11,17 +11,21 @@ OpenHands provides a Graphical User Interface (GUI) mode for interacting with th
|
||||
|
||||
### Initial Setup
|
||||
|
||||
1. Upon first launch, you'll see a settings page.
|
||||
1. Upon first launch, you'll see a settings popup.
|
||||
2. Select an `LLM Provider` and `LLM Model` from the dropdown menus. If the required model does not exist in the list,
|
||||
toggle `Advanced` options and enter it with the correct prefix in the `Custom Model` text box.
|
||||
select `see advanced settings`. Then toggle `Advanced` options and enter it with the correct prefix in the
|
||||
`Custom Model` text box.
|
||||
3. Enter the corresponding `API Key` for your chosen provider.
|
||||
4. Click `Save Changes` to apply the settings.
|
||||
|
||||
### GitHub Token Setup
|
||||
### Version Control Tokens
|
||||
|
||||
OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it is available. This can happen in two ways:
|
||||
OpenHands supports multiple version control providers. You can configure tokens for multiple providers simultaneously.
|
||||
|
||||
#### GitHub Token Setup
|
||||
|
||||
OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if provided:
|
||||
|
||||
**Local Installation**: The user directly inputs their GitHub token.
|
||||
<details>
|
||||
<summary>Setting Up a GitHub Token</summary>
|
||||
|
||||
@@ -32,12 +36,11 @@ OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it
|
||||
- `repo` (Full control of private repositories)
|
||||
- **Fine-Grained Tokens**
|
||||
- All Repositories (You can select specific repositories, but this will impact what returns in repo search)
|
||||
- Minimal Permissions ( Select **Meta Data = Read-only** read for search, **Pull Requests = Read and Write**, **Content = Read and Write** for branch creation)
|
||||
- Minimal Permissions ( Select `Meta Data = Read-only` read for search, `Pull Requests = Read and Write` and `Content = Read and Write` for branch creation)
|
||||
2. **Enter Token in OpenHands**:
|
||||
- Click the Settings button (gear icon).
|
||||
- Navigate to the `GitHub Settings` section.
|
||||
- Paste your token in the `GitHub Token` field.
|
||||
- Click `Save Changes` to apply the changes.
|
||||
- Click `Save` to apply the changes.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -78,21 +81,43 @@ OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it
|
||||
- Check the browser console for any error messages.
|
||||
</details>
|
||||
|
||||
**OpenHands Cloud**: The token is obtained through GitHub OAuth authentication.
|
||||
#### GitLab Token Setup
|
||||
|
||||
OpenHands automatically exports a `GITLAB_TOKEN` to the shell environment if provided:
|
||||
|
||||
<details>
|
||||
<summary>OAuth Authentication</summary>
|
||||
<summary>Setting Up a GitLab Token</summary>
|
||||
|
||||
When using OpenHands Cloud, the GitHub OAuth flow requests the following permissions:
|
||||
- Repository access (read/write)
|
||||
- Workflow management
|
||||
- Organization read access
|
||||
1. **Generate a Personal Access Token (PAT)**:
|
||||
- On GitLab, go to User Settings > Access Tokens.
|
||||
- Create a new token with the following scopes:
|
||||
- `api` (API access)
|
||||
- `read_user` (Read user information)
|
||||
- `read_repository` (Read repository)
|
||||
- `write_repository` (Write repository)
|
||||
- Set an expiration date or leave it blank for a non-expiring token.
|
||||
2. **Enter Token in OpenHands**:
|
||||
- Click the Settings button (gear icon).
|
||||
- Paste your token in the `GitLab Token` field.
|
||||
- Enter your GitLab instance URL if using self-hosted GitLab.
|
||||
- Click `Save` to apply the changes.
|
||||
</details>
|
||||
|
||||
To authenticate OpenHands:
|
||||
- Click `Sign in with GitHub` when prompted.
|
||||
- Review the requested permissions.
|
||||
- Authorize OpenHands to access your GitHub account.
|
||||
- If using an organization, authorize organization access if prompted.
|
||||
<details>
|
||||
<summary>Troubleshooting</summary>
|
||||
|
||||
Common issues and solutions:
|
||||
|
||||
- **Token Not Recognized**:
|
||||
- Ensure the token is properly saved in settings.
|
||||
- Check that the token hasn't expired.
|
||||
- Verify the token has the required scopes.
|
||||
- For self-hosted instances, verify the correct instance URL.
|
||||
|
||||
- **Access Denied**:
|
||||
- Verify project access permissions.
|
||||
- Check if the token has the necessary scopes.
|
||||
- For group/organization repositories, ensure you have proper access.
|
||||
</details>
|
||||
|
||||
### Advanced Settings
|
||||
@@ -111,7 +136,6 @@ OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it
|
||||
## Tips for Effective Use
|
||||
|
||||
- Be specific in your requests to get the most accurate and helpful responses, as described in the [prompting best practices](../prompting/prompting-best-practices).
|
||||
- Use the workspace panel to explore your project structure.
|
||||
- Use one of the recommended models, as described in the [LLMs section](usage/llms/llms.md).
|
||||
|
||||
Remember, the GUI mode of OpenHands is designed to make your interaction with the AI assistant as smooth and intuitive
|
||||
|
||||
@@ -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.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -43,10 +43,13 @@ 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.31 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
|
||||
python -m openhands.core.main -t "write a bash script that prints hi"
|
||||
```
|
||||
|
||||
The `-e SANDBOX_USER_ID=$(id -u)` is passed to the Docker command to ensure the sandbox user matches the host user’s
|
||||
permissions. This prevents the agent from creating root-owned files in the mounted workspace.
|
||||
|
||||
## Advanced Headless Configurations
|
||||
|
||||
To view all available configuration options for headless mode, run the Python command with the `--help` flag.
|
||||
|
||||
@@ -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.31-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.31-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-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.31
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.36
|
||||
```
|
||||
|
||||
You'll find OpenHands running at http://localhost:3000!
|
||||
@@ -116,8 +116,6 @@ We use SemVer so `0.9` will automatically point to the latest `0.9.x` release, a
|
||||
- For the most up-to-date development version, replace $VERSION in `openhands:$VERSION` and `runtime:$VERSION`, with `main`.
|
||||
This version is unstable and is recommended for testing or development purposes only.
|
||||
|
||||
You can choose the tag that best suits your needs based on stability requirements and desired features.
|
||||
|
||||
For the development workflow, see [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
|
||||
|
||||
Are you having trouble? Check out our [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting).
|
||||
|
||||
@@ -1,60 +1,29 @@
|
||||
|
||||
# OpenHands Feature Overview
|
||||
|
||||

|
||||

|
||||
|
||||
## 1. Workspace
|
||||
The Workspace feature provides a comprehensive development environment with the following key capabilities:
|
||||
- File Explorer: Browse, view, and manage project files and directories
|
||||
- Project Management: Import, create, and navigate between different projects
|
||||
- Integrated Development Tools: Seamless integration with various development workflows
|
||||
- File Operations:
|
||||
* View file contents
|
||||
* Create new files and folders
|
||||
* Upload and download files
|
||||
* Basic file manipulation
|
||||
### Chat Panel
|
||||
- Displays the conversation between the user and OpenHands.
|
||||
- OpenHands explains its actions in this panel.
|
||||
|
||||
## 2. Jupyter Notebook
|
||||
The Jupyter Notebook feature offers an interactive coding and data analysis environment:
|
||||
- Interactive Code Cells: Execute Python code in a cell-based interface
|
||||
- Input and Output Tracking: Maintain a history of code inputs and their corresponding outputs
|
||||
- Persistent Session: Preserve code execution context between cells
|
||||
- Supports various Python operations and data analysis tasks
|
||||
- Real-time code execution and result visualization
|
||||
### Changes
|
||||
- Shows the file changes performed by OpenHands.
|
||||
|
||||
## 3. Browser (Beta)
|
||||
The Browser feature provides web interaction capabilities:
|
||||
- Web Page Navigation: Open and browse websites within the application
|
||||
- Screenshot Capture: Automatically generate screenshots of web pages
|
||||
- Interaction Tools:
|
||||
* Click elements
|
||||
* Fill out forms
|
||||
* Scroll pages
|
||||
* Navigate through web content
|
||||
- Supports 15 different browser interaction functions
|
||||
### VS Code
|
||||
- Embedded VS Code for browsing and modifying files.
|
||||
- Can also be used to upload and download files.
|
||||
|
||||
## 4. Terminal
|
||||
The Terminal feature offers a command-line interface within the application:
|
||||
- Execute Shell Commands: Run bash and system commands
|
||||
- Command History: Track and recall previous commands
|
||||
- Environment Interaction: Interact directly with the system's command line
|
||||
- Support for various programming and system administration tasks
|
||||
### Terminal
|
||||
- A space for OpenHands and users to run terminal commands.
|
||||
|
||||
## 5. Chat / AI Conversation
|
||||
The Chat interface provides an AI-powered conversational experience:
|
||||
- Interactive AI Assistant: Engage in natural language conversations
|
||||
- Context-Aware Responses: AI understands and responds to development-related queries
|
||||
- Action Suggestions: Provides actionable recommendations for tasks
|
||||
- Conversation Management: Create, delete, and manage different conversation threads
|
||||
### Jupyter
|
||||
- Shows all Python commands that were executed by OpenHands.
|
||||
- Particularly handy when using OpenHands to perform data visualization tasks.
|
||||
|
||||
## 6. App (Beta)
|
||||
The main application interface combines all these features:
|
||||
- Integrated Workspace: Seamless integration of workspace, browser, terminal, and AI chat
|
||||
- Configurable Layout: Customize the arrangement of different feature panels
|
||||
- State Management: Maintain context and state across different features
|
||||
- Security and Privacy Controls: Manage application settings and permissions
|
||||
### App
|
||||
- Displays the web server when OpenHands runs an application.
|
||||
- Users can interact with the running application.
|
||||
|
||||
### Additional Notes
|
||||
- The application is currently in beta, with ongoing improvements and feature additions
|
||||
- Supports various development workflows and AI-assisted coding
|
||||
- Designed to enhance developer productivity through integrated tools and AI assistance
|
||||
### Browser
|
||||
- Used by OpenHands to browse websites.
|
||||
- The browser is non-interactive.
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# 🤖 LLM Backends
|
||||
|
||||
:::note
|
||||
This section is for users who want to connect OpenHands to different LLMs.
|
||||
:::
|
||||
|
||||
OpenHands can connect to any LLM supported by LiteLLM. However, it requires a powerful model to work.
|
||||
|
||||
## Model Recommendations
|
||||
@@ -9,10 +13,14 @@ recommendations for model selection. Our latest benchmarking results can be foun
|
||||
|
||||
Based on these findings and community feedback, the following models have been verified to work reasonably well with OpenHands:
|
||||
|
||||
- anthropic/claude-3-7-sonnet-20250219 (recommended)
|
||||
- deepseek/deepseek-chat
|
||||
- OpenHands LM
|
||||
- gpt-4o
|
||||
- [anthropic/claude-3-7-sonnet-20250219](https://www.anthropic.com/api) (recommended)
|
||||
- [gemini/gemini-2.5-pro](https://blog.google/technology/google-deepmind/gemini-model-thinking-updates-march-2025/)
|
||||
- [deepseek/deepseek-chat](https://api-docs.deepseek.com/)
|
||||
- [openai/o3-mini](https://openai.com/index/openai-o3-mini/)
|
||||
- [openai/o3](https://openai.com/index/introducing-o3-and-o4-mini/)
|
||||
- [openai/o4-mini](https://openai.com/index/introducing-o3-and-o4-mini/)
|
||||
- [all-hands/openhands-lm-32b-v0.1](https://www.all-hands.dev/blog/introducing-openhands-lm-32b----a-strong-open-coding-agent-model) -- available through [OpenRouter](https://openrouter.ai/all-hands/openhands-lm-32b-v0.1)
|
||||
|
||||
|
||||
:::warning
|
||||
OpenHands will issue many prompts to the LLM you configure. Most of these LLMs cost money, so be sure to set spending
|
||||
|
||||
@@ -15,7 +15,7 @@ It is highly recommended that you use GPUs to serve local models for optimal exp
|
||||
For example, to download [OpenHands LM 32B v0.1](https://huggingface.co/all-hands/openhands-lm-32b-v0.1):
|
||||
|
||||
```bash
|
||||
huggingface-cli download all-hands/openhands-lm-32b-v0.1 --local-dir my_folder/openhands-lm-32b-v0.1
|
||||
huggingface-cli download all-hands/openhands-lm-32b-v0.1 --local-dir all-hands/openhands-lm-32b-v0.1
|
||||
```
|
||||
|
||||
## Create an OpenAI-Compatible Endpoint With a Model Serving Framework
|
||||
@@ -27,7 +27,7 @@ huggingface-cli download all-hands/openhands-lm-32b-v0.1 --local-dir my_folder/o
|
||||
|
||||
```bash
|
||||
SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 python3 -m sglang.launch_server \
|
||||
--model my_folder/openhands-lm-32b-v0.1 \
|
||||
--model all-hands/openhands-lm-32b-v0.1 \
|
||||
--served-model-name openhands-lm-32b-v0.1 \
|
||||
--port 8000 \
|
||||
--tp 2 --dp 1 \
|
||||
@@ -41,7 +41,7 @@ SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 python3 -m sglang.launch_server \
|
||||
- Example launch command for OpenHands LM 32B (with at least 2 GPUs):
|
||||
|
||||
```bash
|
||||
vllm serve my_folder/openhands-lm-32b-v0.1 \
|
||||
vllm serve all-hands/openhands-lm-32b-v0.1 \
|
||||
--host 0.0.0.0 --port 8000 \
|
||||
--api-key mykey \
|
||||
--tensor-parallel-size 2 \
|
||||
@@ -67,7 +67,7 @@ Ensure `config.toml` exists by running `make setup-config` which will create one
|
||||
workspace_base="/path/to/your/workspace"
|
||||
|
||||
[llm]
|
||||
embedding_model="local"
|
||||
model="openhands-lm-32b-v0.1"
|
||||
ollama_base_url="http://localhost:8000"
|
||||
```
|
||||
|
||||
|
||||
96
docs/modules/usage/mcp.md
Normal file
96
docs/modules/usage/mcp.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Model Context Protocol (MCP)
|
||||
|
||||
:::note
|
||||
This page outlines how to configure and use the Model Context Protocol (MCP) in OpenHands, allowing you to extend the agent's capabilities with custom tools.
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
Model Context Protocol (MCP) is a mechanism that allows OpenHands to communicate with external tool servers. These servers can provide additional functionality to the agent, such as specialized data processing, external API access, or custom tools. MCP is based on the open standard defined at [modelcontextprotocol.io](https://modelcontextprotocol.io).
|
||||
|
||||
## Configuration
|
||||
|
||||
MCP configuration is defined in the `[mcp]` section of your `config.toml` file.
|
||||
|
||||
### Configuration Example
|
||||
|
||||
```toml
|
||||
[mcp]
|
||||
# SSE Servers - External servers that communicate via Server-Sent Events
|
||||
sse_servers = [
|
||||
# Basic SSE server with just a URL
|
||||
"http://example.com:8080/mcp",
|
||||
|
||||
# SSE server with API key authentication
|
||||
{url="https://secure-example.com/mcp", api_key="your-api-key"}
|
||||
]
|
||||
|
||||
# Stdio Servers - Local processes that communicate via standard input/output
|
||||
stdio_servers = [
|
||||
# Basic stdio server
|
||||
{name="fetch", command="uvx", args=["mcp-server-fetch"]},
|
||||
|
||||
# Stdio server with environment variables
|
||||
{
|
||||
name="data-processor",
|
||||
command="python",
|
||||
args=["-m", "my_mcp_server"],
|
||||
env={
|
||||
"DEBUG": "true",
|
||||
"PORT": "8080"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### SSE Servers
|
||||
|
||||
SSE servers are configured using either a string URL or an object with the following properties:
|
||||
|
||||
- `url` (required)
|
||||
- Type: `str`
|
||||
- Description: The URL of the SSE server
|
||||
|
||||
- `api_key` (optional)
|
||||
- Type: `str`
|
||||
- Default: `None`
|
||||
- Description: API key for authentication with the SSE server
|
||||
|
||||
### Stdio Servers
|
||||
|
||||
Stdio servers are configured using an object with the following properties:
|
||||
|
||||
- `name` (required)
|
||||
- Type: `str`
|
||||
- Description: A unique name for the server
|
||||
|
||||
- `command` (required)
|
||||
- Type: `str`
|
||||
- Description: The command to run the server
|
||||
|
||||
- `args` (optional)
|
||||
- Type: `list of str`
|
||||
- Default: `[]`
|
||||
- Description: Command-line arguments to pass to the server
|
||||
|
||||
- `env` (optional)
|
||||
- Type: `dict of str to str`
|
||||
- Default: `{}`
|
||||
- Description: Environment variables to set for the server process
|
||||
|
||||
## How MCP Works
|
||||
|
||||
When OpenHands starts, it:
|
||||
|
||||
1. Reads the MCP configuration from `config.toml`
|
||||
2. Connects to any configured SSE servers
|
||||
3. Starts any configured stdio servers
|
||||
4. Registers the tools provided by these servers with the agent
|
||||
|
||||
The agent can then use these tools just like any built-in tool. When the agent calls an MCP tool:
|
||||
|
||||
1. OpenHands routes the call to the appropriate MCP server
|
||||
2. The server processes the request and returns a response
|
||||
3. OpenHands converts the response to an observation and presents it to the agent
|
||||
38
docs/modules/usage/prompting/microagents-keyword.md
Normal file
38
docs/modules/usage/prompting/microagents-keyword.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Keyword-Triggered Microagents
|
||||
|
||||
## Purpose
|
||||
|
||||
Keyword-triggered microagents provide OpenHands with specific instructions that are activated when certain keywords
|
||||
appear in the prompt. This is useful for tailoring behavior based on particular tools, languages, or frameworks.
|
||||
|
||||
## Usage
|
||||
|
||||
These microagents are only loaded when a prompt includes one of the trigger words.
|
||||
|
||||
## Frontmatter Syntax
|
||||
|
||||
Frontmatter is required for keyword-triggered microagents. It must be placed at the top of the file,
|
||||
above the guidelines.
|
||||
|
||||
Enclose the frontmatter in triple dashes (---) and include the following fields:
|
||||
|
||||
| Field | Description | Required | Default |
|
||||
|------------|--------------------------------------------------|----------|------------------|
|
||||
| `triggers` | A list of keywords that activate the microagent. | Yes | None |
|
||||
| `agent` | The agent this microagent applies to. | No | 'CodeActAgent' |
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
Keyword-triggered microagent file example located at `.openhands/microagents/yummy.md`:
|
||||
```
|
||||
---
|
||||
triggers:
|
||||
- yummyhappy
|
||||
- happyyummy
|
||||
---
|
||||
|
||||
The user has said the magic word. Respond with "That was delicious!"
|
||||
```
|
||||
|
||||
[See examples of microagents triggered by keywords in the official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)
|
||||
@@ -1,31 +1,40 @@
|
||||
# Microagents Overview
|
||||
|
||||
Microagents are specialized prompts that enhance OpenHands with domain-specific knowledge, repository-specific context
|
||||
and task-specific workflows. They help by providing expert guidance, automating common tasks, and ensuring
|
||||
consistent practices across projects.
|
||||
Microagents are specialized prompts that enhance OpenHands with domain-specific knowledge.
|
||||
They provide expert guidance, automate common tasks, and ensure consistent practices across projects.
|
||||
|
||||
## Microagent Categories
|
||||
## Microagent Types
|
||||
|
||||
Currently OpenHands supports two categories of microagents:
|
||||
Currently OpenHands supports the following types of microagents:
|
||||
|
||||
- [Repository-specific Microagents](./microagents-repo): Repository-specific context and guidelines for OpenHands.
|
||||
- [Public Microagents](./microagents-public): General guidelines triggered by keywords for all OpenHands users.
|
||||
- [General Repository Microagents](./microagents-repo): General guidelines for OpenHands about the repository.
|
||||
- [Keyword-Triggered Microagents](./microagents-keyword): Guidelines activated by specific keywords in prompts.
|
||||
|
||||
A microagent is classified as repository-specific or public depending on its location:
|
||||
To customize OpenHands' behavior, create a .openhands/microagents/ directory in the root of your repository and
|
||||
add `<microagent_name>.md` files inside.
|
||||
|
||||
- Repository-specific microagents are located in a repository's `.openhands/microagents/` directory
|
||||
- Public microagents are located in the official OpenHands repository inside the `/microagents` folder
|
||||
:::note
|
||||
Loaded microagents take up space in the context window.
|
||||
These microagents, alongside user messages, inform OpenHands about the task and the environment.
|
||||
:::
|
||||
|
||||
When OpenHands works with a repository, it:
|
||||
Example repository structure:
|
||||
|
||||
1. Loads **repository-specific** microagents from `.openhands/microagents/` if present in the repository.
|
||||
2. Loads **public knowledge** microagents triggered by keywords in conversations
|
||||
3. Loads **public tasks** microagents when explicitly requested by the user
|
||||
```
|
||||
some-repository/
|
||||
└── .openhands/
|
||||
└── microagents/
|
||||
└── repo.md # General repository guidelines
|
||||
└── trigger_this.md # Microagent triggered by specific keywords
|
||||
└── trigger_that.md # Microagent triggered by specific keywords
|
||||
```
|
||||
|
||||
You can check out the existing public microagents at the [official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/).
|
||||
## Microagents Frontmatter Requirements
|
||||
|
||||
## Microagent Format
|
||||
Each microagent file may include frontmatter that provides additional information. In some cases, this frontmatter
|
||||
is required:
|
||||
|
||||
All microagents use markdown files with YAML frontmatter that have special instructions to help OpenHands activate them.
|
||||
|
||||
Check out the [syntax documentation](./microagents-syntax) for a comprehensive guide on how to configure your microagents.
|
||||
| Microagent Type | Required |
|
||||
|----------------------------------|----------|
|
||||
| `General Repository Microagents` | No |
|
||||
| `Keyword-Triggered Microagents` | Yes |
|
||||
|
||||
@@ -1,35 +1,17 @@
|
||||
# Public Microagents
|
||||
# Global Microagents
|
||||
|
||||
## Overview
|
||||
|
||||
Public microagents provide specialized context and capabilities for all OpenHands users, regardless of their repository configuration. Unlike repository-specific microagents, public microagents are globally available across all repositories.
|
||||
Global microagents are [keyword-triggered microagents](./microagents-keyword) that apply to all OpenHands users. A list of the current
|
||||
global microagents can be found [in the OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents).
|
||||
|
||||
Public microagents come in two types:
|
||||
## Contributing a Global Microagent
|
||||
|
||||
- **Knowledge microagents**: Automatically activated when keywords in conversations match their triggers
|
||||
- **Task microagents**: Explicitly invoked by users to guide through specific workflows
|
||||
|
||||
Both types follow the same syntax and structure as repository-specific microagents, using markdown files with YAML frontmatter that define their behavior and capabilities. They are located in the official OpenHands repository under:
|
||||
|
||||
- [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) for knowledge microagents
|
||||
- [`microagents/tasks/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks) for task microagents
|
||||
|
||||
Public microagents:
|
||||
|
||||
- Monitor incoming commands for their trigger words.
|
||||
- Activate when relevant triggers are detected.
|
||||
- Apply their specialized knowledge and capabilities.
|
||||
- Follow their specific guidelines and restrictions.
|
||||
|
||||
When loading public microagents, OpenHands scans the official repository's microagents directories recursively, processing all markdown files except README.md. The system categorizes each microagent based on its `type` field in the YAML frontmatter, regardless of its exact file location within the knowledge or tasks directories.
|
||||
|
||||
## Contributing a Public Microagent
|
||||
|
||||
You can create public microagents and share with the community by opening a pull request to the official repository.
|
||||
You can create global microagents and share with the community by opening a pull request to the official repository.
|
||||
|
||||
See the [CONTRIBUTING.md](https://github.com/All-Hands-AI/OpenHands/blob/main/CONTRIBUTING.md) for specific instructions on how to contribute to OpenHands.
|
||||
|
||||
### Public Microagents Best Practices
|
||||
### Global Microagents Best Practices
|
||||
|
||||
- **Clear Scope**: Keep the microagent focused on a specific domain or task.
|
||||
- **Explicit Instructions**: Provide clear, unambiguous guidelines.
|
||||
@@ -37,11 +19,11 @@ See the [CONTRIBUTING.md](https://github.com/All-Hands-AI/OpenHands/blob/main/CO
|
||||
- **Safety First**: Include necessary warnings and constraints.
|
||||
- **Integration Awareness**: Consider how the microagent interacts with other components.
|
||||
|
||||
### Steps to Contribute a Public Microagent
|
||||
### Steps to Contribute a Global Microagent
|
||||
|
||||
#### 1. Plan the Public Microagent
|
||||
#### 1. Plan the Global Microagent
|
||||
|
||||
Before creating a public microagent, consider:
|
||||
Before creating a global microagent, consider:
|
||||
|
||||
- What specific problem or use case will it address?
|
||||
- What unique capabilities or knowledge should it have?
|
||||
@@ -51,23 +33,19 @@ Before creating a public microagent, consider:
|
||||
#### 2. Create File
|
||||
|
||||
Create a new Markdown file with a descriptive name in the appropriate directory:
|
||||
[`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)
|
||||
|
||||
- [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) for knowledge microagents
|
||||
- [`microagents/tasks/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks) for task microagents
|
||||
#### 3. Testing the Global Microagent
|
||||
|
||||
Ensure it follows the correct [syntax](./microagents-syntax.md) and [best practices](./microagents-syntax.md#markdown-content-best-practices).
|
||||
|
||||
#### 3. Testing the Public Microagent
|
||||
|
||||
- Test the agent with various prompts
|
||||
- Verify trigger words activate the agent correctly
|
||||
- Ensure instructions are clear and comprehensive
|
||||
- Check for potential conflicts and overlaps with existing agents
|
||||
- Test the agent with various prompts.
|
||||
- Verify trigger words activate the agent correctly.
|
||||
- Ensure instructions are clear and comprehensive.
|
||||
- Check for potential conflicts and overlaps with existing agents.
|
||||
|
||||
#### 4. Submission Process
|
||||
|
||||
Submit a pull request with:
|
||||
|
||||
- The new microagent file
|
||||
- Updated documentation if needed
|
||||
- Description of the agent's purpose and capabilities
|
||||
- The new microagent file.
|
||||
- Updated documentation if needed.
|
||||
- Description of the agent's purpose and capabilities.
|
||||
|
||||
@@ -1,117 +1,31 @@
|
||||
# Repository-specific Microagents
|
||||
# General Repository Microagents
|
||||
|
||||
## Overview
|
||||
## Purpose
|
||||
|
||||
OpenHands can be customized to work more effectively with specific repositories by providing repository-specific context and guidelines.
|
||||
General guidelines for OpenHands to work more effectively with the repository.
|
||||
|
||||
This section explains how to optimize OpenHands for your project.
|
||||
## Usage
|
||||
|
||||
## Creating Repository Microagents
|
||||
These microagents are always loaded as part of the context.
|
||||
|
||||
You can customize OpenHands' behavior for your repository by creating a `.openhands/microagents/` directory in your repository's root.
|
||||
## Frontmatter Syntax
|
||||
|
||||
You can enhance OpenHands' performance by adding custom microagents to your repository:
|
||||
The frontmatter for this type of microagent is optional.
|
||||
|
||||
1. For overall repository-specific instructions, create a `.openhands/microagents/repo.md` file
|
||||
2. For reusable domain knowledge triggered by keywords, add multiple `.md` files to `.openhands/microagents/knowledge/`
|
||||
3. For common workflows and tasks, create multiple `.md` files to `.openhands/microagents/tasks/`
|
||||
Frontmatter should be enclosed in triple dashes (---) and may include the following fields:
|
||||
|
||||
Check out the [best practices](./microagents-syntax.md#markdown-content-best-practices) for formatting the content of your custom microagent.
|
||||
| Field | Description | Required | Default |
|
||||
|-----------|-----------------------------------------|----------|----------------|
|
||||
| `agent` | The agent this microagent applies to | No | 'CodeActAgent' |
|
||||
|
||||
Keep in mind that loaded microagents take up space in the context window. It's crucial to strike a balance between the additional context provided by microagents and the instructions provided in the user's inputs.
|
||||
|
||||
Note that you can use OpenHands to create new microagents. The public microagent [`add_agent`](https://github.com/All-Hands-AI/OpenHands/blob/main/microagents/knowledge/add_agent.md) is loaded to all OpenHands instance and can support you on this.
|
||||
|
||||
## Types of Microagents
|
||||
|
||||
OpenHands supports three primary types of microagents, each with specific purposes and features to enhance agent performance:
|
||||
|
||||
- [repository](#repository-microagents)
|
||||
- [knowledge](#knowledge-microagents)
|
||||
- [tasks](#tasks-microagents)
|
||||
|
||||
The standard directory structure within a repository is:
|
||||
|
||||
- One main `repo.md` file containing repository-specific instructions
|
||||
- Additional `Knowledge` agents in `.openhands/microagents/knowledge/` directory
|
||||
- Additional `Task` agents in `.openhands/microagents/tasks/` directory
|
||||
|
||||
When processing the `.openhands/microagents/` directory, OpenHands will recursively scan all subfolders and process any `.md` files (except `README.md`) it finds. The system determines the microagent type based on the `type` field in the YAML frontmatter, not by the file's location. However, for organizational clarity, it's recommended to follow the standard directory structure.
|
||||
|
||||
### Repository Microagents
|
||||
|
||||
The `Repository` microagent is loaded specifically from `.openhands/microagents/repo.md` and serves as the main
|
||||
repository-specific instruction file. This single file is automatically loaded whenever OpenHands works with that repository
|
||||
without requiring any keyword matching or explicit call from the user.
|
||||
|
||||
OpenHands does not support multiple `repo.md` files in different locations or multiple microagents with type `repo`.
|
||||
|
||||
If you need to organize different types of repository information, the recommended approach is to use a single `repo.md` file with well-structured sections rather than trying to create multiple microagents with the type `repo`.
|
||||
|
||||
The best practice is to include project-specific instructions, team practices, coding standards, and architectural guidelines that are relevant for **all** prompts in that repository.
|
||||
|
||||
Example structure:
|
||||
## Example
|
||||
|
||||
General repository microagent file example located at `.openhands/microagents/repo.md`:
|
||||
```
|
||||
your-repository/
|
||||
└── .openhands/
|
||||
└── microagents/
|
||||
└── repo.md # Repository-specific instructions
|
||||
This project is a TODO application that allows users to track TODO items.
|
||||
|
||||
To set it up, you can run `npm run build`.
|
||||
Always make sure the tests are passing before committing changes. You can run the tests by running `npm run test`.
|
||||
```
|
||||
|
||||
[See the example in the official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/blob/main/.openhands/microagents/repo.md?plain=1)
|
||||
|
||||
### Knowledge Microagents
|
||||
|
||||
Knowledge microagents provide specialized domain expertise:
|
||||
|
||||
- Recommended to be located in `.openhands/microagents/knowledge/`
|
||||
- Triggered by specific keywords in conversations
|
||||
- Contain expertise on tools, languages, frameworks, and common practices
|
||||
|
||||
Use knowledge microagents to trigger additional context relevant to specific technologies, tools, or workflows. For example, mentioning "git" in your conversation will automatically trigger git-related expertise to help with Git operations.
|
||||
|
||||
Examples structure:
|
||||
|
||||
```
|
||||
your-repository/
|
||||
└── .openhands/
|
||||
└── microagents/
|
||||
└── knowledge/
|
||||
└── git.md
|
||||
└── docker.md
|
||||
└── python.md
|
||||
└── ...
|
||||
└── repo.md
|
||||
```
|
||||
|
||||
You can find several real examples of `Knowledge` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)
|
||||
|
||||
### Tasks Microagents
|
||||
|
||||
Task microagents guide users through interactive workflows:
|
||||
|
||||
- Recommended to be located in `.openhands/microagents/tasks/`
|
||||
- Provide step-by-step processes for common development tasks
|
||||
- Accept inputs and adapt to different scenarios
|
||||
- Ensure consistent outcomes for complex operations
|
||||
|
||||
Task microagents are a convenient way to store multi-step processes you perform regularly. For instance, you can create a `update_pr_description.md` microagent to automatically generate better pull request descriptions based on code changes.
|
||||
|
||||
Examples structure:
|
||||
|
||||
```
|
||||
your-repository/
|
||||
└── .openhands/
|
||||
└── microagents/
|
||||
└── tasks/
|
||||
└── update_pr_description.md
|
||||
└── address_pr_comments.md
|
||||
└── get_test_to_pass.md
|
||||
└── ...
|
||||
└── knowledge/
|
||||
└── ...
|
||||
└── repo.md
|
||||
```
|
||||
|
||||
You can find several real examples of `Tasks` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks)
|
||||
[See more examples of general repository microagents here.](https://github.com/All-Hands-AI/OpenHands/tree/main/.openhands/microagents)
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
# Microagents Syntax
|
||||
|
||||
Microagents are defined using markdown files with YAML frontmatter that specify their behavior, triggers, and capabilities.
|
||||
|
||||
Find below a comprehensive description of the frontmatter syntax and other details about how to use each type of microagent available at OpenHands.
|
||||
|
||||
## Frontmatter Schema
|
||||
|
||||
Every microagent requires a YAML frontmatter section at the beginning of the file, enclosed by triple dashes (`---`). The fields are:
|
||||
|
||||
| Field | Description | Required | Used By |
|
||||
| ---------- | -------------------------------------------------- | ------------------------ | ---------------- |
|
||||
| `name` | Unique identifier for the microagent | Yes | All types |
|
||||
| `type` | Type of microagent: `repo`, `knowledge`, or `task` | Yes | All types |
|
||||
| `version` | Version number (Semantic versioning recommended) | Yes | All types |
|
||||
| `agent` | The agent type (typically `CodeActAgent`) | Yes | All types |
|
||||
| `author` | Creator of the microagent | No | All types |
|
||||
| `triggers` | List of keywords that activate the microagent | Yes for knowledge agents | Knowledge agents |
|
||||
| `inputs` | Defines required user inputs for task execution | Yes for task agents | Task agents |
|
||||
|
||||
## Core Fields
|
||||
|
||||
### `agent`
|
||||
|
||||
**Purpose**: Specifies which agent implementation processes the microagent (typically `CodeActAgent`).
|
||||
|
||||
- Defines a single agent responsible for processing the microagent
|
||||
- Must be available in the OpenHands system (see the [agent hub](https://github.com/All-Hands-AI/OpenHands/tree/main/openhands/agenthub))
|
||||
- If the specified agent is not active, the microagent will not be used
|
||||
|
||||
### `triggers`
|
||||
|
||||
**Purpose**: Defines keywords that activate the `knowledge` microagent.
|
||||
|
||||
**Example**:
|
||||
|
||||
```yaml
|
||||
triggers:
|
||||
- kubernetes
|
||||
- k8s
|
||||
- docker
|
||||
- security
|
||||
- containers cluster
|
||||
```
|
||||
|
||||
**Key points**:
|
||||
|
||||
- Can include both single words and multi-word phrases
|
||||
- Case-insensitive matching is typically used
|
||||
- More specific triggers (like "docker compose") prevent false activations
|
||||
- Multiple triggers increase the chance of activation in relevant contexts
|
||||
- Unique triggers like "flarglebargle" can be used for testing or special functionality
|
||||
- Triggers should be carefully chosen to avoid unwanted activations or conflicts with other microagents
|
||||
- Common terms used in many conversations may cause the microagent to be activated too frequently
|
||||
|
||||
When using multiple triggers, the microagent will be activated if any of the trigger words or phrases appear in the
|
||||
conversation.
|
||||
|
||||
### `inputs`
|
||||
|
||||
**Purpose**: Defines parameters required from the user when a `task` microagent is activated.
|
||||
|
||||
**Schema**:
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- name: INPUT_NAME # Used with {{ INPUT_NAME }}
|
||||
description: 'Description of what this input is for'
|
||||
required: true # Optional, defaults to true
|
||||
```
|
||||
|
||||
**Key points**:
|
||||
|
||||
- The `name` and `description` properties are required for each input
|
||||
- The `required` property is optional and defaults to `true`
|
||||
- Input values are referenced in the microagent body using double curly braces (e.g., `{{ INPUT_NAME }}`)
|
||||
- All inputs defined will be collected from the user before the task microagent executes
|
||||
|
||||
**Variable Usage**: Reference input values using double curly braces `{{ INPUT_NAME }}`.
|
||||
|
||||
## Example Formats
|
||||
|
||||
### Repository Microagent
|
||||
|
||||
Repository microagents provide context and guidelines for a specific repository.
|
||||
|
||||
- Located at: `.openhands/microagents/repo.md`
|
||||
- Automatically loaded when working with the repository
|
||||
- Only one per repository
|
||||
|
||||
The `Repository` microagent is loaded specifically from `.openhands/microagents/repo.md` and serves as the main
|
||||
repository-specific instruction file. This single file is automatically loaded whenever OpenHands works with that repository
|
||||
without requiring any keyword matching or explicit call from the user.
|
||||
|
||||
[See the example in the official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/blob/main/.openhands/microagents/repo.md?plain=1)
|
||||
|
||||
### Knowledge Microagent
|
||||
|
||||
Provides specialized domain expertise triggered by keywords.
|
||||
|
||||
You can find several real examples of `Knowledge` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)
|
||||
|
||||
### Task Microagent
|
||||
|
||||
When explicitly asked by the user, will guide through interactive workflows with specific inputs.
|
||||
|
||||
You can find several real examples of `Tasks` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks)
|
||||
|
||||
## Markdown Content Best Practices
|
||||
|
||||
After the frontmatter, compose the microagent body using Markdown syntax. Examples of elements you can include are:
|
||||
|
||||
- Clear, concise instructions outlining the microagent's purpose and responsibilities
|
||||
- Specific guidelines and constraints the microagent should adhere to
|
||||
- Relevant code snippets and practical examples to illustrate key points
|
||||
- Step-by-step procedures for task agents, guiding users through workflows
|
||||
|
||||
**Design Tips**:
|
||||
|
||||
- Keep microagents focused with a clear purpose
|
||||
- Provide specific guidelines rather than general advice
|
||||
- Use distinctive triggers for knowledge agents
|
||||
- Keep content concise to minimize context window usage
|
||||
- Break large microagents into smaller, focused ones
|
||||
|
||||
Aim for clarity, brevity, and practicality in your writing. Use formatting like bullet points, code blocks, and emphasis to enhance readability and comprehension.
|
||||
|
||||
Remember that balancing microagents details with user input space is important for maintaining effective interactions.
|
||||
@@ -1,37 +1,38 @@
|
||||
# Prompting Best Practices
|
||||
|
||||
When working with OpenHands AI software developer, it's crucial to provide clear and effective prompts. This guide outlines best practices for creating prompts that will yield the most accurate and useful responses.
|
||||
When working with OpenHands AI software developer, providing clear and effective prompts is key to getting accurate
|
||||
and useful responses. This guide outlines best practices for crafting effective prompts.
|
||||
|
||||
## Characteristics of Good Prompts
|
||||
|
||||
Good prompts are:
|
||||
|
||||
- **Concrete**: They explain exactly what functionality should be added or what error needs to be fixed.
|
||||
- **Location-specific**: If known, they explain the locations in the code base that should be modified.
|
||||
- **Appropriately scoped**: They should be the size of a single feature, typically not exceeding 100 lines of code.
|
||||
- **Concrete**: Clearly describe what functionality should be added or what error needs fixing.
|
||||
- **Location-specific**: Specify the locations in the codebase that should be modified, if known.
|
||||
- **Appropriately scoped**: Focus on a single feature, typically not exceeding 100 lines of code.
|
||||
|
||||
## Examples
|
||||
|
||||
### Good Prompt Examples
|
||||
|
||||
- "Add a function `calculate_average` in `utils/math_operations.py` that takes a list of numbers as input and returns their average."
|
||||
- "Fix the TypeError in `frontend/src/components/UserProfile.tsx` occurring on line 42. The error suggests we're trying to access a property of undefined."
|
||||
- "Implement input validation for the email field in the registration form. Update `frontend/src/components/RegistrationForm.tsx` to check if the email is in a valid format before submission."
|
||||
- Add a function `calculate_average` in `utils/math_operations.py` that takes a list of numbers as input and returns their average.
|
||||
- Fix the TypeError in `frontend/src/components/UserProfile.tsx` occurring on line 42. The error suggests we're trying to access a property of undefined.
|
||||
- Implement input validation for the email field in the registration form. Update `frontend/src/components/RegistrationForm.tsx` to check if the email is in a valid format before submission.
|
||||
|
||||
### Bad Prompt Examples
|
||||
|
||||
- "Make the code better." (Too vague, not concrete)
|
||||
- "Rewrite the entire backend to use a different framework." (Not appropriately scoped)
|
||||
- "There's a bug somewhere in the user authentication. Can you find and fix it?" (Lacks specificity and location information)
|
||||
- Make the code better. (Too vague, not concrete)
|
||||
- Rewrite the entire backend to use a different framework. (Not appropriately scoped)
|
||||
- There's a bug somewhere in the user authentication. Can you find and fix it? (Lacks specificity and location information)
|
||||
|
||||
## Tips for Effective Prompting
|
||||
|
||||
- Be as specific as possible about the desired outcome or the problem to be solved.
|
||||
- Provide context, including relevant file paths and line numbers if available.
|
||||
- Break down large tasks into smaller, manageable prompts.
|
||||
- Include any relevant error messages or logs.
|
||||
- Specify the programming language or framework if it's not obvious from the context.
|
||||
- Break large tasks into smaller, manageable prompts.
|
||||
- Include relevant error messages or logs.
|
||||
- Specify the programming language or framework, if not obvious.
|
||||
|
||||
Remember, the more precise and informative your prompt is, the better the AI can assist you in developing or modifying the OpenHands software.
|
||||
The more precise and informative your prompt, the better OpenHands can assist you.
|
||||
|
||||
See [Getting Started with OpenHands](../getting-started) for more examples of helpful prompts.
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Runtime Configuration
|
||||
|
||||
:::note
|
||||
This section is for users that would like to use a runtime other than Docker for OpenHands.
|
||||
:::
|
||||
|
||||
A Runtime is an environment where the OpenHands agent can edit files and run
|
||||
commands.
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ A useful feature is the ability to connect to your local filesystem. To mount yo
|
||||
Be careful! There's nothing stopping the OpenHands agent from deleting or modifying
|
||||
any files that are mounted into its workspace.
|
||||
|
||||
This setup can cause some issues with file permissions (hence the `SANDBOX_USER_ID` variable)
|
||||
but seems to work well on most systems.
|
||||
The `-e SANDBOX_USER_ID=$(id -u)` is passed to the Docker command to ensure the sandbox user matches the host user’s
|
||||
permissions. This prevents the agent from creating root-owned files in the mounted workspace.
|
||||
|
||||
## Hardened Docker Installation
|
||||
|
||||
|
||||
@@ -20,25 +20,18 @@ Try these in order:
|
||||
* If using Docker Desktop, ensure `Settings > Advanced > Allow the default Docker socket to be used` is enabled.
|
||||
* Depending on your configuration you may need `Settings > Resources > Network > Enable host networking` enabled in Docker Desktop.
|
||||
* Reinstall Docker Desktop.
|
||||
---
|
||||
|
||||
# Development Workflow Specific
|
||||
### Error building runtime docker image
|
||||
### Permission Error
|
||||
|
||||
**Description**
|
||||
|
||||
Attempts to start a new session fail, and errors with terms like the following appear in the logs:
|
||||
```
|
||||
debian-security bookworm-security
|
||||
InRelease At least one invalid signature was encountered.
|
||||
```
|
||||
On initial prompt, an error is seen with `Permission Denied` or `PermissionError`.
|
||||
|
||||
This seems to happen when the hash of an existing external library changes and your local docker instance has
|
||||
cached a previous version. To work around this, please try the following:
|
||||
**Resolution**
|
||||
|
||||
* Stop any containers where the name has the prefix `openhands-runtime-` :
|
||||
`docker ps --filter name=openhands-runtime- --filter status=running -aq | xargs docker stop`
|
||||
* Remove any containers where the name has the prefix `openhands-runtime-` :
|
||||
`docker rmi $(docker images --filter name=openhands-runtime- -q --no-trunc)`
|
||||
* Stop and Remove any containers / images where the name has the prefix `openhands-runtime-`
|
||||
* Prune containers / images : `docker container prune -f && docker image prune -f`
|
||||
* Check if the `~/.openhands-state` is owned by `root`. If so, you can:
|
||||
* Change the directory's ownership: `sudo chown <user>:<user> ~/.openhands-state`.
|
||||
* or update permissions on the directory: `sudo chmod 777 ~/.openhands-state`
|
||||
* or delete it if you don’t need previous data. OpenHands will recreate it. You'll need to re-enter LLM settings.
|
||||
* If mounting a local directory, ensure your `WORKSPACE_BASE` has the necessary permissions for the user running
|
||||
OpenHands.
|
||||
|
||||
1587
docs/package-lock.json
generated
1587
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,26 +4,30 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"start": "node generate-swagger-ui.js && docusaurus start",
|
||||
"build": "node generate-swagger-ui.js && docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids",
|
||||
"typecheck": "tsc"
|
||||
"typecheck": "tsc",
|
||||
"generate-swagger-ui": "node generate-swagger-ui.js"
|
||||
},
|
||||
"// Note": "The OpenAPI spec is stored in docs/static/openapi.json so it's accessible at /openapi.json in the deployed site",
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^3.7.0",
|
||||
"@docusaurus/plugin-content-pages": "^3.7.0",
|
||||
"@docusaurus/preset-classic": "^3.7.0",
|
||||
"@docusaurus/theme-mermaid": "^3.7.0",
|
||||
"@mdx-js/react": "^3.1.0",
|
||||
"@node-rs/jieba": "^2.0.1",
|
||||
"clsx": "^2.0.0",
|
||||
"docusaurus-lunr-search": "^3.6.0",
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-use": "^17.6.0"
|
||||
},
|
||||
@@ -31,7 +35,9 @@
|
||||
"@docusaurus/module-type-aliases": "^3.5.1",
|
||||
"@docusaurus/tsconfig": "^3.7.0",
|
||||
"@docusaurus/types": "^3.5.1",
|
||||
"typescript": "~5.8.2"
|
||||
"swagger-cli": "^4.0.4",
|
||||
"swagger-ui-dist": "^5.21.0",
|
||||
"typescript": "~5.8.3"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
@@ -47,5 +53,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0"
|
||||
}
|
||||
},
|
||||
"packageManager": "npm@10.5.0"
|
||||
}
|
||||
|
||||
@@ -18,6 +18,27 @@ const sidebars: SidebarsConfig = {
|
||||
label: 'Key Features',
|
||||
id: 'usage/key-features',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'OpenHands Cloud',
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Openhands Cloud',
|
||||
id: 'usage/cloud/openhands-cloud',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Cloud API',
|
||||
id: 'usage/cloud/cloud-api',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Cloud GitHub Resolver',
|
||||
id: 'usage/cloud/cloud-github-resolver',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Prompting',
|
||||
@@ -27,6 +48,17 @@ const sidebars: SidebarsConfig = {
|
||||
label: 'Best Practices',
|
||||
id: 'usage/prompting/prompting-best-practices',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Customization',
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Repository Customization',
|
||||
id: 'usage/customization/repository',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Microagents',
|
||||
@@ -38,34 +70,23 @@ const sidebars: SidebarsConfig = {
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Repository-specific',
|
||||
label: 'General Repository Microagents',
|
||||
id: 'usage/prompting/microagents-repo',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Public',
|
||||
id: 'usage/prompting/microagents-public',
|
||||
label: 'Keyword-Triggered Microagents',
|
||||
id: 'usage/prompting/microagents-keyword',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Syntax',
|
||||
id: 'usage/prompting/microagents-syntax',
|
||||
label: 'Global Microagents',
|
||||
id: 'usage/prompting/microagents-public',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Customization',
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Repository Customization',
|
||||
id: 'usage/customization/repository',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Usage Methods',
|
||||
@@ -90,23 +111,6 @@ const sidebars: SidebarsConfig = {
|
||||
label: 'Github Action',
|
||||
id: 'usage/how-to/github-action',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Cloud',
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Openhands Cloud',
|
||||
id: 'usage/cloud/openhands-cloud',
|
||||
},
|
||||
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Cloud GitHub Resolver',
|
||||
id: 'usage/cloud/cloud-github-resolver',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -45,7 +45,6 @@ export function HomepageHeader() {
|
||||
<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>
|
||||
<a href="https://codecov.io/github/All-Hands-AI/OpenHands?branch=main"><img alt="CodeCov" src="https://img.shields.io/codecov/c/github/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" /></a>
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE"><img src="https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="MIT License" /></a>
|
||||
<br/>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community" /></a>
|
||||
@@ -53,7 +52,7 @@ export function HomepageHeader() {
|
||||
<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://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>
|
||||
<a href="https://docs.google.com/spreadsheets/d/1wOUdFCMyY6Nt0AIqF705KN4JKOWgeI4wUGUP60krXXs/edit?gid=0#gid=0"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score" /></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
15
docs/static/README.md
vendored
Normal file
15
docs/static/README.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Static Files for OpenHands Documentation
|
||||
|
||||
This directory contains static files that are copied directly to the build output of the Docusaurus documentation.
|
||||
|
||||
## OpenAPI Specification
|
||||
|
||||
The `openapi.json` file in this directory is the OpenAPI specification for the OpenHands API. It is copied to the build output and is accessible at `/openapi.json` in the deployed site.
|
||||
|
||||
This file is used by the Swagger UI interface, which is accessible at `/swagger-ui/` in the deployed site.
|
||||
|
||||
## Why is the OpenAPI spec in the static directory?
|
||||
|
||||
The OpenAPI specification is placed in the static directory so that it's accessible at a predictable URL in the deployed site. This allows the Swagger UI to reference it directly.
|
||||
|
||||
We only need one copy of the OpenAPI spec file, which is this one in the static directory.
|
||||
BIN
docs/static/img/docs/api-key-generation.png
vendored
Normal file
BIN
docs/static/img/docs/api-key-generation.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
BIN
docs/static/img/oh-features.png
vendored
Normal file
BIN
docs/static/img/oh-features.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
2086
docs/static/openapi.json
vendored
Normal file
2086
docs/static/openapi.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9911
docs/yarn.lock
9911
docs/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -131,9 +131,9 @@ def get_config(
|
||||
)
|
||||
)
|
||||
agent_config = AgentConfig(
|
||||
codeact_enable_jupyter=False,
|
||||
codeact_enable_browsing=RUN_WITH_BROWSING,
|
||||
codeact_enable_llm_editor=False,
|
||||
enable_jupyter=False,
|
||||
enable_browsing=RUN_WITH_BROWSING,
|
||||
enable_llm_editor=False,
|
||||
)
|
||||
config.set_agent_config(agent_config)
|
||||
return config
|
||||
|
||||
@@ -79,8 +79,8 @@ def get_config(
|
||||
agent_config.enable_prompt_extensions = False
|
||||
agent_config = AgentConfig(
|
||||
function_calling=False,
|
||||
codeact_enable_jupyter=True,
|
||||
codeact_enable_browsing_delegate=True,
|
||||
enable_jupyter=True,
|
||||
enable_browsing=True,
|
||||
)
|
||||
config.set_agent_config(agent_config)
|
||||
return config
|
||||
|
||||
1
evaluation/benchmarks/lca_ci_build_repair/.gitignore
vendored
Normal file
1
evaluation/benchmarks/lca_ci_build_repair/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
config.yaml
|
||||
35
evaluation/benchmarks/lca_ci_build_repair/README.MD
Normal file
35
evaluation/benchmarks/lca_ci_build_repair/README.MD
Normal file
@@ -0,0 +1,35 @@
|
||||
# CI Builds Repair Benchmark Integration
|
||||
|
||||
This module integrates the CI Builds Repair benchmark developed by [JetBrains-Research](https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair/ci-builds-repair-benchmark).
|
||||
|
||||
For more information, refer to the [GitHub repository](https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair/ci-builds-repair-benchmark) and the associated [research paper](https://arxiv.org/abs/2406.11612).
|
||||
See notice below for details
|
||||
|
||||
## Setup
|
||||
|
||||
Before running any scripts, make sure to configure the benchmark by setting up `config.yaml`.
|
||||
This benchmark pushes to JetBrains' private GitHub repository. You will to request a `token_gh` provided by their team, to run this benchmark.
|
||||
|
||||
## Inference
|
||||
|
||||
To run inference with your model:
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/lca_ci_build_repair/scripts/run_infer.sh llm.yourmodel
|
||||
```
|
||||
|
||||
## Evaluation
|
||||
|
||||
To evaluate the predictions:
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/lca_ci_build_repair/scripts/eval_infer.sh predictions_path_containing_output
|
||||
```
|
||||
|
||||
## Results
|
||||
The benchmark contains 68 instances, we skip instances #126 and #145, and only run 66 instances due to dockerization errors.
|
||||
|
||||
Due to running in live GitHub machines, the benchmark is sensitive to the date it is run. Even the golden patches in the dataset might present failures due to updates.
|
||||
For example, on 2025-04-09, running the benchmark against the golden patches gave 57/67 successes, with 1 job left in the waiting list.
|
||||
|
||||
On 2025-04-10, running the benchmark full with OH and no oracle, 37 succeeded. That is 54% of the complete set of 68 instances and 64% of the 57 that succeed with golden patches.
|
||||
@@ -0,0 +1,11 @@
|
||||
LCA_PATH: path #where to clone lca-ci rep
|
||||
model_name: OpenHands
|
||||
benchmark_owner: ICML-25-BenchName-builds-repair
|
||||
token_gh: your_token
|
||||
#for lca-ci-repo
|
||||
repos_folder: /path/to/repos # here the cloned repos would be stored
|
||||
out_folder: /out/folder # here the result files would be stored
|
||||
data_cache_dir: /data/cache/dir/ # here the cached dataset would be stored
|
||||
username_gh: username-gh # your GitHub username
|
||||
# test_username: test_user # username that would be displayed in the benchmark. Optional. If ommitted, username_gh would be used
|
||||
language: Python # dataset language (now only Python is available)
|
||||
242
evaluation/benchmarks/lca_ci_build_repair/eval_infer.py
Normal file
242
evaluation/benchmarks/lca_ci_build_repair/eval_infer.py
Normal file
@@ -0,0 +1,242 @@
|
||||
"""Implements evaluation on JetBrains CI builds repair baselines
|
||||
|
||||
Please see https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair
|
||||
and https://huggingface.co/datasets/JetBrains-Research/lca-ci-builds-repair
|
||||
|
||||
TODOs:
|
||||
- Add more flags
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import ruamel.yaml
|
||||
|
||||
from evaluation.utils.shared import (
|
||||
EvalMetadata,
|
||||
get_default_sandbox_config_for_eval,
|
||||
make_metadata,
|
||||
)
|
||||
from openhands.core.config import (
|
||||
AppConfig,
|
||||
LLMConfig,
|
||||
get_parser,
|
||||
load_app_config,
|
||||
)
|
||||
from openhands.core.logger import openhands_logger as logger
|
||||
from openhands.core.main import create_runtime
|
||||
from openhands.events.action import CmdRunAction
|
||||
from openhands.events.observation import CmdOutputObservation
|
||||
from openhands.runtime.base import Runtime
|
||||
from openhands.utils.async_utils import call_async_from_sync
|
||||
|
||||
|
||||
def get_config(
|
||||
metadata: EvalMetadata,
|
||||
) -> AppConfig:
|
||||
sandbox_config = get_default_sandbox_config_for_eval()
|
||||
sandbox_config.base_container_image = 'python:3.12-bookworm'
|
||||
config = AppConfig(
|
||||
default_agent=metadata.agent_class,
|
||||
run_as_openhands=False,
|
||||
runtime='docker',
|
||||
max_iterations=metadata.max_iterations,
|
||||
sandbox=sandbox_config,
|
||||
# do not mount workspace
|
||||
workspace_base=None,
|
||||
workspace_mount_path=None,
|
||||
)
|
||||
config.set_llm_config(metadata.llm_config)
|
||||
agent_config = config.get_agent_config(metadata.agent_class)
|
||||
agent_config.enable_prompt_extensions = False
|
||||
return config
|
||||
|
||||
|
||||
config = load_app_config()
|
||||
|
||||
|
||||
def load_bench_config():
|
||||
script_dir = os.path.dirname(
|
||||
os.path.abspath(__file__)
|
||||
) # Get the absolute path of the script
|
||||
config_path = os.path.join(script_dir, 'config.yaml')
|
||||
yaml = ruamel.yaml.YAML(typ='rt')
|
||||
with open(config_path, 'r') as file:
|
||||
return yaml.load(file)
|
||||
|
||||
|
||||
bench_config = load_bench_config()
|
||||
|
||||
|
||||
def run_eval(
|
||||
runtime: Runtime,
|
||||
):
|
||||
"""Run the evaluation and create report"""
|
||||
logger.info(f"{'-' * 50} BEGIN Runtime Initialization Fn {'-' * 50}")
|
||||
obs: CmdOutputObservation
|
||||
|
||||
lca_path = bench_config['LCA_PATH']
|
||||
lca_ci_path = os.path.join(
|
||||
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
|
||||
)
|
||||
|
||||
model_name = bench_config['model_name']
|
||||
|
||||
action = CmdRunAction(command=f'mkdir {lca_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
action = CmdRunAction(command=f'cd {lca_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
lca_repo_url = 'https://github.com/juanmichelini/lca-baselines'
|
||||
action = CmdRunAction(command=f'git clone {lca_repo_url}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
action = CmdRunAction(command=f'cd {lca_ci_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
action = CmdRunAction(command='git switch open-hands-integration')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
script_dir = os.path.dirname(
|
||||
os.path.abspath(__file__)
|
||||
) # Get the absolute path of the script
|
||||
config_path = os.path.join(script_dir, 'config.yaml')
|
||||
runtime.copy_to(config_path, lca_ci_path)
|
||||
|
||||
token_gh = bench_config['token_gh']
|
||||
commandf = f'export TOKEN_GH={token_gh}'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
action = CmdRunAction(command='poetry install')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
# Set up the task environment
|
||||
commandf = f'poetry run python run_eval_jobs.py --model-name "{model_name}" --config-path "{lca_ci_path}/config.yaml" --job-ids-file "/tmp/output_lca.jsonl" --result-filename "testfile.jsonl" > /tmp/single_output.txt'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(f'run_eval_jobs.py gave {obs.content} !')
|
||||
# assert obs.exit_code == 0
|
||||
|
||||
commandf = 'cat /tmp/single_output.txt'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(f' {commandf} gave {obs.content}!')
|
||||
|
||||
testfile_path = os.path.join(bench_config['out_folder'], 'testfile.jsonl')
|
||||
commandf = f'cat {testfile_path}'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
report_str = obs.content
|
||||
|
||||
logger.info(f"{'-' * 50} END Runtime Initialization Fn {'-' * 50}")
|
||||
return report_str
|
||||
|
||||
|
||||
def process_predictions(predictions_path: str):
|
||||
output_path = Path(predictions_path)
|
||||
if output_path.suffix != '.jsonl':
|
||||
raise ValueError('output_path must end in .jsonl')
|
||||
|
||||
output_lca_path = output_path.with_name(output_path.stem + '_lca.jsonl')
|
||||
|
||||
with output_path.open() as infile, output_lca_path.open('w') as outfile:
|
||||
for line in infile:
|
||||
data = json.loads(line)
|
||||
json.dump(data.get('test_result'), outfile)
|
||||
outfile.write('\n')
|
||||
|
||||
return str(output_lca_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = get_parser()
|
||||
parser.add_argument(
|
||||
'-s',
|
||||
'--eval-split',
|
||||
type=str,
|
||||
default='test',
|
||||
choices=['test'],
|
||||
help='data split to evaluate on, must be test',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--predictions-path',
|
||||
type=str,
|
||||
help='Path to the directory containing the output.jsonl with the predictions.',
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
data_split = args.eval_split
|
||||
|
||||
llm_config = LLMConfig(model='dummy_model')
|
||||
|
||||
metadata = make_metadata(
|
||||
llm_config,
|
||||
f'jetbrains-lca-ci--{data_split}',
|
||||
args.agent_cls,
|
||||
args.max_iterations,
|
||||
args.eval_note,
|
||||
args.predictions_path,
|
||||
)
|
||||
|
||||
# prepare image
|
||||
config = get_config(metadata)
|
||||
runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
logger.info('Converting output.jsonl into output_lca.jsonl')
|
||||
predictions_lca_path = process_predictions(
|
||||
os.path.join(args.predictions_path, 'output.jsonl')
|
||||
)
|
||||
runtime.copy_to(predictions_lca_path, '/tmp')
|
||||
|
||||
# get results
|
||||
results_str = run_eval(runtime)
|
||||
results_path = os.path.join(args.predictions_path, 'results.jsonl')
|
||||
with open(results_path, 'w') as file:
|
||||
file.write(results_str)
|
||||
logger.info(f'Saved results to {results_path}')
|
||||
|
||||
# make a summary
|
||||
resolved_instances = []
|
||||
unresolved_instances = []
|
||||
for line in results_str.strip().splitlines():
|
||||
data = json.loads(line)
|
||||
conclusion = data.get('conclusion')
|
||||
if conclusion == 'success':
|
||||
resolved_instances.append(data)
|
||||
elif conclusion == 'failure':
|
||||
unresolved_instances.append(data)
|
||||
|
||||
completed_instances = resolved_instances + unresolved_instances
|
||||
|
||||
report = {
|
||||
'success': len(resolved_instances),
|
||||
'failure': len(unresolved_instances),
|
||||
'resolved_instances': resolved_instances,
|
||||
'unresolved_instances': unresolved_instances,
|
||||
'completed_instances': completed_instances,
|
||||
}
|
||||
|
||||
print(f'Results: {report}')
|
||||
report_path = os.path.join(args.predictions_path, 'report.jsonl')
|
||||
with open(report_path, 'w') as out_f:
|
||||
out_f.write(json.dumps(report) + '\n')
|
||||
|
||||
logger.info(f'Saved report of results in swebench format to {report_path}')
|
||||
406
evaluation/benchmarks/lca_ci_build_repair/run_infer.py
Normal file
406
evaluation/benchmarks/lca_ci_build_repair/run_infer.py
Normal file
@@ -0,0 +1,406 @@
|
||||
"""Implements inference on JetBrains CI builds repair baselines
|
||||
|
||||
Please see https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair
|
||||
and https://huggingface.co/datasets/JetBrains-Research/lca-ci-builds-repair
|
||||
|
||||
TODOs:
|
||||
- Add EXP_NAME
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
import pandas as pd
|
||||
import ruamel.yaml
|
||||
from datasets import load_dataset
|
||||
|
||||
from evaluation.utils.shared import (
|
||||
EvalMetadata,
|
||||
EvalOutput,
|
||||
codeact_user_response,
|
||||
compatibility_for_eval_history_pairs,
|
||||
get_default_sandbox_config_for_eval,
|
||||
make_metadata,
|
||||
prepare_dataset,
|
||||
reset_logger_for_multiprocessing,
|
||||
run_evaluation,
|
||||
)
|
||||
from openhands.controller.state.state import State
|
||||
from openhands.core.config import (
|
||||
AppConfig,
|
||||
get_llm_config_arg,
|
||||
get_parser,
|
||||
load_app_config,
|
||||
)
|
||||
from openhands.core.logger import openhands_logger as logger
|
||||
from openhands.core.main import create_runtime, run_controller
|
||||
from openhands.events.action import CmdRunAction, MessageAction
|
||||
from openhands.events.observation import CmdOutputObservation
|
||||
from openhands.runtime.base import Runtime
|
||||
from openhands.utils.async_utils import call_async_from_sync
|
||||
|
||||
|
||||
def get_config(
|
||||
metadata: EvalMetadata,
|
||||
) -> AppConfig:
|
||||
sandbox_config = get_default_sandbox_config_for_eval()
|
||||
sandbox_config.base_container_image = 'python:3.12-bookworm'
|
||||
config = AppConfig(
|
||||
default_agent=metadata.agent_class,
|
||||
run_as_openhands=False,
|
||||
runtime='docker',
|
||||
max_iterations=metadata.max_iterations,
|
||||
sandbox=sandbox_config,
|
||||
# do not mount workspace
|
||||
workspace_base=None,
|
||||
workspace_mount_path=None,
|
||||
)
|
||||
config.set_llm_config(metadata.llm_config)
|
||||
agent_config = config.get_agent_config(metadata.agent_class)
|
||||
agent_config.enable_prompt_extensions = False
|
||||
return config
|
||||
|
||||
|
||||
config = load_app_config()
|
||||
|
||||
|
||||
def load_bench_config():
|
||||
script_dir = os.path.dirname(
|
||||
os.path.abspath(__file__)
|
||||
) # Get the absolute path of the script
|
||||
config_path = os.path.join(script_dir, 'config.yaml')
|
||||
yaml = ruamel.yaml.YAML(typ='rt')
|
||||
with open(config_path, 'r') as file:
|
||||
return yaml.load(file)
|
||||
|
||||
|
||||
bench_config = load_bench_config()
|
||||
|
||||
AGENT_CLS_TO_FAKE_USER_RESPONSE_FN = {
|
||||
'CodeActAgent': codeact_user_response,
|
||||
}
|
||||
|
||||
AGENT_CLS_TO_INST_SUFFIX = {
|
||||
'CodeActAgent': 'When you think you have completed the task, please finish the interaction using the "finish" tool.\n'
|
||||
}
|
||||
|
||||
|
||||
def initialize_runtime(
|
||||
runtime: Runtime,
|
||||
instance: pd.Series,
|
||||
):
|
||||
"""Initialize the runtime for the agent.
|
||||
|
||||
This function is called before the runtime is used to run the agent.
|
||||
"""
|
||||
logger.info(f"{'-' * 50} BEGIN Runtime Initialization Fn {'-' * 50}")
|
||||
obs: CmdOutputObservation
|
||||
|
||||
lca_path = bench_config['LCA_PATH']
|
||||
lca_ci_path = os.path.join(
|
||||
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
|
||||
)
|
||||
|
||||
repo_name = instance['repo_name']
|
||||
repos_path = bench_config['repos_folder']
|
||||
repo_owner = instance['repo_owner']
|
||||
repo_path = os.path.join(repos_path, f'{repo_owner}__{repo_name}')
|
||||
model_name = bench_config['model_name']
|
||||
|
||||
action = CmdRunAction(command=f'mkdir {lca_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
action = CmdRunAction(command=f'cd {lca_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
lca_repo_url = 'https://github.com/juanmichelini/lca-baselines'
|
||||
action = CmdRunAction(command=f'git clone {lca_repo_url}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
action = CmdRunAction(command=f'cd {lca_ci_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
action = CmdRunAction(command='git switch open-hands-integration')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
script_dir = os.path.dirname(
|
||||
os.path.abspath(__file__)
|
||||
) # Get the absolute path of the script
|
||||
config_path = os.path.join(script_dir, 'config.yaml')
|
||||
with open(config_path, 'r') as file:
|
||||
config_as_text = file.read()
|
||||
|
||||
commandf = f"echo '{config_as_text}' > config.yaml"
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
token_gh = bench_config['token_gh']
|
||||
commandf = f'export TOKEN_GH={token_gh}'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
action = CmdRunAction(command='poetry install')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
# Set up the task environment
|
||||
commandf = f'poetry run python run_get_datapoint.py --model-name {model_name} --id {instance["id"]} > branch_name.txt'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
if obs.exit_code != 0:
|
||||
print(f'run_get_datapoint.py failed at {instance["id"]} with {obs.content}')
|
||||
assert obs.exit_code == 0
|
||||
|
||||
commandf = 'cat branch_name.txt'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
bench_config['user_branch_name'] = obs.content
|
||||
|
||||
# Navigate to the task's code path
|
||||
action = CmdRunAction(command=f'cd {repo_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
logger.info(f"{'-' * 50} END Runtime Initialization Fn {'-' * 50}")
|
||||
|
||||
|
||||
def complete_runtime(
|
||||
runtime: Runtime,
|
||||
instance: pd.Series,
|
||||
) -> dict[str, Any]:
|
||||
"""Complete the runtime for the agent.
|
||||
|
||||
This function is called before the runtime is used to run the agent.
|
||||
If you need to do something in the sandbox to get the correctness metric after
|
||||
the agent has run, modify this function.
|
||||
"""
|
||||
logger.info(f"{'-' * 50} BEGIN Runtime Completion Fn {'-' * 50}")
|
||||
obs: CmdOutputObservation
|
||||
|
||||
model_name = bench_config['model_name']
|
||||
|
||||
lca_path = bench_config['LCA_PATH']
|
||||
lca_ci_path = os.path.join(
|
||||
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
|
||||
)
|
||||
|
||||
user_branch_name = bench_config['user_branch_name']
|
||||
|
||||
token_gh = bench_config['token_gh']
|
||||
commandf = f'export TOKEN_GH={token_gh}'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
# Navigate to the lca-baseslines scripts path
|
||||
action = CmdRunAction(command=f'cd {lca_ci_path}')
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
assert obs.exit_code == 0
|
||||
|
||||
commandf = f'poetry run python run_push_datapoint.py --id {instance["id"]} --model-name {model_name} --user-branch-name {user_branch_name} > single_output.json'
|
||||
logger.info(f'Running push script: {commandf}')
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
# assert obs.exit_code == 0
|
||||
|
||||
commandf = 'cat single_output.json'
|
||||
action = CmdRunAction(command=commandf)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
result = json.loads(obs.content)
|
||||
|
||||
logger.info(f"{'-' * 50} END Runtime Completion Fn {'-' * 50}")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def process_instance(instance: Any, metadata: EvalMetadata, reset_logger: bool = True):
|
||||
config = get_config(metadata)
|
||||
|
||||
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
|
||||
if reset_logger:
|
||||
log_dir = os.path.join(metadata.eval_output_dir, 'infer_logs')
|
||||
reset_logger_for_multiprocessing(logger, instance['instance_id'], log_dir)
|
||||
else:
|
||||
logger.info(f'Starting evaluation for instance {instance["instance_id"]}.')
|
||||
|
||||
repo_name = instance['repo_name']
|
||||
repo_workflow = instance['workflow_path']
|
||||
repo_logs = instance['logs']
|
||||
repos_path = bench_config['repos_folder']
|
||||
repo_owner = instance['repo_owner']
|
||||
repo_path = os.path.join(repos_path, f'{repo_owner}__{repo_name}')
|
||||
|
||||
# Prepare the task instruction
|
||||
instruction_no_oracle = f"""
|
||||
<uploaded_files>
|
||||
{repo_path}
|
||||
</uploaded_files>
|
||||
|
||||
I've uploaded a python code repository in the directory {repo_path}, Consider the following issue:
|
||||
|
||||
<issue_description>
|
||||
The repository must pass the CI workflow {repo_workflow}.
|
||||
but it gave the following error
|
||||
{repo_logs}
|
||||
</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 {repo_path} directory to ensure the <issue_description> is satisfied.
|
||||
|
||||
Follow these phases to resolve the issue:
|
||||
|
||||
Phase 1. READING: read the problem and reword it in clearer terms
|
||||
1.1 If there are code or config snippets. Express in words any best practices or conventions in them.
|
||||
1.2 Hightlight message errors, method names, variables, file names, stack traces, and technical details.
|
||||
1.3 Explain the problem in clear terms.
|
||||
1.4 Enumerate the steps to reproduce the problem.
|
||||
1.5 Hightlight any best practices to take into account when testing and fixing the issue
|
||||
|
||||
Phase 2. RUNNING: install and run the tests on the repository
|
||||
2.1 Follow the readme
|
||||
2.2 Install the environment and anything needed
|
||||
2.2 Iterate and figure out how to run the tests
|
||||
|
||||
Phase 3. EXPLORATION: find the files that are related to the problem and possible solutions
|
||||
3.1 Use `grep` to search for relevant methods, classes, keywords and error messages.
|
||||
3.2 Identify all files related to the problem statement.
|
||||
3.3 Propose the methods and files to fix the issue and explain why.
|
||||
3.4 From the possible file locations, select the most likely location to fix the issue.
|
||||
|
||||
Phase 4. TEST CREATION: before implementing any fix, create a script to reproduce and verify the issue.
|
||||
4.1 Look at existing test files in the repository to understand the test format/structure.
|
||||
4.2 Create a minimal reproduction script that reproduces the located issue.
|
||||
4.3 Run the reproduction script to confirm you are reproducing the issue.
|
||||
4.4 Adjust the reproduction script as necessary.
|
||||
|
||||
Phase 5. FIX ANALYSIS: state clearly the problem and how to fix it
|
||||
5.1 State clearly what the problem is.
|
||||
5.2 State clearly where the problem is located.
|
||||
5.3 State clearly how the test reproduces the issue.
|
||||
5.4 State clearly the best practices to take into account in the fix.
|
||||
5.5 State clearly how to fix the problem.
|
||||
|
||||
Phase 6. FIX IMPLEMENTATION: Edit the source code to implement your chosen solution.
|
||||
6.1 Make minimal, focused changes to fix the issue.
|
||||
|
||||
Phase 7. VERIFICATION: Test your implementation thoroughly.
|
||||
7.1 Run your reproduction script to verify the fix works.
|
||||
7.2 Add edge cases to your test script to ensure comprehensive coverage.
|
||||
7.3 Run existing tests related to the modified code to ensure you haven't broken anything. Run any tests in the repository related to:
|
||||
7.2.1 The issue you are fixing
|
||||
7.2.2 The files you modified
|
||||
7.2.3 The functions you changed
|
||||
7.4 If any tests fail, revise your implementation until all tests pass
|
||||
|
||||
Phase 8. REVIEW: Carefully re-read the problem description and compare your changes with the base commit {instance["sha_fail"]}.
|
||||
8.1 Ensure you've fully addressed all requirements.
|
||||
|
||||
Once all phases are done, announce: 'Agent Task Complete'.
|
||||
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.
|
||||
"""
|
||||
runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
initialize_runtime(runtime, instance)
|
||||
|
||||
# Run the agent
|
||||
state: State | None = asyncio.run(
|
||||
run_controller(
|
||||
config=config,
|
||||
initial_user_action=MessageAction(content=instruction_no_oracle),
|
||||
runtime=runtime,
|
||||
fake_user_response_fn=AGENT_CLS_TO_FAKE_USER_RESPONSE_FN.get(
|
||||
metadata.agent_class
|
||||
),
|
||||
)
|
||||
)
|
||||
assert state is not None
|
||||
metrics = state.metrics.get() if state.metrics else {}
|
||||
|
||||
test_result = complete_runtime(runtime, instance)
|
||||
|
||||
# history is now available as a stream of events, rather than list of pairs of (Action, Observation)
|
||||
# for compatibility with the existing output format, we can remake the pairs here
|
||||
# remove when it becomes unnecessary
|
||||
histories = compatibility_for_eval_history_pairs(state.history)
|
||||
|
||||
# Save the output
|
||||
output = EvalOutput(
|
||||
instance_id=instance['instance_id'],
|
||||
# instance=instance.to_dict(orient='recorods'),
|
||||
instruction=instruction_no_oracle,
|
||||
metadata=metadata,
|
||||
history=histories,
|
||||
test_result=test_result,
|
||||
metrics=metrics,
|
||||
)
|
||||
return output
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = get_parser()
|
||||
parser.add_argument(
|
||||
'-s',
|
||||
'--eval-split',
|
||||
type=str,
|
||||
default='test',
|
||||
choices=['test'],
|
||||
help='data split to evaluate on, must be test',
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
data_split = args.eval_split
|
||||
|
||||
bench = load_dataset(
|
||||
'JetBrains-Research/lca-ci-builds-repair', split=data_split
|
||||
).to_pandas()
|
||||
# todo: see why 126 is giving problems on inference
|
||||
# todo: see why 145 is giving problems on eval
|
||||
bench = bench[bench['id'] != 126]
|
||||
bench = bench[bench['id'] != 145]
|
||||
# bench = bench.iloc[0:56]
|
||||
# add column instnace_id for compatibility with oh repo, old id column must be kept for lca repo
|
||||
bench['instance_id'] = bench['id'].astype(str)
|
||||
|
||||
llm_config = None
|
||||
if args.llm_config:
|
||||
llm_config = get_llm_config_arg(args.llm_config)
|
||||
# modify_params must be False for evaluation purpose, for reproducibility and accurancy of results
|
||||
llm_config.modify_params = False
|
||||
if llm_config is None:
|
||||
raise ValueError(f'Could not find LLM config: --llm_config {args.llm_config}')
|
||||
|
||||
metadata = make_metadata(
|
||||
llm_config,
|
||||
f'jetbrains-lca-ci--{data_split}',
|
||||
args.agent_cls,
|
||||
args.max_iterations,
|
||||
args.eval_note,
|
||||
args.eval_output_dir,
|
||||
)
|
||||
output_file = os.path.join(metadata.eval_output_dir, 'output.jsonl')
|
||||
instances = prepare_dataset(bench, output_file, args.eval_n_limit)
|
||||
|
||||
run_evaluation(
|
||||
instances, metadata, output_file, args.eval_num_workers, process_instance
|
||||
)
|
||||
33
evaluation/benchmarks/lca_ci_build_repair/scripts/eval_infer.sh
Executable file
33
evaluation/benchmarks/lca_ci_build_repair/scripts/eval_infer.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
source "evaluation/utils/version_control.sh"
|
||||
|
||||
PROCESS_FILEPATH=$1
|
||||
if [ -z "$PROCESS_FILEPATH" ]; then
|
||||
echo "Error: PROCESS_FILEPATH is empty. Usage: ./eval_infer.sh <output_file> [instance_id] [dataset_name] [split]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_openhands_version
|
||||
|
||||
PROCESS_FILEPATH=$(realpath $PROCESS_FILEPATH)
|
||||
echo "OPENHANDS_VERSION: $OPENHANDS_VERSION"
|
||||
echo "PROCESS_FILEPATH: $PROCESS_FILEPATH"
|
||||
|
||||
EVAL_NOTE="$OPENHANDS_VERSION"
|
||||
if [ -n "$EXP_NAME" ]; then
|
||||
EVAL_NOTE="$EVAL_NOTE-$EXP_NAME"
|
||||
fi
|
||||
|
||||
function run_eval() {
|
||||
COMMAND="poetry run python ./evaluation/benchmarks/lca_ci_build_repair/eval_infer.py \
|
||||
--predictions-path $PROCESS_FILEPATH "
|
||||
|
||||
echo "RUNNING: $COMMAND"
|
||||
# Run the command
|
||||
eval $COMMAND
|
||||
}
|
||||
|
||||
unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
|
||||
run_eval
|
||||
27
evaluation/benchmarks/lca_ci_build_repair/scripts/run_infer.sh
Executable file
27
evaluation/benchmarks/lca_ci_build_repair/scripts/run_infer.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
source "evaluation/utils/version_control.sh"
|
||||
|
||||
MODEL_CONFIG=$1
|
||||
|
||||
get_openhands_version
|
||||
|
||||
echo "OPENHANDS_VERSION: $OPENHANDS_VERSION"
|
||||
echo "MODEL_CONFIG: $MODEL_CONFIG"
|
||||
|
||||
EVAL_NOTE="$OPENHANDS_VERSION"
|
||||
if [ -n "$EXP_NAME" ]; then
|
||||
EVAL_NOTE="$EVAL_NOTE-$EXP_NAME"
|
||||
fi
|
||||
|
||||
function run_eval() {
|
||||
COMMAND="poetry run python ./evaluation/benchmarks/lca_ci_build_repair/run_infer.py \
|
||||
--llm-config $MODEL_CONFIG "
|
||||
|
||||
# Run the command
|
||||
eval $COMMAND
|
||||
}
|
||||
|
||||
#unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
|
||||
run_eval
|
||||
60
evaluation/benchmarks/lca_ci_build_repair/setup.py
Normal file
60
evaluation/benchmarks/lca_ci_build_repair/setup.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""Installs LCA CI Build Repair benchmark with scripts for OH integration."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
def setup():
|
||||
# Read config.yaml
|
||||
print('Reading config.yaml')
|
||||
script_dir = os.path.dirname(
|
||||
os.path.abspath(__file__)
|
||||
) # Get the absolute path of the script
|
||||
config_path = os.path.join(script_dir, 'config.yaml')
|
||||
with open(config_path, 'r') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
lca_path = config['LCA_PATH']
|
||||
lca_ci_path = os.path.join(
|
||||
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
|
||||
)
|
||||
repo_url = 'https://github.com/juanmichelini/lca-baselines'
|
||||
|
||||
# Clone the repository to LCA_CI_PATH
|
||||
print(f'Cloning lca-baselines repository from {repo_url} into {lca_path}')
|
||||
result = subprocess.run(
|
||||
['git', 'clone', repo_url], cwd=lca_path, capture_output=True, text=True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f'Warning cloning repository: {result.stderr}')
|
||||
|
||||
# Clone the repository to LCA_CI_PATH
|
||||
print('Switching branches')
|
||||
result = subprocess.run(
|
||||
['git', 'switch', 'open-hands-integration'],
|
||||
cwd=lca_ci_path,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f'Warning switching repository: {result.stderr}')
|
||||
|
||||
# Move and rename config_lca.yaml (overwrite if exists)
|
||||
lca_ci_config_path = os.path.join(lca_ci_path, 'config.yaml')
|
||||
print(f'Copying config.yaml to {lca_ci_config_path}')
|
||||
shutil.copy(config_path, lca_ci_config_path)
|
||||
|
||||
# Run poetry install in LCA_CI_PATH
|
||||
print(f"Running 'poetry install' in {lca_ci_path}")
|
||||
result = subprocess.run(
|
||||
['poetry', 'install'], cwd=lca_ci_path, capture_output=True, text=True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f'Warning during poetry install: {result.stderr}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
setup()
|
||||
65
evaluation/benchmarks/multi_swe_bench/README.md
Normal file
65
evaluation/benchmarks/multi_swe_bench/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Multi-swe-bench Evaluation with OpenHands
|
||||
|
||||
## LLM Setup
|
||||
|
||||
Please follow [here](../../README.md#setup).
|
||||
|
||||
## Dataset Preparing
|
||||
|
||||
Please download the [**Multi-SWE-Bench** dataset](https://huggingface.co/datasets/bytedance-research/Multi-SWE-Bench).
|
||||
And change the dataset following [script](scripts/data/data_change.py).
|
||||
|
||||
```bash
|
||||
python evaluation/benchmarks/multi_swe_bench/scripts/data/data_change.py
|
||||
```
|
||||
|
||||
## Docker image download
|
||||
|
||||
Please download the multi-swe-bench dokcer images from [here](https://github.com/multi-swe-bench/multi-swe-bench?tab=readme-ov-file#run-evaluation).
|
||||
|
||||
## Generate patch
|
||||
|
||||
Please edit the [script](infer.sh) and run it.
|
||||
|
||||
```bash
|
||||
bash evaluation/benchmarks/multi_swe_bench/infer.sh
|
||||
```
|
||||
|
||||
Script variable explanation:
|
||||
|
||||
- `models`, e.g. `llm.eval_gpt4_1106_preview`, is the config group name for your
|
||||
LLM settings, as defined in your `config.toml`.
|
||||
- `git-version`, e.g. `HEAD`, is the git commit hash of the OpenHands version you would
|
||||
like to evaluate. It could also be a release tag like `0.6.2`.
|
||||
- `agent`, e.g. `CodeActAgent`, is the name of the agent for benchmarks, defaulting to `CodeActAgent`.
|
||||
- `eval_limit`, e.g. `10`, limits the evaluation to the first `eval_limit` instances. By
|
||||
default, the script evaluates the (500 issues), which will no exceed the maximum of the dataset number.
|
||||
- `max_iter`, e.g. `20`, is the maximum number of iterations for the agent to run. By
|
||||
default, it is set to 50.
|
||||
- `num_workers`, e.g. `3`, is the number of parallel workers to run the evaluation. By
|
||||
default, it is set to 1.
|
||||
- `language`, the language of your evaluating dataset.
|
||||
- `dataset`, the absolute position of the dataset jsonl.
|
||||
|
||||
The results will be generated in evaluation/evaluation_outputs/outputs/XXX/CodeActAgent/YYY/output.jsonl, you can refer to the [example](examples/output.jsonl).
|
||||
|
||||
## Runing evaluation
|
||||
|
||||
First, install [multi-swe-bench](https://github.com/multi-swe-bench/multi-swe-bench).
|
||||
|
||||
```bash
|
||||
pip install multi-swe-bench
|
||||
```
|
||||
|
||||
Second, convert the output.jsonl to patch.jsonl with [script](scripts/eval/convert.py), you can refer to the [example](examples/patch.jsonl).
|
||||
|
||||
```bash
|
||||
python evaluation/benchmarks/multi_swe_bench/scripts/eval/convert.py
|
||||
```
|
||||
|
||||
Finally, evaluate with multi-swe-bench.
|
||||
The config file config.json can be refer to the [example](examples/config.json) or [github](https://github.com/multi-swe-bench/multi-swe-bench/tree/main?tab=readme-ov-file#configuration-file-example).
|
||||
|
||||
```bash
|
||||
python -m multi_swe_bench.harness.run_evaluation --config config.json
|
||||
```
|
||||
0
evaluation/benchmarks/multi_swe_bench/__init__.py
Normal file
0
evaluation/benchmarks/multi_swe_bench/__init__.py
Normal file
456
evaluation/benchmarks/multi_swe_bench/eval_infer.py
Normal file
456
evaluation/benchmarks/multi_swe_bench/eval_infer.py
Normal file
@@ -0,0 +1,456 @@
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
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 (
|
||||
get_instance_resource_factor,
|
||||
)
|
||||
from evaluation.benchmarks.swe_bench.run_infer import get_instance_docker_image
|
||||
from evaluation.utils.shared import (
|
||||
EvalMetadata,
|
||||
EvalOutput,
|
||||
get_default_sandbox_config_for_eval,
|
||||
prepare_dataset,
|
||||
reset_logger_for_multiprocessing,
|
||||
run_evaluation,
|
||||
)
|
||||
from openhands.core.config import (
|
||||
AppConfig,
|
||||
LLMConfig,
|
||||
get_parser,
|
||||
)
|
||||
from openhands.core.logger import openhands_logger as logger
|
||||
from openhands.core.main import create_runtime
|
||||
from openhands.events.action import CmdRunAction
|
||||
from openhands.events.observation import CmdOutputObservation
|
||||
from openhands.utils.async_utils import call_async_from_sync
|
||||
|
||||
# TODO: migrate all swe-bench docker to ghcr.io/openhands
|
||||
DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/xingyaoww/')
|
||||
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
|
||||
|
||||
|
||||
def process_git_patch(patch):
|
||||
if not isinstance(patch, str):
|
||||
return ''
|
||||
|
||||
if not patch.strip():
|
||||
# skip empty patches
|
||||
return ''
|
||||
|
||||
patch = patch.replace('\r\n', '\n')
|
||||
# There might be some weird characters at the beginning of the patch
|
||||
# due to some OpenHands inference command outputs
|
||||
|
||||
# FOR EXAMPLE:
|
||||
# git diff --no-color --cached 895f28f9cbed817c00ab68770433170d83132d90
|
||||
# [A[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[C[K0
|
||||
# diff --git a/django/db/models/sql/.backup.query.py b/django/db/models/sql/.backup.query.py
|
||||
# new file mode 100644
|
||||
# index 0000000000..fc13db5948
|
||||
|
||||
# We "find" the first line that starts with "diff" and then we remove lines before it
|
||||
lines = patch.split('\n')
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('diff --git'):
|
||||
patch = '\n'.join(lines[i:])
|
||||
break
|
||||
|
||||
patch = patch.rstrip() + '\n' # Make sure the last line ends with a newline
|
||||
return patch
|
||||
|
||||
|
||||
def get_config(metadata: EvalMetadata, instance: pd.Series) -> AppConfig:
|
||||
# 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.'
|
||||
)
|
||||
sandbox_config = get_default_sandbox_config_for_eval()
|
||||
sandbox_config.base_container_image = base_container_image
|
||||
sandbox_config.remote_runtime_resource_factor = get_instance_resource_factor(
|
||||
dataset_name=metadata.dataset,
|
||||
instance_id=instance['instance_id'],
|
||||
)
|
||||
config = AppConfig(
|
||||
run_as_openhands=False,
|
||||
runtime=os.environ.get('RUNTIME', 'docker'),
|
||||
sandbox=sandbox_config,
|
||||
# do not mount workspace
|
||||
workspace_base=None,
|
||||
workspace_mount_path=None,
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
def process_instance(
|
||||
instance: pd.Series,
|
||||
metadata: EvalMetadata,
|
||||
reset_logger: bool = True,
|
||||
log_dir: str | None = None,
|
||||
runtime_failure_count: int = 0,
|
||||
) -> EvalOutput:
|
||||
"""
|
||||
Evaluate agent performance on a SWE-bench problem instance.
|
||||
|
||||
Note that this signature differs from the expected input to `run_evaluation`. Use
|
||||
`functools.partial` to provide optional arguments before passing to the evaluation harness.
|
||||
|
||||
Args:
|
||||
log_dir (str | None, default=None): Path to directory where log files will be written. Must
|
||||
be provided if `reset_logger` is set.
|
||||
|
||||
Raises:
|
||||
AssertionError: if the `reset_logger` flag is set without a provided log directory.
|
||||
"""
|
||||
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
|
||||
if reset_logger:
|
||||
assert (
|
||||
log_dir is not None
|
||||
), "Can't reset logger without a provided log directory."
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
reset_logger_for_multiprocessing(logger, instance.instance_id, log_dir)
|
||||
else:
|
||||
logger.info(f'Starting evaluation for instance {instance.instance_id}.')
|
||||
|
||||
config = get_config(metadata, instance)
|
||||
instance_id = instance.instance_id
|
||||
model_patch = instance['model_patch']
|
||||
test_spec: TestSpec = instance['test_spec']
|
||||
logger.info(f'Starting evaluation for instance {instance_id}.')
|
||||
|
||||
if 'test_result' not in instance.keys():
|
||||
instance['test_result'] = {}
|
||||
instance['test_result']['report'] = {
|
||||
'empty_generation': False,
|
||||
'resolved': False,
|
||||
'failed_apply_patch': False,
|
||||
'error_eval': False,
|
||||
'test_timeout': False,
|
||||
}
|
||||
|
||||
if model_patch == '':
|
||||
instance['test_result']['report']['empty_generation'] = True
|
||||
return EvalOutput(
|
||||
instance_id=instance_id,
|
||||
test_result=instance['test_result'],
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Increase resource_factor with increasing attempt_id
|
||||
if runtime_failure_count > 0:
|
||||
config.sandbox.remote_runtime_resource_factor = min(
|
||||
config.sandbox.remote_runtime_resource_factor * (2**runtime_failure_count),
|
||||
8,
|
||||
)
|
||||
logger.warning(
|
||||
f'This is the {runtime_failure_count + 1}th attempt for instance {instance.instance_id}, setting resource factor to {config.sandbox.remote_runtime_resource_factor}'
|
||||
)
|
||||
|
||||
try:
|
||||
runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
# Get patch and save it to /tmp/patch.diff
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# Patch file
|
||||
patch_file_path = os.path.join(temp_dir, 'patch.diff')
|
||||
with open(patch_file_path, 'w') as f:
|
||||
f.write(model_patch)
|
||||
runtime.copy_to(patch_file_path, '/tmp')
|
||||
# Eval script
|
||||
eval_script_path = os.path.join(temp_dir, 'eval.sh')
|
||||
with open(eval_script_path, 'w') as f:
|
||||
f.write(test_spec.eval_script)
|
||||
runtime.copy_to(eval_script_path, '/tmp')
|
||||
|
||||
# Set +x
|
||||
action = CmdRunAction(command='chmod +x /tmp/eval.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 obs.exit_code == 0
|
||||
|
||||
# Apply patch
|
||||
exec_command = (
|
||||
'cd /testbed && '
|
||||
"(git apply -v /tmp/patch.diff && echo 'APPLY_PATCH_PASS' || "
|
||||
"(echo 'Failed to apply patch with git apply, trying with patch command...' && "
|
||||
"(patch --batch --fuzz=5 -p1 -i /tmp/patch.diff && echo 'APPLY_PATCH_PASS' || "
|
||||
"echo 'APPLY_PATCH_FAIL')))"
|
||||
)
|
||||
action = CmdRunAction(command=exec_command)
|
||||
action.set_hard_timeout(600)
|
||||
obs = runtime.run_action(action)
|
||||
assert isinstance(obs, CmdOutputObservation)
|
||||
apply_patch_output = obs.content
|
||||
assert isinstance(apply_patch_output, str)
|
||||
instance['test_result']['apply_patch_output'] = apply_patch_output
|
||||
|
||||
if 'APPLY_PATCH_FAIL' in apply_patch_output:
|
||||
logger.info(f'[{instance_id}] {APPLY_PATCH_FAIL}:\n{apply_patch_output}')
|
||||
instance['test_result']['report']['failed_apply_patch'] = True
|
||||
|
||||
return EvalOutput(
|
||||
instance_id=instance_id,
|
||||
test_result=instance['test_result'],
|
||||
metadata=metadata,
|
||||
)
|
||||
elif 'APPLY_PATCH_PASS' in apply_patch_output:
|
||||
logger.info(f'[{instance_id}] {APPLY_PATCH_PASS}:\n{apply_patch_output}')
|
||||
|
||||
# Run eval script in background and save output to log file
|
||||
log_file = '/tmp/eval_output.log'
|
||||
action = CmdRunAction(command=f'/tmp/eval.sh > {log_file} 2>&1 & echo $!')
|
||||
action.set_hard_timeout(300) # Short timeout just to get the process ID
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
if isinstance(obs, CmdOutputObservation) and obs.exit_code == 0:
|
||||
pid = obs.content.split()[-1].strip()
|
||||
logger.info(
|
||||
f'[{instance_id}] Evaluation process started with PID: {pid}'
|
||||
)
|
||||
|
||||
# Poll for completion
|
||||
start_time = time.time()
|
||||
timeout = 1800 # 30 minutes
|
||||
while True:
|
||||
seconds_elapsed = time.time() - start_time
|
||||
if seconds_elapsed > timeout:
|
||||
logger.info(
|
||||
f'[{instance_id}] Evaluation timed out after {timeout} seconds'
|
||||
)
|
||||
instance['test_result']['report']['test_timeout'] = True
|
||||
break
|
||||
check_action = CmdRunAction(
|
||||
command=f'ps -p {pid} > /dev/null; echo $?'
|
||||
)
|
||||
check_action.set_hard_timeout(300)
|
||||
check_obs = runtime.run_action(check_action)
|
||||
if (
|
||||
isinstance(check_obs, CmdOutputObservation)
|
||||
and check_obs.content.split()[-1].strip() == '1'
|
||||
):
|
||||
logger.info(
|
||||
f'[{instance_id}] Evaluation process completed after {seconds_elapsed} seconds'
|
||||
)
|
||||
break
|
||||
logger.info(
|
||||
f'[{instance_id}] [{seconds_elapsed:.0f}s] Evaluation still running, waiting...'
|
||||
)
|
||||
time.sleep(30) # Wait for 30 seconds before checking again
|
||||
|
||||
# Read the log file
|
||||
cat_action = CmdRunAction(command=f'cat {log_file}')
|
||||
cat_action.set_hard_timeout(300)
|
||||
cat_obs = runtime.run_action(cat_action)
|
||||
|
||||
# Grade answer
|
||||
if isinstance(cat_obs, CmdOutputObservation) and cat_obs.exit_code == 0:
|
||||
test_output = cat_obs.content
|
||||
assert isinstance(test_output, str)
|
||||
instance['test_result']['test_output'] = test_output
|
||||
|
||||
# Get report from test output
|
||||
logger.info(f'[{instance_id}] Grading answer...')
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# Create a directory structure that matches the expected format
|
||||
# NOTE: this is a hack to make the eval report format consistent
|
||||
# with the original SWE-Bench eval script
|
||||
log_dir = os.path.join(temp_dir, 'logs', instance_id.lower())
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
test_output_path = os.path.join(log_dir, 'test_output.txt')
|
||||
with open(test_output_path, 'w') as f:
|
||||
f.write(test_output)
|
||||
try:
|
||||
_report = get_eval_report(
|
||||
test_spec=test_spec,
|
||||
prediction={
|
||||
'model_patch': model_patch,
|
||||
'instance_id': instance_id,
|
||||
},
|
||||
log_path=test_output_path,
|
||||
include_tests_status=True,
|
||||
)
|
||||
report = _report[instance_id]
|
||||
logger.info(
|
||||
f"[{instance_id}] report: {report}\nResult for {instance_id}: resolved: {report['resolved']}"
|
||||
)
|
||||
instance['test_result']['report']['resolved'] = report[
|
||||
'resolved'
|
||||
]
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f'[{instance_id}] Error when getting eval report: {e}'
|
||||
)
|
||||
instance['test_result']['report']['resolved'] = False
|
||||
instance['test_result']['report']['error_eval'] = True
|
||||
else:
|
||||
logger.info(f'[{instance_id}] Error when starting eval:\n{obs.content}')
|
||||
instance['test_result']['report']['error_eval'] = True
|
||||
|
||||
return EvalOutput(
|
||||
instance_id=instance_id,
|
||||
test_result=instance['test_result'],
|
||||
metadata=metadata,
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
f'[{instance_id}] Unexpected output when applying patch:\n{apply_patch_output}'
|
||||
)
|
||||
raise RuntimeError(
|
||||
instance_id,
|
||||
f'Unexpected output when applying patch:\n{apply_patch_output}',
|
||||
logger,
|
||||
)
|
||||
finally:
|
||||
runtime.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = get_parser()
|
||||
parser.add_argument(
|
||||
'--input-file',
|
||||
type=str,
|
||||
help='Path to input predictions file',
|
||||
required=True,
|
||||
)
|
||||
parser.add_argument(
|
||||
'--dataset',
|
||||
type=str,
|
||||
default='princeton-nlp/SWE-bench',
|
||||
help='data set to evaluate on, either full-test or lite-test',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--split',
|
||||
type=str,
|
||||
default='test',
|
||||
help='split to evaluate on',
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
# Load SWE-Bench dataset
|
||||
full_dataset: list[SWEbenchInstance] = load_swebench_dataset(
|
||||
args.dataset, args.split
|
||||
)
|
||||
instance_id_to_instance = {
|
||||
instance['instance_id']: instance for instance in full_dataset
|
||||
}
|
||||
logger.info(
|
||||
f'Loaded dataset {args.dataset} with split {args.split} to run inference on.'
|
||||
)
|
||||
|
||||
# Load predictions
|
||||
assert args.input_file.endswith('.jsonl'), 'Input file must be a jsonl file.'
|
||||
required_fields = ['instance_id', 'model_patch', 'test_result']
|
||||
with open(args.input_file) as f:
|
||||
predictions = pd.DataFrame.from_records(
|
||||
[
|
||||
{k: v for k, v in json.loads(line).items() if k in required_fields}
|
||||
for line in tqdm(f, desc='Loading predictions')
|
||||
]
|
||||
)
|
||||
assert (
|
||||
'instance_id' in predictions.columns
|
||||
), 'Input file must contain instance_id column.'
|
||||
|
||||
if 'model_patch' not in predictions.columns and (
|
||||
'test_result' in predictions.columns
|
||||
and 'model_patch' in predictions['test_result'].iloc[0]
|
||||
):
|
||||
raise ValueError(
|
||||
'Input file must contain model_patch column OR test_result column with model_patch field.'
|
||||
)
|
||||
assert len(predictions['instance_id'].unique()) == len(
|
||||
predictions
|
||||
), 'instance_id column must be unique.'
|
||||
|
||||
if 'model_patch' not in predictions.columns:
|
||||
predictions['model_patch'] = predictions['test_result'].apply(
|
||||
lambda x: x.get('git_patch', '')
|
||||
)
|
||||
assert {'instance_id', 'model_patch'}.issubset(
|
||||
set(predictions.columns)
|
||||
), 'Input file must contain instance_id and model_patch columns.'
|
||||
|
||||
# Process model_patch
|
||||
predictions['model_patch'] = predictions['model_patch'].apply(process_git_patch)
|
||||
|
||||
# Merge predictions with dataset
|
||||
predictions['instance'] = predictions['instance_id'].apply(
|
||||
lambda x: instance_id_to_instance[x]
|
||||
)
|
||||
predictions['test_spec'] = predictions['instance'].apply(make_test_spec)
|
||||
|
||||
# Prepare dataset
|
||||
output_file = args.input_file.replace('.jsonl', '.swebench_eval.jsonl')
|
||||
instances = prepare_dataset(predictions, output_file, args.eval_n_limit)
|
||||
|
||||
# If possible, load the relevant metadata to avoid issues with `run_evaluation`.
|
||||
metadata: EvalMetadata | None = None
|
||||
metadata_filepath = os.path.join(os.path.dirname(args.input_file), 'metadata.json')
|
||||
if os.path.exists(metadata_filepath):
|
||||
with open(metadata_filepath, 'r') as metadata_file:
|
||||
data = metadata_file.read()
|
||||
metadata = EvalMetadata.model_validate_json(data)
|
||||
else:
|
||||
# Initialize with a dummy metadata when file doesn't exist
|
||||
metadata = EvalMetadata(
|
||||
agent_class='dummy_agent', # Placeholder agent class
|
||||
llm_config=LLMConfig(model='dummy_model'), # Minimal LLM config
|
||||
max_iterations=1, # Minimal iterations
|
||||
eval_output_dir=os.path.dirname(
|
||||
args.input_file
|
||||
), # Use input file dir as output dir
|
||||
start_time=time.strftime('%Y-%m-%d %H:%M:%S'), # Current time
|
||||
git_commit=subprocess.check_output(['git', 'rev-parse', 'HEAD'])
|
||||
.decode('utf-8')
|
||||
.strip(), # Current commit
|
||||
dataset=args.dataset, # Dataset name from args
|
||||
)
|
||||
|
||||
# The evaluation harness constrains the signature of `process_instance_func` but we need to
|
||||
# pass extra information. Build a new function object to avoid issues with multiprocessing.
|
||||
process_instance_func = partial(
|
||||
process_instance, log_dir=output_file.replace('.jsonl', '.logs')
|
||||
)
|
||||
|
||||
run_evaluation(
|
||||
instances,
|
||||
metadata=metadata,
|
||||
output_file=output_file,
|
||||
num_workers=args.eval_num_workers,
|
||||
process_instance_func=process_instance_func,
|
||||
)
|
||||
|
||||
# Load evaluated predictions & print number of resolved predictions
|
||||
evaluated_predictions = pd.read_json(output_file, lines=True)
|
||||
fields = ['resolved', 'failed_apply_patch', 'error_eval', 'empty_generation']
|
||||
|
||||
def count_report_field(row, field):
|
||||
return row['test_result']['report'][field]
|
||||
|
||||
report = {}
|
||||
for field in fields:
|
||||
count = evaluated_predictions.apply(
|
||||
count_report_field, args=(field,), axis=1
|
||||
).sum()
|
||||
report[field] = count
|
||||
logger.info(
|
||||
f'# {field}: {count} / {len(evaluated_predictions)}. ({count / len(evaluated_predictions):.2%})'
|
||||
)
|
||||
24
evaluation/benchmarks/multi_swe_bench/examples/config.json
Normal file
24
evaluation/benchmarks/multi_swe_bench/examples/config.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"mode": "evaluation",
|
||||
"workdir": "./data/workdir",
|
||||
"patch_files": [
|
||||
"./data/patches/<your_patch_file>.jsonl"
|
||||
],
|
||||
"dataset_files": [
|
||||
"./data/patches/<to_evaluate_dataset_file>.jsonl"
|
||||
],
|
||||
"force_build": false,
|
||||
"output_dir": "./data/dataset",
|
||||
"specifics": [],
|
||||
"skips": [],
|
||||
"repo_dir": "./data/repos",
|
||||
"need_clone": false,
|
||||
"global_env": [],
|
||||
"clear_env": true,
|
||||
"stop_on_error": true,
|
||||
"max_workers": 8,
|
||||
"max_workers_build_image": 8,
|
||||
"max_workers_run_instance": 8,
|
||||
"log_dir": "./data/logs",
|
||||
"log_level": "DEBUG"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
{"org": "ponylang", "repo": "ponyc", "number": "4595", "fix_patch": "diff --git a/src/libponyc/ast/parser.c b/src/libponyc/ast/parser.c\nindex 9852922f..2c37d6b8 100644\n--- a/src/libponyc/ast/parser.c\n+++ b/src/libponyc/ast/parser.c\n@@ -693,6 +693,7 @@ DEF(idseqsingle);\n AST_NODE(TK_LET);\n TOKEN(\"variable name\", TK_ID);\n AST_NODE(TK_NONE); // Type\n+ SET_FLAG(AST_FLAG_IN_PARENS);\n DONE();\n \n // idseq"}
|
||||
{"org": "ponylang", "repo": "ponyc", "number": "4593", "fix_patch": "diff --git a/packages/cli/command_parser.pony b/packages/cli/command_parser.pony\nindex a5acce8e..fa97808b 100644\n--- a/packages/cli/command_parser.pony\n+++ b/packages/cli/command_parser.pony\n@@ -100,6 +100,7 @@ class CommandParser\n | let cs: CommandSpec box =>\n return CommandParser._sub(cs, this).\n _parse_command(tokens, options, args, envsmap, opt_stop)\n+// Correctly handle parent default options\n end\n else\n return SyntaxError(token, \"unknown command\")"}
|
||||
{"org": "ponylang", "repo": "ponyc", "number": "4588", "fix_patch": "diff --git a/src/libponyc/expr/match.c b/src/libponyc/expr/match.c\nindex 7d16066f..c2ec7056 100644\n--- a/src/libponyc/expr/match.c\n+++ b/src/libponyc/expr/match.c\n@@ -314,8 +314,10 @@ static ast_t* make_pattern_type(pass_opt_t* opt, ast_t* pattern)\n case TK_DONTCAREREF:\n case TK_MATCH_CAPTURE:\n case TK_MATCH_DONTCARE:\n+ if (ast_id(pattern_type) == TK_ISO) pattern_type = set_cap_and_ephemeral(pattern_type, TK_TRN, TK_EPHEMERAL);\n return pattern_type;\n \n+\n case TK_TUPLE:\n {\n ast_t* pattern_child = ast_child(pattern);"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user