diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000000..50a641bbec --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1 @@ +This way of running OpenHands is not officially supported. It is maintained by the community. diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh index 5912a3c6eb..3661ea83d1 100755 --- a/.devcontainer/setup.sh +++ b/.devcontainer/setup.sh @@ -7,5 +7,8 @@ git config --global --add safe.directory "$(realpath .)" # Install `nc` sudo apt update && sudo apt install netcat -y +# Install `uv` and `uvx` +wget -qO- https://astral.sh/uv/install.sh | sh + # Do common setup tasks source .openhands/setup.sh diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 651810028e..8aee64d59c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,12 +1,32 @@ -- [ ] 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 +## Summary of PR -**End-user friendly description of the problem this fixes or functionality this introduces.** + +## Change Type ---- -**Summarize what the PR does, explaining any non-trivial design decisions.** + +- [ ] Bug fix +- [ ] New feature +- [ ] Breaking change +- [ ] Refactor +- [ ] Other (dependency update, docs, typo fixes, etc.) ---- -**Link of any specific issues this addresses:** +## Checklist + + +- [ ] I have read and reviewed the code and I understand what the code is doing. +- [ ] I have tested the code to the best of my ability and ensured it works as expected. + +## Fixes + + + +Resolves #(issue) + +## Release Notes + + + +- [ ] Include this change in the Release Notes. diff --git a/.github/scripts/check_version_consistency.py b/.github/scripts/check_version_consistency.py deleted file mode 100755 index fe4d77c2d2..0000000000 --- a/.github/scripts/check_version_consistency.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python3 -import os -import re -import sys - - -def find_version_references(directory: str) -> tuple[set[str], set[str]]: - openhands_versions = set() - runtime_versions = set() - - version_pattern_openhands = re.compile(r'openhands:(\d{1})\.(\d{2})') - version_pattern_runtime = re.compile(r'runtime:(\d{1})\.(\d{2})') - - for root, _, files in os.walk(directory): - # Skip .git directory and docs/build directory - if '.git' in root or 'docs/build' in root: - continue - - for file in files: - if file.endswith( - ('.md', '.yml', '.yaml', '.txt', '.html', '.py', '.js', '.ts') - ): - file_path = os.path.join(root, file) - try: - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - - # Find all openhands version references - matches = version_pattern_openhands.findall(content) - if matches: - print(f'Found openhands version {matches} in {file_path}') - openhands_versions.update(matches) - - # Find all runtime version references - matches = version_pattern_runtime.findall(content) - if matches: - print(f'Found runtime version {matches} in {file_path}') - runtime_versions.update(matches) - except Exception as e: - print(f'Error reading {file_path}: {e}', file=sys.stderr) - - return openhands_versions, runtime_versions - - -def main(): - repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - print(f'Checking version consistency in {repo_root}') - openhands_versions, runtime_versions = find_version_references(repo_root) - - print(f'Found openhands versions: {sorted(openhands_versions)}') - print(f'Found runtime versions: {sorted(runtime_versions)}') - - exit_code = 0 - - if len(openhands_versions) > 1: - print('Error: Multiple openhands versions found:', file=sys.stderr) - print('Found versions:', sorted(openhands_versions), file=sys.stderr) - exit_code = 1 - elif len(openhands_versions) == 0: - print('Warning: No openhands version references found', file=sys.stderr) - - if len(runtime_versions) > 1: - print('Error: Multiple runtime versions found:', file=sys.stderr) - print('Found versions:', sorted(runtime_versions), file=sys.stderr) - exit_code = 1 - elif len(runtime_versions) == 0: - print('Warning: No runtime version references found', file=sys.stderr) - - sys.exit(exit_code) - - -if __name__ == '__main__': - main() diff --git a/.github/scripts/update_pr_description.sh b/.github/scripts/update_pr_description.sh index cca991e2d4..4457b74955 100755 --- a/.github/scripts/update_pr_description.sh +++ b/.github/scripts/update_pr_description.sh @@ -13,12 +13,12 @@ DOCKER_RUN_COMMAND="docker run -it --rm \ -p 3000:3000 \ -v /var/run/docker.sock:/var/run/docker.sock \ --add-host host.docker.internal:host-gateway \ - -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:${SHORT_SHA}-nikolaik \ + -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.openhands.dev/openhands/runtime:${SHORT_SHA}-nikolaik \ --name openhands-app-${SHORT_SHA} \ - docker.all-hands.dev/all-hands-ai/openhands:${SHORT_SHA}" + docker.openhands.dev/openhands/openhands:${SHORT_SHA}" # Define the uvx command -UVX_RUN_COMMAND="uvx --python 3.12 --from git+https://github.com/All-Hands-AI/OpenHands@${BRANCH_NAME} openhands" +UVX_RUN_COMMAND="uvx --python 3.12 --from git+https://github.com/OpenHands/OpenHands@${BRANCH_NAME}#subdirectory=openhands-cli openhands" # Get the current PR body PR_BODY=$(gh pr view "$PR_NUMBER" --json body --jq .body) diff --git a/.github/workflows/check-package-versions.yml b/.github/workflows/check-package-versions.yml new file mode 100644 index 0000000000..44e680ff4b --- /dev/null +++ b/.github/workflows/check-package-versions.yml @@ -0,0 +1,65 @@ +name: Check Package Versions + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + check-package-versions: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Check for any 'rev' fields in pyproject.toml + run: | + python - <<'PY' + import sys, tomllib, pathlib + + path = pathlib.Path("pyproject.toml") + if not path.exists(): + print("❌ ERROR: pyproject.toml not found") + sys.exit(1) + + try: + data = tomllib.loads(path.read_text(encoding="utf-8")) + except Exception as e: + print(f"❌ ERROR: Failed to parse pyproject.toml: {e}") + sys.exit(1) + + poetry = data.get("tool", {}).get("poetry", {}) + sections = { + "dependencies": poetry.get("dependencies", {}), + } + + errors = [] + + print("🔍 Checking for any dependencies with 'rev' fields...\n") + for section_name, deps in sections.items(): + if not isinstance(deps, dict): + continue + + for pkg_name, cfg in deps.items(): + if isinstance(cfg, dict) and "rev" in cfg: + msg = f" ✖ {pkg_name} in [{section_name}] uses rev='{cfg['rev']}' (NOT ALLOWED)" + print(msg) + errors.append(msg) + else: + print(f" • {pkg_name}: OK") + + if errors: + print("\n❌ FAILED: Found dependencies using 'rev' fields:\n" + "\n".join(errors)) + print("\nPlease use versioned releases instead, e.g.:") + print(' my-package = "1.0.0"') + sys.exit(1) + + print("\n✅ SUCCESS: No 'rev' fields found. All dependencies are using proper versioned releases.") + PY diff --git a/.github/workflows/cli-build-binary-and-optionally-release.yml b/.github/workflows/cli-build-binary-and-optionally-release.yml new file mode 100644 index 0000000000..0aefcd3820 --- /dev/null +++ b/.github/workflows/cli-build-binary-and-optionally-release.yml @@ -0,0 +1,122 @@ +# Workflow that builds and tests the CLI binary executable +name: CLI - Build binary and optionally release + +# Run on pushes to main branch and CLI tags, and on pull requests when CLI files change +on: + push: + branches: + - main + tags: + - "*-cli" + pull_request: + paths: + - "openhands-cli/**" + +permissions: + contents: write # needed to create releases or upload assets + +# Cancel previous runs if a new commit is pushed +concurrency: + group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }} + cancel-in-progress: true + +jobs: + build-binary: + name: Build binary executable + strategy: + matrix: + include: + # Build on Ubuntu 22.04 for maximum GLIBC compatibility (GLIBC 2.31) + - os: ubuntu-22.04 + platform: linux + artifact_name: openhands-cli-linux + # Build on macOS for macOS users + - os: macos-15 + platform: macos + artifact_name: openhands-cli-macos + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + version: "latest" + + - name: Install dependencies + working-directory: openhands-cli + run: | + uv sync + + - name: Build binary executable + working-directory: openhands-cli + run: | + ./build.sh --install-pyinstaller | tee output.log + echo "Full output:" + cat output.log + + if grep -q "❌" output.log; then + echo "❌ Found failure marker in output" + exit 1 + fi + + echo "✅ Build & test finished without ❌ markers" + + - name: Verify binary files exist + run: | + if ! ls openhands-cli/dist/openhands* 1> /dev/null 2>&1; then + echo "❌ No binaries found to upload!" + exit 1 + fi + echo "✅ Found binaries to upload." + + - name: Upload binary artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact_name }} + path: openhands-cli/dist/openhands* + retention-days: 30 + + create-github-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: build-binary + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release assets + run: | + mkdir -p release-assets + # Copy binaries with appropriate names for release + if [ -f artifacts/openhands-cli-linux/openhands ]; then + cp artifacts/openhands-cli-linux/openhands release-assets/openhands-linux + fi + if [ -f artifacts/openhands-cli-macos/openhands ]; then + cp artifacts/openhands-cli-macos/openhands release-assets/openhands-macos + fi + ls -la release-assets/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: release-assets/* + draft: true + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/dispatch-to-docs.yml b/.github/workflows/dispatch-to-docs.yml index b784f67392..301cab5fa5 100644 --- a/.github/workflows/dispatch-to-docs.yml +++ b/.github/workflows/dispatch-to-docs.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - repo: ["All-Hands-AI/docs"] + repo: ["OpenHands/docs"] steps: - name: Push to docs repo uses: peter-evans/repository-dispatch@v3 diff --git a/.github/workflows/enterprise-check-migrations.yml b/.github/workflows/enterprise-check-migrations.yml new file mode 100644 index 0000000000..8daca0e1b1 --- /dev/null +++ b/.github/workflows/enterprise-check-migrations.yml @@ -0,0 +1,52 @@ +name: Enterprise Check Migrations + +on: + pull_request: + paths: + - 'enterprise/migrations/**' + +jobs: + check-sync: + runs-on: ubuntu-latest + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + + - name: Fetch base branch + run: git fetch origin ${{ github.event.pull_request.base.ref }} + + - name: Check if base branch is ancestor of PR + id: check_up_to_date + shell: bash + run: | + BASE="origin/${{ github.event.pull_request.base.ref }}" + HEAD="${{ github.event.pull_request.head.sha }}" + if git merge-base --is-ancestor "$BASE" "$HEAD"; then + echo "We're up to date with base $BASE" + exit 0 + else + echo "NOT up to date with base $BASE" + exit 1 + fi + + - name: Find Comment + uses: peter-evans/find-comment@v3 + id: find-comment + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: | + ⚠️ This PR contains **migrations** + + - name: Comment warning on PR + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + comment-id: ${{ steps.find-comment.outputs.comment-id }} + edit-mode: replace + body: | + ⚠️ This PR contains **migrations**. Please synchronize before merging to prevent conflicts. diff --git a/.github/workflows/enterprise-preview.yml b/.github/workflows/enterprise-preview.yml index 9a66fda825..e31222827b 100644 --- a/.github/workflows/enterprise-preview.yml +++ b/.github/workflows/enterprise-preview.yml @@ -26,4 +26,4 @@ jobs: -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \ -H "Accept: application/vnd.github+json" \ -d "{\"ref\": \"main\", \"inputs\": {\"openhandsPrNumber\": \"${{ github.event.pull_request.number }}\", \"deployEnvironment\": \"feature\", \"enterpriseImageTag\": \"pr-${{ github.event.pull_request.number }}\" }}" \ - https://api.github.com/repos/All-Hands-AI/deploy/actions/workflows/deploy.yaml/dispatches + https://api.github.com/repos/OpenHands/deploy/actions/workflows/deploy.yaml/dispatches diff --git a/.github/workflows/ghcr-build.yml b/.github/workflows/ghcr-build.yml index 82bf9ff6b3..40848816dd 100644 --- a/.github/workflows/ghcr-build.yml +++ b/.github/workflows/ghcr-build.yml @@ -37,7 +37,6 @@ jobs: 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" }, @@ -87,7 +86,7 @@ jobs: # Builds the runtime Docker images ghcr_build_runtime: - name: Build Image + name: Build Runtime Image runs-on: blacksmith-8vcpu-ubuntu-2204 if: "!(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/ext-v'))" permissions: @@ -125,7 +124,7 @@ jobs: - name: Install Python dependencies using Poetry 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 + run: poetry run python3 -m openhands.runtime.utils.runtime_build --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 @@ -136,6 +135,7 @@ jobs: 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) @@ -198,7 +198,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ghcr.io/all-hands-ai/enterprise-server + images: ghcr.io/openhands/enterprise-server tags: | type=ref,event=branch type=ref,event=pr @@ -211,6 +211,8 @@ jobs: latest=auto prefix= suffix= + env: + DOCKER_METADATA_PR_HEAD_SHA: true - name: Determine app image tag shell: bash run: | @@ -248,13 +250,13 @@ jobs: -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \ -H "Accept: application/vnd.github+json" \ -d "{\"ref\": \"main\", \"inputs\": {\"openhandsPrNumber\": \"${{ github.event.pull_request.number }}\", \"deployEnvironment\": \"feature\", \"enterpriseImageTag\": \"pr-${{ github.event.pull_request.number }}\" }}" \ - https://api.github.com/repos/All-Hands-AI/deploy/actions/workflows/deploy.yaml/dispatches + https://api.github.com/repos/OpenHands/deploy/actions/workflows/deploy.yaml/dispatches # Run unit tests with the Docker runtime Docker images as root test_runtime_root: name: RT Unit Tests (Root) needs: [ghcr_build_runtime, define-matrix] - runs-on: blacksmith-8vcpu-ubuntu-2204 + runs-on: blacksmith-4vcpu-ubuntu-2404 strategy: fail-fast: false matrix: @@ -296,7 +298,7 @@ jobs: # We install pytest-xdist in order to run tests across CPUs poetry run pip install pytest-xdist - # Install to be able to retry on failures for flaky tests + # Install to be able to retry on failures for flakey tests poetry run pip install pytest-rerunfailures image_name=ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }} @@ -309,14 +311,14 @@ jobs: SANDBOX_RUNTIME_CONTAINER_IMAGE=$image_name \ TEST_IN_CI=true \ RUN_AS_OPENHANDS=false \ - poetry run pytest -n 0 -raRs --reruns 2 --reruns-delay 5 -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py --durations=10 + poetry run pytest -n 5 -raRs --reruns 2 --reruns-delay 3 -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py --durations=10 env: DEBUG: "1" # Run unit tests with the Docker runtime Docker images as openhands user test_runtime_oh: name: RT Unit Tests (openhands) - runs-on: blacksmith-8vcpu-ubuntu-2204 + runs-on: blacksmith-4vcpu-ubuntu-2404 needs: [ghcr_build_runtime, define-matrix] strategy: matrix: @@ -368,7 +370,7 @@ jobs: SANDBOX_RUNTIME_CONTAINER_IMAGE=$image_name \ TEST_IN_CI=true \ RUN_AS_OPENHANDS=true \ - poetry run pytest -n 0 -raRs --reruns 2 --reruns-delay 5 -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py --durations=10 + poetry run pytest -n 5 -raRs --reruns 2 --reruns-delay 3 -s ./tests/runtime --ignore=tests/runtime/test_browsergym_envs.py --durations=10 env: DEBUG: "1" diff --git a/.github/workflows/integration-runner.yml b/.github/workflows/integration-runner.yml deleted file mode 100644 index e8d318c3e6..0000000000 --- a/.github/workflows/integration-runner.yml +++ /dev/null @@ -1,199 +0,0 @@ -name: Run Integration Tests - -on: - pull_request: - types: [labeled] - workflow_dispatch: - inputs: - reason: - description: 'Reason for manual trigger' - required: true - default: '' - schedule: - - cron: '30 22 * * *' # Runs at 10:30pm UTC every day - -env: - N_PROCESSES: 10 # Global configuration for number of parallel processes for evaluation - -jobs: - run-integration-tests: - if: github.event.label.name == 'integration-test' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' - runs-on: blacksmith-4vcpu-ubuntu-2204 - permissions: - contents: "read" - id-token: "write" - pull-requests: "write" - issues: "write" - strategy: - matrix: - python-version: ["3.12"] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install poetry via pipx - run: pipx install poetry - - - name: Set up Python - uses: useblacksmith/setup-python@v6 - with: - python-version: ${{ matrix.python-version }} - cache: "poetry" - - - name: Setup Node.js - uses: useblacksmith/setup-node@v5 - with: - node-version: '22.x' - - - name: Comment on PR if 'integration-test' label is present - if: github.event_name == 'pull_request' && github.event.label.name == 'integration-test' - uses: KeisukeYamashita/create-comment@v1 - with: - unique: false - comment: | - Hi! I started running the integration tests on your PR. You will receive a comment with the results shortly. - - - name: Install Python dependencies using Poetry - run: poetry install --with dev,test,runtime,evaluation - - - name: Configure config.toml for testing with Haiku - env: - LLM_MODEL: "litellm_proxy/claude-3-5-haiku-20241022" - LLM_API_KEY: ${{ secrets.LLM_API_KEY }} - LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} - MAX_ITERATIONS: 10 - run: | - echo "[llm.eval]" > config.toml - echo "model = \"$LLM_MODEL\"" >> config.toml - echo "api_key = \"$LLM_API_KEY\"" >> config.toml - echo "base_url = \"$LLM_BASE_URL\"" >> config.toml - echo "temperature = 0.0" >> config.toml - - - name: Build environment - run: make build - - - name: Run integration test evaluation for Haiku - env: - SANDBOX_FORCE_REBUILD_RUNTIME: True - run: | - poetry run ./evaluation/integration_tests/scripts/run_infer.sh llm.eval HEAD CodeActAgent '' 10 $N_PROCESSES '' 'haiku_run' - - # get integration tests report - REPORT_FILE_HAIKU=$(find evaluation/evaluation_outputs/outputs/integration_tests/CodeActAgent/*haiku*_maxiter_10_N* -name "report.md" -type f | head -n 1) - echo "REPORT_FILE: $REPORT_FILE_HAIKU" - echo "INTEGRATION_TEST_REPORT_HAIKU<> $GITHUB_ENV - cat $REPORT_FILE_HAIKU >> $GITHUB_ENV - echo >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - - name: Wait a little bit - run: sleep 10 - - - name: Configure config.toml for testing with DeepSeek - env: - LLM_MODEL: "litellm_proxy/deepseek-chat" - LLM_API_KEY: ${{ secrets.LLM_API_KEY }} - LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} - MAX_ITERATIONS: 10 - run: | - echo "[llm.eval]" > config.toml - echo "model = \"$LLM_MODEL\"" >> config.toml - echo "api_key = \"$LLM_API_KEY\"" >> config.toml - echo "base_url = \"$LLM_BASE_URL\"" >> config.toml - echo "temperature = 0.0" >> config.toml - - - name: Run integration test evaluation for DeepSeek - env: - SANDBOX_FORCE_REBUILD_RUNTIME: True - run: | - poetry run ./evaluation/integration_tests/scripts/run_infer.sh llm.eval HEAD CodeActAgent '' 10 $N_PROCESSES '' 'deepseek_run' - - # get integration tests report - REPORT_FILE_DEEPSEEK=$(find evaluation/evaluation_outputs/outputs/integration_tests/CodeActAgent/deepseek*_maxiter_10_N* -name "report.md" -type f | head -n 1) - echo "REPORT_FILE: $REPORT_FILE_DEEPSEEK" - echo "INTEGRATION_TEST_REPORT_DEEPSEEK<> $GITHUB_ENV - cat $REPORT_FILE_DEEPSEEK >> $GITHUB_ENV - echo >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - # ------------------------------------------------------------- - # Run VisualBrowsingAgent tests for DeepSeek, limited to t05 and t06 - - name: Wait a little bit (again) - run: sleep 5 - - - name: Configure config.toml for testing VisualBrowsingAgent (DeepSeek) - env: - LLM_MODEL: "litellm_proxy/deepseek-chat" - LLM_API_KEY: ${{ secrets.LLM_API_KEY }} - LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} - MAX_ITERATIONS: 15 - run: | - echo "[llm.eval]" > config.toml - echo "model = \"$LLM_MODEL\"" >> config.toml - echo "api_key = \"$LLM_API_KEY\"" >> config.toml - echo "base_url = \"$LLM_BASE_URL\"" >> config.toml - echo "temperature = 0.0" >> config.toml - - name: Run integration test evaluation for VisualBrowsingAgent (DeepSeek) - env: - SANDBOX_FORCE_REBUILD_RUNTIME: True - run: | - poetry run ./evaluation/integration_tests/scripts/run_infer.sh llm.eval HEAD VisualBrowsingAgent '' 15 $N_PROCESSES "t05_simple_browsing,t06_github_pr_browsing.py" 'visualbrowsing_deepseek_run' - - # Find and export the visual browsing agent test results - REPORT_FILE_VISUALBROWSING_DEEPSEEK=$(find evaluation/evaluation_outputs/outputs/integration_tests/VisualBrowsingAgent/deepseek*_maxiter_15_N* -name "report.md" -type f | head -n 1) - echo "REPORT_FILE_VISUALBROWSING_DEEPSEEK: $REPORT_FILE_VISUALBROWSING_DEEPSEEK" - echo "INTEGRATION_TEST_REPORT_VISUALBROWSING_DEEPSEEK<> $GITHUB_ENV - cat $REPORT_FILE_VISUALBROWSING_DEEPSEEK >> $GITHUB_ENV - echo >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - - name: Create archive of evaluation outputs - run: | - TIMESTAMP=$(date +'%y-%m-%d-%H-%M') - cd evaluation/evaluation_outputs/outputs # Change to the outputs directory - tar -czvf ../../../integration_tests_${TIMESTAMP}.tar.gz integration_tests/CodeActAgent/* integration_tests/VisualBrowsingAgent/* # Only include the actual result directories - - - name: Upload evaluation results as artifact - uses: actions/upload-artifact@v4 - id: upload_results_artifact - with: - name: integration-test-outputs-${{ github.run_id }}-${{ github.run_attempt }} - path: integration_tests_*.tar.gz - - - name: Get artifact URLs - run: | - echo "ARTIFACT_URL=${{ steps.upload_results_artifact.outputs.artifact-url }}" >> $GITHUB_ENV - - - name: Set timestamp and trigger reason - run: | - echo "TIMESTAMP=$(date +'%Y-%m-%d-%H-%M')" >> $GITHUB_ENV - if [[ "${{ github.event_name }}" == "pull_request" ]]; then - echo "TRIGGER_REASON=pr-${{ github.event.pull_request.number }}" >> $GITHUB_ENV - elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - echo "TRIGGER_REASON=manual-${{ github.event.inputs.reason }}" >> $GITHUB_ENV - else - echo "TRIGGER_REASON=nightly-scheduled" >> $GITHUB_ENV - fi - - - name: Comment with results and artifact link - id: create_comment - uses: KeisukeYamashita/create-comment@v1 - with: - # if triggered by PR, use PR number, otherwise use 9745 as fallback issue number for manual triggers - number: ${{ github.event_name == 'pull_request' && github.event.pull_request.number || 9745 }} - unique: false - comment: | - Trigger by: ${{ github.event_name == 'pull_request' && format('Pull Request (integration-test label on PR #{0})', github.event.pull_request.number) || (github.event_name == 'workflow_dispatch' && format('Manual Trigger: {0}', github.event.inputs.reason)) || 'Nightly Scheduled Run' }} - Commit: ${{ github.sha }} - **Integration Tests Report (Haiku)** - Haiku LLM Test Results: - ${{ env.INTEGRATION_TEST_REPORT_HAIKU }} - --- - **Integration Tests Report (DeepSeek)** - DeepSeek LLM Test Results: - ${{ env.INTEGRATION_TEST_REPORT_DEEPSEEK }} - --- - **Integration Tests Report VisualBrowsing (DeepSeek)** - ${{ env.INTEGRATION_TEST_REPORT_VISUALBROWSING_DEEPSEEK }} - --- - Download testing outputs (includes both Haiku and DeepSeek results): [Download](${{ steps.upload_results_artifact.outputs.artifact-url }}) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 69ebc3d4e1..360f68b8fe 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -71,7 +71,7 @@ jobs: run: pip install pre-commit==4.2.0 - name: Run pre-commit hooks working-directory: ./enterprise - run: pre-commit run --all-files --config ./dev_config/python/.pre-commit-config.yaml + run: pre-commit run --all-files --show-diff-on-failure --config ./dev_config/python/.pre-commit-config.yaml lint-cli-python: name: Lint CLI python @@ -86,20 +86,7 @@ jobs: python-version: 3.12 cache: "pip" - name: Install pre-commit - run: pip install pre-commit==3.7.0 + run: pip install pre-commit==4.2.0 - name: Run pre-commit hooks working-directory: ./openhands-cli - run: pre-commit run --all-files --config ../dev_config/python/.pre-commit-config.yaml - - # Check version consistency across documentation - check-version-consistency: - name: Check version consistency - runs-on: blacksmith-4vcpu-ubuntu-2204 - steps: - - uses: actions/checkout@v4 - - name: Set up python - uses: useblacksmith/setup-python@v6 - with: - python-version: 3.12 - - name: Run version consistency check - run: .github/scripts/check_version_consistency.py + run: pre-commit run --all-files --config ./dev_config/python/.pre-commit-config.yaml diff --git a/.github/workflows/openhands-resolver.yml b/.github/workflows/openhands-resolver.yml index 1012df45ca..cfb7298974 100644 --- a/.github/workflows/openhands-resolver.yml +++ b/.github/workflows/openhands-resolver.yml @@ -201,7 +201,7 @@ jobs: issue_number: ${{ env.ISSUE_NUMBER }}, owner: context.repo.owner, repo: context.repo.repo, - body: `[OpenHands](https://github.com/All-Hands-AI/OpenHands) started fixing the ${issueType}! You can monitor the progress [here](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}).` + body: `[OpenHands](https://github.com/OpenHands/OpenHands) started fixing the ${issueType}! You can monitor the progress [here](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}).` }); - name: Install OpenHands @@ -233,7 +233,7 @@ jobs: if (isExperimentalLabel || isIssueCommentExperimental || isReviewCommentExperimental) { console.log("Installing experimental OpenHands..."); - await exec.exec("pip install git+https://github.com/all-hands-ai/openhands.git"); + await exec.exec("pip install git+https://github.com/openhands/openhands.git"); } else { console.log("Installing from requirements.txt..."); diff --git a/.github/workflows/py-tests.yml b/.github/workflows/py-tests.yml index 245706817d..4506f1ea75 100644 --- a/.github/workflows/py-tests.yml +++ b/.github/workflows/py-tests.yml @@ -19,12 +19,16 @@ jobs: # Run python tests on Linux test-on-linux: name: Python Tests on Linux - runs-on: blacksmith-4vcpu-ubuntu-2204 + runs-on: blacksmith-4vcpu-ubuntu-2404 env: INSTALL_DOCKER: "0" # Set to '0' to skip Docker installation strategy: matrix: python-version: ["3.12"] + permissions: + # For coverage comment and python-coverage-comment-action branch + pull-requests: write + contents: write steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx @@ -44,48 +48,32 @@ jobs: python-version: ${{ matrix.python-version }} cache: "poetry" - name: Install Python dependencies using Poetry - run: poetry install --with dev,test,runtime + run: | + poetry install --with dev,test,runtime + poetry run pip install pytest-xdist + poetry run pip install pytest-rerunfailures - name: Build Environment run: make build - name: Run Unit Tests - run: PYTHONPATH=".:$PYTHONPATH" poetry run pytest --forked -n auto -svv ./tests/unit + run: PYTHONPATH=".:$PYTHONPATH" poetry run pytest --forked -n auto -s ./tests/unit --cov=openhands --cov-branch + env: + COVERAGE_FILE: ".coverage.${{ matrix.python_version }}" - name: Run Runtime Tests with CLIRuntime - run: PYTHONPATH=".:$PYTHONPATH" TEST_RUNTIME=cli poetry run pytest -svv tests/runtime/test_bash.py - - # Run specific Windows python tests - test-on-windows: - name: Python Tests on Windows - runs-on: windows-latest - strategy: - matrix: - python-version: ["3.12"] - steps: - - uses: actions/checkout@v4 - - name: Install pipx - run: pip install pipx - - name: Install poetry via pipx - run: pipx install poetry - - name: Set up Python - uses: actions/setup-python@v5 + run: PYTHONPATH=".:$PYTHONPATH" TEST_RUNTIME=cli poetry run pytest -n 5 --reruns 2 --reruns-delay 3 -s tests/runtime/test_bash.py --cov=openhands --cov-branch + env: + COVERAGE_FILE: ".coverage.runtime.${{ matrix.python_version }}" + - name: Store coverage file + uses: actions/upload-artifact@v4 with: - python-version: ${{ matrix.python-version }} - cache: "poetry" - - name: Install Python dependencies using Poetry - run: poetry install --with dev,test,runtime - - name: Run Windows unit tests - run: poetry run pytest -svv tests/unit/runtime/utils/test_windows_bash.py - env: - PYTHONPATH: ".;$env:PYTHONPATH" - DEBUG: "1" - - name: Run Windows runtime tests with LocalRuntime - run: $env:TEST_RUNTIME="local"; poetry run pytest -svv tests/runtime/test_bash.py - env: - PYTHONPATH: ".;$env:PYTHONPATH" - TEST_RUNTIME: local - DEBUG: "1" + name: coverage-openhands + path: | + .coverage.${{ matrix.python_version }} + .coverage.runtime.${{ matrix.python_version }} + include-hidden-files: true + test-enterprise: name: Enterprise Python Unit Tests - runs-on: blacksmith-4vcpu-ubuntu-2204 + runs-on: blacksmith-4vcpu-ubuntu-2404 strategy: matrix: python-version: ["3.12"] @@ -102,13 +90,24 @@ jobs: working-directory: ./enterprise run: poetry install --with dev,test - name: Run Unit Tests - working-directory: ./enterprise - run: PYTHONPATH=".:$PYTHONPATH" poetry run pytest --forked -n auto -svv -p no:ddtrace -p no:ddtrace.pytest_bdd -p no:ddtrace.pytest_benchmark ./tests/unit + # Use base working directory for coverage paths to line up. + run: PYTHONPATH=".:$PYTHONPATH" poetry run --project=enterprise pytest --forked -n auto -s -p no:ddtrace -p no:ddtrace.pytest_bdd -p no:ddtrace.pytest_benchmark ./enterprise/tests/unit --cov=enterprise --cov-branch + env: + COVERAGE_FILE: ".coverage.enterprise.${{ matrix.python_version }}" + - name: Store coverage file + uses: actions/upload-artifact@v4 + with: + name: coverage-enterprise + path: ".coverage.enterprise.${{ matrix.python_version }}" + include-hidden-files: true # Run CLI unit tests test-cli-python: name: CLI Unit Tests - runs-on: blacksmith-4vcpu-ubuntu-2204 + runs-on: blacksmith-4vcpu-ubuntu-2404 + strategy: + matrix: + python-version: ["3.12"] steps: - name: Checkout repository uses: actions/checkout@v4 @@ -118,7 +117,7 @@ jobs: - name: Set up Python uses: useblacksmith/setup-python@v6 with: - python-version: 3.12 + python-version: ${{ matrix.python-version }} - name: Install uv uses: astral-sh/setup-uv@v3 @@ -132,5 +131,45 @@ jobs: - name: Run CLI unit tests working-directory: ./openhands-cli + env: + # write coverage to repo root so the merge step finds it + COVERAGE_FILE: "${{ github.workspace }}/.coverage.openhands-cli.${{ matrix.python-version }}" run: | - uv run pytest -v + uv run pytest --forked -n auto -s \ + -p no:ddtrace -p no:ddtrace.pytest_bdd -p no:ddtrace.pytest_benchmark \ + tests --cov=openhands_cli --cov-branch + + - name: Store coverage file + uses: actions/upload-artifact@v4 + with: + name: coverage-openhands-cli + path: ".coverage.openhands-cli.${{ matrix.python-version }}" + include-hidden-files: true + + coverage-comment: + name: Coverage Comment + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + needs: [test-on-linux, test-enterprise, test-cli-python] + + permissions: + pull-requests: write + contents: write + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v5 + id: download + with: + pattern: coverage-* + merge-multiple: true + + - name: Create symlink for CLI source files + run: ln -sf openhands-cli/openhands_cli openhands_cli + + - name: Coverage comment + id: coverage_comment + uses: py-cov-action/python-coverage-comment-action@v3 + with: + GITHUB_TOKEN: ${{ github.token }} + MERGE_COVERAGE_FILES: true diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index 28efba4976..89a64aa58a 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -1,18 +1,28 @@ # Publishes the OpenHands PyPi package name: Publish PyPi Package -# Triggered manually on: workflow_dispatch: inputs: reason: - description: 'Reason for manual trigger' + description: "What are you publishing?" required: true - default: '' + type: choice + options: + - app server + - cli + default: app server + push: + tags: + - "*" jobs: release: runs-on: blacksmith-4vcpu-ubuntu-2204 + # Run when manually dispatched for "app server" OR for tag pushes that don't contain '-cli' + if: | + (github.event_name == 'workflow_dispatch' && github.event.inputs.reason == 'app server') + || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-cli')) steps: - uses: actions/checkout@v4 - uses: useblacksmith/setup-python@v6 @@ -29,3 +39,36 @@ jobs: run: ./build.sh - name: publish run: poetry publish -u __token__ -p ${{ secrets.PYPI_TOKEN }} + + release-cli: + name: Publish CLI to PyPI + runs-on: ubuntu-latest + # Run when manually dispatched for "cli" OR for tag pushes that contain '-cli' + if: | + (github.event_name == 'workflow_dispatch' && github.event.inputs.reason == 'cli') + || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && contains(github.ref, '-cli')) + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + version: "latest" + + - name: Build CLI package + working-directory: openhands-cli + run: | + # Clean dist directory to avoid conflicts with binary builds + rm -rf dist/ + uv build + + - name: Publish CLI to PyPI + working-directory: openhands-cli + run: | + uv publish --token ${{ secrets.PYPI_TOKEN_OPENHANDS }} diff --git a/.github/workflows/run-eval.yml b/.github/workflows/run-eval.yml index 6bca1df097..d586a0b0a6 100644 --- a/.github/workflows/run-eval.yml +++ b/.github/workflows/run-eval.yml @@ -101,7 +101,7 @@ jobs: -H "Authorization: Bearer ${{ secrets.PAT_TOKEN }}" \ -H "Accept: application/vnd.github+json" \ -d "{\"ref\": \"main\", \"inputs\": {\"github-repo\": \"${{ steps.eval_params.outputs.repo_url }}\", \"github-branch\": \"${{ steps.eval_params.outputs.eval_branch }}\", \"pr-number\": \"${PR_NUMBER}\", \"eval-instances\": \"${{ steps.eval_params.outputs.eval_instances }}\"}}" \ - https://api.github.com/repos/All-Hands-AI/evaluation/actions/workflows/create-branch.yml/dispatches + https://api.github.com/repos/OpenHands/evaluation/actions/workflows/create-branch.yml/dispatches # Send Slack message if [[ "${{ github.event_name }}" == "pull_request" ]]; then diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 66cac495b2..233dce8a24 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -19,4 +19,4 @@ jobs: close-issue-message: 'This issue was automatically closed due to 50 days of inactivity. We do this to help keep the issues somewhat manageable and focus on active issues.' close-pr-message: 'This PR was closed because it had no activity for 50 days. If you feel this was closed in error, and you would like to continue the PR, please resubmit or let us know.' days-before-close: 10 - operations-per-run: 150 + operations-per-run: 300 diff --git a/.github/workflows/welcome-good-first-issue.yml b/.github/workflows/welcome-good-first-issue.yml index 058e3b92e8..9db74146b9 100644 --- a/.github/workflows/welcome-good-first-issue.yml +++ b/.github/workflows/welcome-good-first-issue.yml @@ -45,7 +45,7 @@ jobs: "This issue has been labeled as **good first issue**, which means it's a great place to get started with the OpenHands project.\n\n" + "If you're interested in working on it, feel free to! No need to ask for permission.\n\n" + "Be sure to check out our [development setup guide](" + repoUrl + "/blob/main/Development.md) to get your environment set up, and follow our [contribution guidelines](" + repoUrl + "/blob/main/CONTRIBUTING.md) when you're ready to submit a fix.\n\n" + - "Feel free to join our developer community on [Slack](dub.sh/openhands). You can ask for [help](https://openhands-ai.slack.com/archives/C078L0FUGUX), [feedback](https://openhands-ai.slack.com/archives/C086ARSNMGA), and even ask for a [PR review](https://openhands-ai.slack.com/archives/C08D8FJ5771).\n\n" + + "Feel free to join our developer community on [Slack](https://all-hands.dev/joinslack). You can ask for [help](https://openhands-ai.slack.com/archives/C078L0FUGUX), [feedback](https://openhands-ai.slack.com/archives/C086ARSNMGA), and even ask for a [PR review](https://openhands-ai.slack.com/archives/C08D8FJ5771).\n\n" + "🙌 Happy hacking! 🙌\n\n" + "" }); diff --git a/.gitignore b/.gitignore index 1cc2065e27..6cc0d2a8a9 100644 --- a/.gitignore +++ b/.gitignore @@ -186,6 +186,9 @@ cython_debug/ .repomix repomix-output.txt +# Emacs backup +*~ + # evaluation evaluation/evaluation_outputs evaluation/outputs diff --git a/.openhands/microagents/repo.md b/.openhands/microagents/repo.md index 9fbe104109..ceb87bc2f7 100644 --- a/.openhands/microagents/repo.md +++ b/.openhands/microagents/repo.md @@ -83,6 +83,116 @@ VSCode Extension: - Use `vscode.window.createOutputChannel()` for debug logging instead of `showErrorMessage()` popups - Pre-commit process runs both frontend and backend checks when committing extension changes +## Enterprise Directory + +The `enterprise/` directory contains additional functionality that extends the open-source OpenHands codebase. This includes: +- Authentication and user management (Keycloak integration) +- Database migrations (Alembic) +- Integration services (GitHub, GitLab, Jira, Linear, Slack) +- Billing and subscription management (Stripe) +- Telemetry and analytics (PostHog, custom metrics framework) + +### Enterprise Development Setup + +**Prerequisites:** +- Python 3.12 +- Poetry (for dependency management) +- Node.js 22.x (for frontend) +- Docker (optional) + +**Setup Steps:** +1. First, build the main OpenHands project: `make build` +2. Then install enterprise dependencies: `cd enterprise && poetry install --with dev,test` (This can take a very long time. Be patient.) +3. Set up enterprise pre-commit hooks: `poetry run pre-commit install --config ./dev_config/python/.pre-commit-config.yaml` + +**Running Enterprise Tests:** +```bash +# Enterprise unit tests (full suite) +PYTHONPATH=".:$PYTHONPATH" poetry run --project=enterprise pytest --forked -n auto -s -p no:ddtrace -p no:ddtrace.pytest_bdd -p no:ddtrace.pytest_benchmark ./enterprise/tests/unit --cov=enterprise --cov-branch + +# Test specific modules (faster for development) +cd enterprise +PYTHONPATH=".:$PYTHONPATH" poetry run pytest tests/unit/telemetry/ --confcutdir=tests/unit/telemetry + +# Enterprise linting (IMPORTANT: use --show-diff-on-failure to match GitHub CI) +poetry run pre-commit run --all-files --show-diff-on-failure --config ./dev_config/python/.pre-commit-config.yaml +``` + +**Running Enterprise Server:** +```bash +cd enterprise +make start-backend # Development mode with hot reload +# or +make run # Full application (backend + frontend) +``` + +**Key Configuration Files:** +- `enterprise/pyproject.toml` - Enterprise-specific dependencies +- `enterprise/Makefile` - Enterprise build and run commands +- `enterprise/dev_config/python/` - Linting and type checking configuration +- `enterprise/migrations/` - Database migration files + +**Database Migrations:** +Enterprise uses Alembic for database migrations. When making schema changes: +1. Create migration files in `enterprise/migrations/versions/` +2. Test migrations thoroughly +3. The CI will check for migration conflicts on PRs + +**Integration Development:** +The enterprise codebase includes integrations for: +- **GitHub** - PR management, webhooks, app installations +- **GitLab** - Similar to GitHub but for GitLab instances +- **Jira** - Issue tracking and project management +- **Linear** - Modern issue tracking +- **Slack** - Team communication and notifications + +Each integration follows a consistent pattern with service classes, storage models, and API endpoints. + +**Important Notes:** +- Enterprise code is licensed under Polyform Free Trial License (30-day limit) +- The enterprise server extends the OSS server through dynamic imports +- Database changes require careful migration planning in `enterprise/migrations/` +- Always test changes in both OSS and enterprise contexts +- Use the enterprise-specific Makefile commands for development + +**Enterprise Testing Best Practices:** + +**Database Testing:** +- Use SQLite in-memory databases (`sqlite:///:memory:`) for unit tests instead of real PostgreSQL +- Create module-specific `conftest.py` files with database fixtures +- Mock external database connections in unit tests to avoid dependency on running services +- Use real database connections only for integration tests + +**Import Patterns:** +- Use relative imports without `enterprise.` prefix in enterprise code +- Example: `from storage.database import session_maker` not `from enterprise.storage.database import session_maker` +- This ensures code works in both OSS and enterprise contexts + +**Test Structure:** +- Place tests in `enterprise/tests/unit/` following the same structure as the source code +- Use `--confcutdir=tests/unit/[module]` when testing specific modules +- Create comprehensive fixtures for complex objects (databases, external services) +- Write platform-agnostic tests (avoid hardcoded OS-specific assertions) + +**Mocking Strategy:** +- Use `AsyncMock` for async operations and `MagicMock` for complex objects +- Mock all external dependencies (databases, APIs, file systems) in unit tests +- Use `patch` with correct import paths (e.g., `telemetry.registry.logger` not `enterprise.telemetry.registry.logger`) +- Test both success and failure scenarios with proper error handling + +**Coverage Goals:** +- Aim for 90%+ test coverage on new enterprise modules +- Focus on critical business logic and error handling paths +- Use `--cov-report=term-missing` to identify uncovered lines + +**Troubleshooting:** +- If tests fail, ensure all dependencies are installed: `poetry install --with dev,test` +- For database issues, check migration status and run migrations if needed +- For frontend issues, ensure the main OpenHands frontend is built: `make build` +- Check logs in the `logs/` directory for runtime issues +- If tests fail with import errors, verify `PYTHONPATH=".:$PYTHONPATH"` is set +- **If GitHub CI fails but local linting passes**: Always use `--show-diff-on-failure` flag to match CI behavior exactly + ## Template for Github Pull Request If you are starting a pull request (PR), please follow the template in `.github/pull_request_template.md`. diff --git a/.vscode/settings.json b/.vscode/settings.json index 70599b8520..5f1e58f516 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,4 +3,20 @@ "files.eol": "\n", "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true, + + "python.defaultInterpreterPath": "./.venv/bin/python", + "python.terminal.activateEnvironment": true, + "python.analysis.autoImportCompletions": true, + "python.analysis.autoSearchPaths": true, + "python.analysis.extraPaths": [ + "./.venv/lib/python3.12/site-packages" + ], + "python.analysis.packageIndexDepths": [ + { + "name": "openhands", + "depth": 10, + "includeAllSymbols": true + } + ], + "python.analysis.stubPath": "./.venv/lib/python3.12/site-packages", } diff --git a/CNAME b/CNAME new file mode 100644 index 0000000000..169c574c15 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +docs.all-hands.dev diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 8cf32bb41f..aa03899d44 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -113,19 +113,19 @@ individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. -### Slack and Discord Etiquettes +### Slack Etiquettes -These Slack and Discord etiquette guidelines are designed to foster an inclusive, respectful, and productive environment for all community members. By following these best practices, we ensure effective communication and collaboration while minimizing disruptions. Let’s work together to build a supportive and welcoming community! +These Slack etiquette guidelines are designed to foster an inclusive, respectful, and productive environment for all community members. By following these best practices, we ensure effective communication and collaboration while minimizing disruptions. Let’s work together to build a supportive and welcoming community! - Communicate respectfully and professionally, avoiding sarcasm or harsh language, and remember that tone can be difficult to interpret in text. - Use threads for specific discussions to keep channels organized and easier to follow. - Tag others only when their input is critical or urgent, and use @here, @channel or @everyone sparingly to minimize disruptions. - Be patient, as open-source contributors and maintainers often have other commitments and may need time to respond. -- Post questions or discussions in the most relevant channel (e.g., for [slack - #general](https://openhands-ai.slack.com/archives/C06P5NCGSFP) for general topics, [slack - #questions](https://openhands-ai.slack.com/archives/C06U8UTKSAD) for queries/questions, [discord - #general](https://discord.com/channels/1222935860639563850/1222935861386018885)). +- Post questions or discussions in the most relevant channel (e.g., for [slack - #general](https://openhands-ai.slack.com/archives/C06P5NCGSFP) for general topics, [slack - #questions](https://openhands-ai.slack.com/archives/C06U8UTKSAD) for queries/questions. - When asking for help or raising issues, include necessary details like links, screenshots, or clear explanations to provide context. - Keep discussions in public channels whenever possible to allow others to benefit from the conversation, unless the matter is sensitive or private. -- Always adhere to [our standards](https://github.com/All-Hands-AI/OpenHands/blob/main/CODE_OF_CONDUCT.md#our-standards) to ensure a welcoming and collaborative environment. -- If you choose to mute a channel, consider setting up alerts for topics that still interest you to stay engaged. For Slack, Go to Settings → Notifications → My Keywords to add specific keywords that will notify you when mentioned. For example, if you're here for discussions about LLMs, mute the channel if it’s too busy, but set notifications to alert you only when “LLMs” appears in messages. Also for Discord, go to the channel notifications and choose the option that best describes your need. +- Always adhere to [our standards](https://github.com/OpenHands/OpenHands/blob/main/CODE_OF_CONDUCT.md#our-standards) to ensure a welcoming and collaborative environment. +- If you choose to mute a channel, consider setting up alerts for topics that still interest you to stay engaged. For Slack, Go to Settings → Notifications → My Keywords to add specific keywords that will notify you when mentioned. For example, if you're here for discussions about LLMs, mute the channel if it’s too busy, but set notifications to alert you only when “LLMs” appears in messages. ## Attribution diff --git a/COMMUNITY.md b/COMMUNITY.md index 6edb4dff31..1c49b3932e 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -8,7 +8,7 @@ If this resonates with you, we'd love to have you join us in our quest! ## 🤝 How to Join -Check out our [How to Join the Community section.](https://github.com/All-Hands-AI/OpenHands?tab=readme-ov-file#-how-to-join-the-community) +Check out our [How to Join the Community section.](https://github.com/OpenHands/OpenHands?tab=readme-ov-file#-how-to-join-the-community) ## 💪 Becoming a Contributor diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 39c7341dcf..e2338202cf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,15 +13,15 @@ To understand the codebase, please refer to the README in each module: ## Setting up Your Development Environment -We have a separate doc [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md) that tells you how to set up a development workflow. +We have a separate doc [Development.md](https://github.com/OpenHands/OpenHands/blob/main/Development.md) that tells you how to set up a development workflow. ## How Can I Contribute? There are many ways that you can contribute: -1. **Download and use** OpenHands, and send [issues](https://github.com/All-Hands-AI/OpenHands/issues) when you encounter something that isn't working or a feature that you'd like to see. +1. **Download and use** OpenHands, and send [issues](https://github.com/OpenHands/OpenHands/issues) when you encounter something that isn't working or a feature that you'd like to see. 2. **Send feedback** after each session by [clicking the thumbs-up thumbs-down buttons](https://docs.all-hands.dev/usage/feedback), so we can see where things are working and failing, and also build an open dataset for training code agents. -3. **Improve the Codebase** by sending [PRs](#sending-pull-requests-to-openhands) (see details below). In particular, we have some [good first issues](https://github.com/All-Hands-AI/OpenHands/labels/good%20first%20issue) that may be ones to start on. +3. **Improve the Codebase** by sending [PRs](#sending-pull-requests-to-openhands) (see details below). In particular, we have some [good first issues](https://github.com/OpenHands/OpenHands/labels/good%20first%20issue) that may be ones to start on. ## What Can I Build? Here are a few ways you can help improve the codebase. @@ -35,7 +35,7 @@ of the application, please open an issue first, or better, join the #eng-ui-ux c to gather consensus from our design team first. #### Improving the agent -Our main agent is the CodeAct agent. You can [see its prompts here](https://github.com/All-Hands-AI/OpenHands/tree/main/openhands/agenthub/codeact_agent). +Our main agent is the CodeAct agent. You can [see its prompts here](https://github.com/OpenHands/OpenHands/tree/main/openhands/agenthub/codeact_agent). Changes to these prompts, and to the underlying behavior in Python, can have a huge impact on user experience. You can try modifying the prompts to see how they change the behavior of the agent as you use the app @@ -54,11 +54,11 @@ The agent needs a place to run code and commands. When you run OpenHands on your to do this by default. But there are other ways of creating a sandbox for the agent. If you work for a company that provides a cloud-based runtime, you could help us add support for that runtime -by implementing the [interface specified here](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/base.py). +by implementing the [interface specified here](https://github.com/OpenHands/OpenHands/blob/main/openhands/runtime/base.py). #### Testing When you write code, it is also good to write tests. Please navigate to the [`./tests`](./tests) folder to see existing test suites. -At the moment, we have two kinds of tests: [`unit`](./tests/unit) and [`integration`](./evaluation/integration_tests). Please refer to the README for each test suite. These tests also run on GitHub's continuous integration to ensure quality of the project. +At the moment, we have these kinds of tests: [`unit`](./tests/unit), [`runtime`](./tests/runtime), and [`end-to-end (e2e)`](./tests/e2e). Please refer to the README for each test suite. These tests also run on GitHub's continuous integration to ensure quality of the project. ## Sending Pull Requests to OpenHands @@ -84,7 +84,7 @@ For example, a PR title could be: - `refactor: modify package path` - `feat(frontend): xxxx`, where `(frontend)` means that this PR mainly focuses on the frontend component. -You may also check out previous PRs in the [PR list](https://github.com/All-Hands-AI/OpenHands/pulls). +You may also check out previous PRs in the [PR list](https://github.com/OpenHands/OpenHands/pulls). ### Pull Request description - If your PR is small (such as a typo fix), you can go brief. @@ -97,7 +97,7 @@ please include a short message that we can add to our changelog. ### Opening Issues -If you notice any bugs or have any feature requests please open them via the [issues page](https://github.com/All-Hands-AI/OpenHands/issues). We will triage based on how critical the bug is or how potentially useful the improvement is, discuss, and implement the ones that the community has interest/effort for. +If you notice any bugs or have any feature requests please open them via the [issues page](https://github.com/OpenHands/OpenHands/issues). We will triage based on how critical the bug is or how potentially useful the improvement is, discuss, and implement the ones that the community has interest/effort for. Further, if you see an issue you like, please leave a "thumbs-up" or a comment, which will help us prioritize. diff --git a/CREDITS.md b/CREDITS.md index 873742b7e0..3dc74fe103 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -2,7 +2,7 @@ ## Contributors -We would like to thank all the [contributors](https://github.com/All-Hands-AI/OpenHands/graphs/contributors) who have helped make OpenHands possible. We greatly appreciate your dedication and hard work. +We would like to thank all the [contributors](https://github.com/OpenHands/OpenHands/graphs/contributors) who have helped make OpenHands possible. We greatly appreciate your dedication and hard work. ## Open Source Projects @@ -14,7 +14,7 @@ OpenHands includes and adapts the following open source projects. We are gratefu #### [Aider](https://github.com/paul-gauthier/aider) - License: Apache License 2.0 - - Description: AI pair programming tool. OpenHands has adapted and integrated its linter module for code-related tasks in [`agentskills utilities`](https://github.com/All-Hands-AI/OpenHands/tree/main/openhands/runtime/plugins/agent_skills/utils/aider) + - Description: AI pair programming tool. OpenHands has adapted and integrated its linter module for code-related tasks in [`agentskills utilities`](https://github.com/OpenHands/OpenHands/tree/main/openhands/runtime/plugins/agent_skills/utils/aider) #### [BrowserGym](https://github.com/ServiceNow/BrowserGym) - License: Apache License 2.0 diff --git a/Development.md b/Development.md index 7a4c5ce8bd..8b524be511 100644 --- a/Development.md +++ b/Development.md @@ -2,7 +2,7 @@ This guide is for people working on OpenHands and editing the source code. If you wish to contribute your changes, check out the -[CONTRIBUTING.md](https://github.com/All-Hands-AI/OpenHands/blob/main/CONTRIBUTING.md) +[CONTRIBUTING.md](https://github.com/OpenHands/OpenHands/blob/main/CONTRIBUTING.md) on how to clone and setup the project initially before moving on. Otherwise, you can clone the OpenHands project directly. @@ -159,7 +159,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.57-nikolaik` +Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/openhands/runtime:0.62-nikolaik` ## Develop inside Docker container @@ -193,7 +193,7 @@ Here's a guide to the important documentation files in the repository: - [/README.md](./README.md): Main project overview, features, and basic setup instructions - [/Development.md](./Development.md) (this file): Comprehensive guide for developers working on OpenHands - [/CONTRIBUTING.md](./CONTRIBUTING.md): Guidelines for contributing to the project, including code style and PR process -- [/docs/DOC_STYLE_GUIDE.md](./docs/DOC_STYLE_GUIDE.md): Standards for writing and maintaining project documentation +- [DOC_STYLE_GUIDE.md](https://github.com/All-Hands-AI/docs/blob/main/openhands/DOC_STYLE_GUIDE.md): Standards for writing and maintaining project documentation - [/openhands/README.md](./openhands/README.md): Details about the backend Python implementation - [/frontend/README.md](./frontend/README.md): Frontend React application setup and development guide - [/containers/README.md](./containers/README.md): Information about Docker containers and deployment diff --git a/README.md b/README.md index 368ea21d21..cd47210ef1 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,32 @@
- Logo + Logo

OpenHands: Code Less, Make More

- Contributors - Stargazers - MIT License + Contributors + Stargazers + MIT License
- Join our Slack community - Join our Discord community - Credits + Join our Slack community + Credits
Check out the documentation Paper on Arxiv Evaluation Benchmark Score - Deutsch | - Español | - français | - 日本語 | - 한국어 | - Português | - Русский | - 中文 + Deutsch | + Español | + français | + 日本語 | + 한국어 | + Português | + Русский | + 中文
@@ -39,16 +38,20 @@ call APIs, and yes—even copy code snippets from StackOverflow. 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] +> **Upcoming change**: We are renaming our GitHub Org from `All-Hands-AI` to `OpenHands` on October 20th, 2025. +> Check the [tracking issue](https://github.com/All-Hands-AI/OpenHands/issues/11376) for more information. + + > [!IMPORTANT] > Using OpenHands for work? We'd love to chat! Fill out > [this short form](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform) > to join our Design Partner program, where you'll get early access to commercial features and the opportunity to provide input on our product roadmap. -![App screenshot](./docs/static/img/screenshot.png) - ## ☁️ OpenHands Cloud The easiest way to get started with OpenHands is on [OpenHands Cloud](https://app.all-hands.dev), -which comes with $20 in free credits for new users. +which comes with $10 in free credits for new users. ## 💻 Running OpenHands Locally @@ -63,10 +66,10 @@ See the [uv installation guide](https://docs.astral.sh/uv/getting-started/instal **Launch OpenHands**: ```bash # Launch the GUI server -uvx --python 3.12 --from openhands-ai openhands serve +uvx --python 3.12 openhands serve # Or launch the CLI -uvx --python 3.12 --from openhands-ai openhands +uvx --python 3.12 openhands ``` You'll find OpenHands running at [http://localhost:3000](http://localhost:3000) (for GUI mode)! @@ -79,17 +82,17 @@ You'll find OpenHands running at [http://localhost:3000](http://localhost:3000) You can also run OpenHands directly with Docker: ```bash -docker pull docker.all-hands.dev/all-hands-ai/runtime:0.57-nikolaik +docker pull docker.openhands.dev/openhands/runtime:0.62-nikolaik docker run -it --rm --pull=always \ - -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.57-nikolaik \ + -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.openhands.dev/openhands/runtime:0.62-nikolaik \ -e LOG_ALL_EVENTS=true \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.openhands:/.openhands \ -p 3000:3000 \ --add-host host.docker.internal:host-gateway \ --name openhands-app \ - docker.all-hands.dev/all-hands-ai/openhands:0.57 + docker.openhands.dev/openhands/openhands:0.62 ``` @@ -103,7 +106,7 @@ docker run -it --rm --pull=always \ ### Getting Started When you open the application, you'll be asked to choose an LLM provider and add an API key. -[Anthropic's Claude Sonnet 4](https://www.anthropic.com/api) (`anthropic/claude-sonnet-4-20250514`) +[Anthropic's Claude Sonnet 4.5](https://www.anthropic.com/api) (`anthropic/claude-sonnet-4-5-20250929`) works best, but you have [many options](https://docs.all-hands.dev/usage/llms). See the [Running OpenHands](https://docs.all-hands.dev/usage/installation) guide for @@ -116,7 +119,7 @@ system requirements and more information. > 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, check out the source-available, commercially-licensed -> [OpenHands Cloud Helm Chart](https://github.com/all-Hands-AI/OpenHands-cloud) +> [OpenHands Cloud Helm Chart](https://github.com/openHands/OpenHands-cloud) You can [connect OpenHands to your local filesystem](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), interact with it via a [friendly CLI](https://docs.all-hands.dev/usage/how-to/cli-mode), @@ -125,7 +128,7 @@ or run it on tagged issues with [a github action](https://docs.all-hands.dev/usa Visit [Running OpenHands](https://docs.all-hands.dev/usage/installation) for more information and setup instructions. -If you want to modify the OpenHands source code, check out [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md). +If you want to modify the OpenHands source code, check out [Development.md](https://github.com/OpenHands/OpenHands/blob/main/Development.md). Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/usage/troubleshooting) can help. @@ -140,21 +143,20 @@ troubleshooting resources, and advanced configuration options. ## 🤝 How to Join the Community OpenHands is a community-driven project, and we welcome contributions from everyone. We do most of our communication -through Slack, so this is the best place to start, but we also are happy to have you contact us on Discord or Github: +through Slack, so this is the best place to start, but we also are happy to have you contact us on Github: -- [Join our Slack workspace](https://dub.sh/openhands) - Here we talk about research, architecture, and future development. -- [Join our Discord server](https://discord.gg/ESHStjSjD4) - This is a community-run server for general discussion, questions, and feedback. -- [Read or post Github Issues](https://github.com/All-Hands-AI/OpenHands/issues) - Check out the issues we're working on, or add your own ideas. +- [Join our Slack workspace](https://all-hands.dev/joinslack) - Here we talk about research, architecture, and future development. +- [Read or post Github Issues](https://github.com/OpenHands/OpenHands/issues) - Check out the issues we're working on, or add your own ideas. See more about the community in [COMMUNITY.md](./COMMUNITY.md) or find details on contributing in [CONTRIBUTING.md](./CONTRIBUTING.md). ## 📈 Progress -See the monthly OpenHands roadmap [here](https://github.com/orgs/All-Hands-AI/projects/1) (updated at the maintainer's meeting at the end of each month). +See the monthly OpenHands roadmap [here](https://github.com/orgs/OpenHands/projects/1) (updated at the maintainer's meeting at the end of each month).

- - Star History Chart + + Star History Chart

diff --git a/README_CN.md b/README_CN.md deleted file mode 100644 index 6fb15100b0..0000000000 --- a/README_CN.md +++ /dev/null @@ -1,148 +0,0 @@ - - - -
- Logo -

OpenHands: 少写代码,多做事

-
- - -
- Contributors - Stargazers - MIT License -
- 加入我们的Slack社区 - 加入我们的Discord社区 - 致谢 -
- 查看文档 - Arxiv论文 - 评估基准分数 -
-
- -欢迎使用OpenHands(前身为OpenDevin),这是一个由AI驱动的软件开发代理平台。 - -OpenHands代理可以完成人类开发者能做的任何事情:修改代码、运行命令、浏览网页、调用API,甚至从StackOverflow复制代码片段。 - -在[docs.all-hands.dev](https://docs.all-hands.dev)了解更多信息,或[注册OpenHands Cloud](https://app.all-hands.dev)开始使用。 - -> [!IMPORTANT] -> 在工作中使用OpenHands?我们很想与您交流!填写 -> [这份简短表格](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform) -> 加入我们的设计合作伙伴计划,您将获得商业功能的早期访问权限,并有机会对我们的产品路线图提供意见。 - -![应用截图](./docs/static/img/screenshot.png) - -## ☁️ OpenHands Cloud -开始使用OpenHands的最简单方式是在[OpenHands Cloud](https://app.all-hands.dev)上, -新用户可获得$50的免费额度。 - -## 💻 在本地运行OpenHands - -OpenHands也可以使用Docker在本地系统上运行。 -查看[运行OpenHands](https://docs.all-hands.dev/usage/installation)指南了解 -系统要求和更多信息。 - -> [!WARNING] -> 在公共网络上?请参阅我们的[强化Docker安装指南](https://docs.all-hands.dev/usage/runtimes/docker#hardened-docker-installation) -> 通过限制网络绑定和实施其他安全措施来保护您的部署。 - - -```bash -docker pull docker.all-hands.dev/all-hands-ai/runtime:0.57-nikolaik - -docker run -it --rm --pull=always \ - -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.57-nikolaik \ - -e LOG_ALL_EVENTS=true \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v ~/.openhands:/.openhands \ - -p 3000:3000 \ - --add-host host.docker.internal:host-gateway \ - --name openhands-app \ - docker.all-hands.dev/all-hands-ai/openhands:0.57 -``` - -> **注意**: 如果您在0.44版本之前使用过OpenHands,您可能需要运行 `mv ~/.openhands-state ~/.openhands` 来将对话历史迁移到新位置。 - -您将在[http://localhost:3000](http://localhost:3000)找到运行中的OpenHands! - -打开应用程序时,您将被要求选择一个LLM提供商并添加API密钥。 -[Anthropic的Claude Sonnet 4](https://www.anthropic.com/api)(`anthropic/claude-sonnet-4-20250514`) -效果最佳,但您还有[许多选择](https://docs.all-hands.dev/usage/llms)。 - -## 💡 运行OpenHands的其他方式 - -> [!CAUTION] -> OpenHands旨在由单个用户在其本地工作站上运行。 -> 它不适合多租户部署,即多个用户共享同一实例。没有内置的身份验证、隔离或可扩展性。 -> -> 如果您有兴趣在多租户环境中运行OpenHands,请 -> [与我们联系](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform) -> 了解高级部署选项。 - -您还可以[将OpenHands连接到本地文件系统](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), -以可编程的[无头模式](https://docs.all-hands.dev/usage/how-to/headless-mode)运行OpenHands, -通过[友好的CLI](https://docs.all-hands.dev/usage/how-to/cli-mode)与其交互, -或使用[GitHub Action](https://docs.all-hands.dev/usage/how-to/github-action)在标记的问题上运行它。 - -访问[运行OpenHands](https://docs.all-hands.dev/usage/installation)获取更多信息和设置说明。 - -如果您想修改OpenHands源代码,请查看[Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)。 - -遇到问题?[故障排除指南](https://docs.all-hands.dev/usage/troubleshooting)可以提供帮助。 - -## 📖 文档 - Ask DeepWiki - -要了解有关项目的更多信息,以及使用OpenHands的技巧, -请查看我们的[文档](https://docs.all-hands.dev/usage/getting-started)。 - -在那里,您将找到有关如何使用不同LLM提供商、 -故障排除资源和高级配置选项的资源。 - -## 🤝 如何加入社区 - -OpenHands是一个社区驱动的项目,我们欢迎每个人的贡献。我们大部分沟通 -通过Slack进行,因此这是开始的最佳场所,但我们也很乐意您通过Discord或Github与我们联系: - -- [加入我们的Slack工作空间](https://dub.sh/openhands) - 这里我们讨论研究、架构和未来发展。 -- [加入我们的Discord服务器](https://discord.gg/ESHStjSjD4) - 这是一个社区运营的服务器,用于一般讨论、问题和反馈。 -- [阅读或发布Github问题](https://github.com/All-Hands-AI/OpenHands/issues) - 查看我们正在处理的问题,或添加您自己的想法。 - -在[COMMUNITY.md](./COMMUNITY.md)中了解更多关于社区的信息,或在[CONTRIBUTING.md](./CONTRIBUTING.md)中找到有关贡献的详细信息。 - -## 📈 进展 - -在[这里](https://github.com/orgs/All-Hands-AI/projects/1)查看OpenHands月度路线图(每月月底在维护者会议上更新)。 - -

- - Star History Chart - -

- -## 📜 许可证 - -根据MIT许可证分发。有关更多信息,请参阅[`LICENSE`](./LICENSE)。 - -## 🙏 致谢 - -OpenHands由大量贡献者构建,每一份贡献都备受感谢!我们还借鉴了其他开源项目,对他们的工作深表感谢。 - -有关OpenHands中使用的开源项目和许可证列表,请参阅我们的[CREDITS.md](./CREDITS.md)文件。 - -## 📚 引用 - -``` -@misc{openhands, - title={{OpenHands: An Open Platform for AI Software Developers as Generalist Agents}}, - author={Xingyao Wang and Boxuan Li and Yufan Song and Frank F. Xu and Xiangru Tang and Mingchen Zhuge and Jiayi Pan and Yueqi Song and Bowen Li and Jaskirat Singh and Hoang H. Tran and Fuqiang Li and Ren Ma and Mingzhang Zheng and Bill Qian and Yanjun Shao and Niklas Muennighoff and Yizhe Zhang and Binyuan Hui and Junyang Lin and Robert Brennan and Hao Peng and Heng Ji and Graham Neubig}, - year={2024}, - eprint={2407.16741}, - archivePrefix={arXiv}, - primaryClass={cs.SE}, - url={https://arxiv.org/abs/2407.16741}, -} -``` diff --git a/README_JA.md b/README_JA.md deleted file mode 100644 index 6446c35abf..0000000000 --- a/README_JA.md +++ /dev/null @@ -1,60 +0,0 @@ - - -
- Logo -

OpenHands: コードを減らして、もっと作ろう

-
- -
- Contributors - Stargazers - MIT License -
- Slackコミュニティに参加 - Discordコミュニティに参加 - クレジット -
- ドキュメントを見る - Arxiv論文 - 評価ベンチマークスコア -
-
- -OpenHands(旧OpenDevin)へようこそ。これはAIが駆動するソフトウェア開発エージェントのプラットフォームです。 - -OpenHandsのエージェントは人間の開発者ができることは何でもこなします。コードを修正し、コマンドを実行し、ウェブを閲覧し、APIを呼び出し、StackOverflowからコードスニペットをコピーすることさえできます。 - -詳細は[docs.all-hands.dev](https://docs.all-hands.dev)をご覧いただくか、[OpenHands Cloud](https://app.all-hands.dev)に登録して始めましょう。 - -> [!IMPORTANT] -> 仕事でOpenHandsを使っていますか?ぜひお話を聞かせてください。[こちらの短いフォーム](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)にご記入いただき、Design Partnerプログラムにご参加ください。商用機能の早期アクセスや製品ロードマップへのフィードバックの機会を提供します。 - -![アプリのスクリーンショット](./docs/static/img/screenshot.png) - -## ☁️ OpenHands Cloud -OpenHandsを始める最も簡単な方法は[OpenHands Cloud](https://app.all-hands.dev)を利用することです。新規ユーザーには50ドル分の無料クレジットが付与されます。 - -## 💻 OpenHandsをローカルで実行する - -OpenHandsはDockerを利用してローカル環境でも実行できます。システム要件や詳細については[Running OpenHands](https://docs.all-hands.dev/usage/installation)ガイドをご覧ください。 - -> [!WARNING] -> 公共ネットワークで実行していますか?[Hardened Docker Installation Guide](https://docs.all-hands.dev/usage/runtimes/docker#hardened-docker-installation)を参照して、ネットワークバインディングの制限や追加のセキュリティ対策を実施してください。 - -```bash -docker pull docker.all-hands.dev/all-hands-ai/runtime:0.57-nikolaik - -docker run -it --rm --pull=always \ - -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.57-nikolaik \ - -e LOG_ALL_EVENTS=true \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v ~/.openhands:/.openhands \ - -p 3000:3000 \ - --add-host host.docker.internal:host-gateway \ - --name openhands-app \ - docker.all-hands.dev/all-hands-ai/openhands:0.57 -``` - -**注**: バージョン0.44以前のOpenHandsを使用していた場合は、会話履歴を移行するために `mv ~/.openhands-state ~/.openhands` を実行してください。 - -OpenHandsは[http://localhost:3000](http://localhost:3000)で起動します! diff --git a/config.template.toml b/config.template.toml index e7b7836dcd..68b4eed281 100644 --- a/config.template.toml +++ b/config.template.toml @@ -189,7 +189,7 @@ model = "gpt-4o" # Whether to use native tool calling if supported by the model. Can be true, false, or None by default, which chooses the model's default behavior based on the evaluation. # ATTENTION: Based on evaluation, enabling native function calling may lead to worse results # in some scenarios. Use with caution and consider testing with your specific use case. -# https://github.com/All-Hands-AI/OpenHands/pull/4711 +# https://github.com/OpenHands/OpenHands/pull/4711 #native_tool_calling = None diff --git a/containers/app/Dockerfile b/containers/app/Dockerfile index 87f9adfcd3..372e5b1ef6 100644 --- a/containers/app/Dockerfile +++ b/containers/app/Dockerfile @@ -1,5 +1,5 @@ ARG OPENHANDS_BUILD_VERSION=dev -FROM node:24.3.0-bookworm-slim AS frontend-builder +FROM node:24.8-trixie-slim AS frontend-builder WORKDIR /app @@ -9,7 +9,7 @@ RUN npm ci COPY frontend ./ RUN npm run build -FROM python:3.12.10-slim AS base +FROM python:3.13.7-slim-trixie AS base FROM base AS backend-builder WORKDIR /app diff --git a/containers/app/config.sh b/containers/app/config.sh index 6ed9ac329e..41d00c84a0 100644 --- a/containers/app/config.sh +++ b/containers/app/config.sh @@ -1,4 +1,4 @@ DOCKER_REGISTRY=ghcr.io -DOCKER_ORG=all-hands-ai +DOCKER_ORG=openhands DOCKER_IMAGE=openhands DOCKER_BASE_DIR="." diff --git a/containers/dev/Dockerfile b/containers/dev/Dockerfile index 29118ff8cf..b4b95209ab 100644 --- a/containers/dev/Dockerfile +++ b/containers/dev/Dockerfile @@ -104,6 +104,9 @@ RUN apt-get update && apt-get install -y \ && apt-get clean \ && apt-get autoremove -y +# mark /app as safe git directory to avoid pre-commit errors +RUN git config --system --add safe.directory /app + WORKDIR /app # cache build dependencies diff --git a/containers/dev/README.md b/containers/dev/README.md index 0fb1bbc3b3..4f2df5cb0b 100644 --- a/containers/dev/README.md +++ b/containers/dev/README.md @@ -1,7 +1,7 @@ # Develop in Docker > [!WARNING] -> This is not officially supported and may not work. +> This way of running OpenHands is not officially supported. It is maintained by the community and may not work. Install [Docker](https://docs.docker.com/engine/install/) on your host machine and run: diff --git a/containers/dev/compose.yml b/containers/dev/compose.yml index 884e65a49b..c6168b094f 100644 --- a/containers/dev/compose.yml +++ b/containers/dev/compose.yml @@ -12,7 +12,7 @@ services: - SANDBOX_API_HOSTNAME=host.docker.internal - DOCKER_HOST_ADDR=host.docker.internal # - - SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.57-nikolaik} + - SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/openhands/runtime:0.62-nikolaik} - SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234} - WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace} ports: diff --git a/containers/runtime/README.md b/containers/runtime/README.md index 9fbed76aa3..7671c32865 100644 --- a/containers/runtime/README.md +++ b/containers/runtime/README.md @@ -6,7 +6,7 @@ that depends on the `base_image` **AND** a [Python source distribution](https:// The following command will generate a `Dockerfile` file for `nikolaik/python-nodejs:python3.12-nodejs22` (the default base image), an updated `config.sh` and the runtime source distribution files/folders into `containers/runtime`: ```bash -poetry run python3 openhands/runtime/utils/runtime_build.py \ +poetry run python3 -m openhands.runtime.utils.runtime_build \ --base_image nikolaik/python-nodejs:python3.12-nodejs22 \ --build_folder containers/runtime ``` diff --git a/containers/runtime/config.sh b/containers/runtime/config.sh index 99d2eb66cc..d0250b6dfe 100644 --- a/containers/runtime/config.sh +++ b/containers/runtime/config.sh @@ -1,5 +1,5 @@ DOCKER_REGISTRY=ghcr.io -DOCKER_ORG=all-hands-ai +DOCKER_ORG=openhands DOCKER_BASE_DIR="./containers/runtime" DOCKER_IMAGE=runtime # These variables will be appended by the runtime_build.py script diff --git a/docker-compose.yml b/docker-compose.yml index 3ab2ba83ce..b663324625 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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.57-nikolaik} + - SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.openhands.dev/openhands/runtime:0.62-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 for this user - WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace} ports: diff --git a/docs/DOC_STYLE_GUIDE.md b/docs/DOC_STYLE_GUIDE.md deleted file mode 100644 index 213e857078..0000000000 --- a/docs/DOC_STYLE_GUIDE.md +++ /dev/null @@ -1,67 +0,0 @@ -# Documentation Style Guide - -## General Writing Principles - -- **Clarity & Conciseness**: Always prioritize clarity and brevity. Avoid unnecessary jargon or overly complex explanations. -Keep sentences short and to the point. -- **Gradual Complexity**: Start with the simplest, most basic setup, and then gradually introduce more advanced -concepts and configurations. - -## Formatting Guidelines - -### Headers - -Use **Title Case** for the first and second level headers. - -Example: - - **Basic Usage** - - **Advanced Configuration Options** - -### Lists - -When listing items or options, use bullet points to enhance readability. - -Example: - - Option A - - Option B - - Option C - -### Procedures - -For instructions or processes that need to be followed in a specific order, use numbered steps. - -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. - -### Code Blocks - -* Use code blocks for multi-line inputs, outputs, commands and code samples. - -Example: -```bash -docker run -it \ - -e THIS=this \ - -e THAT=that - ... -``` - -### Use of Note and Warning - -When adding a note or warning, use the built-in note and warning syntax. - -Example: - -This section is for advanced users only. - - -### Referring to UI Elements - -When referencing UI elements, use ``. - -Example: -1. Toggle the `Advanced` option -2. Enter your model in the `Custom Model` textbox. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 299ae6938e..0000000000 --- a/docs/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# OpenHands Documentation - -This directory contains the documentation for OpenHands. The documentation is automatically synchronized with the [All-Hands-AI/docs](https://github.com/All-Hands-AI/docs) repository, which hosts the unified documentation site using Mintlify. - -## Documentation Structure - -The documentation files in this directory are automatically included in the main documentation site via Git submodules. When you make changes to documentation in this repository, they will be automatically synchronized to the docs repository. - -## How It Works - -1. **Automatic Sync**: When documentation changes are pushed to the `main` branch, a GitHub Action automatically notifies the docs repository -2. **Submodule Update**: The docs repository updates its submodule reference to include your latest changes -3. **Site Rebuild**: Mintlify automatically rebuilds and deploys the documentation site - -## Making Documentation Changes - -Simply edit the documentation files in this directory as usual. The synchronization happens automatically when changes are merged to the main branch. - -## Local Development - -For local documentation development in this repository only: - -```bash -npm install -g mint -# or -yarn global add mint - -# Preview local changes -mint dev -``` - -For the complete unified documentation site, work with the [All-Hands-AI/docs](https://github.com/All-Hands-AI/docs) repository. - -## Configuration - -The Mintlify configuration (`docs.json`) has been moved to the root of the [All-Hands-AI/docs](https://github.com/All-Hands-AI/docs) repository to enable unified documentation across multiple repositories. diff --git a/docs/README_JA.md b/docs/README_JA.md deleted file mode 100644 index 03d4715cfa..0000000000 --- a/docs/README_JA.md +++ /dev/null @@ -1,17 +0,0 @@ -# セットアップ - -``` -npm install -g mint -``` - -または - -``` -yarn global add mint -``` - -# プレビュー - -``` -mint dev -``` diff --git a/docs/docs.json b/docs/docs.json deleted file mode 100644 index e242e1eb32..0000000000 --- a/docs/docs.json +++ /dev/null @@ -1,230 +0,0 @@ -{ - "$schema": "https://mintlify.com/docs.json", - "theme": "mint", - "name": "All Hands Docs", - "colors": { - "primary": "#99873c", - "light": "#ffe165", - "dark": "#ffe165" - }, - "background": { - "color": { - "light": "#f7f3ee", - "dark": "#0B0D0E" - } - }, - "appearance": { - "default": "light" - }, - "favicon": "/logo-square.png", - "navigation": { - "tabs": [ - { - "tab": "Docs", - "pages": [ - "index", - "usage/installation", - "usage/getting-started", - "usage/key-features", - "usage/faqs", - { - "group": "OpenHands Cloud", - "pages": [ - "usage/cloud/openhands-cloud", - { - "group": "Integrations", - "pages": [ - "usage/cloud/bitbucket-installation", - "usage/cloud/github-installation", - "usage/cloud/gitlab-installation", - "usage/cloud/slack-installation", - { - "group": "Project Management Tools", - "pages": [ - "usage/cloud/project-management/overview", - "usage/cloud/project-management/jira-integration", - "usage/cloud/project-management/jira-dc-integration", - "usage/cloud/project-management/linear-integration" - ] - } - ] - }, - "usage/cloud/cloud-ui", - "usage/cloud/cloud-api" - ] - }, - { - "group": "Run OpenHands on Your Own", - "pages": [ - "usage/local-setup", - "usage/how-to/gui-mode", - "usage/how-to/cli-mode", - "usage/how-to/headless-mode", - "usage/how-to/github-action", - { - "group": "Advanced Configuration", - "pages": [ - { - "group": "LLM Configuration", - "pages": [ - "usage/llms/llms", - { - "group": "Providers", - "pages": [ - "usage/llms/openhands-llms", - "usage/llms/azure-llms", - "usage/llms/google-llms", - "usage/llms/groq", - "usage/llms/local-llms", - "usage/llms/litellm-proxy", - "usage/llms/moonshot", - "usage/llms/openai-llms", - "usage/llms/openrouter" - ] - } - ] - }, - { - "group": "Runtime Configuration", - "pages": [ - "usage/runtimes/overview", - { - "group": "Providers", - "pages": [ - "usage/runtimes/docker", - "usage/runtimes/remote", - "usage/runtimes/local", - { - "group": "Third-Party Providers", - "pages": [ - "usage/runtimes/modal", - "usage/runtimes/daytona", - "usage/runtimes/runloop", - "usage/runtimes/e2b" - ] - } - ] - } - ] - }, - "usage/configuration-options", - "usage/how-to/custom-sandbox-guide", - "usage/search-engine-setup", - "usage/mcp" - ] - } - ] - }, - { - "group": "Customizations & Settings", - "pages": [ - "usage/common-settings", - "usage/prompting/repository", - { - "group": "Microagents", - "pages": [ - "usage/prompting/microagents-overview", - "usage/prompting/microagents-repo", - "usage/prompting/microagents-keyword", - "usage/prompting/microagents-org", - "usage/prompting/microagents-public" - ] - } - ] - }, - { - "group": "Tips and Tricks", - "pages": [ - "usage/prompting/prompting-best-practices" - ] - }, - { - "group": "Troubleshooting & Feedback", - "pages": [ - "usage/troubleshooting/troubleshooting", - "usage/feedback" - ] - }, - { - "group": "OpenHands Developers", - "pages": [ - "usage/how-to/development-overview", - { - "group": "Architecture", - "pages": [ - "usage/architecture/backend", - "usage/architecture/runtime" - ] - }, - "usage/how-to/debugging", - "usage/how-to/evaluation-harness", - "usage/how-to/websocket-connection" - ] - } - ] - }, - { - "tab": "Success Stories", - "pages": [ - "success-stories/index" - ] - }, - { - "tab": "API Reference", - "openapi": "/openapi.json" - } - ], - "global": { - "anchors": [ - { - "anchor": "Company", - "href": "https://www.all-hands.dev/", - "icon": "house" - }, - { - "anchor": "Blog", - "href": "https://www.all-hands.dev/blog", - "icon": "newspaper" - }, - { - "anchor": "OpenHands Cloud", - "href": "https://app.all-hands.dev", - "icon": "cloud" - } - ] - } - }, - "logo": { - "light": "/logo/light.svg", - "dark": "/logo/dark.svg" - }, - "navbar": { - "links": [ - ], - "primary": { - "type": "github", - "href": "https://github.com/All-Hands-AI/OpenHands" - } - }, - "footer": { - "socials": { - "slack": "https://dub.sh/openhands", - "github": "https://github.com/All-Hands-AI/OpenHands", - "discord": "https://discord.gg/ESHStjSjD4" - } - }, - "contextual": { - "options": [ - "copy", - "view", - "chatgpt", - "claude" - ] - }, - "redirects": [ - { - "source": "/modules/:slug*", - "destination": "/:slug*" - } - ] -} diff --git a/docs/favicon.svg b/docs/favicon.svg deleted file mode 100644 index b785c738bf..0000000000 --- a/docs/favicon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/docs/index.mdx b/docs/index.mdx deleted file mode 100644 index 4fb2874a0f..0000000000 --- a/docs/index.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Introduction -description: OpenHands - Code Less, Make More -icon: book-open -mode: wide ---- -Use AI to tackle the toil in your backlog. Our agents have all the same tools as a human developer: they can modify code, run commands, browse the web, call APIs, and yes-even copy code snippets from StackOverflow. - - diff --git a/docs/logo-square.png b/docs/logo-square.png deleted file mode 100644 index a260f507bc..0000000000 Binary files a/docs/logo-square.png and /dev/null differ diff --git a/docs/logo/dark.svg b/docs/logo/dark.svg deleted file mode 100644 index 5632a89e4a..0000000000 --- a/docs/logo/dark.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/logo/light.svg b/docs/logo/light.svg deleted file mode 100644 index 80f4eccf39..0000000000 --- a/docs/logo/light.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/openapi.json b/docs/openapi.json deleted file mode 100644 index d073f858ca..0000000000 --- a/docs/openapi.json +++ /dev/null @@ -1,3942 +0,0 @@ -{ - "openapi": "3.1.0", - "info": { - "title": "OpenHands", - "description": "OpenHands: Code Less, Make More", - "version": "0.53.0" - }, - "paths": { - "/api/options/models": { - "get": { - "summary": "List Supported Models", - "description": "List model identifiers available on this server based on configured providers.", - "operationId": "get_litellm_models_api_options_models_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Response Get Litellm Models Api Options Models Get" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/options/agents": { - "get": { - "summary": "List Agents", - "description": "List available agent types supported by this server.", - "operationId": "get_agents_api_options_agents_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Response Get Agents Api Options Agents Get" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/options/security-analyzers": { - "get": { - "summary": "List Security Analyzers", - "description": "List supported security analyzers.", - "operationId": "get_security_analyzers_api_options_security_analyzers_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Response Get Security Analyzers Api Options Security Analyzers Get" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/options/config": { - "get": { - "summary": "Get Config", - "description": "Get current config.", - "operationId": "get_config_api_options_config_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response Get Config Api Options Config Get" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/conversations/{conversation_id}/list-files": { - "get": { - "summary": "List Workspace Files", - "description": "List workspace files visible to the conversation runtime. Applies .gitignore and internal ignore rules.", - "operationId": "list_files_api_conversations__conversation_id__list_files_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - }, - { - "name": "path", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Path" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - }, - "title": "Response List Files Api Conversations Conversation Id List Files Get" - } - } - } - }, - "404": { - "description": "Runtime not initialized", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 404 List Files Api Conversations Conversation Id List Files Get" - } - } - } - }, - "500": { - "description": "Error listing or filtering files", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 500 List Files Api Conversations Conversation Id List Files Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/select-file": { - "get": { - "summary": "Get File Content", - "description": "Return the content of the given file from the conversation workspace.", - "operationId": "select_file_api_conversations__conversation_id__select_file_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - }, - { - "name": "file", - "in": "query", - "required": true, - "schema": { - "type": "string", - "title": "File" - } - } - ], - "responses": { - "200": { - "description": "File content returned as JSON", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "title": "Response 200 Select File Api Conversations Conversation Id Select File Get" - } - } - } - }, - "500": { - "description": "Error opening file", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 500 Select File Api Conversations Conversation Id Select File Get" - } - } - } - }, - "415": { - "description": "Unsupported media type", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 415 Select File Api Conversations Conversation Id Select File Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/zip-directory": { - "get": { - "summary": "Download Workspace Archive", - "operationId": "zip_current_workspace_api_conversations__conversation_id__zip_directory_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Zipped workspace returned as FileResponse", - "content": { - "application/json": { - "schema": {} - } - } - }, - "500": { - "description": "Error zipping workspace", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 500 Zip Current Workspace Api Conversations Conversation Id Zip Directory Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - }, - "description": "Return a ZIP archive of the current conversation workspace." - } - }, - "/api/conversations/{conversation_id}/git/changes": { - "get": { - "summary": "Git Changes", - "operationId": "git_changes_api_conversations__conversation_id__git_changes_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "title": "Response Git Changes Api Conversations Conversation Id Git Changes Get" - } - } - } - }, - "404": { - "description": "Not a git repository", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 404 Git Changes Api Conversations Conversation Id Git Changes Get" - } - } - } - }, - "500": { - "description": "Error getting changes", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 500 Git Changes Api Conversations Conversation Id Git Changes Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/git/diff": { - "get": { - "summary": "Git Diff", - "operationId": "git_diff_api_conversations__conversation_id__git_diff_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - }, - { - "name": "path", - "in": "query", - "required": true, - "schema": { - "type": "string", - "title": "Path" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response Git Diff Api Conversations Conversation Id Git Diff Get" - } - } - } - }, - "500": { - "description": "Error getting diff", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true, - "title": "Response 500 Git Diff Api Conversations Conversation Id Git Diff Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/upload-files": { - "post": { - "summary": "Upload Files", - "operationId": "upload_files_api_conversations__conversation_id__upload_files_post", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_upload_files_api_conversations__conversation_id__upload_files_post" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/POSTUploadFilesModel" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/submit-feedback": { - "post": { - "summary": "Submit Feedback", - "description": "Submit user feedback.\n\nThis function stores the provided feedback data.\n\nTo submit feedback:", - "operationId": "submit_feedback_api_conversations__conversation_id__submit_feedback_post", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/config": { - "get": { - "summary": "Get Remote Runtime Config", - "description": "Retrieve the runtime configuration.\n\nCurrently, this is the session ID and runtime ID (if available).", - "operationId": "get_remote_runtime_config_api_conversations__conversation_id__config_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/events": { - "get": { - "summary": "Search Events", - "description": "Search through the event stream with filtering and pagination.", - "operationId": "search_events_api_conversations__conversation_id__events_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - }, - { - "name": "start_id", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 0, - "title": "Start Id" - } - }, - { - "name": "end_id", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "End Id" - } - }, - { - "name": "reverse", - "in": "query", - "required": false, - "schema": { - "type": "boolean", - "default": false, - "title": "Reverse" - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "title": "Limit" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/EventFilter" - }, - { - "type": "null" - } - ], - "title": "Filter" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "post": { - "summary": "Add Event", - "operationId": "add_event_api_conversations__conversation_id__events_post", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/microagents": { - "get": { - "summary": "Get Microagents", - "description": "Get all microagents associated with the conversation.\n\nThis endpoint returns all repository and knowledge microagents that are loaded for the conversation.", - "operationId": "get_microagents_api_conversations__conversation_id__microagents_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations": { - "post": { - "summary": "New Conversation", - "description": "Initialize a new session or join an existing one.\n\nAfter successful initialization, the client should connect to the WebSocket\nusing the returned conversation ID.", - "operationId": "new_conversation_api_conversations_post", - "security": [ - { - "APIKeyHeader": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InitSessionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationResponse" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "get": { - "summary": "Search Conversations", - "operationId": "search_conversations_api_conversations_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "page_id", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Page Id" - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "title": "Limit" - } - }, - { - "name": "selected_repository", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Selected Repository" - } - }, - { - "name": "conversation_trigger", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/ConversationTrigger" - }, - { - "type": "null" - } - ], - "title": "Conversation Trigger" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationInfoResultSet" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}": { - "get": { - "summary": "Get Conversation", - "operationId": "get_conversation_api_conversations__conversation_id__get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/ConversationInfo" - }, - { - "type": "null" - } - ], - "title": "Response Get Conversation Api Conversations Conversation Id Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "delete": { - "summary": "Delete Conversation", - "operationId": "delete_conversation_api_conversations__conversation_id__delete", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "boolean", - "title": "Response Delete Conversation Api Conversations Conversation Id Delete" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "patch": { - "summary": "Update Conversation", - "description": "Update conversation metadata.\n\nThis endpoint allows updating conversation details like title.\nOnly the conversation owner can update the conversation.", - "operationId": "update_conversation_api_conversations__conversation_id__patch", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateConversationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "boolean", - "title": "Response Update Conversation Api Conversations Conversation Id Patch" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/remember-prompt": { - "get": { - "summary": "Get Prompt", - "operationId": "get_prompt_api_conversations__conversation_id__remember_prompt_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - }, - { - "name": "event_id", - "in": "query", - "required": true, - "schema": { - "type": "integer", - "title": "Event Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/start": { - "post": { - "summary": "Start Conversation", - "description": "Start an agent loop for a conversation.\n\nThis endpoint calls the conversation_manager's maybe_start_agent_loop method\nto start a conversation. If the conversation is already running, it will\nreturn the existing agent loop info.", - "operationId": "start_conversation_api_conversations__conversation_id__start_post", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProvidersSetModel" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationResponse" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/stop": { - "post": { - "summary": "Stop Conversation", - "description": "Stop an agent loop for a conversation.\n\nThis endpoint calls the conversation_manager's close_session method\nto stop a conversation.", - "operationId": "stop_conversation_api_conversations__conversation_id__stop_post", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationResponse" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/settings": { - "get": { - "summary": "Load Settings", - "operationId": "load_settings_api_settings_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GETSettingsModel" - } - } - } - }, - "404": { - "description": "Settings not found", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response 404 Load Settings Api Settings Get" - } - } - } - }, - "401": { - "description": "Invalid token", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response 401 Load Settings Api Settings Get" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - }, - "post": { - "summary": "Store Settings", - "operationId": "store_settings_api_settings_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Settings" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Settings stored successfully", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response 200 Store Settings Api Settings Post" - } - } - } - }, - "500": { - "description": "Error storing settings", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response 500 Store Settings Api Settings Post" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/reset-settings": { - "post": { - "summary": "Reset Settings", - "description": "Resets user settings. (Deprecated)", - "operationId": "reset_settings_api_reset_settings_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "410": { - "description": "Reset settings functionality has been removed", - "content": { - "application/json": { - "schema": { - "additionalProperties": true, - "type": "object", - "title": "Response 410 Reset Settings Api Reset Settings Post" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/add-git-providers": { - "post": { - "summary": "Store Provider Tokens", - "operationId": "store_provider_tokens_api_add_git_providers_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/POSTProviderModel" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/unset-provider-tokens": { - "post": { - "summary": "Unset Provider Tokens", - "operationId": "unset_provider_tokens_api_unset_provider_tokens_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Response Unset Provider Tokens Api Unset Provider Tokens Post" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/secrets": { - "get": { - "summary": "Load Custom Secrets Names", - "operationId": "load_custom_secrets_names_api_secrets_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GETCustomSecrets" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - }, - "post": { - "summary": "Create Custom Secret", - "operationId": "create_custom_secret_api_secrets_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomSecretModel" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Response Create Custom Secret Api Secrets Post" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/secrets/{secret_id}": { - "put": { - "summary": "Update Custom Secret", - "operationId": "update_custom_secret_api_secrets__secret_id__put", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "secret_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Secret Id" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomSecretWithoutValueModel" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "title": "Response Update Custom Secret Api Secrets Secret Id Put" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "delete": { - "summary": "Delete Custom Secret", - "operationId": "delete_custom_secret_api_secrets__secret_id__delete", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "secret_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Secret Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/user/installations": { - "get": { - "summary": "Get User Installations", - "operationId": "get_user_installations_api_user_installations_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "provider", - "in": "query", - "required": true, - "schema": { - "$ref": "#/components/schemas/ProviderType" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - }, - "title": "Response Get User Installations Api User Installations Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/user/repositories": { - "get": { - "summary": "Get User Repositories", - "operationId": "get_user_repositories_api_user_repositories_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "sort", - "in": "query", - "required": false, - "schema": { - "type": "string", - "default": "pushed", - "title": "Sort" - } - }, - { - "name": "selected_provider", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/ProviderType" - }, - { - "type": "null" - } - ], - "title": "Selected Provider" - } - }, - { - "name": "page", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Page" - } - }, - { - "name": "per_page", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Per Page" - } - }, - { - "name": "installation_id", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Installation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Repository" - }, - "title": "Response Get User Repositories Api User Repositories Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/user/info": { - "get": { - "summary": "Get User", - "operationId": "get_user_api_user_info_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/user/search/repositories": { - "get": { - "summary": "Search Repositories", - "operationId": "search_repositories_api_user_search_repositories_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "query", - "in": "query", - "required": true, - "schema": { - "type": "string", - "title": "Query" - } - }, - { - "name": "per_page", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 5, - "title": "Per Page" - } - }, - { - "name": "sort", - "in": "query", - "required": false, - "schema": { - "type": "string", - "default": "stars", - "title": "Sort" - } - }, - { - "name": "order", - "in": "query", - "required": false, - "schema": { - "type": "string", - "default": "desc", - "title": "Order" - } - }, - { - "name": "selected_provider", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/ProviderType" - }, - { - "type": "null" - } - ], - "title": "Selected Provider" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Repository" - }, - "title": "Response Search Repositories Api User Search Repositories Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/user/suggested-tasks": { - "get": { - "summary": "Get Suggested Tasks", - "description": "Get suggested tasks for the authenticated user across their most recently pushed repositories.", - "operationId": "get_suggested_tasks_api_user_suggested_tasks_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/SuggestedTask" - }, - "type": "array", - "title": "Response Get Suggested Tasks Api User Suggested Tasks Get" - } - } - } - } - }, - "security": [ - { - "APIKeyHeader": [] - } - ] - } - }, - "/api/user/repository/branches": { - "get": { - "summary": "Get Repository Branches", - "description": "Get branches for a repository.", - "operationId": "get_repository_branches_api_user_repository_branches_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "repository", - "in": "query", - "required": true, - "schema": { - "type": "string", - "title": "Repository" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Branch" - }, - "title": "Response Get Repository Branches Api User Repository Branches Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/user/repository/{repository_name}/microagents": { - "get": { - "summary": "Get Repository Microagents", - "description": "Scan the microagents directory of a repository and return the list of microagents.\n\nThe microagents directory location depends on the git provider and actual repository name:\n- If git provider is not GitLab and actual repository name is \".openhands\": scans \"microagents\" folder\n- If git provider is GitLab and actual repository name is \"openhands-config\": scans \"microagents\" folder\n- Otherwise: scans \".openhands/microagents\" folder", - "operationId": "get_repository_microagents_api_user_repository__repository_name__microagents_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "repository_name", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Repository Name" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MicroagentResponse" - }, - "title": "Response Get Repository Microagents Api User Repository Repository Name Microagents Get" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/user/repository/{repository_name}/microagents/content": { - "get": { - "summary": "Get Repository Microagent Content", - "description": "Fetch the content of a specific microagent file from a repository.", - "operationId": "get_repository_microagent_content_api_user_repository__repository_name__microagents_content_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "repository_name", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Repository Name" - } - }, - { - "name": "file_path", - "in": "query", - "required": true, - "schema": { - "type": "string", - "description": "Path to the microagent file within the repository", - "title": "File Path" - }, - "description": "Path to the microagent file within the repository" - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MicroagentContentResponse" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/conversations/{conversation_id}/trajectory": { - "get": { - "summary": "Get Trajectory", - "description": "Get trajectory.\n\nThis function retrieves the current trajectory and returns it.", - "operationId": "get_trajectory_api_conversations__conversation_id__trajectory_get", - "security": [ - { - "APIKeyHeader": [] - } - ], - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/alive": { - "get": { - "summary": "Alive", - "operationId": "alive_alive_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - } - } - } - }, - "/health": { - "get": { - "summary": "Health", - "operationId": "health_health_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "string", - "title": "Response Health Health Get" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "Body_upload_files_api_conversations__conversation_id__upload_files_post": { - "properties": { - "files": { - "items": { - "type": "string", - "format": "binary" - }, - "type": "array", - "title": "Files" - } - }, - "type": "object", - "required": [ - "files" - ], - "title": "Body_upload_files_api_conversations__conversation_id__upload_files_post" - }, - "Branch": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "commit_sha": { - "type": "string", - "title": "Commit Sha" - }, - "protected": { - "type": "boolean", - "title": "Protected" - }, - "last_push_date": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Last Push Date" - } - }, - "type": "object", - "required": [ - "name", - "commit_sha", - "protected" - ], - "title": "Branch" - }, - "ConversationInfo": { - "properties": { - "conversation_id": { - "type": "string", - "title": "Conversation Id" - }, - "title": { - "type": "string", - "title": "Title" - }, - "last_updated_at": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "null" - } - ], - "title": "Last Updated At" - }, - "status": { - "$ref": "#/components/schemas/ConversationStatus", - "default": "STOPPED" - }, - "runtime_status": { - "anyOf": [ - { - "$ref": "#/components/schemas/RuntimeStatus" - }, - { - "type": "null" - } - ] - }, - "selected_repository": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Selected Repository" - }, - "selected_branch": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Selected Branch" - }, - "git_provider": { - "anyOf": [ - { - "$ref": "#/components/schemas/ProviderType" - }, - { - "type": "null" - } - ] - }, - "trigger": { - "anyOf": [ - { - "$ref": "#/components/schemas/ConversationTrigger" - }, - { - "type": "null" - } - ] - }, - "num_connections": { - "type": "integer", - "title": "Num Connections", - "default": 0 - }, - "url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Url" - }, - "session_api_key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Session Api Key" - }, - "created_at": { - "type": "string", - "format": "date-time", - "title": "Created At" - }, - "pr_number": { - "items": { - "type": "integer" - }, - "type": "array", - "title": "Pr Number" - } - }, - "type": "object", - "required": [ - "conversation_id", - "title" - ], - "title": "ConversationInfo" - }, - "ConversationInfoResultSet": { - "properties": { - "results": { - "items": { - "$ref": "#/components/schemas/ConversationInfo" - }, - "type": "array", - "title": "Results" - }, - "next_page_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Next Page Id" - } - }, - "type": "object", - "title": "ConversationInfoResultSet" - }, - "ConversationResponse": { - "properties": { - "status": { - "type": "string", - "title": "Status" - }, - "conversation_id": { - "type": "string", - "title": "Conversation Id" - }, - "message": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Message" - }, - "conversation_status": { - "anyOf": [ - { - "$ref": "#/components/schemas/ConversationStatus" - }, - { - "type": "null" - } - ] - } - }, - "type": "object", - "required": [ - "status", - "conversation_id" - ], - "title": "ConversationResponse" - }, - "ConversationStatus": { - "type": "string", - "enum": [ - "STARTING", - "RUNNING", - "STOPPED" - ], - "title": "ConversationStatus" - }, - "ConversationTrigger": { - "type": "string", - "enum": [ - "resolver", - "gui", - "suggested_task", - "openhands_api", - "slack", - "microagent_management", - "jira", - "jira_dc", - "linear" - ], - "title": "ConversationTrigger" - }, - "CreateMicroagent": { - "properties": { - "repo": { - "type": "string", - "title": "Repo" - }, - "git_provider": { - "anyOf": [ - { - "$ref": "#/components/schemas/ProviderType" - }, - { - "type": "null" - } - ] - }, - "title": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Title" - } - }, - "type": "object", - "required": [ - "repo" - ], - "title": "CreateMicroagent" - }, - "CustomSecretModel": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Description" - }, - "value": { - "type": "string", - "format": "password", - "title": "Value", - "writeOnly": true - } - }, - "type": "object", - "required": [ - "name", - "value" - ], - "title": "CustomSecretModel", - "description": "Custom secret model with value" - }, - "CustomSecretWithoutValueModel": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Description" - } - }, - "type": "object", - "required": [ - "name" - ], - "title": "CustomSecretWithoutValueModel", - "description": "Custom secret model without value" - }, - "EventFilter": { - "properties": { - "exclude_hidden": { - "type": "boolean", - "title": "Exclude Hidden", - "default": false - }, - "query": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Query" - }, - "include_types": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Include Types" - }, - "exclude_types": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Exclude Types" - }, - "source": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Source" - }, - "start_date": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Start Date" - }, - "end_date": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "End Date" - } - }, - "type": "object", - "title": "EventFilter" - }, - "ExperimentConfig": { - "properties": { - "config": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Config" - } - }, - "type": "object", - "title": "ExperimentConfig" - }, - "GETCustomSecrets": { - "properties": { - "custom_secrets": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/CustomSecretWithoutValueModel" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Custom Secrets" - } - }, - "type": "object", - "title": "GETCustomSecrets", - "description": "Custom secrets names" - }, - "GETSettingsModel": { - "properties": { - "language": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Language" - }, - "agent": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Agent" - }, - "max_iterations": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Max Iterations" - }, - "security_analyzer": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Security Analyzer" - }, - "confirmation_mode": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Confirmation Mode" - }, - "llm_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Llm Model" - }, - "llm_api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Llm Api Key" - }, - "llm_base_url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Llm Base Url" - }, - "remote_runtime_resource_factor": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Remote Runtime Resource Factor" - }, - "secrets_store": { - "$ref": "#/components/schemas/UserSecrets-Output" - }, - "enable_default_condenser": { - "type": "boolean", - "title": "Enable Default Condenser", - "default": true - }, - "enable_sound_notifications": { - "type": "boolean", - "title": "Enable Sound Notifications", - "default": false - }, - "enable_proactive_conversation_starters": { - "type": "boolean", - "title": "Enable Proactive Conversation Starters", - "default": true - }, - "enable_solvability_analysis": { - "type": "boolean", - "title": "Enable Solvability Analysis", - "default": true - }, - "user_consents_to_analytics": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "User Consents To Analytics" - }, - "sandbox_base_container_image": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Sandbox Base Container Image" - }, - "sandbox_runtime_container_image": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Sandbox Runtime Container Image" - }, - "mcp_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/MCPConfig" - }, - { - "type": "null" - } - ] - }, - "search_api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Search Api Key" - }, - "sandbox_api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Sandbox Api Key" - }, - "max_budget_per_task": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Max Budget Per Task" - }, - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Email" - }, - "email_verified": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Email Verified" - }, - "git_user_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Git User Name" - }, - "git_user_email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Git User Email" - }, - "provider_tokens_set": { - "anyOf": [ - { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "propertyNames": { - "$ref": "#/components/schemas/ProviderType" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Provider Tokens Set" - }, - "llm_api_key_set": { - "type": "boolean", - "title": "Llm Api Key Set" - }, - "search_api_key_set": { - "type": "boolean", - "title": "Search Api Key Set", - "default": false - } - }, - "type": "object", - "required": [ - "llm_api_key_set" - ], - "title": "GETSettingsModel", - "description": "Settings with additional token data for the frontend" - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - "type": "array", - "title": "Detail" - } - }, - "type": "object", - "title": "HTTPValidationError" - }, - "InitSessionRequest": { - "properties": { - "repository": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Repository" - }, - "git_provider": { - "anyOf": [ - { - "$ref": "#/components/schemas/ProviderType" - }, - { - "type": "null" - } - ] - }, - "selected_branch": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Selected Branch" - }, - "initial_user_msg": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Initial User Msg" - }, - "image_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Image Urls" - }, - "replay_json": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Replay Json" - }, - "suggested_task": { - "anyOf": [ - { - "$ref": "#/components/schemas/SuggestedTask" - }, - { - "type": "null" - } - ] - }, - "create_microagent": { - "anyOf": [ - { - "$ref": "#/components/schemas/CreateMicroagent" - }, - { - "type": "null" - } - ] - }, - "conversation_instructions": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Conversation Instructions" - }, - "mcp_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/MCPConfig" - }, - { - "type": "null" - } - ] - }, - "conversation_id": { - "type": "string", - "title": "Conversation Id" - } - }, - "additionalProperties": false, - "type": "object", - "title": "InitSessionRequest" - }, - "MCPConfig": { - "properties": { - "sse_servers": { - "items": { - "$ref": "#/components/schemas/MCPSSEServerConfig" - }, - "type": "array", - "title": "Sse Servers" - }, - "stdio_servers": { - "items": { - "$ref": "#/components/schemas/MCPStdioServerConfig" - }, - "type": "array", - "title": "Stdio Servers" - }, - "shttp_servers": { - "items": { - "$ref": "#/components/schemas/MCPSHTTPServerConfig" - }, - "type": "array", - "title": "Shttp Servers" - } - }, - "additionalProperties": false, - "type": "object", - "title": "MCPConfig", - "description": "Configuration for MCP (Message Control Protocol) settings.\n\nAttributes:\n sse_servers: List of MCP SSE server configs\n stdio_servers: List of MCP stdio server configs. These servers will be added to the MCP Router running inside runtime container.\n shttp_servers: List of MCP HTTP server configs." - }, - "MCPSHTTPServerConfig": { - "properties": { - "url": { - "type": "string", - "title": "Url" - }, - "api_key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Api Key" - } - }, - "type": "object", - "required": [ - "url" - ], - "title": "MCPSHTTPServerConfig" - }, - "MCPSSEServerConfig": { - "properties": { - "url": { - "type": "string", - "title": "Url" - }, - "api_key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Api Key" - } - }, - "type": "object", - "required": [ - "url" - ], - "title": "MCPSSEServerConfig", - "description": "Configuration for a single MCP server.\n\nAttributes:\n url: The server URL\n api_key: Optional API key for authentication" - }, - "MCPStdioServerConfig": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "command": { - "type": "string", - "title": "Command" - }, - "args": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Args" - }, - "env": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Env" - } - }, - "type": "object", - "required": [ - "name", - "command" - ], - "title": "MCPStdioServerConfig", - "description": "Configuration for a MCP server that uses stdio.\n\nAttributes:\n name: The name of the server\n command: The command to run the server\n args: The arguments to pass to the server\n env: The environment variables to set for the server" - }, - "MicroagentContentResponse": { - "properties": { - "content": { - "type": "string", - "title": "Content" - }, - "path": { - "type": "string", - "title": "Path" - }, - "triggers": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Triggers", - "default": [] - }, - "git_provider": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Git Provider" - } - }, - "type": "object", - "required": [ - "content", - "path" - ], - "title": "MicroagentContentResponse", - "description": "Response model for individual microagent content endpoint." - }, - "MicroagentResponse": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "path": { - "type": "string", - "title": "Path" - }, - "created_at": { - "type": "string", - "format": "date-time", - "title": "Created At" - } - }, - "type": "object", - "required": [ - "name", - "path", - "created_at" - ], - "title": "MicroagentResponse", - "description": "Response model for microagents endpoint.\n\nNote: This model only includes basic metadata that can be determined\nwithout parsing microagent content. Use the separate content API\nto get detailed microagent information." - }, - "OwnerType": { - "type": "string", - "enum": [ - "user", - "organization" - ], - "title": "OwnerType" - }, - "POSTProviderModel": { - "properties": { - "mcp_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/MCPConfig" - }, - { - "type": "null" - } - ] - }, - "provider_tokens": { - "additionalProperties": { - "$ref": "#/components/schemas/ProviderToken" - }, - "propertyNames": { - "$ref": "#/components/schemas/ProviderType" - }, - "type": "object", - "title": "Provider Tokens", - "default": {} - } - }, - "type": "object", - "title": "POSTProviderModel", - "description": "Settings for POST requests" - }, - "POSTUploadFilesModel": { - "properties": { - "file_urls": { - "items": { - "type": "string" - }, - "type": "array", - "title": "File Urls" - }, - "skipped_files": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Skipped Files" - } - }, - "type": "object", - "required": [ - "file_urls", - "skipped_files" - ], - "title": "POSTUploadFilesModel", - "description": "Upload files response model" - }, - "ProviderToken": { - "properties": { - "token": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Token" - }, - "user_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "User Id" - }, - "host": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Host" - } - }, - "type": "object", - "title": "ProviderToken" - }, - "ProviderType": { - "type": "string", - "enum": [ - "github", - "gitlab", - "bitbucket", - "enterprise_sso" - ], - "title": "ProviderType" - }, - "ProvidersSetModel": { - "properties": { - "providers_set": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/ProviderType" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Providers Set" - } - }, - "type": "object", - "title": "ProvidersSetModel" - }, - "Repository": { - "properties": { - "id": { - "type": "string", - "title": "Id" - }, - "full_name": { - "type": "string", - "title": "Full Name" - }, - "git_provider": { - "$ref": "#/components/schemas/ProviderType" - }, - "is_public": { - "type": "boolean", - "title": "Is Public" - }, - "stargazers_count": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Stargazers Count" - }, - "link_header": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Link Header" - }, - "pushed_at": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Pushed At" - }, - "owner_type": { - "anyOf": [ - { - "$ref": "#/components/schemas/OwnerType" - }, - { - "type": "null" - } - ] - }, - "main_branch": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Main Branch" - } - }, - "type": "object", - "required": [ - "id", - "full_name", - "git_provider", - "is_public" - ], - "title": "Repository" - }, - "RuntimeStatus": { - "type": "string", - "enum": [ - "STATUS$STOPPED", - "STATUS$BUILDING_RUNTIME", - "STATUS$STARTING_RUNTIME", - "STATUS$RUNTIME_STARTED", - "STATUS$SETTING_UP_WORKSPACE", - "STATUS$SETTING_UP_GIT_HOOKS", - "STATUS$READY", - "STATUS$ERROR", - "STATUS$ERROR_RUNTIME_DISCONNECTED", - "STATUS$ERROR_LLM_AUTHENTICATION", - "STATUS$ERROR_LLM_SERVICE_UNAVAILABLE", - "STATUS$ERROR_LLM_INTERNAL_SERVER_ERROR", - "STATUS$ERROR_LLM_OUT_OF_CREDITS", - "STATUS$ERROR_LLM_CONTENT_POLICY_VIOLATION", - "CHAT_INTERFACE$AGENT_RATE_LIMITED_STOPPED_MESSAGE", - "STATUS$GIT_PROVIDER_AUTHENTICATION_ERROR", - "STATUS$LLM_RETRY", - "STATUS$ERROR_MEMORY" - ], - "title": "RuntimeStatus" - }, - "Settings": { - "properties": { - "language": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Language" - }, - "agent": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Agent" - }, - "max_iterations": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Max Iterations" - }, - "security_analyzer": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Security Analyzer" - }, - "confirmation_mode": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Confirmation Mode" - }, - "llm_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Llm Model" - }, - "llm_api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Llm Api Key" - }, - "llm_base_url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Llm Base Url" - }, - "remote_runtime_resource_factor": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Remote Runtime Resource Factor" - }, - "secrets_store": { - "$ref": "#/components/schemas/UserSecrets-Input" - }, - "enable_default_condenser": { - "type": "boolean", - "title": "Enable Default Condenser", - "default": true - }, - "enable_sound_notifications": { - "type": "boolean", - "title": "Enable Sound Notifications", - "default": false - }, - "enable_proactive_conversation_starters": { - "type": "boolean", - "title": "Enable Proactive Conversation Starters", - "default": true - }, - "enable_solvability_analysis": { - "type": "boolean", - "title": "Enable Solvability Analysis", - "default": true - }, - "user_consents_to_analytics": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "User Consents To Analytics" - }, - "sandbox_base_container_image": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Sandbox Base Container Image" - }, - "sandbox_runtime_container_image": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Sandbox Runtime Container Image" - }, - "mcp_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/MCPConfig" - }, - { - "type": "null" - } - ] - }, - "search_api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Search Api Key" - }, - "sandbox_api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Sandbox Api Key" - }, - "max_budget_per_task": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Max Budget Per Task" - }, - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Email" - }, - "email_verified": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Email Verified" - }, - "git_user_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Git User Name" - }, - "git_user_email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Git User Email" - } - }, - "type": "object", - "title": "Settings", - "description": "Persisted settings for OpenHands sessions" - }, - "SuggestedTask": { - "properties": { - "git_provider": { - "$ref": "#/components/schemas/ProviderType" - }, - "task_type": { - "$ref": "#/components/schemas/TaskType" - }, - "repo": { - "type": "string", - "title": "Repo" - }, - "issue_number": { - "type": "integer", - "title": "Issue Number" - }, - "title": { - "type": "string", - "title": "Title" - } - }, - "type": "object", - "required": [ - "git_provider", - "task_type", - "repo", - "issue_number", - "title" - ], - "title": "SuggestedTask" - }, - "TaskType": { - "type": "string", - "enum": [ - "MERGE_CONFLICTS", - "FAILING_CHECKS", - "UNRESOLVED_COMMENTS", - "OPEN_ISSUE", - "OPEN_PR", - "CREATE_MICROAGENT" - ], - "title": "TaskType" - }, - "UpdateConversationRequest": { - "properties": { - "title": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "title": "Title", - "description": "New conversation title" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "title" - ], - "title": "UpdateConversationRequest", - "description": "Request model for updating conversation metadata." - }, - "User": { - "properties": { - "id": { - "type": "string", - "title": "Id" - }, - "login": { - "type": "string", - "title": "Login" - }, - "avatar_url": { - "type": "string", - "title": "Avatar Url" - }, - "company": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Company" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Name" - }, - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Email" - } - }, - "type": "object", - "required": [ - "id", - "login", - "avatar_url" - ], - "title": "User" - }, - "UserSecrets-Input": { - "properties": { - "provider_tokens": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Provider Tokens" - }, - "custom_secrets": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Custom Secrets" - } - }, - "type": "object", - "title": "UserSecrets" - }, - "UserSecrets-Output": { - "properties": { - "provider_tokens": { - "additionalProperties": { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - {} - ] - }, - "type": "object" - }, - "type": "object", - "title": "Provider Tokens" - }, - "custom_secrets": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Custom Secrets" - } - }, - "type": "object", - "title": "UserSecrets" - }, - "ValidationError": { - "properties": { - "loc": { - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - }, - "type": "array", - "title": "Location" - }, - "msg": { - "type": "string", - "title": "Message" - }, - "type": { - "type": "string", - "title": "Error Type" - } - }, - "type": "object", - "required": [ - "loc", - "msg", - "type" - ], - "title": "ValidationError" - } - }, - "securitySchemes": { - "APIKeyHeader": { - "type": "apiKey", - "in": "header", - "name": "X-Session-API-Key" - } - } - }, - "servers": [ - { - "url": "https://app.all-hands.dev", - "description": "Production server" - }, - { - "url": "http://localhost:3000", - "description": "Local development server" - } - ] -} \ No newline at end of file diff --git a/docs/static/img/api-key-generation.png b/docs/static/img/api-key-generation.png deleted file mode 100644 index 7506076401..0000000000 Binary files a/docs/static/img/api-key-generation.png and /dev/null differ diff --git a/docs/static/img/backend_architecture.png b/docs/static/img/backend_architecture.png deleted file mode 100644 index 2cc41a3e67..0000000000 Binary files a/docs/static/img/backend_architecture.png and /dev/null differ diff --git a/docs/static/img/backend_architecture.puml b/docs/static/img/backend_architecture.puml deleted file mode 100644 index c96651ab46..0000000000 --- a/docs/static/img/backend_architecture.puml +++ /dev/null @@ -1,201 +0,0 @@ -@startuml openhands -!pragma useIntermediatePackages false - -class openhands.action.agent.AgentEchoAction { - content: str - runnable: bool - action: str -} -class openhands.action.agent.AgentFinishAction { - runnable: bool - action: str -} -class openhands.observation.AgentMessageObservation { - role: str - observation: str -} -class openhands.action.agent.AgentSummarizeAction { - summary: str - action: str -} -class openhands.action.agent.AgentThinkAction { - thought: str - runnable: bool - action: str -} -class openhands.action.base.ExecutableAction { -} -class openhands.action.base.NotExecutableAction { -} -class openhands.observation.Observation { - content: str -} -class openhands.action.base.Action { -} -class openhands.action.base.NullAction { - action: str -} -class openhands.action.bash.CmdRunAction { - command: str - action: str -} -class openhands.action.browse.BrowseURLAction { - url: str - action: str -} -class openhands.observation.BrowserOutputObservation { - url: str - status_code: int - error: bool - observation: str -} -class openhands.action.fileop.FileReadAction { - path: str - action: str -} -class openhands.observation.FileReadObservation { - path: str - observation: str -} -class openhands.action.fileop.FileWriteAction { - path: str - contents: str - action: str -} -class openhands.observation.FileWriteObservation { - path: str - observation: str -} -class openhands.action.tasks.AddTaskAction { - parent: str - goal: str - subtasks: list - action: str -} -class openhands.action.tasks.ModifyTaskAction { - id: str - state: str - action: str -} -abstract class openhands.agent.Agent { - _registry: Dict[str, Type[Agent]] {static} - llm: LLM - _complete: None -} -class openhands.llm.llm.LLM { - model: None - api_key: None - base_url: None - _debug_dir: None - _debug_idx: None - _debug_id: None - _completion: None -} -class openhands.controller.agent_controller.AgentController { - agent: Agent - max_iterations: int - workdir: str - command_manager: CommandManager - state: State - plan: Plan - callbacks: List[Callable] -} -class openhands.observation.AgentErrorObservation { - observation: str -} -class openhands.controller.command_manager.CommandManager { - directory: None - shell: None -} -class openhands.observation.NullObservation { - observation: str -} -class openhands.plan.Plan { - main_goal: str {static} - task: Task {static} - main_goal: str - task: None -} -class openhands.state.State { - plan: Plan - iteration: int - history: List[Tuple[Action, Observation]] - updated_info: List[Tuple[Action, Observation]] -} -class openhands.observation.CmdOutputObservation { - command: str - exit_code: int - observation: str -} -class openhands.sandbox.sandbox.DockerInteractive { - instance_id: None - instance_id: None - workspace_dir: None - workspace_dir: None - workspace_dir: None - timeout: int - base_container_image: None - container_name: None -} -class openhands.observation.UserMessageObservation { - role: str - observation: str -} -class openhands.plan.Task { - id: str {static} - goal: str {static} - parent: Task | None {static} - subtasks: List[Task] {static} - id: None - id: None - parent: None - goal: str - subtasks: None -} - -class openhands.server.session.Session { - websocket: None - controller: Optional[AgentController] - agent: Optional[Agent] - agent_task: None -} - -openhands.action.base.ExecutableAction <|-- openhands.action.agent.AgentEchoAction -openhands.action.base.NotExecutableAction <|-- openhands.action.agent.AgentFinishAction -openhands.observation.Observation <|-- openhands.observation.AgentMessageObservation -openhands.action.base.NotExecutableAction <|-- openhands.action.agent.AgentSummarizeAction -openhands.action.base.NotExecutableAction <|-- openhands.action.agent.AgentThinkAction -openhands.action.base.Action <|-- openhands.action.base.ExecutableAction -openhands.action.base.Action <|-- openhands.action.base.NotExecutableAction -openhands.action.base.NotExecutableAction <|-- openhands.action.base.NullAction -openhands.action.base.ExecutableAction <|-- openhands.action.bash.CmdRunAction -openhands.action.base.ExecutableAction <|-- openhands.action.browse.BrowseURLAction -openhands.observation.Observation <|-- openhands.observation.BrowserOutputObservation -openhands.action.base.ExecutableAction <|-- openhands.action.fileop.FileReadAction -openhands.observation.Observation <|-- openhands.observation.FileReadObservation -openhands.action.base.ExecutableAction <|-- openhands.action.fileop.FileWriteAction -openhands.observation.Observation <|-- openhands.observation.FileWriteObservation -openhands.action.base.NotExecutableAction <|-- openhands.action.tasks.AddTaskAction -openhands.action.base.NotExecutableAction <|-- openhands.action.tasks.ModifyTaskAction -openhands.agent.Agent *-- openhands.agent.Agent -openhands.agent.Agent *-- openhands.llm.llm.LLM -openhands.controller.agent_controller.AgentController *-- openhands.agent.Agent -openhands.observation.Observation <|-- openhands.observation.AgentErrorObservation -openhands.observation.Observation <|-- openhands.observation.NullObservation -openhands.plan.Plan *-- openhands.plan.Task -openhands.state.State *-- openhands.plan.Plan -openhands.state.State *-- openhands.observation.CmdOutputObservation -openhands.state.State *-- openhands.action.base.Action -openhands.state.State *-- openhands.observation.Observation -openhands.observation.Observation <|-- openhands.observation.CmdOutputObservation -openhands.observation.Observation <|-- openhands.observation.UserMessageObservation -openhands.plan.Task *-- openhands.plan.Task -openhands.server.session.Session *-- openhands.controller.agent_controller.AgentController -openhands.server.session.Session *-- openhands.agent.Agent -openhands.controller.agent_controller.AgentController -> openhands.state.State -openhands.controller.agent_controller.AgentController -> openhands.plan.Plan -openhands.controller.agent_controller.AgentController -> openhands.controller.command_manager.CommandManager -openhands.controller.command_manager.CommandManager -> openhands.sandbox.sandbox.DockerInteractive - -footer Based on f3fda42; Generated by //py2puml// -@enduml diff --git a/docs/static/img/backend_architecture.svg b/docs/static/img/backend_architecture.svg deleted file mode 100644 index a5fc173d5a..0000000000 --- a/docs/static/img/backend_architecture.svg +++ /dev/null @@ -1 +0,0 @@ -openhandsactionagentbasebashbrowsefileoptasksobservationagentllm.llmcontrolleragent_controllercommand_managerplanstatesandbox.sandboxserver.sessionAgentEchoActioncontent: strrunnable: boolaction: strAgentFinishActionrunnable: boolaction: strAgentRecallActionquery: straction: strAgentSummarizeActionsummary: straction: strAgentThinkActionthought: strrunnable: boolaction: strExecutableActionNotExecutableActionActionNullActionaction: strCmdKillActionid: intaction: strCmdRunActioncommand: strbackground: boolaction: strBrowseURLActionurl: straction: strFileReadActionpath: straction: strFileWriteActionpath: strcontents: straction: strAddTaskActionparent: strgoal: strsubtasks: listaction: strModifyTaskActionid: strstate: straction: strAgentMessageObservationrole: strobservation: strAgentRecallObservationmemories: List[str]role: strobservation: strObservationcontent: strBrowserOutputObservationurl: strstatus_code: interror: boolobservation: strFileReadObservationpath: strobservation: strFileWriteObservationpath: strobservation: strAgentErrorObservationobservation: strNullObservationobservation: strCmdOutputObservationcommand_id: intcommand: strexit_code: intobservation: strUserMessageObservationrole: strobservation: strAgent_registry: Dict[str, Type[Agent]]llm: LLM_complete: NoneLLMmodel: Noneapi_key: Nonebase_url: None_debug_dir: None_debug_idx: None_debug_id: None_completion: NoneAgentControlleragent: Agentmax_iterations: intworkdir: strcommand_manager: CommandManagerstate: Stateplan: Plancallbacks: List[Callable]CommandManagerdirectory: Noneshell: NonePlanmain_goal: strtask: Taskmain_goal: strtask: NoneTaskid: strgoal: strparent: Task | Nonesubtasks: List[Task]id: Noneid: Noneparent: Nonegoal: strsubtasks: NoneStateplan: Planiteration: intbackground_commands_obs: List[CmdOutputObservation]history: List[Tuple[Action, Observation]]updated_info: List[Tuple[Action, Observation]]DockerInteractivebackground_commands: Dict[int, BackgroundCommand]instance_id: Noneinstance_id: Noneworkspace_dir: Noneworkspace_dir: Noneworkspace_dir: Nonetimeout: intbase_container_image: Nonecontainer_name: NoneBackgroundCommandSessionwebsocket: Nonecontroller: Optional[AgentController]agent: Optional[Agent]agent_task: NoneBased on f3fda42; Generated bypy2puml diff --git a/docs/static/img/connect-repo-no-github.png b/docs/static/img/connect-repo-no-github.png deleted file mode 100644 index bbc3af3c3a..0000000000 Binary files a/docs/static/img/connect-repo-no-github.png and /dev/null differ diff --git a/docs/static/img/connect-repo.png b/docs/static/img/connect-repo.png deleted file mode 100644 index 9eb86dc79a..0000000000 Binary files a/docs/static/img/connect-repo.png and /dev/null differ diff --git a/docs/static/img/jira-admin-configure.png b/docs/static/img/jira-admin-configure.png deleted file mode 100644 index 088869cdcc..0000000000 Binary files a/docs/static/img/jira-admin-configure.png and /dev/null differ diff --git a/docs/static/img/jira-admin-edit.png b/docs/static/img/jira-admin-edit.png deleted file mode 100644 index 544d57b85d..0000000000 Binary files a/docs/static/img/jira-admin-edit.png and /dev/null differ diff --git a/docs/static/img/jira-dc-admin-configure.png b/docs/static/img/jira-dc-admin-configure.png deleted file mode 100644 index 52dc35e188..0000000000 Binary files a/docs/static/img/jira-dc-admin-configure.png and /dev/null differ diff --git a/docs/static/img/jira-dc-admin-edit.png b/docs/static/img/jira-dc-admin-edit.png deleted file mode 100644 index ff085c308c..0000000000 Binary files a/docs/static/img/jira-dc-admin-edit.png and /dev/null differ diff --git a/docs/static/img/jira-dc-user-link.png b/docs/static/img/jira-dc-user-link.png deleted file mode 100644 index 0fd2e0cfee..0000000000 Binary files a/docs/static/img/jira-dc-user-link.png and /dev/null differ diff --git a/docs/static/img/jira-dc-user-unlink.png b/docs/static/img/jira-dc-user-unlink.png deleted file mode 100644 index 29ea93bf07..0000000000 Binary files a/docs/static/img/jira-dc-user-unlink.png and /dev/null differ diff --git a/docs/static/img/jira-user-link.png b/docs/static/img/jira-user-link.png deleted file mode 100644 index e0868d2c09..0000000000 Binary files a/docs/static/img/jira-user-link.png and /dev/null differ diff --git a/docs/static/img/jira-user-unlink.png b/docs/static/img/jira-user-unlink.png deleted file mode 100644 index 39f07ce0cb..0000000000 Binary files a/docs/static/img/jira-user-unlink.png and /dev/null differ diff --git a/docs/static/img/linear-admin-configure.png b/docs/static/img/linear-admin-configure.png deleted file mode 100644 index 513365604a..0000000000 Binary files a/docs/static/img/linear-admin-configure.png and /dev/null differ diff --git a/docs/static/img/linear-admin-edit.png b/docs/static/img/linear-admin-edit.png deleted file mode 100644 index 930cb22b76..0000000000 Binary files a/docs/static/img/linear-admin-edit.png and /dev/null differ diff --git a/docs/static/img/linear-user-link.png b/docs/static/img/linear-user-link.png deleted file mode 100644 index 83f75107d0..0000000000 Binary files a/docs/static/img/linear-user-link.png and /dev/null differ diff --git a/docs/static/img/linear-user-unlink.png b/docs/static/img/linear-user-unlink.png deleted file mode 100644 index b167402e3d..0000000000 Binary files a/docs/static/img/linear-user-unlink.png and /dev/null differ diff --git a/docs/static/img/logo-square.png b/docs/static/img/logo-square.png deleted file mode 100644 index a260f507bc..0000000000 Binary files a/docs/static/img/logo-square.png and /dev/null differ diff --git a/docs/static/img/logo.png b/docs/static/img/logo.png deleted file mode 100644 index 799c7ee739..0000000000 Binary files a/docs/static/img/logo.png and /dev/null differ diff --git a/docs/static/img/oh-features.png b/docs/static/img/oh-features.png deleted file mode 100644 index 3f4236d065..0000000000 Binary files a/docs/static/img/oh-features.png and /dev/null differ diff --git a/docs/static/img/openhands-llm-api-key.png b/docs/static/img/openhands-llm-api-key.png deleted file mode 100644 index 67efda8ab6..0000000000 Binary files a/docs/static/img/openhands-llm-api-key.png and /dev/null differ diff --git a/docs/static/img/openhands-provider-cli.png b/docs/static/img/openhands-provider-cli.png deleted file mode 100644 index 30437589e9..0000000000 Binary files a/docs/static/img/openhands-provider-cli.png and /dev/null differ diff --git a/docs/static/img/results.png b/docs/static/img/results.png deleted file mode 100644 index 48a6275f49..0000000000 Binary files a/docs/static/img/results.png and /dev/null differ diff --git a/docs/static/img/screenshot.png b/docs/static/img/screenshot.png deleted file mode 100644 index 2027ac2a2d..0000000000 Binary files a/docs/static/img/screenshot.png and /dev/null differ diff --git a/docs/static/img/slack-create-conversation.png b/docs/static/img/slack-create-conversation.png deleted file mode 100644 index 5cdd58542b..0000000000 Binary files a/docs/static/img/slack-create-conversation.png and /dev/null differ diff --git a/docs/static/img/slack-pro-tip.png b/docs/static/img/slack-pro-tip.png deleted file mode 100644 index 74f211f2f9..0000000000 Binary files a/docs/static/img/slack-pro-tip.png and /dev/null differ diff --git a/docs/static/img/slack-results-and-follow-up.png b/docs/static/img/slack-results-and-follow-up.png deleted file mode 100644 index 26a434336a..0000000000 Binary files a/docs/static/img/slack-results-and-follow-up.png and /dev/null differ diff --git a/docs/static/img/system_architecture.png b/docs/static/img/system_architecture.png deleted file mode 100644 index 42c05b1d4a..0000000000 Binary files a/docs/static/img/system_architecture.png and /dev/null differ diff --git a/docs/static/img/system_architecture.puml b/docs/static/img/system_architecture.puml deleted file mode 100644 index b1b9713ef4..0000000000 --- a/docs/static/img/system_architecture.puml +++ /dev/null @@ -1,67 +0,0 @@ -@startuml "System Architecture" - - -node frontend as frontend{ - - component App - - package components{ - - component Terminal - - component ChatInterface - - component BannerSettings - - } - - package services{ - component chatService - - component settingsService - - chatService -[hidden]u-> settingsService - } - - package socket - - App -> Terminal - App -> ChatInterface - App -> BannerSettings - ChatInterface -> chatService - BannerSettings -> settingsService - Terminal -> socket - chatService -d-> socket - settingsService -d-> socket - services -[hidden]d-> socket - - Terminal -[hidden]u-> ChatInterface - ChatInterface -[hidden]u-> BannerSettings - - - - interface "HTTP (:3001)" as HTTP - HTTP - App - -} - -node backend{ - package server as serverpackage{ - component Server - - 'defined in server/server.py, port is defined at startup with uvicorn - interface "Client WS\n(:3000/ws)" as client_socket - client_socket - Server - - - } - node AgentController{ - - } - Server -d-> AgentController -} - - -socket -d-> client_socket: connects to \n VITE_TERMINAL_WS_URL - -@enduml diff --git a/docs/static/img/system_architecture.svg b/docs/static/img/system_architecture.svg deleted file mode 100644 index d259a4ca3b..0000000000 --- a/docs/static/img/system_architecture.svg +++ /dev/null @@ -1 +0,0 @@ -frontendcomponentsservicesbackendserverAppsocketHTTP (:3001)TerminalChatInterfaceBannerSettingschatServicesettingsServiceServerClient WS(:3000/ws)AgentControllerconnects toVITE_TERMINAL_WS_URL diff --git a/docs/static/img/system_architecture_overview.png b/docs/static/img/system_architecture_overview.png deleted file mode 100644 index a9174fc6ba..0000000000 Binary files a/docs/static/img/system_architecture_overview.png and /dev/null differ diff --git a/docs/static/img/teaser.mp4 b/docs/static/img/teaser.mp4 deleted file mode 100644 index 3d3a28b156..0000000000 Binary files a/docs/static/img/teaser.mp4 and /dev/null differ diff --git a/docs/success-stories/index.mdx b/docs/success-stories/index.mdx deleted file mode 100644 index afc71093b3..0000000000 --- a/docs/success-stories/index.mdx +++ /dev/null @@ -1,217 +0,0 @@ ---- -title: "Success Stories" -description: "Real-world examples of what you can achieve with OpenHands" ---- - -Discover how developers and teams are using OpenHands to automate their software development workflows. From quick fixes to complex projects, see what's possible with AI-powered development assistance. - -Check out the [#success-stories](https://www.linen.dev/s/openhands/c/success-stories) channel on our Slack for more! - - - -## One of the cool things about OpenHands, and especially the Slack Integration, is the ability to empower folks who are on the ‘front lines’ with customers. - -For example, often times Support and Customer Success teams will field bug reports, doc questions, and other ‘nits’ from customers. They tend to have few options to deal with this, other than file a feedback ticket with product teams and hope it gets prioritized in an upcoming sprint. - -Instead, with tools like OpenHands and the Slack integration, they can request OpenHands to make fixes proactively and then have someone on the engineering team (like a lead engineer, a merge engineer, or even technical product manager) review the PR and approve it — thus reducing the cycle time for ‘quick wins’ from weeks to just a few hours. - -Here's how we do that with the OpenHands project: - - - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29124350/one-of-the-cool-things-about-openhands-and-especially-the-sl#25029f37-7b0d-4535-9187-83b3e06a4011) - - - - - - -## Asked openhands to “show me some love” and... - -Asked openhands to “show me some love” and it coded up this app for me, actually kinda genuinely feel loved - - - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100731/asked-openhands-to-show-me-some-love-and-it-coded-up-this-ap#1e08af6b-b7d5-4167-8a53-17e6806555e0) - - - - - -## Now, OpenHands does 100% of my infra IAM research for me - -Got an IAM error on GCP? Send a screenshot to OH... and it just works!!! -Can't imagine going back to the early days without OH: I'd spend an entire afternoon figuring how to get IAM right - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100732/now-openhands-does-100-of-my-infra-iam-research-for-me-sweat#20482a73-4e2e-4edd-b6d1-c9e8442fccd1) - -![](/success-stories/stories/2025-06-11-infra-iam/s1.png) -![](/success-stories/stories/2025-06-11-infra-iam/s2.png) - - - - - -## Very simple example, but baby steps.... - -I am a professor of architecture and urban design. We built, me and some students, an interactive map prototype to help visitors and new students to find important places in the campus. Considering that we lack a lot of knowledge in programming, that was really nice to build and a smooth process. -We first created the main components with all-hands and then adjusted some details locally. Definitely, saved us a lot of time and money. -That's a prototype but we will have all the info by tuesday. -https://buriti-emau.github.io/Mapa-UFU/ - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100736/very-simple-example-but-baby-steps-i-am-a-professor-of-archi#8f2e3f3f-44e6-44ea-b9a8-d53487470179) - -![](/success-stories/stories/2025-06-08-map/s1.png) - - - - - - -## Tavily adapter helps solve persistent debugging issue - -Big congratulations to the new [Tavily adapter](https://www.all-hands.dev/blog/building-a-provably-versatile-agent)... OpenHands and I have been beavering away at a Lightstreamer client library for most of this week but were getting a persistent (and unhelpful) "unexpected error" from the server. - -Coming back to the problem today, after trying several unsuccessful fixes prompted by me, OH decided all by itself to search the web, and found the cause of the problem (of course it was simply CRLF line endings...). I was on the verge of giving up - good thing OH has more stamina than me! - -This demonstrates how OpenHands' web search capabilities can help solve debugging issues that would otherwise require extensive manual research. - - - - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100737/big-congratulations-to-the-new-tavily-adapter-openhands-and-#76f1fb26-6ef7-4709-b9ea-fb99105e47e4) - - - - - -## I asked OpenHands to update my personal website for the "OpenHands Versa" paper. - -It is an extremely trivial task: You just need to browse to arxiv, copy the author names, format them for BibTeX, and then modify the papers.bib file. But now I'm getting way too lazy to even open my IDE and actually do this one-file change! - -[Original Tweet/X thread](https://x.com/xingyaow_/status/1930796287919542410) - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100738/i-asked-openhands-to-update-my-personal-website-for-the-open#f0324022-b12b-4d34-b12b-bdbc43823f69) - - - - - -## I asked OpenHands to make an animated gif of swe-bench verified scores over time. - -It took a bit of prompting but ended up looking pretty nice I think - - - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100744/i-asked-openhands-to-make-an-animated-gif-of-swe-bench-verif#fb3b82c9-6222-4311-b97b-b2ac1cfe6dff) - - - - - -## Quick AWS security group fix - -I really don't like trying to fix issues with AWS, especially security groups and other finicky things like this. But I started up an instance and wasn't able to ssh in. So I asked OpenHands: - -> Currently, the following ssh command is timing out: -> -> $ ssh -i gneubig.pem ubuntu@XXX.us-east-2.compute.amazonaws.com -> ssh: connect to host XXX.us-east-2.compute.amazonaws.com port 22: Operation timed out -> -> Use the provided AWS credentials to take a look at i-XXX and examine why - -And 2 minutes later I was able to SSH in! - -This shows how OpenHands can quickly diagnose and fix AWS infrastructure issues that would normally require manual investigation. - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100747/i-really-don-t-like-trying-to-fix-issues-with-aws-especially#d92a66d2-3bc1-4467-9d09-dc983004d083) - - - - - - -## OpenHands builds Chrome extension for GitHub integration - -I asked OpenHands to write a Chrome extension based on our [OpenHands Cloud API](https://docs.all-hands.dev/modules/usage/cloud/cloud-api). Once installed, you can now easily launch an OpenHands cloud session from your GitHub webpage/PR! - -This demonstrates OpenHands' ability to create browser extensions and integrate with external APIs, enabling seamless workflows between GitHub and OpenHands Cloud. - -![Chrome extension](/success-stories/stories/2025-05-04-chrome-extension/s1.png) -![Chrome extension](/success-stories/stories/2025-05-04-chrome-extension/s2.png) - -[GitHub Repository](https://github.com/xingyaoww/openhands-chrome-extension) - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100755/i-asked-openhands-to-write-a-chrome-extension-based-on-our-h#88f14b7f-f8ff-40a6-83c2-bd64e95924c5) - - - - - - -## OpenHands tests UI automatically with visual browsing - -Thanks to visual browsing -- OpenHands can actually test some simple UI by serving the website, clicking the button in the browser and looking at screenshots now! - -Prompt is just: -``` -I want to create a Hello World app in Javascript that: -* Displays Hello World in the middle. -* Has a button that when clicked, changes the greeting with a bouncing animation to fun versions of Hello. -* Has a counter for how many times the button has been clicked. -* Has another button that changes the app's background color. -``` - -Eager-to-work Sonnet 3.7 will test stuff for you without you asking! - -This showcases OpenHands' visual browsing capabilities, enabling it to create, serve, and automatically test web applications through actual browser interactions and screenshot analysis. - -![Visual UI testing](/success-stories/stories/2025-04-11-visual-ui/s1.png) - -[Original Slack thread](https://www.linen.dev/s/openhands/t/29100764/thanks-to-u07k0p3bdb9-s-visual-browsing-openhands-can-actual#21beb9bc-1a04-4272-87e9-4d3e3b9925e7) - - - - - -## OpenHands fixes crashes before you notice them - -Interesting story, I asked OpenHands to start an app on port 12000, it showed up on the app pane. I started using the app, and then it crashed... But because it crashed in OpenHands, OpenHands immediately saw the error message and started fixing the problem without me having to do anything. It was already fixing the problem before I even realized what was going wrong. - -This demonstrates OpenHands' proactive monitoring capabilities - it doesn't just execute commands, but actively watches for errors and begins remediation automatically, often faster than human reaction time. - - - - - -## Pair programming for interactive design projects - -Used OpenHands as a pair programmer to do heavy lifting for a creative/interactive design project in p5js. - -I usually take around 2 days for high fidelity interactions (planning strategy + writing code + circling back with designer), did this in around 5hrs instead with the designer watching curiously the entire time. - -This showcases how OpenHands can accelerate creative and interactive design workflows, reducing development time by 75% while maintaining high quality output. - -[Original Tweet](https://x.com/rohit_malh5/status/1863995531657425225) - - diff --git a/docs/success-stories/stories/2025-04-11-visual-ui/s1.png b/docs/success-stories/stories/2025-04-11-visual-ui/s1.png deleted file mode 100644 index bcfaffd986..0000000000 Binary files a/docs/success-stories/stories/2025-04-11-visual-ui/s1.png and /dev/null differ diff --git a/docs/success-stories/stories/2025-05-04-chrome-extension/s1.png b/docs/success-stories/stories/2025-05-04-chrome-extension/s1.png deleted file mode 100644 index f9c7742831..0000000000 Binary files a/docs/success-stories/stories/2025-05-04-chrome-extension/s1.png and /dev/null differ diff --git a/docs/success-stories/stories/2025-05-04-chrome-extension/s2.png b/docs/success-stories/stories/2025-05-04-chrome-extension/s2.png deleted file mode 100644 index c26d5a6ec9..0000000000 Binary files a/docs/success-stories/stories/2025-05-04-chrome-extension/s2.png and /dev/null differ diff --git a/docs/success-stories/stories/2025-06-02-swebench-score/s1.mp4 b/docs/success-stories/stories/2025-06-02-swebench-score/s1.mp4 deleted file mode 100644 index 0ced83feda..0000000000 Binary files a/docs/success-stories/stories/2025-06-02-swebench-score/s1.mp4 and /dev/null differ diff --git a/docs/success-stories/stories/2025-06-08-map/s1.png b/docs/success-stories/stories/2025-06-08-map/s1.png deleted file mode 100644 index 1584c3143c..0000000000 Binary files a/docs/success-stories/stories/2025-06-08-map/s1.png and /dev/null differ diff --git a/docs/success-stories/stories/2025-06-11-infra-iam/s1.png b/docs/success-stories/stories/2025-06-11-infra-iam/s1.png deleted file mode 100644 index a759c8ca0a..0000000000 Binary files a/docs/success-stories/stories/2025-06-11-infra-iam/s1.png and /dev/null differ diff --git a/docs/success-stories/stories/2025-06-11-infra-iam/s2.png b/docs/success-stories/stories/2025-06-11-infra-iam/s2.png deleted file mode 100644 index 988717c5eb..0000000000 Binary files a/docs/success-stories/stories/2025-06-11-infra-iam/s2.png and /dev/null differ diff --git a/docs/success-stories/stories/2025-06-13-show-love/v1.mp4 b/docs/success-stories/stories/2025-06-13-show-love/v1.mp4 deleted file mode 100644 index a917130a9e..0000000000 Binary files a/docs/success-stories/stories/2025-06-13-show-love/v1.mp4 and /dev/null differ diff --git a/docs/usage/about.mdx b/docs/usage/about.mdx deleted file mode 100644 index 0d52f410ba..0000000000 --- a/docs/usage/about.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: About OpenHands ---- - -## Research Strategy - -Achieving full replication of production-grade applications with LLMs is a complex endeavor. Our strategy involves: - -- **Core Technical Research:** Focusing on foundational research to understand and improve the technical aspects of code generation and handling. -- **Task Planning:** Developing capabilities for bug detection, codebase management, and optimization. -- **Evaluation:** Establishing comprehensive evaluation metrics to better understand and improve our agents. - -## Default Agent - -Our default Agent is currently the [CodeActAgent](./agents), which is capable of generating code and handling files. - -## Built With - -OpenHands is built using a combination of powerful frameworks and libraries, providing a robust foundation for its -development. Here are the key technologies used in the project: - -![FastAPI](https://img.shields.io/badge/FastAPI-black?style=for-the-badge) ![uvicorn](https://img.shields.io/badge/uvicorn-black?style=for-the-badge) ![LiteLLM](https://img.shields.io/badge/LiteLLM-black?style=for-the-badge) ![Docker](https://img.shields.io/badge/Docker-black?style=for-the-badge) ![Ruff](https://img.shields.io/badge/Ruff-black?style=for-the-badge) ![MyPy](https://img.shields.io/badge/MyPy-black?style=for-the-badge) ![LlamaIndex](https://img.shields.io/badge/LlamaIndex-black?style=for-the-badge) ![React](https://img.shields.io/badge/React-black?style=for-the-badge) - -Please note that the selection of these technologies is in progress, and additional technologies may be added or -existing ones may be removed as the project evolves. We strive to adopt the most suitable and efficient tools to -enhance the capabilities of OpenHands. - -## License - -Distributed under MIT [License](https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE). diff --git a/docs/usage/agents.mdx b/docs/usage/agents.mdx deleted file mode 100644 index ec51228bcf..0000000000 --- a/docs/usage/agents.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Main Agent and Capabilities ---- - -## CodeActAgent - -### Description - -This agent implements the CodeAct idea ([paper](https://arxiv.org/abs/2402.01030), [tweet](https://twitter.com/xingyaow_/status/1754556835703751087)) that consolidates LLM agents’ **act**ions into a -unified **code** action space for both _simplicity_ and _performance_. - -The conceptual idea is illustrated below. At each turn, the agent can: - -1. **Converse**: Communicate with humans in natural language to ask for clarification, confirmation, etc. -2. **CodeAct**: Choose to perform the task by executing code - -- Execute any valid Linux `bash` command -- Execute any valid `Python` code with [an interactive Python interpreter](https://ipython.org/). This is simulated through `bash` command, see plugin system below for more details. - -![image](https://github.com/All-Hands-AI/OpenHands/assets/38853559/92b622e3-72ad-4a61-8f41-8c040b6d5fb3) - -### Demo - -https://github.com/All-Hands-AI/OpenHands/assets/38853559/f592a192-e86c-4f48-ad31-d69282d5f6ac - -_Example of CodeActAgent with `gpt-4-turbo-2024-04-09` performing a data science task (linear regression)_. diff --git a/docs/usage/architecture/backend.mdx b/docs/usage/architecture/backend.mdx deleted file mode 100644 index 2a97e7e51c..0000000000 --- a/docs/usage/architecture/backend.mdx +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Backend Architecture ---- - - -This is a high-level overview of the system architecture. The system is divided into two main components: the frontend and the backend. The frontend is responsible for handling user interactions and displaying the results. The backend is responsible for handling the business logic and executing the agents. - -# System overview - -```mermaid -flowchart LR - U["User"] --> FE["Frontend (SPA)"] - FE -- "HTTP/WS" --> BE["OpenHands Backend"] - BE --> ES["EventStream"] - BE --> ST["Storage"] - BE --> RT["Runtime Interface"] - BE --> LLM["LLM Providers"] - - subgraph Runtime - direction TB - RT --> DRT["Docker Runtime"] - RT --> LRT["Local Runtime"] - RT --> RRT["Remote Runtime"] - DRT --> AES["Action Execution Server"] - LRT --> AES - RRT --> AES - AES --> Bash["Bash Session"] - AES --> Jupyter["Jupyter Plugin"] - AES --> Browser["BrowserEnv"] - end -``` - -This Overview is simplified to show the main components and their interactions. For a more detailed view of the backend architecture, see the Backend Architecture section below. - -# Backend Architecture - - -```mermaid -classDiagram - class Agent { - <> - +sandbox_plugins: list[PluginRequirement] - } - class CodeActAgent { - +tools - } - Agent <|-- CodeActAgent - - class EventStream - class Observation - class Action - Action --> Observation - Agent --> EventStream - - class Runtime { - +connect() - +send_action_for_execution() - } - class ActionExecutionClient { - +_send_action_server_request() - } - class DockerRuntime - class LocalRuntime - class RemoteRuntime - Runtime <|-- ActionExecutionClient - ActionExecutionClient <|-- DockerRuntime - ActionExecutionClient <|-- LocalRuntime - ActionExecutionClient <|-- RemoteRuntime - - class ActionExecutionServer { - +/execute_action - +/alive - } - class BashSession - class JupyterPlugin - class BrowserEnv - ActionExecutionServer --> BashSession - ActionExecutionServer --> JupyterPlugin - ActionExecutionServer --> BrowserEnv - - Agent --> Runtime - Runtime ..> ActionExecutionServer : REST -``` - -
- Updating this Diagram -
- We maintain architecture diagrams inline with Mermaid in this MDX. - - Guidance: - - Edit the Mermaid blocks directly (flowchart/classDiagram). - - Quote labels and edge text for GitHub preview compatibility. - - Keep relationships concise and reflect stable abstractions (agents, runtime client/server, plugins). - - Verify accuracy against code: - - openhands/runtime/impl/action_execution/action_execution_client.py - - openhands/runtime/impl/docker/docker_runtime.py - - openhands/runtime/impl/local/local_runtime.py - - openhands/runtime/action_execution_server.py - - openhands/runtime/plugins/* - - Build docs locally or view on GitHub to confirm diagrams render. - -
-
diff --git a/docs/usage/architecture/runtime.mdx b/docs/usage/architecture/runtime.mdx deleted file mode 100644 index 7e6666c006..0000000000 --- a/docs/usage/architecture/runtime.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Runtime Architecture ---- - -The OpenHands Docker Runtime is the core component that enables secure and flexible execution of AI agent's action. -It creates a sandboxed environment using Docker, where arbitrary code can be run safely without risking the host system. - -## Why do we need a sandboxed runtime? - -OpenHands needs to execute arbitrary code in a secure, isolated environment for several reasons: - -1. Security: Executing untrusted code can pose significant risks to the host system. A sandboxed environment prevents malicious code from accessing or modifying the host system's resources -2. Consistency: A sandboxed environment ensures that code execution is consistent across different machines and setups, eliminating "it works on my machine" issues -3. Resource Control: Sandboxing allows for better control over resource allocation and usage, preventing runaway processes from affecting the host system -4. Isolation: Different projects or users can work in isolated environments without interfering with each other or the host system -5. Reproducibility: Sandboxed environments make it easier to reproduce bugs and issues, as the execution environment is consistent and controllable - -## How does the Runtime work? - -The OpenHands Runtime system uses a client-server architecture implemented with Docker containers. Here's an overview of how it works: - -```mermaid -graph TD - A[User-provided Custom Docker Image] --> B[OpenHands Backend] - B -->|Builds| C[OH Runtime Image] - C -->|Launches| D[Action Executor] - D -->|Initializes| E[Browser] - D -->|Initializes| F[Bash Shell] - D -->|Initializes| G[Plugins] - G -->|Initializes| L[Jupyter Server] - - B -->|Spawn| H[Agent] - B -->|Spawn| I[EventStream] - I <--->|Execute Action to - Get Observation - via REST API - | D - - H -->|Generate Action| I - I -->|Obtain Observation| H - - subgraph "Docker Container" - D - E - F - G - L - end -``` - -1. User Input: The user provides a custom base Docker image -2. Image Building: OpenHands builds a new Docker image (the "OH runtime image") based on the user-provided image. This new image includes OpenHands-specific code, primarily the "runtime client" -3. Container Launch: When OpenHands starts, it launches a Docker container using the OH runtime image -4. Action Execution Server Initialization: The action execution server initializes an `ActionExecutor` inside the container, setting up necessary components like a bash shell and loading any specified plugins -5. Communication: The OpenHands backend (client: `openhands/runtime/impl/action_execution/action_execution_client.py`; runtimes: `openhands/runtime/impl/docker/docker_runtime.py`, `openhands/runtime/impl/local/local_runtime.py`) communicates with the action execution server over RESTful API, sending actions and receiving observations -6. Action Execution: The runtime client receives actions from the backend, executes them in the sandboxed environment, and sends back observations -7. Observation Return: The action execution server sends execution results back to the OpenHands backend as observations - -The role of the client: - -- It acts as an intermediary between the OpenHands backend and the sandboxed environment -- It executes various types of actions (shell commands, file operations, Python code, etc.) safely within the container -- It manages the state of the sandboxed environment, including the current working directory and loaded plugins -- It formats and returns observations to the backend, ensuring a consistent interface for processing results - -## How OpenHands builds and maintains OH Runtime images - -OpenHands' approach to building and managing runtime images ensures efficiency, consistency, and flexibility in creating and maintaining Docker images for both production and development environments. - -Check out the [relevant code](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/utils/runtime_build.py) if you are interested in more details. - -### Image Tagging System - -OpenHands uses a three-tag system for its runtime images to balance reproducibility with flexibility. -The tags are: - -- **Versioned Tag**: `oh_v{openhands_version}_{base_image}` (e.g.: `oh_v0.9.9_nikolaik_s_python-nodejs_t_python3.12-nodejs22`) -- **Lock Tag**: `oh_v{openhands_version}_{16_digit_lock_hash}` (e.g.: `oh_v0.9.9_1234567890abcdef`) -- **Source Tag**: `oh_v{openhands_version}_{16_digit_lock_hash}_{16_digit_source_hash}` - (e.g.: `oh_v0.9.9_1234567890abcdef_1234567890abcdef`) - -#### Source Tag - Most Specific - -This is the first 16 digits of the MD5 of the directory hash for the source directory. This gives a hash -for only the openhands source - -#### Lock Tag - -This hash is built from the first 16 digits of the MD5 of: - -- The name of the base image upon which the image was built (e.g.: `nikolaik/python-nodejs:python3.12-nodejs22`) -- The content of the `pyproject.toml` included in the image. -- The content of the `poetry.lock` included in the image. - -This effectively gives a hash for the dependencies of Openhands independent of the source code. - -#### Versioned Tag - Most Generic - -This tag is a concatenation of openhands version and the base image name (transformed to fit in tag standard). - -#### Build Process - -When generating an image... - -- **No re-build**: OpenHands first checks whether an image with the same **most specific source tag** exists. If there is such an image, - no build is performed - the existing image is used. -- **Fastest re-build**: OpenHands next checks whether an image with the **generic lock tag** exists. If there is such an image, - OpenHands builds a new image based upon it, bypassing all installation steps (like `poetry install` and - `apt-get`) except a final operation to copy the current source code. The new image is tagged with a - **source** tag only. -- **Ok-ish re-build**: If neither a **source** nor **lock** tag exists, an image will be built based upon the **versioned** tag image. - In versioned tag image, most dependencies should already been installed hence saving time. -- **Slowest re-build**: If all of the three tags don't exists, a brand new image is built based upon the base - image (Which is a slower operation). This new image is tagged with all the **source**, **lock**, and **versioned** tags. - -This tagging approach allows OpenHands to efficiently manage both development and production environments. - -1. Identical source code and Dockerfile always produce the same image (via hash-based tags) -2. The system can quickly rebuild images when minor changes occur (by leveraging recent compatible images) -3. The **lock** tag (e.g., `runtime:oh_v0.9.3_1234567890abcdef`) always points to the latest build for a particular base image, dependency, and OpenHands version combination - -## Volume mounts: named volumes and overlay - -OpenHands supports both bind mounts and Docker named volumes in SandboxConfig.volumes: - -- Bind mount: "/abs/host/path:/container/path[:mode]" -- Named volume: "volume:``:/container/path[:mode]" or any non-absolute host spec treated as a named volume - -Overlay mode (copy-on-write layer) is supported for bind mounts by appending ":overlay" to the mode (e.g., ":ro,overlay"). -To enable overlay COW, set SANDBOX_VOLUME_OVERLAYS to a writable host directory; per-container upper/work dirs are created under it. If SANDBOX_VOLUME_OVERLAYS is unset, overlay mounts are skipped. - -Implementation references: -- openhands/runtime/impl/docker/docker_runtime.py (named volumes in _build_docker_run_args; overlay mounts in _process_overlay_mounts) -- openhands/core/config/sandbox_config.py (volumes field) - - -## Runtime Plugin System - -The OpenHands Runtime supports a plugin system that allows for extending functionality and customizing the runtime environment. Plugins are initialized when the action execution server starts up inside the runtime. - -## Ports and URLs - -- Host port allocation uses file-locked ranges for stability and concurrency: - - Main runtime port: find_available_port_with_lock on configured range - - VSCode port: SandboxConfig.sandbox.vscode_port if provided, else find_available_port_with_lock in VSCODE_PORT_RANGE - - App ports: two additional ranges for plugin/web apps -- DOCKER_HOST_ADDR (if set) adjusts how URLs are formed for LocalRuntime/Docker environments. -- VSCode URL is exposed with a connection token from the action execution server endpoint /vscode/connection_token and rendered as: - - Docker/Local: http://localhost:{port}/?tkn={token}&folder={workspace_mount_path_in_sandbox} - - RemoteRuntime: scheme://vscode-{host}/?tkn={token}&folder={workspace_mount_path_in_sandbox} - -References: -- openhands/runtime/impl/docker/docker_runtime.py (port ranges, locking, DOCKER_HOST_ADDR, vscode_url) -- openhands/runtime/impl/local/local_runtime.py (vscode_url factory) -- openhands/runtime/impl/remote/remote_runtime.py (vscode_url mapping) -- openhands/runtime/action_execution_server.py (/vscode/connection_token) - - -Examples: -- Jupyter: openhands/runtime/plugins/jupyter/__init__.py (JupyterPlugin, Kernel Gateway) -- VS Code: openhands/runtime/plugins/vscode/* (VSCodePlugin, exposes tokenized URL) -- Agent Skills: openhands/runtime/plugins/agent_skills/* - -Key aspects of the plugin system: - -1. Plugin Definition: Plugins are defined as Python classes that inherit from a base `Plugin` class -2. Plugin Registration: Available plugins are registered in `openhands/runtime/plugins/__init__.py` via `ALL_PLUGINS` -3. Plugin Specification: Plugins are associated with `Agent.sandbox_plugins: list[PluginRequirement]`. Users can specify which plugins to load when initializing the runtime -4. Initialization: Plugins are initialized asynchronously when the runtime starts and are accessible to actions -5. Usage: Plugins extend capabilities (e.g., Jupyter for IPython cells); the server exposes any web endpoints (ports) via host port mapping diff --git a/docs/usage/cloud/bitbucket-installation.mdx b/docs/usage/cloud/bitbucket-installation.mdx deleted file mode 100644 index da42a19cb1..0000000000 --- a/docs/usage/cloud/bitbucket-installation.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Bitbucket Integration -description: This guide walks you through the process of installing OpenHands Cloud for your Bitbucket repositories. Once - set up, it will allow OpenHands to work with your Bitbucket repository. ---- - -## Prerequisites - -- Signed in to [OpenHands Cloud](https://app.all-hands.dev) with [a Bitbucket account](/usage/cloud/openhands-cloud). - -## IP Whitelisting - -If your Bitbucket Cloud instance has IP restrictions, you'll need to whitelist the following IP addresses to allow OpenHands to access your repositories: - -### Core App IP -``` -34.68.58.200 -``` - -### Runtime IPs -``` -34.10.175.217 -34.136.162.246 -34.45.0.142 -34.28.69.126 -35.224.240.213 -34.70.174.52 -34.42.4.87 -35.222.133.153 -34.29.175.97 -34.60.55.59 -``` - -## Adding Bitbucket Repository Access - -Upon signing into OpenHands Cloud with a Bitbucket account, OpenHands will have access to your repositories. - -## Working With Bitbucket Repos in Openhands Cloud - -After signing in with a Bitbucket account, use the `select a repo` and `select a branch` dropdowns to select the -appropriate repository and branch you'd like OpenHands to work on. Then click on `Launch` to start the conversation! - -![Connect Repo](/static/img/connect-repo-no-github.png) - -## Next Steps - -- [Learn about the Cloud UI](/usage/cloud/cloud-ui). -- [Use the Cloud API](/usage/cloud/cloud-api) to programmatically interact with OpenHands. diff --git a/docs/usage/cloud/cloud-api.mdx b/docs/usage/cloud/cloud-api.mdx deleted file mode 100644 index 12438a6b70..0000000000 --- a/docs/usage/cloud/cloud-api.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Cloud API -description: OpenHands Cloud provides a REST API that allows you to programmatically interact with OpenHands. - This guide explains how to obtain an API key and use the API to start conversations and retrieve their status. ---- - -For the available API endpoints, refer to the -[OpenHands API Reference](https://docs.all-hands.dev/api-reference). - -## 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. Select the `API Keys` tab. -4. Click `Create API Key`. -5. Give your key a descriptive name (Example: "Development" or "Production") and select `Create`. -6. Copy the generated API key and store it securely. It will only be shown once. - -![API Key Generation](/static/img/api-key-generation.png) - -## API Usage - -### Starting a New Conversation - -To start a new conversation with OpenHands to perform 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 - - - - ```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" - }' - ``` - - - - ```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['conversation_id']}") - print(f"Status: {conversation['status']}") - ``` - - - - ```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(); - ``` - - -#### Response - -The API will return a JSON object with details about the created conversation: - -```json -{ - "status": "ok", - "conversation_id": "abc1234", -} -``` - -You may receive an `AuthenticationError` if: - -- You provided an invalid API key. -- You provided the wrong repository name. -- You don't have access to the repository. - - -### 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 - - - ```bash - curl -X GET "https://app.all-hands.dev/api/conversations/{conversation_id}" \ - -H "Authorization: Bearer YOUR_API_KEY" - ``` - - -#### 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 - -If you have too many conversations running at once, older conversations will be paused to limit the number of concurrent conversations. -If you're running into issues and need a higher limit for your use case, please contact us at [contact@all-hands.dev](mailto:contact@all-hands.dev). diff --git a/docs/usage/cloud/cloud-ui.mdx b/docs/usage/cloud/cloud-ui.mdx deleted file mode 100644 index d63ac66c99..0000000000 --- a/docs/usage/cloud/cloud-ui.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Cloud UI -description: The Cloud UI provides a web interface for interacting with OpenHands. This page provides references on - how to use the OpenHands Cloud UI. ---- - -## Landing Page - -The landing page is where you can: - -- [Add GitHub repository access](/usage/cloud/github-installation#adding-github-repository-access) to OpenHands. -- [Select a GitHub repo](/usage/cloud/github-installation#working-with-github-repos-in-openhands-cloud), - [a GitLab repo](/usage/cloud/gitlab-installation#working-with-gitlab-repos-in-openhands-cloud) or - [a Bitbucket repo](/usage/cloud/bitbucket-installation#working-with-bitbucket-repos-in-openhands-cloud) to start working on. -- See `Suggested Tasks` for repositories that OpenHands has access to. -- Launch an empty conversation using `Launch from Scratch`. - -## Settings - -The Settings page allows you to: - -- [Configure GitHub repository access](/usage/cloud/github-installation#modifying-repository-access) for OpenHands. -- [Install the OpenHands Slack app](/usage/cloud/slack-installation). -- Set application settings like your preferred language, notifications and other preferences. -- Add credits to your account. -- [Generate custom secrets](/usage/common-settings#secrets-management). -- [Create API keys to work with OpenHands programmatically](/usage/cloud/cloud-api). -- Change your email address. - -## Key Features - -For an overview of the key features available inside a conversation, please refer to the [Key Features](/usage/key-features) -section of the documentation. - -## Next Steps - -- [Install GitHub Integration](/usage/cloud/github-installation) to use OpenHands with your GitHub repositories. -- [Install GitLab Integration](/usage/cloud/gitlab-installation) to use OpenHands with your GitLab repositories. -- [Use the Cloud API](/usage/cloud/cloud-api) to programmatically interact with OpenHands. diff --git a/docs/usage/cloud/github-installation.mdx b/docs/usage/cloud/github-installation.mdx deleted file mode 100644 index ae0428b0c1..0000000000 --- a/docs/usage/cloud/github-installation.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: GitHub Integration -description: This guide walks you through the process of installing OpenHands Cloud for your GitHub repositories. Once - set up, it will allow OpenHands to work with your GitHub repository through the Cloud UI or straight from GitHub! ---- - -## Prerequisites - -- Signed in to [OpenHands Cloud](https://app.all-hands.dev) with [a GitHub account](/usage/cloud/openhands-cloud). - -## Adding GitHub Repository Access - -You can grant OpenHands access to specific GitHub repositories: - -1. Click on `Add GitHub repos` on the landing page. -2. Select your organization and choose the specific repositories to grant OpenHands access to. - - - OpenHands requests short-lived tokens (8-hour expiration) with these permissions: - - Actions: Read and write - - 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: - - Permission granted for the repository - - User's GitHub permissions (owner/collaborator) - - -3. Click `Install & Authorize`. - -## Modifying Repository Access - -You can modify GitHub repository access at any time by: -- Selecting `Add GitHub repos` on the landing page or -- Visiting the Settings page and selecting `Configure GitHub Repositories` under the `Integrations` tab - -## Working With GitHub Repos in Openhands Cloud - -Once you've granted GitHub repository access, you can start working with your GitHub repository. Use the `select a repo` -and `select a branch` dropdowns to select the appropriate repository and branch you'd like OpenHands to work on. Then -click on `Launch` to start the conversation! - -![Connect Repo](/static/img/connect-repo.png) - -## Working on Github Issues and Pull Requests Using Openhands - -Giving GitHub repository access to OpenHands also allows you to work on GitHub issues and pull requests directly. - -### Working with Issues - -On your repository, label an issue with `openhands` or add a message starting with `@openhands`. OpenHands will: -1. Comment on the issue to let you know it is working on it. - - You can click on the link to track the progress on OpenHands Cloud. -2. Open a pull request if it determines that the issue has been successfully resolved. -3. Comment on the issue with a summary of the performed tasks and a link to the PR. - -### Working with Pull Requests - -To get OpenHands to work on pull requests, mention `@openhands` in the comments to: -- Ask questions -- Request updates -- Get code explanations - -**Important Note**: The `@openhands` mention functionality in pull requests only works if the pull request is both *to* and *from* a repository that you have added through the interface. This is because OpenHands needs appropriate permissions to access both repositories. - -## Next Steps - -- [Learn about the Cloud UI](/usage/cloud/cloud-ui). -- [Use the Cloud API](/usage/cloud/cloud-api) to programmatically interact with OpenHands. diff --git a/docs/usage/cloud/gitlab-installation.mdx b/docs/usage/cloud/gitlab-installation.mdx deleted file mode 100644 index 46111d17e3..0000000000 --- a/docs/usage/cloud/gitlab-installation.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: GitLab Integration -description: This guide walks you through the process of installing OpenHands Cloud for your GitLab repositories. Once - set up, it will allow OpenHands to work with your GitLab repository through the Cloud UI or straight from GitLab!. ---- - -## Prerequisites - -- Signed in to [OpenHands Cloud](https://app.all-hands.dev) with [a GitLab account](/usage/cloud/openhands-cloud). - -## Adding GitLab Repository Access - -Upon signing into OpenHands Cloud with a GitLab account, OpenHands will have access to your repositories. - -## Working With GitLab Repos in Openhands Cloud - -After signing in with a Gitlab account, use the `select a repo` and `select a branch` dropdowns to select the -appropriate repository and branch you'd like OpenHands to work on. Then click on `Launch` to start the conversation! - -![Connect Repo](/static/img/connect-repo-no-github.png) - -## Using Tokens with Reduced Scopes - -OpenHands requests an API-scoped token during OAuth authentication. By default, this token is provided to the agent. -To restrict the agent's permissions, you can define a custom secret `GITLAB_TOKEN`, which will override the default token assigned to the agent. -While the high-permission API token is still requested and used for other components of the application (e.g. opening merge requests), the agent will not have access to it. - -## Working on GitLab Issues and Merge Requests Using Openhands - - -This feature works for personal projects and is available for group projects with a -[Premium or Ultimate tier subscription](https://docs.gitlab.com/user/project/integrations/webhooks/#group-webhooks). - -A webhook is automatically installed within a few minutes after the owner/maintainer of the project or group logs into -OpenHands Cloud. If you decide to delete the webhook, then re-installing will require the support of All Hands AI but we are planning to improve this in a future release. - - -Giving GitLab repository access to OpenHands also allows you to work on GitLab issues and merge requests directly. - -### Working with Issues - -On your repository, label an issue with `openhands` or add a message starting with `@openhands`. OpenHands will: -1. Comment on the issue to let you know it is working on it. - - You can click on the link to track the progress on OpenHands Cloud. -2. Open a merge request if it determines that the issue has been successfully resolved. -3. Comment on the issue with a summary of the performed tasks and a link to the PR. - -### Working with Merge Requests - -To get OpenHands to work on merge requests, mention `@openhands` in the comments to: -- Ask questions -- Request updates -- Get code explanations - -## Next Steps - -- [Learn about the Cloud UI](/usage/cloud/cloud-ui). -- [Use the Cloud API](/usage/cloud/cloud-api) to programmatically interact with OpenHands. diff --git a/docs/usage/cloud/openhands-cloud.mdx b/docs/usage/cloud/openhands-cloud.mdx deleted file mode 100644 index 6c0e363497..0000000000 --- a/docs/usage/cloud/openhands-cloud.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Getting Started -description: Getting started with OpenHands Cloud. ---- - -## Accessing OpenHands Cloud - -OpenHands Cloud is the hosted cloud version of All Hands AI's OpenHands. To get started with OpenHands Cloud, -visit [app.all-hands.dev](https://app.all-hands.dev). - -You'll be prompted to connect with your GitHub, GitLab or Bitbucket account: - -1. Click `Log in with GitHub`, `Log in with GitLab` or `Log in with Bitbucket`. -2. Review the permissions requested by OpenHands and authorize the application. - - OpenHands will require certain permissions from your account. To read more about these permissions, - you can click the `Learn more` link on the authorization page. -3. Review and accept the `terms of service` and select `Continue`. - -## Next Steps - -Once you've connected your account, you can: - -- [Install GitHub Integration](/usage/cloud/github-installation) to use OpenHands with your GitHub repositories. -- [Install GitLab Integration](/usage/cloud/gitlab-installation) to use OpenHands with your GitLab repositories. -- [Install Bitbucket Integration](/usage/cloud/bitbucket-installation) to use OpenHands with your Bitbucket repositories. -- [Learn about the Cloud UI](/usage/cloud/cloud-ui). -- [Use the Cloud API](/usage/cloud/cloud-api) to programmatically interact with OpenHands. diff --git a/docs/usage/cloud/project-management/jira-dc-integration.mdx b/docs/usage/cloud/project-management/jira-dc-integration.mdx deleted file mode 100644 index 1488bbf70b..0000000000 --- a/docs/usage/cloud/project-management/jira-dc-integration.mdx +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: Jira Data Center Integration (Coming soon...) -description: Complete guide for setting up Jira Data Center integration with OpenHands Cloud, including service account creation, personal access token generation, webhook configuration, and workspace integration setup. ---- - -# Jira Data Center Integration - -## Platform Configuration - -### Step 1: Create Service Account - -1. **Access User Management** - - Log in to Jira Data Center as administrator - - Go to **Administration** > **User Management** - -2. **Create User** - - Click **Create User** - - Username: `openhands-agent` - - Full Name: `OpenHands Agent` - - Email: `openhands@yourcompany.com` (replace with your preferred service account email) - - Password: Set a secure password - - Click **Create** - -3. **Assign Permissions** - - Add user to appropriate groups - - Ensure access to relevant projects - - Grant necessary project permissions - -### Step 2: Generate API Token - -1. **Personal Access Tokens** - - Log in as the service account - - Go to **Profile** > **Personal Access Tokens** - - Click **Create token** - - Name: `OpenHands Cloud Integration` - - Expiry: Set appropriate expiration (recommend 1 year) - - Click **Create** - - **Important**: Copy and store the token securely - -### Step 3: Configure Webhook - -1. **Create Webhook** - - Go to **Administration** > **System** > **WebHooks** - - Click **Create a WebHook** - - **Name**: `OpenHands Cloud Integration` - - **URL**: `https://app.all-hands.dev/integration/jira-dc/events` - - Set a suitable webhook secret - - **Issue related events**: Select the following: - - Issue updated - - Comment created - - **JQL Filter**: Leave empty (or customize as needed) - - Click **Create** - - **Important**: Copy and store the webhook secret securely (you'll need this for workspace integration) - ---- - -## Workspace Integration - -### Step 1: Log in to OpenHands Cloud - -1. **Navigate and Authenticate** - - Go to [OpenHands Cloud](https://app.all-hands.dev/) - - Sign in with your Git provider (GitHub, GitLab, or BitBucket) - - **Important:** Make sure you're signing in with the same Git provider account that contains the repositories you want the OpenHands agent to work on. - -### Step 2: Configure Jira Data Center Integration - -1. **Access Integration Settings** - - Navigate to **Settings** > **Integrations** - - Locate **Jira Data Center** section - -2. **Configure Workspace** - - Click **Configure** button - - Enter your workspace name and click **Connect** - - If no integration exists, you'll be prompted to enter additional credentials required for the workspace integration: - - **Webhook Secret**: The webhook secret from Step 3 above - - **Service Account Email**: The service account email from Step 1 above - - **Service Account API Key**: The personal access token from Step 2 above - - Ensure **Active** toggle is enabled - - -Workspace name is the host name of your Jira Data Center instance. - -Eg: http://jira.all-hands.dev/projects/OH/issues/OH-77 - -Here the workspace name is **jira.all-hands.dev**. - - -3. **Complete OAuth Flow** - - You'll be redirected to Jira Data Center to complete OAuth verification - - Grant the necessary permissions to verify your workspace access. If you have access to multiple workspaces, select the correct one that you initially provided - - If successful, you will be redirected back to the **Integrations** settings in the OpenHands Cloud UI - -### Managing Your Integration - -**Edit Configuration:** -- Click the **Edit** button next to your configured platform -- Update any necessary credentials or settings -- Click **Update** to apply changes -- You will need to repeat the OAuth flow as before -- **Important:** Only the original user who created the integration can see the edit view - -**Unlink Workspace:** -- In the edit view, click **Unlink** next to the workspace name -- This will deactivate your workspace link -- **Important:** If the original user who configured the integration chooses to unlink their integration, any users currently linked to that integration will also be unlinked, and the workspace integration will be deactivated. The integration can only be reactivated by the original user. - -### Screenshots - - - -![workspace-link.png](/static/img/jira-dc-user-link.png) - - - -![workspace-link.png](/static/img/jira-dc-admin-configure.png) - - - -![workspace-link.png](/static/img/jira-dc-user-unlink.png) - - - -![workspace-link.png](/static/img/jira-dc-admin-edit.png) - - diff --git a/docs/usage/cloud/project-management/jira-integration.mdx b/docs/usage/cloud/project-management/jira-integration.mdx deleted file mode 100644 index 68c3b524a5..0000000000 --- a/docs/usage/cloud/project-management/jira-integration.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Jira Cloud Integration (Coming soon...) -description: Complete guide for setting up Jira Cloud integration with OpenHands Cloud, including service account creation, API token generation, webhook configuration, and workspace integration setup. ---- - -# Jira Cloud Integration - -## Platform Configuration - -### Step 1: Create Service Account - -1. **Navigate to User Management** - - Go to [Atlassian Admin](https://admin.atlassian.com/) - - Select your organization - - Go to **Directory** > **Users** - -2. **Create OpenHands Service Account** - - Click **Service accounts** - - Click **Create a service account** - - Name: `OpenHands Agent` - - Click **Next** - - Select **User** role for Jira app - - Click **Create** - -### Step 2: Generate API Token - -1. **Access Service Account Configuration** - - Locate the created service account from above step and click on it - - Click **Create API token** - - Set the expiry to 365 days (maximum allowed value) - - Click **Next** - - In **Select token scopes** screen, filter by following values - - App: Jira - - Scope type: Classic - - Scope actions: Write, Read - - Select `read:jira-work` and `write:jira-work` scopes - - Click **Next** - - Review and create API token - - **Important**: Copy and securely store the token immediately - -### Step 3: Configure Webhook - -1. **Navigate to Webhook Settings** - - Go to **Jira Settings** > **System** > **WebHooks** - - Click **Create a WebHook** - -2. **Configure Webhook** - - **Name**: `OpenHands Cloud Integration` - - **Status**: Enabled - - **URL**: `https://app.all-hands.dev/integration/jira/events` - - **Issue related events**: Select the following: - - Issue updated - - Comment created - - **JQL Filter**: Leave empty (or customize as needed) - - Click **Create** - - **Important**: Copy and store the webhook secret securely (you'll need this for workspace integration) - ---- - -## Workspace Integration - -### Step 1: Log in to OpenHands Cloud - -1. **Navigate and Authenticate** - - Go to [OpenHands Cloud](https://app.all-hands.dev/) - - Sign in with your Git provider (GitHub, GitLab, or BitBucket) - - **Important:** Make sure you're signing in with the same Git provider account that contains the repositories you want the OpenHands agent to work on. - -### Step 2: Configure Jira Integration - -1. **Access Integration Settings** - - Navigate to **Settings** > **Integrations** - - Locate **Jira Cloud** section - -2. **Configure Workspace** - - Click **Configure** button - - Enter your workspace name and click **Connect** - - **Important:** Make sure you enter the full workspace name, eg: **yourcompany.atlassian.net** - - If no integration exists, you'll be prompted to enter additional credentials required for the workspace integration: - - **Webhook Secret**: The webhook secret from Step 3 above - - **Service Account Email**: The service account email from Step 1 above - - **Service Account API Key**: The API token from Step 2 above - - Ensure **Active** toggle is enabled - - -Workspace name is the host name when accessing a resource in Jira Cloud. - -Eg: https://all-hands.atlassian.net/browse/OH-55 - -Here the workspace name is **all-hands**. - - -3. **Complete OAuth Flow** - - You'll be redirected to Jira Cloud to complete OAuth verification - - Grant the necessary permissions to verify your workspace access. - - If successful, you will be redirected back to the **Integrations** settings in the OpenHands Cloud UI - -### Managing Your Integration - -**Edit Configuration:** -- Click the **Edit** button next to your configured platform -- Update any necessary credentials or settings -- Click **Update** to apply changes -- You will need to repeat the OAuth flow as before -- **Important:** Only the original user who created the integration can see the edit view - -**Unlink Workspace:** -- In the edit view, click **Unlink** next to the workspace name -- This will deactivate your workspace link -- **Important:** If the original user who configured the integration chooses to unlink their integration, any users currently linked to that workspace integration will also be unlinked, and the workspace integration will be deactivated. The integration can only be reactivated by the original user. - -### Screenshots - - - -![workspace-link.png](/static/img/jira-user-link.png) - - - -![workspace-link.png](/static/img/jira-admin-configure.png) - - - -![workspace-link.png](/static/img/jira-user-unlink.png) - - - -![workspace-link.png](/static/img/jira-admin-edit.png) - - diff --git a/docs/usage/cloud/project-management/linear-integration.mdx b/docs/usage/cloud/project-management/linear-integration.mdx deleted file mode 100644 index c01da4ae70..0000000000 --- a/docs/usage/cloud/project-management/linear-integration.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Linear Integration (Coming soon...) -description: Complete guide for setting up Linear integration with OpenHands Cloud, including service account creation, API key generation, webhook configuration, and workspace integration setup. ---- - -# Linear Integration - -## Platform Configuration - -### Step 1: Create Service Account - -1. **Access Team Settings** - - Log in to Linear as a team admin - - Go to **Settings** > **Members** - -2. **Invite Service Account** - - Click **Invite members** - - Email: `openhands@yourcompany.com` (replace with your preferred service account email) - - Role: **Member** (with appropriate team access) - - Send invitation - -3. **Complete Setup** - - Accept invitation from the service account email - - Complete profile setup - - Ensure access to relevant teams/workspaces - -### Step 2: Generate API Key - -1. **Access API Settings** - - Log in as the service account - - Go to **Settings** > **Security & access** - -2. **Create Personal API Key** - - Click **Create new key** - - Name: `OpenHands Cloud Integration` - - Scopes: Select the following: - - `Read` - Read access to issues and comments - - `Create comments` - Ability to create or update comments - - Select the teams you want to provide access to, or allow access for all teams you have permissions for - - Click **Create** - - **Important**: Copy and store the API key securely - -### Step 3: Configure Webhook - -1. **Access Webhook Settings** - - Go to **Settings** > **API** > **Webhooks** - - Click **New webhook** - -2. **Configure Webhook** - - **Label**: `OpenHands Cloud Integration` - - **URL**: `https://app.all-hands.dev/integration/linear/events` - - **Resource types**: Select: - - `Comment` - For comment events - - `Issue` - For issue updates (label changes) - - Select the teams you want to provide access to, or allow access for all public teams - - Click **Create webhook** - - **Important**: Copy and store the webhook secret securely (you'll need this for workspace integration) - ---- - -## Workspace Integration - -### Step 1: Log in to OpenHands Cloud - -1. **Navigate and Authenticate** - - Go to [OpenHands Cloud](https://app.all-hands.dev/) - - Sign in with your Git provider (GitHub, GitLab, or BitBucket) - - **Important:** Make sure you're signing in with the same Git provider account that contains the repositories you want the OpenHands agent to work on. - -### Step 2: Configure Linear Integration - -1. **Access Integration Settings** - - Navigate to **Settings** > **Integrations** - - Locate **Linear** section - -2. **Configure Workspace** - - Click **Configure** button - - Enter your workspace name and click **Connect** - - If no integration exists, you'll be prompted to enter additional credentials required for the workspace integration: - - **Webhook Secret**: The webhook secret from Step 3 above - - **Service Account Email**: The service account email from Step 1 above - - **Service Account API Key**: The API key from Step 2 above - - Ensure **Active** toggle is enabled - - -Workspace name is the identifier after the host name when accessing a resource in Linear. - -Eg: https://linear.app/allhands/issue/OH-37 - -Here the workspace name is **allhands**. - - -3. **Complete OAuth Flow** - - You'll be redirected to Linear to complete OAuth verification - - Grant the necessary permissions to verify your workspace access. If you have access to multiple workspaces, select the correct one that you initially provided - - If successful, you will be redirected back to the **Integrations** settings in the OpenHands Cloud UI - -### Managing Your Integration - -**Edit Configuration:** -- Click the **Edit** button next to your configured platform -- Update any necessary credentials or settings -- Click **Update** to apply changes -- You will need to repeat the OAuth flow as before -- **Important:** Only the original user who created the integration can see the edit view - -**Unlink Workspace:** -- In the edit view, click **Unlink** next to the workspace name -- This will deactivate your workspace link -- **Important:** If the original user who configured the integration chooses to unlink their integration, any users currently linked to that integration will also be unlinked, and the workspace integration will be deactivated. The integration can only be reactivated by the original user. - -### Screenshots - - - -![workspace-link.png](/static/img/linear-user-link.png) - - - -![workspace-link.png](/static/img/linear-admin-configure.png) - - - -![workspace-link.png](/static/img/linear-admin-edit.png) - - - -![workspace-link.png](/static/img/workspace-admin-edit.png) - - diff --git a/docs/usage/cloud/project-management/overview.mdx b/docs/usage/cloud/project-management/overview.mdx deleted file mode 100644 index 54c84abfe2..0000000000 --- a/docs/usage/cloud/project-management/overview.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Project Management Tool Integrations (Coming soon...) -description: Overview of OpenHands Cloud integrations with project management platforms including Jira Cloud, Jira Data Center, and Linear. Learn about setup requirements, usage methods, and troubleshooting. ---- - -# Project Management Tool Integrations - -## Overview - -OpenHands Cloud integrates with project management platforms (Jira Cloud, Jira Data Center, and Linear) to enable AI-powered task delegation. Users can invoke the OpenHands agent by: -- Adding `@openhands` in ticket comments -- Adding the `openhands` label to tickets - -## Prerequisites - -Integration requires two levels of setup: -1. **Platform Configuration** - Administrative setup of service accounts and webhooks on your project management platform (see individual platform documentation below) -2. **Workspace Integration** - Self-service configuration through the OpenHands Cloud UI to link your OpenHands account to the target workspace - -### Platform-Specific Setup Guides: -- [Jira Cloud Integration (Coming soon...)](./jira-integration.md) -- [Jira Data Center Integration (Coming soon...)](./jira-dc-integration.md) -- [Linear Integration (Coming soon...)](./linear-integration.md) - -## Usage - -Once both the platform configuration and workspace integration are completed, users can trigger the OpenHands agent within their project management platforms using two methods: - -### Method 1: Comment Mention -Add a comment to any issue with `@openhands` followed by your task description: -``` -@openhands Please implement the user authentication feature described in this ticket -``` - -### Method 2: Label-based Delegation -Add the label `openhands` to any issue. The OpenHands agent will automatically process the issue based on its description and requirements. - -### Git Repository Detection - -The OpenHands agent needs to identify which Git repository to work with when processing your issues. Here's how to ensure proper repository detection: - -#### Specifying the Target Repository - -**Required:** Include the target Git repository in your issue description or comment to ensure the agent works with the correct codebase. - -**Supported Repository Formats:** -- Full HTTPS URL: `https://github.com/owner/repository.git` -- GitHub URL without .git: `https://github.com/owner/repository` -- Owner/repository format: `owner/repository` - -#### Platform-Specific Behavior - -**Linear Integration:** When GitHub integration is enabled for your Linear workspace with issue sync activated, the target repository is automatically detected from the linked GitHub issue. Manual specification is not required in this configuration. - -**Jira Integrations:** Always include the repository information in your issue description or `@openhands` comment to ensure proper repository detection. - -## Troubleshooting - -### Platform Configuration Issues -- **Webhook not triggering**: Verify the webhook URL is correct and the proper event types are selected (Comment, Issue updated) -- **API authentication failing**: Check API key/token validity and ensure required scopes are granted. If your current API token is expired, make sure to update it in the respective integration settings -- **Permission errors**: Ensure the service account has access to relevant projects/teams and appropriate permissions - -### Workspace Integration Issues -- **Workspace linking requests credentials**: If there are no active workspace integrations for the workspace you specified, you need to configure it first. Contact your platform administrator that you want to integrate with (eg: Jira, Linear) -- **Integration not found**: Verify the workspace name matches exactly and that platform configuration was completed first -- **OAuth flow fails**: Make sure that you're authorizing with the correct account with proper workspace access - -### General Issues -- **Agent not responding**: Check webhook logs in your platform settings and verify service account status -- **Authentication errors**: Verify Git provider permissions and OpenHands Cloud access -- **Agent fails to identify git repo**: Ensure you're signing in with the same Git provider account that contains the repositories you want OpenHands to work on -- **Partial functionality**: Ensure both platform configuration and workspace integration are properly completed - -### Getting Help -For additional support, contact OpenHands Cloud support with: -- Your integration platform (Linear, Jira Cloud, or Jira Data Center) -- Workspace name -- Error logs from webhook/integration attempts -- Screenshots of configuration settings (without sensitive credentials) diff --git a/docs/usage/cloud/slack-installation.mdx b/docs/usage/cloud/slack-installation.mdx deleted file mode 100644 index 34c8a8f372..0000000000 --- a/docs/usage/cloud/slack-installation.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Slack Integration (Beta) -description: This guide walks you through installing the OpenHands Slack app. ---- - - - - -OpenHands utilizes a large language model (LLM), which may generate responses that are inaccurate or incomplete. While we strive for accuracy, OpenHands' outputs are not guaranteed to be correct, and we encourage users to validate critical information independently. - - -## Prerequisites - -- Access to OpenHands Cloud. - -## Installation Steps - - - - - **This step is for Slack admins/owners** - - 1. Make sure you have permissions to install Apps to your workspace. - 2. Click the button below to install OpenHands Slack App Add to Slack - 3. In the top right corner, select the workspace to install the OpenHands Slack app. - 4. Review permissions and click allow. - - - - - - **Make sure your Slack workspace admin/owner has installed OpenHands Slack App first.** - - Every user in the Slack workspace (including admins/owners) must link their OpenHands Cloud account to the OpenHands Slack App. To do this: - 1. Visit [integrations settings](https://app.all-hands.dev/settings/integrations) in OpenHands Cloud. - 2. Click `Install OpenHands Slack App`. - 3. In the top right corner, select the workspace to install the OpenHands Slack app. - 4. Review permissions and click allow. - - Depending on the workspace settings, you may need approval from your Slack admin to authorize the Slack App. - - - - - - -## Working With the Slack App - -To start a new conversation, you can mention `@openhands` in a new message or a thread inside any Slack channel. - -Once a conversation is started, all thread messages underneath it will be follow-up messages to OpenHands. - -To send follow-up messages for the same conversation, mention `@openhands` in a thread reply to the original message. You must be the user who started the conversation. - -## Example conversation - -### Start a new conversation, and select repo - -Conversation is started by mentioning `@openhands`. - -![slack-create-conversation.png](/static/img/slack-create-conversation.png) - -### See agent response and send follow up messages - -Initial request is followed up by mentioning `@openhands` in a thread reply. - -![slack-results-and-follow-up.png](/static/img/slack-results-and-follow-up.png) - -## Pro tip - -You can mention a repo name when starting a new conversation in the following formats - -1. "My-Repo" repo (e.g `@openhands in the openhands repo ...`) -2. "All-Hands-AI/OpenHands" (e.g `@openhands in All-Hands-AI/OpenHands ...`) - -The repo match is case insensitive. If a repo name match is made, it will kick off the conversation. -If the repo name partially matches against multiple repos, you'll be asked to select a repo from the filtered list. - -![slack-pro-tip.png](/static/img/slack-pro-tip.png) diff --git a/docs/usage/common-settings.mdx b/docs/usage/common-settings.mdx deleted file mode 100644 index cf08a8cd53..0000000000 --- a/docs/usage/common-settings.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: OpenHands Settings -description: Overview of some of the settings available in OpenHands. ---- - -## Openhands Cloud vs Running on Your Own - -There are some differences between the settings available in OpenHands Cloud and those available when running OpenHands -on your own: -* [OpenHands Cloud settings](/usage/cloud/cloud-ui#settings) -* [Settings available when running on your own](/usage/how-to/gui-mode#settings) - -Refer to these pages for more detailed information. - -## Secrets Management - -OpenHands provides a secrets manager that allows you to securely store and manage sensitive information that can be -accessed by the agent during runtime, such as API keys. These secrets are automatically exported as environment -variables in the agent's runtime environment. - -### Accessing the Secrets Manager - -In the Settings page, navigate to the `Secrets` tab. Here, you'll see a list of all your existing custom secrets. - -### Adding a New Secret -1. Click `Add a new secret`. -2. Fill in the following fields: - - **Name**: A unique identifier for your secret (e.g., `AWS_ACCESS_KEY`). This will be the environment variable name. - - **Value**: The sensitive information you want to store. - - **Description** (optional): A brief description of what the secret is used for, which is also provided to the agent. -3. Click `Add secret` to save. - -### Editing a Secret - -1. Click the `Edit` button next to the secret you want to modify. -2. You can update the name and description of the secret. - - For security reasons, you cannot view or edit the value of an existing secret. If you need to change the - value, delete the secret and create a new one. - - -### Deleting a Secret - -1. Click the `Delete` button next to the secret you want to remove. -2. Select `Confirm` to delete the secret. - -### Using Secrets in the Agent - - All custom secrets are automatically exported as environment variables in the agent's runtime environment. - - You can access them in your code using standard environment variable access methods - (e.g., `os.environ['SECRET_NAME']` in Python). - - Example: If you create a secret named `OPENAI_API_KEY`, you can access it in your code as - `process.env.OPENAI_API_KEY` in JavaScript or `os.environ['OPENAI_API_KEY']` in Python. diff --git a/docs/usage/configuration-options.mdx b/docs/usage/configuration-options.mdx deleted file mode 100644 index fc3fcdb579..0000000000 --- a/docs/usage/configuration-options.mdx +++ /dev/null @@ -1,437 +0,0 @@ ---- -title: Configuration Options -description: 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. - - - - **Looking for Environment Variables?** All configuration options can also be set using environment variables. - See the [Environment Variables Reference](./environment-variables) for a complete list with examples. - - -## Location of the `config.toml` File - -When running OpenHands in CLI, headless, or development mode, you can use a project-specific `config.toml` file for configuration, which must be -located in the same directory from which the command is run. Alternatively, you may use the `--config-file` option to -specify a different path to the `config.toml` file. - -## Core Configuration - -The core configuration options are defined in the `[core]` section of the `config.toml` file. - -Core configuration options can be set as environment variables by converting to uppercase. For example: -- `debug` → `DEBUG` -- `cache_dir` → `CACHE_DIR` -- `runtime` → `RUNTIME` - -### Workspace -- `workspace_base` **(Deprecated)** - - Type: `str` - - Default: `"./workspace"` - - Description: Base path for the workspace. **Deprecated: Use `SANDBOX_VOLUMES` instead.** - -- `cache_dir` - - Type: `str` - - Default: `"/tmp/cache"` - - Description: Cache directory path - -### Debugging and Logging -- `debug` - - Type: `bool` - - Default: `false` - - Description: Enable debugging - -- `disable_color` - - Type: `bool` - - Default: `false` - - Description: Disable color in terminal output - -### Trajectories -- `save_trajectory_path` - - Type: `str` - - Default: `"./trajectories"` - - Description: Path to store trajectories (can be a folder or a file). If it's a folder, the trajectories will be saved in a file named with the session id name and .json extension, in that folder. - -- `replay_trajectory_path` - - Type: `str` - - Default: `""` - - Description: Path to load a trajectory and replay. If given, must be a path to the trajectory file in JSON format. The actions in the trajectory file would be replayed first before any user instruction is executed. - -### File Store -- `file_store_path` - - Type: `str` - - Default: `"/tmp/file_store"` - - Description: File store path - -- `file_store` - - Type: `str` - - Default: `"memory"` - - Description: File store type - -- `file_uploads_allowed_extensions` - - Type: `list of str` - - Default: `[".*"]` - - Description: List of allowed file extensions for uploads - -- `file_uploads_max_file_size_mb` - - Type: `int` - - Default: `0` - - Description: Maximum file size for uploads, in megabytes - -- `file_uploads_restrict_file_types` - - Type: `bool` - - Default: `false` - - Description: Restrict file types for file uploads - -- `file_uploads_allowed_extensions` - - Type: `list of str` - - Default: `[".*"]` - - Description: List of allowed file extensions for uploads - -### Task Management -- `max_budget_per_task` - - Type: `float` - - Default: `0.0` - - Description: Maximum budget per task (0.0 means no limit) - -- `max_iterations` - - Type: `int` - - Default: `100` - - Description: Maximum number of iterations - -### Sandbox Configuration -- `volumes` - - Type: `str` - - Default: `None` - - Description: Volume mounts in the format 'host_path:container_path[:mode]', e.g. '/my/host/dir:/workspace:rw'. Multiple mounts can be specified using commas, e.g. '/path1:/workspace/path1,/path2:/workspace/path2:ro' - -- `workspace_mount_path_in_sandbox` **(Deprecated)** - - Type: `str` - - Default: `"/workspace"` - - Description: Path to mount the workspace in the sandbox. **Deprecated: Use `SANDBOX_VOLUMES` instead.** - -- `workspace_mount_path` **(Deprecated)** - - Type: `str` - - Default: `""` - - Description: Path to mount the workspace. **Deprecated: Use `SANDBOX_VOLUMES` instead.** - -- `workspace_mount_rewrite` **(Deprecated)** - - Type: `str` - - Default: `""` - - Description: Path to rewrite the workspace mount path to. You can usually ignore this, it refers to special cases of running inside another container. **Deprecated: Use `SANDBOX_VOLUMES` instead.** - -### Miscellaneous -- `run_as_openhands` - - Type: `bool` - - Default: `true` - - Description: Run as OpenHands - -- `runtime` - - Type: `str` - - Default: `"docker"` - - Description: Runtime environment - -- `default_agent` - - Type: `str` - - Default: `"CodeActAgent"` - - Description: Name of the default agent - -- `jwt_secret` - - Type: `str` - - Default: `uuid.uuid4().hex` - - Description: JWT secret for authentication. Please set it to your own value. - -## LLM Configuration - -The LLM (Large Language Model) configuration options are defined in the `[llm]` section of the `config.toml` file. - -To use these with the docker command, pass in `-e LLM_