Compare commits

..

79 Commits

Author SHA1 Message Date
chuckbutkus
8d882ff5f0 Merge branch 'main' into fix-redirect 2025-05-23 00:58:47 -04:00
Chuck Butkus
f876bbe76a Don't always navigate to / after login 2025-05-23 00:57:05 -04:00
Chuck Butkus
955e201e2c Don't set flag for auth modal 2025-05-23 00:13:46 -04:00
openhands
78c5f5578b Fix: Only redirect to last page after actual login, not on refresh or new tab 2025-05-23 03:09:34 +00:00
Robert Brennan
50d4c79094 Add CLIRuntime implementation for local command execution (#8264)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Engel Nyst <engel.nyst@gmail.com>
2025-05-23 03:03:22 +00:00
Chuck Butkus
815cc8e660 Only redirect to last page if going to home page 2025-05-22 22:51:19 -04:00
tofarr
f7cdf4720f Fix gitlab header error in console (#8631) 2025-05-22 14:22:02 -06:00
mamoodi
6d3c2170b1 Release 0.39.1 (#8608)
Co-authored-by: tofarr <tofarr@gmail.com>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
2025-05-22 16:18:54 -04:00
Xingyao Wang
926b425e12 add claude 4 to prompt caching and fn call list; do not add icl for devstral (#8642) 2025-05-22 19:10:00 +00:00
Ryan H. Tran
3980ba53c9 Add option to run patch evaluation on Modal (#8607)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-23 00:45:45 +07:00
Xingyao Wang
be78cc07bd docs: add documentation for adding user settings and tooltips (#8634)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-22 17:38:54 +00:00
Graham Neubig
13f9acd48a Fix Cloud documentation structure and consolidate issue resolver information (#8558)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: mamoodi <mamoodiha@gmail.com>
2025-05-22 11:05:15 -04:00
Xingyao Wang
2906a9023f fix(frontend): MCP tool name rendering (#8623)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-22 21:46:40 +08:00
dependabot[bot]
66f33bfa96 chore(deps-dev): bump swagger-ui-dist from 5.21.0 to 5.22.0 in /docs in the version-all group (#8611)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 17:11:14 +04:00
kotauchisunsun
cfa2725abd Split IssueResolver class into a separate file (#8619) 2025-05-22 09:53:55 +02:00
Rohit Malhotra
097f757c65 [Refactor]: Update resolver instructions (#8601)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-21 19:26:48 -04:00
Rohit Malhotra
ac87ff8d27 [Fix]: Don't start conversations without user instructions for remote api key conversations (#8626) 2025-05-21 17:51:48 -04:00
tofarr
a3d1a92353 Nested Conversation Support (#8588)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Robert Brennan <contact@rbren.io>
2025-05-21 15:17:30 -06:00
Xingyao Wang
70573dcbc0 fix(mcp): fix the config conflict between microagent MCP tools & MCP config (#8620)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-21 20:26:02 +00:00
Engel Nyst
637cb0726a specify condenser config for evals (#8177)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-21 22:08:57 +02:00
tofarr
2bd10de636 Revert "Fix for issue where initial env vars are not passed to runtime" (#8624) 2025-05-21 20:00:56 +00:00
dependabot[bot]
70322c8418 chore(deps): bump the version-all group across 1 directory with 8 updates (#8617)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
2025-05-21 19:34:59 +00:00
Rohit Malhotra
8b08958efe [Fix]: make mcp config optional in settings (#8622) 2025-05-21 19:17:43 +00:00
dependabot[bot]
5b021ad1bb chore(deps): bump the version-all group across 1 directory with 2 updates (#8618)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 16:39:07 +00:00
Rohit Malhotra
890796cc9d [Feat]: Git mcp server to open PRs (#8348)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
Co-authored-by: Robert Brennan <accounts@rbren.io>
2025-05-21 11:48:02 -04:00
sp.wack
7305c8fb31 hotfix(frontend): Prevent merging conversation events when switching between conversations (#8614) 2025-05-21 15:12:04 +00:00
Xingyao Wang
f1897b8095 docs: add Devstral MLX link for local models documentation (#8615) 2025-05-21 15:04:50 +00:00
Engel Nyst
c26ef180f2 Fix unsupported MCP tools param (#8610) 2025-05-21 14:41:01 +00:00
Robert Brennan
37e9933092 Revert "Fix passing environment" (#8612) 2025-05-21 14:32:47 +00:00
Xingyao Wang
c353fb6e7e docs: update local llm documentation (#8609)
Co-authored-by: mamoodi <mamoodiha@gmail.com>
2025-05-21 14:05:21 +00:00
chuckbutkus
3280f450ac Update to login if session times out and return to previous conversation (#8587)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-20 22:10:28 +00:00
Graham Neubig
6335afb010 Fix environment variable casting for dict and list types (#8494)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-20 17:47:07 -04:00
mamoodi
40d9b0b13a Remove duplicated documentation from cognition (#8600) 2025-05-20 21:23:12 +00:00
Boxuan Li
005c5d6bde Document native windows support without WSL (#8567)
Co-authored-by: mamoodi <mamoodiha@gmail.com>
2025-05-20 20:54:32 +00:00
Rohit Malhotra
0deabd5935 [Feat]: add context msg to new conversation endpoint (#8586)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-20 20:47:15 +00:00
Erkin Alp Güney
6f5bb4341f Add a DeepWiki reference (#8350) 2025-05-20 16:20:56 -04:00
dependabot[bot]
a5daf0e3c1 chore(deps): bump the version-all group with 6 updates (#8596)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-20 21:35:22 +02:00
tofarr
3873d9f002 Fix for issue where initial env vars are not passed to runtime (#8597) 2025-05-20 10:58:43 -06:00
Robert Brennan
5e1039e4b5 Make chat auto-scroll functionality more explicit (#8562)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-20 12:58:05 -04:00
mamoodi
d648d249d8 Release 0.39.0 (#8539) 2025-05-20 11:39:55 -04:00
tofarr
aa55da27fa Fix unlocalized strings in frontend components (#8585)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-19 19:12:26 +00:00
tofarr
e69d6b3ef1 fix: add missing translation keys to declaration.ts (#8580)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-19 11:49:57 -06:00
tofarr
be1ddaa57d Add conversationUrl static variable with getter and setter methods (#8531)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-19 11:28:07 -06:00
Robert Brennan
7b59e81048 make scrollbar prettier (#8581) 2025-05-19 17:23:47 +00:00
dependabot[bot]
470687f826 chore(deps): bump the mcp-packages group with 2 updates (#8546)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 18:37:11 +02:00
tofarr
38b4d93237 Add Session API Key Authentication for Runtime Communication (#8550) 2025-05-19 09:59:22 -06:00
dependabot[bot]
872b97a3c8 chore(deps): bump the version-all group across 1 directory with 20 updates (#8545)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
2025-05-19 15:49:53 +00:00
sp.wack
14334040f1 chore(frontend): Refactor chat interface-related event handling (#8403) 2025-05-19 15:15:09 +00:00
sp.wack
b244138ec5 fix(frontend): Prevent making too many calls to /git/changes on conversation load (#8579) 2025-05-19 18:57:18 +04:00
Xingyao Wang
4a3d2e6859 Fix #8551: Show images produced in Jupyter Notebook to LLM directly (#8552)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-19 14:14:00 +00:00
luolin101
1a3cb16ba6 add Visual SWE-bench benchmark (#7131)
Co-authored-by: tsukimi <yuailun@pku.edu.cn>
Co-authored-by: Ryan H. Tran <descience.thh10@gmail.com>
2025-05-19 12:08:46 +07:00
Xingyao Wang
2ecc39ffcc [eval]: disable MCP for SWE-Bench evaluation (#8574)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Engel Nyst <engel.nyst@gmail.com>
2025-05-19 01:32:46 +00:00
Graham Neubig
0b26174d60 Add documentation microagent (#8563)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-18 16:34:15 -04:00
Calvin Smith
b0005d4e09 Limit size of browser events (#8559)
Co-authored-by: Calvin Smith <calvin@all-hands.dev>
2025-05-18 11:35:09 -06:00
Graham Neubig
2dc7b37fe8 Fix flaky TestLocalFileStore tests (#8569)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-18 06:37:28 -04:00
Carlos Freund
27c18f5bdd build(makefile) Develop in OpenhandsCloud (#7440)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Boxuan Li <liboxuan@connect.hku.hk>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-17 14:40:46 +00:00
Graham Neubig
5077fea5c7 Fix: Run setup.sh script in GitHub resolver (#8548)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-17 09:52:34 -04:00
Justin Coffi
bf383b4881 Add SSH Microagent (#8436)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Xingyao Wang <xingyaoww@gmail.com>
2025-05-17 05:56:51 +00:00
OpenHands
c17b0ebfc6 Fix issue #8304: [Bug]: Non-native tool use converter fails when builtin tools are disabled (#8310)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Engel Nyst <engel.nyst@gmail.com>
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
2025-05-17 06:37:45 +02:00
Xingyao Wang
1f390430e5 feat(MCP, microagent): MCP-support for Repo Microagent & add fetch as default tool (#8360)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-16 23:32:38 +00:00
Robert Brennan
819bad0777 Fix: Only show login modal for genuine 401 errors, not connection issues (#8540)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 13:33:06 -04:00
dependabot[bot]
2faed14139 chore(deps): bump the version-all group with 5 updates (#8541)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 17:17:38 +00:00
tofarr
4733270e3c Add event search endpoints with filtering and pagination (#8538)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 09:51:40 -06:00
Robert Brennan
21dd91de63 Add info logging for 401 Unauthorized responses (#8527)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 11:46:15 -04:00
Graham Neubig
25619c5a93 Fix #8510: Improve error messages for invalid microagent format (#8511)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 15:01:39 +00:00
Robert Brennan
15f71e7ed6 Update microagent message from "Activated" to "ready" (#8536)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 10:44:37 -04:00
mamoodi
5b583e5f27 Organization and user microagents (#8506) 2025-05-16 10:42:32 -04:00
Rohit Malhotra
c191a17afb [Fix]: don't access secrets if doesn't exist (#8535)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 14:30:16 +00:00
Robert Brennan
8ec5d0e043 Add WebSocket connection documentation (#8404)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 10:12:05 -04:00
Robert Brennan
f3f038bb60 Fix mypy error for pkg_resources import (#8537)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 14:06:41 +00:00
Robert Brennan
b8d3027cfe Always enable logout button regardless of GitHub connection status (#8529)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-16 09:09:33 -04:00
Rohit Malhotra
feb04dc65f Plumb custom secrets to runtime (#8330)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-15 20:06:30 -04:00
Engel Nyst
1f827170f4 Fix resolver test (#8530) 2025-05-15 21:57:02 +00:00
Engel Nyst
f7cb2d0f64 Restore previous conversation in CLI (#8431) 2025-05-15 23:47:41 +02:00
tofarr
033788c2d0 API Updates to facilitate nested runtimes. (#8525) 2025-05-15 15:38:09 -06:00
dependabot[bot]
21d0990be4 chore(deps): bump the version-all group with 7 updates (#8522)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-15 20:17:51 +00:00
tofarr
6227073cff Add missing Ukrainian translations for secrets-related keys (#8526)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-15 19:25:06 +00:00
Graham Neubig
4c38113cb7 Fix CI to check for missing translations (#8486)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-15 13:31:44 -04:00
Emmanuel Ferdman
fb516dfa0f Remove obsolete task.py file (#8517)
Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
2025-05-15 18:54:25 +02:00
309 changed files with 12966 additions and 5453 deletions

View File

@@ -13,6 +13,10 @@ updates:
browsergym:
patterns:
- "browsergym*"
mcp-packages:
patterns:
- "mcp"
- "mcpm"
security-all:
applies-to: "security-updates"
patterns:

View File

@@ -30,11 +30,12 @@ jobs:
run: |
cd frontend
npm install --frozen-lockfile
- name: Lint and TypeScript compilation
- name: Lint, TypeScript compilation, and translation checks
run: |
cd frontend
npm run lint
npm run make-i18n && tsc
npm run check-translation-completeness
# Run lint on the python code
lint-python:

View File

@@ -47,8 +47,10 @@ jobs:
run: poetry install --without evaluation
- name: Build Environment
run: make build
- name: Run Tests
- name: Run Unit Tests
run: poetry run pytest --forked -n auto -svv ./tests/unit
- name: Run Runtime Tests with CLIRuntime
run: TEST_RUNTIME=cli poetry run pytest -svv tests/runtime/test_bash.py
# Run specific Windows python tests
test-on-windows:
@@ -72,5 +74,5 @@ jobs:
run: poetry install --without evaluation
- name: Run Windows unit tests
run: poetry run pytest -svv tests/unit/test_windows_bash.py
- name: Run Windows runtime tests
- name: Run Windows runtime tests with LocalRuntime
run: $env:TEST_RUNTIME="local"; poetry run pytest -svv tests/runtime/test_bash.py

View File

@@ -0,0 +1,33 @@
---
name: documentation
type: knowledge
version: 1.0.0
agent: CodeActAgent
triggers:
- documentation
- docs
- document
---
# Documentation Guidelines
All documentation must be grounded in fact, so you must not make anything up without proper evidence. When you have finished writing documentation, convey to the user what reference source, including web pages, source code, or other sources of documentation you referenced when writing each new fact in the documentation. If you cannot reference a source for anything do not include it in the pull request.
## Best Practices for Documentation
1. **Be Factual**: Only include information that can be verified from reliable sources.
2. **Cite Sources**: Always reference the source of information (code, web pages, official documentation).
3. **Be Clear and Concise**: Use simple language and avoid unnecessary jargon.
4. **Use Examples**: Include practical examples to illustrate concepts.
5. **Structure Properly**: Use headings, lists, and code blocks to organize information.
6. **Keep Updated**: Ensure documentation reflects the current state of the code or system.
## Documentation Process
1. Research and gather information from reliable sources
2. Draft documentation based on verified facts
3. Review for accuracy and completeness
4. Include references for all factual statements
5. Submit only when all information is properly sourced
Remember: If you cannot verify a piece of information, it's better to exclude it than to include potentially incorrect information.

View File

@@ -66,3 +66,18 @@ These details may or may not be useful for your current task.
- Actions with `thought` property are displayed in the UI based on their action type:
- Regular actions (like "run", "edit") display the thought as a separate message
- Special actions (like "think") are displayed as collapsible elements only
#### Adding User Settings:
- To add a new user setting to OpenHands, follow these steps:
1. Add the setting to the frontend:
- Add the setting to the `Settings` type in `frontend/src/types/settings.ts`
- Add the setting to the `ApiSettings` type in the same file
- Add the setting with an appropriate default value to `DEFAULT_SETTINGS` in `frontend/src/services/settings.ts`
- Update the `useSettings` hook in `frontend/src/hooks/query/use-settings.ts` to map the API response
- Update the `useSaveSettings` hook in `frontend/src/hooks/mutation/use-save-settings.ts` to include the setting in API requests
- Add UI components (like toggle switches) in the appropriate settings screen (e.g., `frontend/src/routes/app-settings.tsx`)
- Add i18n translations for the setting name and any tooltips in `frontend/src/i18n/translation.json`
- Add the translation key to `frontend/src/i18n/declaration.ts`
2. Add the setting to the backend:
- Add the setting to the `Settings` model in `openhands/storage/data_models/settings.py`
- Update any relevant backend code to apply the setting (e.g., in session creation)

View File

@@ -123,7 +123,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.38-nikolaik`
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.39-nikolaik`
## Develop inside Docker container

View File

@@ -5,6 +5,7 @@ SHELL=/usr/bin/env bash
BACKEND_HOST ?= "127.0.0.1"
BACKEND_PORT = 3000
BACKEND_HOST_PORT = "$(BACKEND_HOST):$(BACKEND_PORT)"
FRONTEND_HOST ?= "127.0.0.1"
FRONTEND_PORT = 3001
DEFAULT_WORKSPACE_DIR = "./workspace"
DEFAULT_MODEL = "gpt-4o"
@@ -154,20 +155,21 @@ install-python-dependencies:
fi
@if [ "${INSTALL_PLAYWRIGHT}" != "false" ] && [ "${INSTALL_PLAYWRIGHT}" != "0" ]; then \
if [ -f "/etc/manjaro-release" ]; then \
echo "$(BLUE)Detected Manjaro Linux. Installing Patchright dependencies...$(RESET)"; \
poetry run patchright install chromium; \
echo "$(BLUE)Detected Manjaro Linux. Installing Playwright dependencies...$(RESET)"; \
poetry run pip install playwright; \
poetry run playwright install chromium; \
else \
if [ ! -f cache/patchright_chromium_is_installed.txt ]; then \
echo "Installing patchright chromium..."; \
poetry run patchright install chromium; \
if [ ! -f cache/playwright_chromium_is_installed.txt ]; then \
echo "Running playwright install --with-deps chromium..."; \
poetry run playwright install --with-deps chromium; \
mkdir -p cache; \
touch cache/patchright_chromium_is_installed.txt; \
touch cache/playwright_chromium_is_installed.txt; \
else \
echo "Setup already done. Skipping patchright installation."; \
echo "Setup already done. Skipping playwright installation."; \
fi \
fi \
else \
echo "Skipping Patchright installation (INSTALL_PLAYWRIGHT=${INSTALL_PLAYWRIGHT})."; \
echo "Skipping Playwright installation (INSTALL_PLAYWRIGHT=${INSTALL_PLAYWRIGHT})."; \
fi
@echo "$(GREEN)Python dependencies installed successfully.$(RESET)"
@@ -287,6 +289,15 @@ setup-config-prompts:
@read -p "Enter your LLM base URL [mostly used for local LLMs, leave blank if not needed - example: http://localhost:5001/v1/]: " llm_base_url; \
if [[ ! -z "$$llm_base_url" ]]; then echo "base_url=\"$$llm_base_url\"" >> $(CONFIG_FILE).tmp; fi
setup-config-basic:
@printf '%s\n' \
'[core]' \
'workspace_base="./workspace"' \
> config.toml
@echo "$(GREEN)config.toml created.$(RESET)"
openhands-cloud-run:
@$(MAKE) run BACKEND_HOST="0.0.0.0" BACKEND_PORT="12000" FRONTEND_HOST="0.0.0.0" FRONTEND_PORT="12001"
# Develop in container
docker-dev:
@@ -321,5 +332,4 @@ help:
@echo " $(GREEN)help$(RESET) - Display this help message, providing information on available targets."
# Phony targets
.PHONY: build check-dependencies check-python check-npm check-docker check-poetry install-python-dependencies install-frontend-dependencies install-pre-commit-hooks lint start-backend start-frontend run run-wsl setup-config setup-config-prompts help
.PHONY: docker-dev docker-run
.PHONY: build check-dependencies check-system check-python check-npm check-nodejs check-docker check-poetry install-python-dependencies install-frontend-dependencies install-pre-commit-hooks lint-backend lint-frontend lint test-frontend test build-frontend start-backend start-frontend _run_setup run run-wsl setup-config setup-config-prompts setup-config-basic openhands-cloud-run docker-dev docker-run clean help

View File

@@ -51,17 +51,17 @@ system requirements and more information.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.38
docker.all-hands.dev/all-hands-ai/openhands:0.39
```
You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)!
@@ -92,6 +92,7 @@ If you want to modify the OpenHands source code, check out [Development.md](http
Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting) can help.
## 📖 Documentation
<a href="https://deepwiki.com/All-Hands-AI/OpenHands"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki" title="Autogenerated Documentation by DeepWiki"></a>
To learn more about the project, and for tips on using OpenHands,
check out our [documentation](https://docs.all-hands.dev/modules/usage/getting-started).

View File

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

View File

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

View File

@@ -1,33 +0,0 @@
# Résolveur GitHub Cloud
Le Résolveur GitHub automatise les corrections de code et fournit une assistance intelligente pour vos dépôts.
## Configuration
Le Résolveur GitHub Cloud est disponible automatiquement lorsque vous
[accordez l'accès au dépôt OpenHands Cloud](./openhands-cloud#adding-repository-access).
## Utilisation
Après avoir accordé l'accès au dépôt OpenHands Cloud, vous pouvez utiliser le Résolveur GitHub Cloud sur les problèmes et les pull requests
du dépôt.
### Problèmes (Issues)
Sur votre dépôt, étiquetez un problème avec `openhands`. OpenHands va :
1. Commenter le problème pour vous informer qu'il y travaille.
- Vous pouvez cliquer sur le lien pour suivre la progression sur OpenHands Cloud.
2. Ouvrir une pull request s'il détermine que le problème a été résolu avec succès.
3. Commenter le problème avec un résumé des tâches effectuées et un lien vers la pull request.
### Pull Requests
Pour qu'OpenHands travaille sur des pull requests, utilisez `@openhands` dans les commentaires de premier niveau ou en ligne pour :
- Poser des questions
- Demander des mises à jour
- Obtenir des explications de code
OpenHands va :
1. Commenter la PR pour vous informer qu'il y travaille.
2. Effectuer la tâche.

View File

@@ -0,0 +1,32 @@
# Résolveur de Problèmes Cloud
Le Résolveur de Problèmes Cloud automatise les corrections de code et fournit une assistance intelligente pour vos dépôts sur GitHub et GitLab.
## Configuration
Le Résolveur de Problèmes Cloud est disponible automatiquement lorsque vous accordez l'accès au dépôt OpenHands Cloud :
- [Accès au dépôt GitHub](./github-installation#adding-repository-access)
- [Accès au dépôt GitLab](./gitlab-installation#adding-repository-access)
## Utilisation
Après avoir accordé l'accès au dépôt OpenHands Cloud, vous pouvez utiliser le Résolveur de Problèmes Cloud sur les problèmes et les pull/merge requests dans vos dépôts.
### Travailler avec les Problèmes
Sur votre dépôt, étiquetez un problème avec `openhands`. OpenHands va :
1. Commenter le problème pour vous faire savoir qu'il y travaille
- Vous pouvez cliquer sur le lien pour suivre la progression sur OpenHands Cloud
2. Ouvrir une pull request (GitHub) ou une merge request (GitLab) s'il détermine que le problème a été résolu avec succès
3. Commenter le problème avec un résumé des tâches effectuées et un lien vers la PR/MR
### Travailler avec les Pull/Merge Requests
Pour qu'OpenHands travaille sur les pull requests (GitHub) ou les merge requests (GitLab), mentionnez `@openhands` dans les commentaires pour :
- Poser des questions
- Demander des mises à jour
- Obtenir des explications de code
OpenHands va :
1. Commenter pour vous faire savoir qu'il y travaille
2. Effectuer la tâche demandée

View File

@@ -0,0 +1,29 @@
# Interface Cloud
L'interface Cloud fournit une interface web pour interagir avec OpenHands AI. Cette page explique comment accéder et utiliser l'interface Cloud d'OpenHands.
## Accès à l'Interface
L'interface Cloud d'OpenHands est accessible à [app.all-hands.dev](https://app.all-hands.dev). Vous devrez vous connecter avec votre compte GitHub ou GitLab pour accéder à l'interface.
<!-- Image will be added in a future update -->
<!-- ![Interface Cloud OpenHands](/img/docs/openhands-cloud-ui.png) -->
## Fonctionnalités Clés
Pour des informations détaillées sur les fonctionnalités disponibles dans l'interface Cloud d'OpenHands, veuillez consulter la section [Fonctionnalités Clés](../key-features.md) de la documentation.
## Paramètres
La page des paramètres vous permet de :
1. Configurer les préférences de votre compte
2. Gérer l'accès aux dépôts
3. Générer des clés API pour un accès programmatique
4. Personnaliser votre expérience OpenHands
## Prochaines Étapes
- [Utiliser le Résolveur de Problèmes Cloud](./cloud-issue-resolver.md) pour automatiser les corrections de code et obtenir de l'aide
- [En savoir plus sur l'API Cloud](./cloud-api.md) pour un accès programmatique
- [Retourner à la Mise en Route](./openhands-cloud.md)

View File

@@ -0,0 +1,55 @@
# Installation GitHub
Ce guide vous accompagne dans le processus d'installation et de configuration d'OpenHands Cloud pour vos dépôts GitHub.
## Prérequis
- Un compte GitHub
- Accès à OpenHands Cloud
## Étapes d'Installation
1. Connectez-vous à [OpenHands Cloud](https://app.all-hands.dev)
2. Si vous n'avez pas encore connecté votre compte GitHub :
- Cliquez sur `Se connecter à GitHub`
- Examinez et acceptez les conditions d'utilisation
- Autorisez l'application OpenHands AI
## Ajout d'Accès au Dépôt
Vous pouvez accorder à OpenHands l'accès à des dépôts spécifiques :
1. Cliquez sur le menu déroulant `Sélectionner un projet GitHub`, puis sélectionnez `Ajouter plus de dépôts...`
2. Sélectionnez votre organisation et choisissez les dépôts spécifiques auxquels vous souhaitez accorder l'accès à OpenHands.
- OpenHands demande des jetons à courte durée de vie (expiration de 8 heures) avec ces permissions :
- Actions : Lecture et écriture
- Administration : Lecture seule
- Statuts de commit : Lecture et écriture
- Contenus : Lecture et écriture
- Problèmes : Lecture et écriture
- Métadonnées : Lecture seule
- Pull requests : Lecture et écriture
- Webhooks : Lecture et écriture
- Workflows : Lecture et écriture
- L'accès au dépôt pour un utilisateur est accordé en fonction de :
- Permission accordée pour le dépôt
- Permissions GitHub de l'utilisateur (propriétaire/collaborateur)
3. Cliquez sur `Installer & Autoriser`
## Modification de l'Accès au Dépôt
Vous pouvez modifier l'accès au dépôt à tout moment :
* En utilisant le même workflow `Sélectionner un projet GitHub > Ajouter plus de dépôts`, ou
* En visitant la page Paramètres et en sélectionnant `Configurer les Dépôts GitHub` dans la section `Paramètres GitHub`.
## Utilisation d'OpenHands avec GitHub
Une fois que vous avez accordé l'accès au dépôt, vous pouvez utiliser OpenHands avec vos dépôts GitHub.
Pour plus de détails sur l'utilisation d'OpenHands avec les problèmes et les pull requests GitHub, consultez la documentation du [Résolveur de Problèmes Cloud](./cloud-issue-resolver.md).
## Prochaines Étapes
- [Accéder à l'Interface Cloud](./cloud-ui.md) pour interagir avec l'interface web
- [Utiliser le Résolveur de Problèmes Cloud](./cloud-issue-resolver.md) pour automatiser les corrections de code et obtenir de l'aide
- [Utiliser l'API Cloud](./cloud-api.md) pour interagir programmatiquement avec OpenHands

View File

@@ -0,0 +1,50 @@
# Installation GitLab
Ce guide vous accompagne dans le processus d'installation et de configuration d'OpenHands Cloud pour vos dépôts GitLab.
## Prérequis
- Un compte GitLab
- Accès à OpenHands Cloud
## Étapes d'Installation
1. Connectez-vous à [OpenHands Cloud](https://app.all-hands.dev)
2. Si vous n'avez pas encore connecté votre compte GitLab :
- Cliquez sur `Se connecter à GitLab`
- Examinez et acceptez les conditions d'utilisation
- Autorisez l'application OpenHands AI
## Ajout d'Accès au Dépôt
Vous pouvez accorder à OpenHands l'accès à des dépôts spécifiques :
1. Cliquez sur le menu déroulant `Sélectionner un projet GitLab`, puis sélectionnez `Ajouter plus de dépôts...`
2. Sélectionnez votre organisation et choisissez les dépôts spécifiques auxquels vous souhaitez accorder l'accès à OpenHands.
- OpenHands demande des permissions avec ces portées :
- api : Accès complet à l'API
- read_user : Lecture des informations utilisateur
- read_repository : Lecture des informations du dépôt
- write_repository : Écriture dans le dépôt
- L'accès au dépôt pour un utilisateur est accordé en fonction de :
- Permission accordée pour le dépôt
- Permissions GitLab de l'utilisateur (propriétaire/mainteneur/développeur)
3. Cliquez sur `Installer & Autoriser`
## Modification de l'Accès au Dépôt
Vous pouvez modifier l'accès au dépôt à tout moment :
* En utilisant le même workflow `Sélectionner un projet GitLab > Ajouter plus de dépôts`, ou
* En visitant la page Paramètres et en sélectionnant `Configurer les Dépôts GitLab` dans la section `Paramètres GitLab`.
## Utilisation d'OpenHands avec GitLab
Une fois que vous avez accordé l'accès au dépôt, vous pouvez utiliser OpenHands avec vos dépôts GitLab.
Pour plus de détails sur l'utilisation d'OpenHands avec les problèmes et les merge requests GitLab, consultez la documentation du [Résolveur de Problèmes Cloud](./cloud-issue-resolver.md).
## Prochaines Étapes
- [Accéder à l'Interface Cloud](./cloud-ui.md) pour interagir avec l'interface web
- [Utiliser le Résolveur de Problèmes Cloud](./cloud-issue-resolver.md) pour automatiser les corrections de code et obtenir de l'aide
- [Utiliser l'API Cloud](./cloud-api.md) pour interagir programmatiquement avec OpenHands

View File

@@ -0,0 +1,24 @@
# OpenHands Cloud
OpenHands Cloud est la version hébergée dans le cloud d'OpenHands par All Hands AI.
## Accès à OpenHands Cloud
Pour commencer avec OpenHands Cloud, visitez [app.all-hands.dev](https://app.all-hands.dev).
Vous serez invité à vous connecter avec votre compte GitHub ou GitLab :
1. Après avoir lu et accepté les conditions d'utilisation, cliquez sur `Se connecter à GitHub` ou `Se connecter à GitLab`.
2. Examinez les permissions demandées par OpenHands et autorisez l'application.
- OpenHands nécessitera certaines permissions de votre compte. Pour en savoir plus sur ces permissions,
vous pouvez cliquer sur le lien `En savoir plus` sur la page d'autorisation.
## Prochaines Étapes
Une fois que vous avez connecté votre compte, vous pouvez :
- [Installer l'Intégration GitHub](./github-installation.md) pour utiliser OpenHands avec vos dépôts GitHub
- [Installer l'Intégration GitLab](./gitlab-installation.md) pour utiliser OpenHands avec vos dépôts GitLab
- [Accéder à l'Interface Cloud](./cloud-ui.md) pour interagir avec l'interface web
- [Utiliser l'API Cloud](./cloud-api.md) pour interagir programmatiquement avec OpenHands
- [Configurer le Résolveur de Problèmes Cloud](./cloud-issue-resolver.md) pour automatiser les corrections de code et fournir une assistance intelligente

View File

@@ -1,65 +0,0 @@
# OpenHands Cloud
OpenHands Cloud est la version hébergée dans le cloud d'OpenHands par All Hands AI.
## Accéder à OpenHands Cloud
OpenHands Cloud est accessible à l'adresse https://app.all-hands.dev/.
Vous pouvez également interagir avec OpenHands Cloud par programmation en utilisant l'[API](./cloud-api).
## Premiers pas
Après avoir visité OpenHands Cloud, il vous sera demandé de vous connecter avec votre compte GitHub ou GitLab :
1. Après avoir lu et accepté les conditions d'utilisation, cliquez sur `Log in with GitHub` ou `Log in with GitLab`.
2. Examinez les autorisations demandées par OpenHands, puis cliquez sur `Authorize OpenHands AI`.
- OpenHands nécessitera certaines autorisations de votre compte GitHub ou GitLab. Pour en savoir plus sur ces autorisations :
- GitHub : Vous pouvez cliquer sur le lien `Learn more` sur la page d'autorisation GitHub.
- GitLab : Vous pouvez développer chaque demande d'autorisation sur la page d'autorisation GitLab.
## Accès aux dépôts
### GitHub
#### Ajouter l'accès aux dépôts
Vous pouvez accorder à OpenHands un accès à des dépôts spécifiques :
1. Cliquez sur `Add GitHub repos` sur la page d'accueil.
2. Sélectionnez l'organisation, puis choisissez les dépôts spécifiques auxquels vous souhaitez donner accès à OpenHands.
<details>
<summary>Détails des autorisations pour l'accès aux dépôts</summary>
Openhands demande des jetons à courte durée de vie (expiration de 8 heures) avec ces autorisations :
- Actions : Lecture et écriture
- Administration : Lecture seule
- Statuts de commit : Lecture et écriture
- Contenus : Lecture et écriture
- Issues : Lecture et écriture
- Métadonnées : Lecture seule
- Pull requests : Lecture et écriture
- Webhooks : Lecture et écriture
- Workflows : Lecture et écriture
L'accès au dépôt pour un utilisateur est accordé en fonction de :
- L'autorisation accordée pour le dépôt.
- Les autorisations GitHub de l'utilisateur (propriétaire/collaborateur).
</details>
3. Cliquez sur `Install & Authorize`.
#### Modifier l'accès aux dépôts
Vous pouvez modifier l'accès aux dépôts GitHub à tout moment en :
* Utilisant le même processus `Add GitHub repos`, ou
* Visitant la page Paramètres et en sélectionnant `Configure GitHub Repositories` dans la section `Git Settings`.
### GitLab
Lorsque vous utilisez votre compte GitLab, OpenHands aura automatiquement accès à vos dépôts.
## Persistance des conversations
- Liste des conversations Affiche uniquement les 10 conversations les plus récentes initiées au cours des 10 derniers jours.
- Espaces de travail Les espaces de travail de conversation sont conservés pendant 14 jours.
- Environnements d'exécution Les environnements d'exécution restent actifs ("chauds") pendant 30 minutes. Après cette période, la reprise d'une conversation peut prendre 1 à 2 minutes.

View File

@@ -37,7 +37,7 @@ Pour exécuter OpenHands en mode CLI avec Docker :
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -46,7 +46,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.cli
```

View File

@@ -34,7 +34,7 @@ Pour exécuter OpenHands en mode Headless avec Docker :
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -44,7 +44,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.main -t "write a bash script that prints hi"
```

View File

@@ -58,17 +58,17 @@ Un système avec un processeur moderne et un minimum de **4 Go de RAM** est reco
La façon la plus simple d'exécuter OpenHands est dans Docker.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.38
docker.all-hands.dev/all-hands-ai/openhands:0.39
```
Vous trouverez OpenHands en cours d'exécution à l'adresse http://localhost:3000 !

View File

@@ -1,8 +1,8 @@
# Aperçu des fonctionnalités d'OpenHands
# Aperçu des Fonctionnalités d'OpenHands
![aperçu](/img/oh-features.png)
### Panneau de discussion
### Panneau de Discussion
- Affiche la conversation entre l'utilisateur et OpenHands.
- OpenHands explique ses actions dans ce panneau.
@@ -10,8 +10,8 @@
- Montre les modifications de fichiers effectuées par OpenHands.
### VS Code
- VS Code intégré pour parcourir et modifier des fichiers.
- Peut également être utilisé pour télécharger et importer des fichiers.
- VS Code intégré pour parcourir et modifier les fichiers.
- Peut également être utilisé pour télécharger et envoyer des fichiers.
### Terminal
- Un espace permettant à OpenHands et aux utilisateurs d'exécuter des commandes terminal.
@@ -25,5 +25,5 @@
- Les utilisateurs peuvent interagir avec l'application en cours d'exécution.
### Navigateur
- Utilisé par OpenHands pour naviguer sur des sites web.
- Utilisé par OpenHands pour naviguer sur les sites web.
- Le navigateur n'est pas interactif.

View File

@@ -1,31 +0,0 @@
# Cloud GitHub Resolver
GitHub Resolverはコードの修正を自動化し、リポジトリに対してインテリジェントな支援を提供します。
## セットアップ
Cloud GitHub Resolverは、[OpenHands Cloudにリポジトリアクセス権を付与する](./openhands-cloud#adding-repository-access)と自動的に利用可能になります。
## 使用方法
OpenHands Cloudにリポジトリアクセス権を付与した後、リポジトリの課題IssueとプルリクエストでCloud GitHub Resolverを使用できます。
### 課題Issues
リポジトリで課題に`openhands`ラベルを付けると、OpenHandsは以下の操作を行います
1. 課題にコメントして、作業中であることを通知します。
- OpenHands Cloudで進捗状況を追跡するためのリンクをクリックできます。
2. 課題が正常に解決されたと判断した場合、プルリクエストを開きます。
3. 実行されたタスクの概要とプルリクエストへのリンクを含むコメントを課題に投稿します。
### プルリクエスト
プルリクエストでOpenHandsを利用するには、トップレベルまたはインラインコメントで`@openhands`を使用して:
- 質問する
- 更新をリクエストする
- コードの説明を取得する
OpenHandsは以下の操作を行います
1. PRにコメントして、作業中であることを通知します。
2. タスクを実行します。

View File

@@ -0,0 +1,32 @@
# クラウド課題リゾルバー
クラウド課題リゾルバーは、GitHubとGitLabのリポジトリに対してコード修正を自動化し、インテリジェントな支援を提供します。
## セットアップ
クラウド課題リゾルバーは、OpenHands Cloudリポジトリアクセスを許可すると自動的に利用可能になります
- [GitHubリポジトリアクセス](./github-installation#adding-repository-access)
- [GitLabリポジトリアクセス](./gitlab-installation#adding-repository-access)
## 使用方法
OpenHands Cloudリポジトリアクセスを許可した後、リポジトリの課題やプルリクエスト/マージリクエストでクラウド課題リゾルバーを使用できます。
### 課題の操作
リポジトリで、課題に`openhands`というラベルを付けます。OpenHandsは以下を行います
1. 課題にコメントして、作業中であることを知らせます
- リンクをクリックすると、OpenHands Cloudで進捗状況を追跡できます
2. 課題が正常に解決されたと判断した場合、プルリクエストGitHubまたはマージリクエストGitLabを開きます
3. 実行されたタスクの概要とPR/MRへのリンクを含むコメントを課題に残します
### プルリクエスト/マージリクエストの操作
プルリクエストGitHubまたはマージリクエストGitLabでOpenHandsを動作させるには、コメントで`@openhands`を言及して以下を行います:
- 質問する
- 更新をリクエストする
- コードの説明を取得する
OpenHandsは以下を行います
1. 作業中であることを知らせるコメントをします
2. リクエストされたタスクを実行します

View File

@@ -0,0 +1,29 @@
# クラウドUI
クラウドUIは、OpenHands AIと対話するためのウェブインターフェースを提供します。このページでは、OpenHands クラウドUIへのアクセス方法と使用方法について説明します。
## UIへのアクセス
OpenHands クラウドUIは[app.all-hands.dev](https://app.all-hands.dev)でアクセスできます。インターフェースにアクセスするには、GitHubまたはGitLabアカウントでサインインする必要があります。
<!-- 画像は将来のアップデートで追加されます -->
<!-- ![OpenHands クラウドUI](/img/docs/openhands-cloud-ui.png) -->
## 主な機能
OpenHands クラウドUIで利用可能な機能の詳細については、ドキュメントの[主な機能](../key-features.md)セクションを参照してください。
## 設定
設定ページでは以下のことができます:
1. アカウント設定の構成
2. リポジトリアクセスの管理
3. プログラムによるアクセスのためのAPIキーの生成
4. OpenHandsエクスペリエンスのカスタマイズ
## 次のステップ
- [クラウド課題リゾルバーを使用する](./cloud-issue-resolver.md)でコード修正を自動化し、支援を受ける
- [クラウドAPIについて学ぶ](./cloud-api.md)でプログラムによるアクセスを行う
- [はじめにに戻る](./openhands-cloud.md)

View File

@@ -0,0 +1,55 @@
# GitHub インストール
このガイドでは、GitHubリポジトリ用にOpenHands Cloudをインストールおよび設定するプロセスについて説明します。
## 前提条件
- GitHubアカウント
- OpenHands Cloudへのアクセス
## インストール手順
1. [OpenHands Cloud](https://app.all-hands.dev)にログインします
2. まだGitHubアカウントを接続していない場合
- `GitHubに接続する`をクリックします
- 利用規約を確認して同意します
- OpenHands AIアプリケーションを承認します
## リポジトリアクセスの追加
特定のリポジトリへのアクセスをOpenHandsに許可できます
1. `GitHubプロジェクトを選択`ドロップダウンをクリックし、`リポジトリを追加...`を選択します
2. 組織を選択し、OpenHandsにアクセスを許可する特定のリポジトリを選択します。
- OpenHandsは以下の権限を持つ短期間のトークン8時間の有効期限をリクエストします
- アクション:読み取りと書き込み
- 管理:読み取り専用
- コミットステータス:読み取りと書き込み
- コンテンツ:読み取りと書き込み
- 課題:読み取りと書き込み
- メタデータ:読み取り専用
- プルリクエスト:読み取りと書き込み
- Webhook読み取りと書き込み
- ワークフロー:読み取りと書き込み
- ユーザーのリポジトリアクセスは以下に基づいて付与されます:
- リポジトリに付与された権限
- ユーザーのGitHub権限所有者/コラボレーター)
3. `インストール&承認`をクリックします
## リポジトリアクセスの変更
リポジトリアクセスはいつでも変更できます:
* 同じ`GitHubプロジェクトを選択 > リポジトリを追加`ワークフローを使用する、または
* 設定ページにアクセスし、`GitHub設定`セクションで`GitHubリポジトリを設定する`を選択します。
## GitHubでのOpenHandsの使用
リポジトリアクセスを許可すると、GitHubリポジトリでOpenHandsを使用できます。
GitHub課題とプルリクエストでOpenHandsを使用する方法の詳細については、[クラウド課題リゾルバー](./cloud-issue-resolver.md)のドキュメントを参照してください。
## 次のステップ
- [クラウドUIにアクセスする](./cloud-ui.md)でウェブインターフェースと対話する
- [クラウド課題リゾルバーを使用する](./cloud-issue-resolver.md)でコード修正を自動化し、支援を受ける
- [クラウドAPIを使用する](./cloud-api.md)でプログラムによりOpenHandsと対話する

View File

@@ -0,0 +1,50 @@
# GitLab インストール
このガイドでは、GitLabリポジトリ用にOpenHands Cloudをインストールおよび設定するプロセスについて説明します。
## 前提条件
- GitLabアカウント
- OpenHands Cloudへのアクセス
## インストール手順
1. [OpenHands Cloud](https://app.all-hands.dev)にログインします
2. まだGitLabアカウントを接続していない場合
- `GitLabに接続する`をクリックします
- 利用規約を確認して同意します
- OpenHands AIアプリケーションを承認します
## リポジトリアクセスの追加
特定のリポジトリへのアクセスをOpenHandsに許可できます
1. `GitLabプロジェクトを選択`ドロップダウンをクリックし、`リポジトリを追加...`を選択します
2. 組織を選択し、OpenHandsにアクセスを許可する特定のリポジトリを選択します。
- OpenHandsは以下のスコープで権限をリクエストします
- api完全なAPIアクセス
- read_userユーザー情報の読み取り
- read_repositoryリポジトリ情報の読み取り
- write_repositoryリポジトリへの書き込み
- ユーザーのリポジトリアクセスは以下に基づいて付与されます:
- リポジトリに付与された権限
- ユーザーのGitLab権限所有者/メンテナー/開発者)
3. `インストール&承認`をクリックします
## リポジトリアクセスの変更
リポジトリアクセスはいつでも変更できます:
* 同じ`GitLabプロジェクトを選択 > リポジトリを追加`ワークフローを使用する、または
* 設定ページにアクセスし、`GitLab設定`セクションで`GitLabリポジトリを設定する`を選択します。
## GitLabでのOpenHandsの使用
リポジトリアクセスを許可すると、GitLabリポジトリでOpenHandsを使用できます。
GitLab課題とマージリクエストでOpenHandsを使用する方法の詳細については、[クラウド課題リゾルバー](./cloud-issue-resolver.md)のドキュメントを参照してください。
## 次のステップ
- [クラウドUIにアクセスする](./cloud-ui.md)でウェブインターフェースと対話する
- [クラウド課題リゾルバーを使用する](./cloud-issue-resolver.md)でコード修正を自動化し、支援を受ける
- [クラウドAPIを使用する](./cloud-api.md)でプログラムによりOpenHandsと対話する

View File

@@ -0,0 +1,24 @@
# OpenHands クラウド
OpenHands クラウドは、All Hands AIのOpenHandsのホスト型クラウドバージョンです。
## OpenHands クラウドへのアクセス
OpenHands クラウドを始めるには、[app.all-hands.dev](https://app.all-hands.dev)にアクセスしてください。
GitHubまたはGitLabアカウントで接続するよう求められます
1. 利用規約を読んで同意した後、`GitHubに接続する`または`GitLabに接続する`をクリックします。
2. OpenHandsがリクエストする権限を確認し、アプリケーションを承認します。
- OpenHandsはあなたのアカウントから特定の権限を必要とします。これらの権限について詳しく知るには、
承認ページの`詳細を見る`リンクをクリックしてください。
## 次のステップ
アカウントを接続したら、以下のことができます:
- [GitHub統合をインストールする](./github-installation.md)でGitHubリポジトリでOpenHandsを使用する
- [GitLab統合をインストールする](./gitlab-installation.md)でGitLabリポジトリでOpenHandsを使用する
- [クラウドUIにアクセスする](./cloud-ui.md)でウェブインターフェースと対話する
- [クラウドAPIを使用する](./cloud-api.md)でプログラムによりOpenHandsと対話する
- [クラウド課題リゾルバーを設定する](./cloud-issue-resolver.md)でコード修正を自動化し、インテリジェントな支援を提供する

View File

@@ -1,65 +0,0 @@
# OpenHands Cloud
OpenHands CloudはAll Hands AIによるOpenHandsのクラウドホスト版です。
## OpenHands Cloudへのアクセス
OpenHands Cloudは https://app.all-hands.dev/ でアクセスできます。
[API](./cloud-api)を使用してプログラム的にOpenHands Cloudと対話することもできます。
## はじめに
OpenHands Cloudにアクセスすると、GitHubまたはGitLabアカウントとの接続を求められます
1. 利用規約を読んで同意した後、`Log in with GitHub`または`Log in with GitLab`をクリックします。
2. OpenHandsが要求する権限を確認し、`Authorize OpenHands AI`をクリックします。
- OpenHandsはGitHubまたはGitLabアカウントからいくつかの権限を必要とします。これらの権限について詳しく知るには
- GitHubGitHub認証ページの`Learn more`リンクをクリックできます。
- GitLabGitLab認証ページで各権限リクエストを展開できます。
## リポジトリアクセス
### GitHub
#### リポジトリアクセスの追加
OpenHandsに特定のリポジトリへのアクセス権を付与できます
1. ホームページで`Add GitHub repos`をクリックします。
2. 組織を選択し、OpenHandsにアクセス権を付与する特定のリポジトリを選択します。
<details>
<summary>リポジトリアクセスの権限詳細</summary>
Openhandsは短期間のトークン8時間で期限切れを以下の権限で要求します
- Actions読み取りと書き込み
- Administration読み取り専用
- Commit statuses読み取りと書き込み
- Contents読み取りと書き込み
- Issues読み取りと書き込み
- Metadata読み取り専用
- Pull requests読み取りと書き込み
- Webhooks読み取りと書き込み
- Workflows読み取りと書き込み
ユーザーのリポジトリアクセスは以下に基づいて付与されます:
- リポジトリに対して付与された権限
- ユーザーのGitHub権限オーナー/コラボレーター)
</details>
3. `Install & Authorize`をクリックします。
#### リポジトリアクセスの変更
GitHubリポジトリアクセスはいつでも以下の方法で変更できます
* 同じ`Add GitHub repos`ワークフローを使用する、または
* 設定ページにアクセスし、`Git Settings`セクションの下にある`Configure GitHub Repositories`を選択する。
### GitLab
GitLabアカウントを使用する場合、OpenHandsは自動的にあなたのリポジトリにアクセスできるようになります。
## 会話の保持
- 会話リスト 過去10日間に開始された最新10件の会話のみが表示されます。
- ワークスペース 会話ワークスペースは14日間保持されます。
- ランタイム ランタイムは30分間アクティブ「ウォーム」な状態を維持します。この期間後、会話を再開するには1〜2分かかる場合があります。

View File

@@ -36,7 +36,7 @@ DockerでOpenHandsをCLIモードで実行するには
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -45,7 +45,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.cli
```

View File

@@ -33,7 +33,7 @@ DockerでヘッドレスモードでOpenHandsを実行するには
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -43,7 +43,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.main -t "write a bash script that prints hi"
```

View File

@@ -58,17 +58,17 @@ OpenHandsを実行するには、最新のプロセッサと最低**4GB RAM**を
OpenHandsを実行する最も簡単な方法はDockerを使用することです。
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.38
docker.all-hands.dev/all-hands-ai/openhands:0.39
```
OpenHandsは http://localhost:3000 で実行されています!

View File

@@ -3,11 +3,11 @@
![概要](/img/oh-features.png)
### チャットパネル
- ユーザーとOpenHandsの会話を表示します。
- ユーザーとOpenHandsの会話を表示します。
- OpenHandsはこのパネルで自身の行動を説明します。
### 変更
- OpenHandsによって実行されたファイル変更を表示します。
### 変更
- OpenHandsによって実行されたファイル変更を表示します。
### VS Code
- ファイルの閲覧や修正のための組み込みVS Code。
@@ -18,7 +18,7 @@
### Jupyter
- OpenHandsによって実行されたすべてのPythonコマンドを表示します。
- OpenHandsを使用してデータ可視化タスクを実行する際に特に便利です。
- データ可視化タスクにOpenHandsを使用する際に特に便利です。
### アプリ
- OpenHandsがアプリケーションを実行する際にウェブサーバーを表示します。
@@ -26,4 +26,4 @@
### ブラウザ
- OpenHandsがウェブサイトを閲覧するために使用します。
- このブラウザは非対話です。
- ブラウザは非対話です。

View File

@@ -1,33 +0,0 @@
# Resolvedor GitHub na Nuvem
O Resolvedor GitHub automatiza correções de código e fornece assistência inteligente para seus repositórios.
## Configuração
O Resolvedor GitHub na Nuvem está disponível automaticamente quando você
[concede acesso de repositório ao OpenHands Cloud](./openhands-cloud#adding-repository-access).
## Uso
Após conceder acesso de repositório ao OpenHands Cloud, você pode usar o Resolvedor GitHub na Nuvem nos problemas e pull requests
do repositório.
### Problemas (Issues)
No seu repositório, rotule um problema com `openhands`. O OpenHands irá:
1. Comentar no problema para informar que está trabalhando nele.
- Você pode clicar no link para acompanhar o progresso no OpenHands Cloud.
2. Abrir um pull request se determinar que o problema foi resolvido com sucesso.
3. Comentar no problema com um resumo das tarefas realizadas e um link para o pull request.
### Pull Requests
Para fazer o OpenHands trabalhar em pull requests, use `@openhands` em comentários de nível superior ou em linha para:
- Fazer perguntas
- Solicitar atualizações
- Obter explicações de código
O OpenHands irá:
1. Comentar no PR para informar que está trabalhando nele.
2. Realizar a tarefa.

View File

@@ -0,0 +1,32 @@
# Resolvedor de Problemas na Nuvem
O Resolvedor de Problemas na Nuvem automatiza correções de código e fornece assistência inteligente para seus repositórios no GitHub e GitLab.
## Configuração
O Resolvedor de Problemas na Nuvem está disponível automaticamente quando você concede acesso ao repositório OpenHands Cloud:
- [Acesso ao repositório GitHub](./github-installation#adding-repository-access)
- [Acesso ao repositório GitLab](./gitlab-installation#adding-repository-access)
## Uso
Após conceder acesso ao repositório OpenHands Cloud, você pode usar o Resolvedor de Problemas na Nuvem em issues e pull/merge requests em seus repositórios.
### Trabalhando com Issues
No seu repositório, rotule uma issue com `openhands`. O OpenHands irá:
1. Comentar na issue para informar que está trabalhando nela
- Você pode clicar no link para acompanhar o progresso no OpenHands Cloud
2. Abrir um pull request (GitHub) ou merge request (GitLab) se determinar que o problema foi resolvido com sucesso
3. Comentar na issue com um resumo das tarefas realizadas e um link para o PR/MR
### Trabalhando com Pull/Merge Requests
Para fazer o OpenHands trabalhar em pull requests (GitHub) ou merge requests (GitLab), mencione `@openhands` nos comentários para:
- Fazer perguntas
- Solicitar atualizações
- Obter explicações de código
O OpenHands irá:
1. Comentar para informar que está trabalhando nisso
2. Realizar a tarefa solicitada

View File

@@ -0,0 +1,29 @@
# Interface da Nuvem
A Interface da Nuvem fornece uma interface web para interagir com o OpenHands AI. Esta página explica como acessar e usar a Interface da Nuvem do OpenHands.
## Acessando a Interface
A Interface da Nuvem do OpenHands pode ser acessada em [app.all-hands.dev](https://app.all-hands.dev). Você precisará fazer login com sua conta do GitHub ou GitLab para acessar a interface.
<!-- A imagem será adicionada em uma atualização futura -->
<!-- ![Interface da Nuvem do OpenHands](/img/docs/openhands-cloud-ui.png) -->
## Recursos Principais
Para informações detalhadas sobre os recursos disponíveis na Interface da Nuvem do OpenHands, consulte a seção [Recursos Principais](../key-features.md) da documentação.
## Configurações
A página de configurações permite que você:
1. Configure as preferências da sua conta
2. Gerencie o acesso ao repositório
3. Gere chaves de API para acesso programático
4. Personalize sua experiência com o OpenHands
## Próximos Passos
- [Use o Resolvedor de Problemas na Nuvem](./cloud-issue-resolver.md) para automatizar correções de código e obter assistência
- [Aprenda sobre a API da Nuvem](./cloud-api.md) para acesso programático
- [Voltar para Introdução](./openhands-cloud.md)

View File

@@ -0,0 +1,55 @@
# Instalação do GitHub
Este guia orienta você pelo processo de instalação e configuração do OpenHands Cloud para seus repositórios GitHub.
## Pré-requisitos
- Uma conta GitHub
- Acesso ao OpenHands Cloud
## Passos de Instalação
1. Faça login no [OpenHands Cloud](https://app.all-hands.dev)
2. Se você ainda não conectou sua conta GitHub:
- Clique em `Conectar ao GitHub`
- Revise e aceite os termos de serviço
- Autorize a aplicação OpenHands AI
## Adicionando Acesso ao Repositório
Você pode conceder ao OpenHands acesso a repositórios específicos:
1. Clique no menu suspenso `Selecionar um projeto GitHub`, depois selecione `Adicionar mais repositórios...`
2. Selecione sua organização e escolha os repositórios específicos para conceder acesso ao OpenHands.
- OpenHands solicita tokens de curta duração (expiração de 8 horas) com estas permissões:
- Ações: Leitura e escrita
- Administração: Somente leitura
- Status de commit: Leitura e escrita
- Conteúdos: Leitura e escrita
- Issues: Leitura e escrita
- Metadados: Somente leitura
- Pull requests: Leitura e escrita
- Webhooks: Leitura e escrita
- Workflows: Leitura e escrita
- O acesso ao repositório para um usuário é concedido com base em:
- Permissão concedida para o repositório
- Permissões do GitHub do usuário (proprietário/colaborador)
3. Clique em `Instalar e Autorizar`
## Modificando o Acesso ao Repositório
Você pode modificar o acesso ao repositório a qualquer momento:
* Usando o mesmo fluxo de trabalho `Selecionar um projeto GitHub > Adicionar mais repositórios`, ou
* Visitando a página de Configurações e selecionando `Configurar Repositórios GitHub` na seção `Configurações do GitHub`.
## Usando OpenHands com GitHub
Depois de conceder acesso ao repositório, você pode usar o OpenHands com seus repositórios GitHub.
Para detalhes sobre como usar o OpenHands com issues e pull requests do GitHub, consulte a documentação do [Resolvedor de Problemas na Nuvem](./cloud-issue-resolver.md).
## Próximos Passos
- [Acesse a Interface da Nuvem](./cloud-ui.md) para interagir com a interface web
- [Use o Resolvedor de Problemas na Nuvem](./cloud-issue-resolver.md) para automatizar correções de código e obter assistência
- [Use a API da Nuvem](./cloud-api.md) para interagir programaticamente com o OpenHands

View File

@@ -0,0 +1,50 @@
# Instalação do GitLab
Este guia orienta você pelo processo de instalação e configuração do OpenHands Cloud para seus repositórios GitLab.
## Pré-requisitos
- Uma conta GitLab
- Acesso ao OpenHands Cloud
## Passos de Instalação
1. Faça login no [OpenHands Cloud](https://app.all-hands.dev)
2. Se você ainda não conectou sua conta GitLab:
- Clique em `Conectar ao GitLab`
- Revise e aceite os termos de serviço
- Autorize a aplicação OpenHands AI
## Adicionando Acesso ao Repositório
Você pode conceder ao OpenHands acesso a repositórios específicos:
1. Clique no menu suspenso `Selecionar um projeto GitLab`, depois selecione `Adicionar mais repositórios...`
2. Selecione sua organização e escolha os repositórios específicos para conceder acesso ao OpenHands.
- OpenHands solicita permissões com estes escopos:
- api: Acesso completo à API
- read_user: Ler informações do usuário
- read_repository: Ler informações do repositório
- write_repository: Escrever no repositório
- O acesso ao repositório para um usuário é concedido com base em:
- Permissão concedida para o repositório
- Permissões do GitLab do usuário (proprietário/mantenedor/desenvolvedor)
3. Clique em `Instalar e Autorizar`
## Modificando o Acesso ao Repositório
Você pode modificar o acesso ao repositório a qualquer momento:
* Usando o mesmo fluxo de trabalho `Selecionar um projeto GitLab > Adicionar mais repositórios`, ou
* Visitando a página de Configurações e selecionando `Configurar Repositórios GitLab` na seção `Configurações do GitLab`.
## Usando OpenHands com GitLab
Depois de conceder acesso ao repositório, você pode usar o OpenHands com seus repositórios GitLab.
Para detalhes sobre como usar o OpenHands com issues e merge requests do GitLab, consulte a documentação do [Resolvedor de Problemas na Nuvem](./cloud-issue-resolver.md).
## Próximos Passos
- [Acesse a Interface da Nuvem](./cloud-ui.md) para interagir com a interface web
- [Use o Resolvedor de Problemas na Nuvem](./cloud-issue-resolver.md) para automatizar correções de código e obter assistência
- [Use a API da Nuvem](./cloud-api.md) para interagir programaticamente com o OpenHands

View File

@@ -1,45 +1,24 @@
# Openhands Cloud
# OpenHands Cloud
O OpenHands Cloud é a versão hospedada na nuvem do OpenHands da All Hands AI.
OpenHands Cloud é a versão hospedada na nuvem do OpenHands da All Hands AI.
## Acessando o OpenHands Cloud
Atualmente, os usuários estão sendo admitidos para acessar o OpenHands Cloud em ondas. Para se inscrever,
[entre na lista de espera](https://www.all-hands.dev/join-waitlist). Assim que for aprovado, você receberá um e-mail com
instruções sobre como acessá-lo.
Para começar com o OpenHands Cloud, visite [app.all-hands.dev](https://app.all-hands.dev).
## Primeiros Passos
Você será solicitado a se conectar com sua conta GitHub ou GitLab:
Após visitar o OpenHands Cloud, você será solicitado a se conectar com sua conta do GitHub:
1. Após ler e aceitar os termos de serviço, clique em `Connect to GitHub`.
2. Revise as permissões solicitadas pelo OpenHands e clique em `Authorize OpenHands AI`.
- O OpenHands exigirá algumas permissões da sua conta do GitHub. Para ler mais sobre essas permissões,
você pode clicar no link `Learn more` na página de autorização do GitHub.
1. Após ler e aceitar os termos de serviço, clique em `Conectar ao GitHub` ou `Conectar ao GitLab`.
2. Revise as permissões solicitadas pelo OpenHands e autorize a aplicação.
- OpenHands exigirá certas permissões da sua conta. Para ler mais sobre essas permissões,
você pode clicar no link `Saiba mais` na página de autorização.
## Acesso ao Repositório
## Próximos Passos
### Adicionando Acesso ao Repositório
Depois de conectar sua conta, você pode:
Você pode conceder ao OpenHands acesso específico ao repositório:
1. Clique no menu suspenso `Select a GitHub project`, selecione `Add more repositories...`.
2. Selecione a organização e escolha os repositórios específicos para conceder acesso ao OpenHands.
- O Openhands solicita tokens de curta duração (expiração de 8 horas) com estas permissões:
- Actions: Read and write
- Administration: Read-only
- Commit statuses: Read and write
- Contents: Read and write
- Issues: Read and write
- Metadata: Read-only
- Pull requests: Read and write
- Webhooks: Read and write
- Workflows: Read and write
- O acesso ao repositório para um usuário é concedido com base em:
- Permissão concedida para o repositório.
- Permissões do GitHub do usuário (proprietário/colaborador).
3. Clique em `Install & Authorize`.
### Modificando o Acesso ao Repositório
Você pode modificar o acesso ao repositório a qualquer momento:
* Usando o mesmo fluxo de trabalho `Select a GitHub project > Add more repositories`, ou
* Visitando a página de Configurações e selecionando `Configure GitHub Repositories` na seção `GitHub Settings`.
- [Instalar a Integração com GitHub](./github-installation.md) para usar o OpenHands com seus repositórios GitHub
- [Instalar a Integração com GitLab](./gitlab-installation.md) para usar o OpenHands com seus repositórios GitLab
- [Acessar a Interface da Nuvem](./cloud-ui.md) para interagir com a interface web
- [Usar a API da Nuvem](./cloud-api.md) para interagir programaticamente com o OpenHands
- [Configurar o Resolvedor de Problemas na Nuvem](./cloud-issue-resolver.md) para automatizar correções de código e fornecer assistência inteligente

View File

@@ -1,65 +0,0 @@
# Openhands Cloud
OpenHands Cloud é a versão hospedada na nuvem do OpenHands pela All Hands AI.
## Acessando o OpenHands Cloud
O OpenHands Cloud pode ser acessado em https://app.all-hands.dev/.
Você também pode interagir com o OpenHands Cloud programaticamente usando a [API](./cloud-api).
## Primeiros Passos
Ao visitar o OpenHands Cloud, você será solicitado a conectar-se com sua conta GitHub ou GitLab:
1. Após ler e aceitar os termos de serviço, clique em `Log in with GitHub` ou `Log in with GitLab`.
2. Revise as permissões solicitadas pelo OpenHands e então clique em `Authorize OpenHands AI`.
- O OpenHands precisará de algumas permissões da sua conta GitHub ou GitLab. Para ler mais sobre essas permissões:
- GitHub: Você pode clicar no link `Learn more` na página de autorização do GitHub.
- GitLab: Você pode expandir cada solicitação de permissão na página de autorização do GitLab.
## Acesso ao Repositório
### GitHub
#### Adicionando Acesso ao Repositório
Você pode conceder ao OpenHands acesso específico ao repositório:
1. Clique em `Add GitHub repos` na página inicial.
2. Selecione a organização e, em seguida, escolha os repositórios específicos para conceder acesso ao OpenHands.
<details>
<summary>Detalhes de Permissão para Acesso ao Repositório</summary>
O Openhands solicita tokens de curta duração (expiração de 8 horas) com estas permissões:
- Actions: Leitura e escrita
- Administration: Somente leitura
- Commit statuses: Leitura e escrita
- Contents: Leitura e escrita
- Issues: Leitura e escrita
- Metadata: Somente leitura
- Pull requests: Leitura e escrita
- Webhooks: Leitura e escrita
- Workflows: Leitura e escrita
O acesso ao repositório para um usuário é concedido com base em:
- Permissão concedida para o repositório.
- Permissões do GitHub do usuário (proprietário/colaborador).
</details>
3. Clique em `Install & Authorize`.
#### Modificando o Acesso ao Repositório
Você pode modificar o acesso ao repositório do GitHub a qualquer momento:
* Usando o mesmo fluxo de trabalho `Add GitHub repos`, ou
* Visitando a página de Configurações e selecionando `Configure GitHub Repositories` na seção `Git Settings`.
### GitLab
Ao usar sua conta GitLab, o OpenHands terá automaticamente acesso aos seus repositórios.
## Persistência de Conversas
- Lista de Conversas Exibe apenas as 10 conversas mais recentes iniciadas nos últimos 10 dias.
- Workspaces Os workspaces de conversas são mantidos por 14 dias.
- Runtimes Os runtimes permanecem ativos ("aquecidos") por 30 minutos. Após esse período, retomar uma conversa pode levar de 1 a 2 minutos.

View File

@@ -37,7 +37,7 @@ Para executar o OpenHands no modo CLI com Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -46,7 +46,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.cli
```

View File

@@ -34,7 +34,7 @@ Para executar o OpenHands em modo Headless com Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -44,7 +44,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.main -t "write a bash script that prints hi"
```

View File

@@ -58,17 +58,17 @@
A maneira mais fácil de executar o OpenHands é no Docker.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.38
docker.all-hands.dev/all-hands-ai/openhands:0.39
```
Você encontrará o OpenHands rodando em http://localhost:3000!

View File

@@ -1,4 +1,4 @@
# Visão Geral dos Recursos do OpenHands
# Visão Geral das Funcionalidades do OpenHands
![visão geral](/img/oh-features.png)
@@ -6,7 +6,7 @@
- Exibe a conversa entre o usuário e o OpenHands.
- O OpenHands explica suas ações neste painel.
### Mudanças
### Alterações
- Mostra as alterações de arquivos realizadas pelo OpenHands.
### VS Code
@@ -14,13 +14,13 @@
- Também pode ser usado para fazer upload e download de arquivos.
### Terminal
- Um espaço para o OpenHands e os usuários executarem comandos de terminal.
- Um espaço para o OpenHands e usuários executarem comandos de terminal.
### Jupyter
- Mostra todos os comandos Python que foram executados pelo OpenHands.
- Particularmente útil ao usar o OpenHands para realizar tarefas de visualização de dados.
- Particularmente útil ao usar o OpenHands para tarefas de visualização de dados.
### App
### Aplicativo
- Exibe o servidor web quando o OpenHands executa uma aplicação.
- Os usuários podem interagir com a aplicação em execução.

View File

@@ -1,31 +0,0 @@
# Cloud GitHub Resolver
GitHub Resolver 自动修复代码并为您的仓库提供智能辅助。
## 设置
当您[授予 OpenHands Cloud 仓库访问权限](./openhands-cloud#adding-repository-access)后Cloud GitHub Resolver 会自动可用。
## 使用方法
授予 OpenHands Cloud 仓库访问权限后,您可以在仓库的 issues 和 pull requests 中使用 Cloud GitHub Resolver。
### Issues
在您的仓库中,给 issue 添加 `openhands` 标签。OpenHands 将会:
1. 在 issue 上发表评论,让您知道它正在处理该问题。
- 您可以点击链接在 OpenHands Cloud 上跟踪进度。
2. 如果确定问题已成功解决,则会打开一个 pull request。
3. 在 issue 上发表评论,总结已执行的任务并提供 pull request 的链接。
### Pull Requests
要让 OpenHands 处理 pull requests请在顶级或内联评论中使用 `@openhands` 来:
- 提问
- 请求更新
- 获取代码解释
OpenHands 将会:
1. 在 PR 上发表评论,让您知道它正在处理该请求。
2. 执行任务。

View File

@@ -0,0 +1,32 @@
# 云问题解决器
云问题解决器可以自动修复代码并为您的GitHub和GitLab仓库提供智能辅助。
## 设置
当您授予OpenHands Cloud仓库访问权限时云问题解决器会自动可用
- [GitHub仓库访问](./github-installation#adding-repository-access)
- [GitLab仓库访问](./gitlab-installation#adding-repository-access)
## 使用方法
授予OpenHands Cloud仓库访问权限后您可以在仓库的问题和拉取/合并请求中使用云问题解决器。
### 处理问题
在您的仓库中,给问题添加`openhands`标签。OpenHands将会
1. 在问题上发表评论,让您知道它正在处理
- 您可以点击链接在OpenHands Cloud上跟踪进度
2. 如果确定问题已成功解决则打开拉取请求GitHub或合并请求GitLab
3. 在问题上发表评论总结已执行的任务并提供PR/MR的链接
### 处理拉取/合并请求
要让OpenHands处理拉取请求GitHub或合并请求GitLab在评论中提及`@openhands`以:
- 提问
- 请求更新
- 获取代码解释
OpenHands将会
1. 发表评论让您知道它正在处理
2. 执行请求的任务

View File

@@ -0,0 +1,29 @@
# 云界面
云界面为与OpenHands AI交互提供了网页界面。本页面说明如何访问和使用OpenHands云界面。
## 访问界面
OpenHands云界面可以在[app.all-hands.dev](https://app.all-hands.dev)访问。您需要使用GitHub或GitLab账户登录才能访问界面。
<!-- 图片将在未来更新中添加 -->
<!-- ![OpenHands云界面](/img/docs/openhands-cloud-ui.png) -->
## 主要功能
有关OpenHands云界面中可用功能的详细信息请参阅文档的[主要功能](../key-features.md)部分。
## 设置
设置页面允许您:
1. 配置您的账户偏好
2. 管理仓库访问权限
3. 生成用于程序化访问的API密钥
4. 自定义您的OpenHands体验
## 下一步
- [使用云问题解决器](./cloud-issue-resolver.md)自动修复代码并获取帮助
- [了解云API](./cloud-api.md)进行程序化访问
- [返回入门指南](./openhands-cloud.md)

View File

@@ -0,0 +1,55 @@
# GitHub 安装
本指南将引导您完成为GitHub仓库安装和配置OpenHands Cloud的过程。
## 前提条件
- GitHub账户
- 访问OpenHands Cloud
## 安装步骤
1. 登录[OpenHands Cloud](https://app.all-hands.dev)
2. 如果您尚未连接GitHub账户
- 点击`连接到GitHub`
- 查看并接受服务条款
- 授权OpenHands AI应用程序
## 添加仓库访问权限
您可以授予OpenHands访问特定仓库的权限
1. 点击`选择GitHub项目`下拉菜单,然后选择`添加更多仓库...`
2. 选择您的组织并选择要授予OpenHands访问权限的特定仓库。
- OpenHands请求短期令牌8小时过期并具有以下权限
- 操作:读取和写入
- 管理:只读
- 提交状态:读取和写入
- 内容:读取和写入
- 问题:读取和写入
- 元数据:只读
- 拉取请求:读取和写入
- Webhooks读取和写入
- 工作流程:读取和写入
- 用户的仓库访问权限基于:
- 为仓库授予的权限
- 用户的GitHub权限所有者/协作者)
3. 点击`安装并授权`
## 修改仓库访问权限
您可以随时修改仓库访问权限:
* 使用相同的`选择GitHub项目 > 添加更多仓库`工作流程,或
* 访问设置页面并在`GitHub设置`部分选择`配置GitHub仓库`
## 使用OpenHands与GitHub
一旦您授予了仓库访问权限您就可以将OpenHands与您的GitHub仓库一起使用。
有关如何将OpenHands与GitHub问题和拉取请求一起使用的详细信息请参阅[云问题解决器](./cloud-issue-resolver.md)文档。
## 下一步
- [访问云界面](./cloud-ui.md)与网页界面交互
- [使用云问题解决器](./cloud-issue-resolver.md)自动修复代码并获取帮助
- [使用云API](./cloud-api.md)以编程方式与OpenHands交互

View File

@@ -0,0 +1,50 @@
# GitLab 安装
本指南将引导您完成为GitLab仓库安装和配置OpenHands Cloud的过程。
## 前提条件
- GitLab账户
- 访问OpenHands Cloud
## 安装步骤
1. 登录[OpenHands Cloud](https://app.all-hands.dev)
2. 如果您尚未连接GitLab账户
- 点击`连接到GitLab`
- 查看并接受服务条款
- 授权OpenHands AI应用程序
## 添加仓库访问权限
您可以授予OpenHands访问特定仓库的权限
1. 点击`选择GitLab项目`下拉菜单,然后选择`添加更多仓库...`
2. 选择您的组织并选择要授予OpenHands访问权限的特定仓库。
- OpenHands请求具有以下范围的权限
- api完全API访问
- read_user读取用户信息
- read_repository读取仓库信息
- write_repository写入仓库
- 用户的仓库访问权限基于:
- 为仓库授予的权限
- 用户的GitLab权限所有者/维护者/开发者)
3. 点击`安装并授权`
## 修改仓库访问权限
您可以随时修改仓库访问权限:
* 使用相同的`选择GitLab项目 > 添加更多仓库`工作流程,或
* 访问设置页面并在`GitLab设置`部分选择`配置GitLab仓库`
## 使用OpenHands与GitLab
一旦您授予了仓库访问权限您就可以将OpenHands与您的GitLab仓库一起使用。
有关如何将OpenHands与GitLab问题和合并请求一起使用的详细信息请参阅[云问题解决器](./cloud-issue-resolver.md)文档。
## 下一步
- [访问云界面](./cloud-ui.md)与网页界面交互
- [使用云问题解决器](./cloud-issue-resolver.md)自动修复代码并获取帮助
- [使用云API](./cloud-api.md)以编程方式与OpenHands交互

View File

@@ -0,0 +1,24 @@
# OpenHands 云
OpenHands 云是All Hands AI的OpenHands的托管云版本。
## 访问OpenHands云
要开始使用OpenHands云请访问[app.all-hands.dev](https://app.all-hands.dev)。
系统将提示您连接您的GitHub或GitLab账户
1. 阅读并接受服务条款后,点击`连接到GitHub``连接到GitLab`
2. 查看OpenHands请求的权限并授权应用程序。
- OpenHands将需要您账户的某些权限。要了解更多关于这些权限的信息
您可以点击授权页面上的`了解更多`链接。
## 下一步
一旦您连接了账户,您可以:
- [安装GitHub集成](./github-installation.md)以将OpenHands与您的GitHub仓库一起使用
- [安装GitLab集成](./gitlab-installation.md)以将OpenHands与您的GitLab仓库一起使用
- [访问云界面](./cloud-ui.md)与网页界面交互
- [使用云API](./cloud-api.md)以编程方式与OpenHands交互
- [设置云问题解决器](./cloud-issue-resolver.md)自动修复代码并提供智能辅助

View File

@@ -1,65 +0,0 @@
# OpenHands Cloud
OpenHands Cloud 是由 All Hands AI 提供的 OpenHands 云托管版本。
## 访问 OpenHands Cloud
OpenHands Cloud 可以通过 https://app.all-hands.dev/ 访问。
您还可以使用 [API](./cloud-api) 以编程方式与 OpenHands Cloud 交互。
## 入门指南
访问 OpenHands Cloud 后,系统会要求您连接您的 GitHub 或 GitLab 账户:
1. 阅读并接受服务条款后,点击 `Log in with GitHub` 或 `Log in with GitLab`。
2. 查看 OpenHands 请求的权限,然后点击 `Authorize OpenHands AI`。
- OpenHands 将需要您的 GitHub 或 GitLab 账户的一些权限。要了解更多关于这些权限的信息:
- GitHub您可以点击 GitHub 授权页面上的 `Learn more` 链接。
- GitLab您可以在 GitLab 授权页面上展开每个权限请求。
## 仓库访问
### GitHub
#### 添加仓库访问权限
您可以授予 OpenHands 特定仓库的访问权限:
1. 在首页点击 `Add GitHub repos`。
2. 选择组织,然后选择要授予 OpenHands 访问权限的特定仓库。
<details>
<summary>仓库访问权限详情</summary>
Openhands 请求短期令牌8小时过期并具有以下权限
- Actions读写权限
- Administration只读权限
- Commit statuses读写权限
- Contents读写权限
- Issues读写权限
- Metadata只读权限
- Pull requests读写权限
- Webhooks读写权限
- Workflows读写权限
用户的仓库访问权限基于:
- 为仓库授予的权限。
- 用户的 GitHub 权限(所有者/协作者)。
</details>
3. 点击 `Install & Authorize`。
#### 修改仓库访问权限
您可以随时修改 GitHub 仓库访问权限,方法是:
* 使用相同的 `Add GitHub repos` 流程,或
* 访问设置页面,在 `Git Settings` 部分下选择 `Configure GitHub Repositories`。
### GitLab
使用 GitLab 账户时OpenHands 将自动获得对您仓库的访问权限。
## 对话持久性
- 对话列表 仅显示过去 10 天内发起的 10 个最近对话。
- 工作区 对话工作区保留 14 天。
- 运行时 运行时保持活跃("热"状态30 分钟。在此期间后,恢复对话可能需要 1-2 分钟。

View File

@@ -36,7 +36,7 @@ poetry run python -m openhands.core.cli
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -45,7 +45,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.cli
```

View File

@@ -33,7 +33,7 @@ poetry run python -m openhands.core.main -t "write a bash script that prints hi"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -43,7 +43,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.core.main -t "write a bash script that prints hi"
```

View File

@@ -58,17 +58,17 @@
运行 OpenHands 最简单的方法是使用 Docker。
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.38
docker.all-hands.dev/all-hands-ai/openhands:0.39
```
OpenHands 将在 http://localhost:3000 运行!

View File

@@ -1,6 +1,6 @@
# OpenHands 功能概览
![overview](/img/oh-features.png)
![概览](/img/oh-features.png)
### 聊天面板
- 显示用户与 OpenHands 之间的对话。
@@ -22,7 +22,7 @@
### 应用
- 当 OpenHands 运行应用程序时显示网络服务器。
- 用户可以与运行的应用程序交互。
- 用户可以与正在运行的应用程序交互。
### 浏览器
- 由 OpenHands 用于浏览网站。

View File

@@ -1,4 +1,4 @@
# OpenHands Cloud API
# Cloud API
OpenHands Cloud provides a REST API that allows you to programmatically interact with the service. This is useful if
you want to kick off your own jobs from your programs in a flexible way.

View File

@@ -1,33 +0,0 @@
# Cloud GitHub Resolver
The GitHub Resolver automates code fixes and provides intelligent assistance for your repositories.
## Setup
The Cloud GitHub Resolver is available automatically when you
[grant OpenHands Cloud repository access](./openhands-cloud#adding-repository-access).
## Usage
After granting OpenHands Cloud repository access, you can use the Cloud GitHub Resolver on the issues and pull requests
on the repository.
### Issues
On your repository, label an issue 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 pull request.
### Pull Requests
To get OpenHands to work on pull requests, use `@openhands` in top level or inline comments to:
- Ask questions
- Request updates
- Get code explanations
OpenHands will:
1. Comment on the PR to let you know it is working on it.
2. Perform the task.

View File

@@ -0,0 +1,32 @@
# Cloud Issue Resolver
The Cloud Issue Resolver automates code fixes and provides intelligent assistance for your repositories on GitHub.
## Setup
The Cloud Issue Resolver is available automatically when you grant OpenHands Cloud repository access:
- [GitHub repository access](./github-installation#adding-repository-access)
## Usage
After granting OpenHands Cloud repository access, you can use the Cloud Issue Resolver on issues and pull requests in your repositories.
### 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 comments to:
- Ask questions
- Request updates
- Get code explanations
OpenHands will:
1. Comment to let you know it is working on it
2. Perform the requested task

View File

@@ -0,0 +1,26 @@
# Cloud UI
The Cloud UI provides a web interface for interacting with OpenHands AI. This page explains how to access and use the OpenHands Cloud UI.
## Accessing the UI
The OpenHands Cloud UI can be accessed at [app.all-hands.dev](https://app.all-hands.dev). You'll need to sign in with your GitHub or GitLab account to access the interface.
## Key Features
For detailed information about the features available in the OpenHands Cloud UI, please refer to the [Key Features](../key-features.md) section of the documentation.
## Settings
The settings page allows you to:
- Configure your account preferences.
- Manage repository access.
- Generate API keys for programmatic access.
- Generate custom secrets for the agent.
## Next Steps
- [Use the Cloud Issue Resolver](./cloud-issue-resolver.md) to automate code fixes and get assistance.
- [Learn about the Cloud API](./cloud-api.md) for programmatic access.

View File

@@ -0,0 +1,53 @@
# GitHub Installation
This guide walks you through the process of installing and configuring OpenHands Cloud for your GitHub repositories.
## Prerequisites
- A GitHub account
- Access to OpenHands Cloud
## Installation Steps
1. Log in to [OpenHands Cloud](https://app.all-hands.dev)
2. If you haven't connected your GitHub account yet:
- Click on `Connect to GitHub`
- Review and accept the terms of service
- Authorize the OpenHands AI application
## Adding Repository Access
You can grant OpenHands access to specific repositories:
1. Click on `Add GitHub repos`
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
- Administration: Read-only
- Commit statuses: Read and write
- Contents: Read and write
- Issues: Read and write
- Metadata: Read-only
- Pull requests: Read and write
- Webhooks: Read and write
- Workflows: Read and write
- Repository access for a user is granted based on:
- Permission granted for the repository
- User's GitHub permissions (owner/collaborator)
3. Click `Install & Authorize`
## Modifying Repository Access
You can modify repository access at any time by visiting the Settings page and selecting `Configure GitHub Repositories` under the `Git` tab.
## Using OpenHands with GitHub
Once you've granted repository access, you can use OpenHands with your GitHub repositories.
For details on how to use OpenHands with GitHub issues and pull requests, see the [Cloud Issue Resolver](./cloud-issue-resolver.md) documentation.
## Next Steps
- [Access the Cloud UI](./cloud-ui.md) to interact with the web interface
- [Use the Cloud Issue Resolver](./cloud-issue-resolver.md) to automate code fixes and get assistance
- [Use the Cloud API](./cloud-api.md) to programmatically interact with OpenHands

View File

@@ -0,0 +1,22 @@
# GitLab Installation
This guide walks you through the process of installing and configuring OpenHands Cloud for your GitLab repositories.
## Prerequisites
- A GitLab account
- Access to OpenHands Cloud
## Installation Steps
1. Log in to [OpenHands Cloud](https://app.all-hands.dev)
2. If you haven't connected your GitLab account yet:
- Click on `Log in with GitLab`
- Authorize the OpenHands application
## Next Steps
- [Access the Cloud UI](./cloud-ui.md) to interact with the web interface
- [Use the Cloud API](./cloud-api.md) to programmatically interact with OpenHands

View File

@@ -0,0 +1,24 @@
# OpenHands Cloud
OpenHands Cloud is the hosted cloud version of All Hands AI's OpenHands.
## Accessing OpenHands Cloud
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 or GitLab account:
1. Click `Log in with GitHub` or `Log in with GitLab`.
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.
## Next Steps
Once you've connected your account, you can:
- [Install GitHub Integration](./github-installation.md) to use OpenHands with your GitHub repositories
- [Install GitLab Integration](./gitlab-installation.md) to use OpenHands with your GitLab repositories
- [Access the Cloud UI](./cloud-ui.md) to interact with the web interface
- [Use the Cloud API](./cloud-api.md) to programmatically interact with OpenHands
- [Set up the Cloud Issue Resolver](./cloud-issue-resolver.md) to automate code fixes and provide intelligent assistance

View File

@@ -31,7 +31,7 @@ This command opens an interactive prompt where you can type tasks or commands an
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.38-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e SANDBOX_VOLUMES=$SANDBOX_VOLUMES \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -40,7 +40,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.38 \
docker.all-hands.dev/all-hands-ai/openhands:0.39 \
python -m openhands.cli.main
```

View File

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

View File

@@ -0,0 +1,181 @@
---
sidebar_position: 9
---
# Connecting to the WebSocket
This guide explains how to connect to the OpenHands WebSocket API to receive real-time events and send actions to the agent.
## Overview
OpenHands uses [Socket.IO](https://socket.io/) for WebSocket communication between the client and server. The WebSocket connection allows you to:
1. Receive real-time events from the agent
2. Send user actions to the agent
3. Maintain a persistent connection for ongoing conversations
## Connecting to the WebSocket
### Connection Parameters
When connecting to the WebSocket, you need to provide the following query parameters:
- `conversation_id`: The ID of the conversation you want to join
- `latest_event_id`: The ID of the latest event you've received (use `-1` for a new connection)
- `providers_set`: (Optional) A comma-separated list of provider types
### Connection Example
Here's a basic example of connecting to the WebSocket using JavaScript:
```javascript
import { io } from "socket.io-client";
const socket = io("http://localhost:3000", {
transports: ["websocket"],
query: {
conversation_id: "your-conversation-id",
latest_event_id: -1,
providers_set: "github,gitlab" // Optional
}
});
socket.on("connect", () => {
console.log("Connected to OpenHands WebSocket");
});
socket.on("oh_event", (event) => {
console.log("Received event:", event);
});
socket.on("connect_error", (error) => {
console.error("Connection error:", error);
});
socket.on("disconnect", (reason) => {
console.log("Disconnected:", reason);
});
```
## Sending Actions to the Agent
To send an action to the agent, use the `oh_user_action` event:
```javascript
// Send a user message to the agent
socket.emit("oh_user_action", {
type: "message",
source: "user",
message: "Hello, can you help me with my project?"
});
```
## Receiving Events from the Agent
The server emits events using the `oh_event` event type. Here are some common event types you might receive:
- User messages (`source: "user", type: "message"`)
- Agent messages (`source: "agent", type: "message"`)
- File edits (`action: "edit"`)
- File writes (`action: "write"`)
- Command executions (`action: "run"`)
Example event handler:
```javascript
socket.on("oh_event", (event) => {
if (event.source === "agent" && event.type === "message") {
console.log("Agent says:", event.message);
} else if (event.action === "run") {
console.log("Command executed:", event.args.command);
console.log("Result:", event.result);
}
});
```
## Using Websocat for Testing
[Websocat](https://github.com/vi/websocat) is a command-line tool for interacting with WebSockets. It's useful for testing your WebSocket connection without writing a full client application.
### Installation
```bash
# On macOS
brew install websocat
# On Linux
curl -L https://github.com/vi/websocat/releases/download/v1.11.0/websocat.x86_64-unknown-linux-musl > websocat
chmod +x websocat
sudo mv websocat /usr/local/bin/
```
### Connecting to the WebSocket
```bash
# Connect to the WebSocket and print all received messages
echo "40{}" | \
websocat "ws://localhost:3000/socket.io/?EIO=4&transport=websocket&conversation_id=your-conversation-id&latest_event_id=-1"
```
### Sending a Message
```bash
# Send a message to the agent
echo '42["oh_user_action",{"type":"message","source":"user","message":"Hello, agent!"}]' | \
websocat "ws://localhost:3000/socket.io/?EIO=4&transport=websocket&conversation_id=your-conversation-id&latest_event_id=-1"
```
### Complete Example with Websocat
Here's a complete example of connecting to the WebSocket, sending a message, and receiving events:
```bash
# Start a persistent connection
websocat -v "ws://localhost:3000/socket.io/?EIO=4&transport=websocket&conversation_id=your-conversation-id&latest_event_id=-1"
# In another terminal, send a message
echo '42["oh_user_action",{"type":"message","source":"user","message":"Can you help me with my project?"}]' | \
websocat "ws://localhost:3000/socket.io/?EIO=4&transport=websocket&conversation_id=your-conversation-id&latest_event_id=-1"
```
## Event Structure
Events sent and received through the WebSocket follow a specific structure:
```typescript
interface OpenHandsEvent {
id: string; // Unique event ID
source: string; // "user" or "agent"
timestamp: string; // ISO timestamp
message?: string; // For message events
type?: string; // Event type (e.g., "message")
action?: string; // Action type (e.g., "run", "edit", "write")
args?: any; // Action arguments
result?: any; // Action result
}
```
## Best Practices
1. **Handle Reconnection**: Implement reconnection logic in your client to handle network interruptions.
2. **Track Event IDs**: Store the latest event ID you've received and use it when reconnecting to avoid duplicate events.
3. **Error Handling**: Implement proper error handling for connection errors and failed actions.
4. **Rate Limiting**: Avoid sending too many actions in a short period to prevent overloading the server.
## Troubleshooting
### Connection Issues
- Verify that the OpenHands server is running and accessible
- Check that you're providing the correct conversation ID
- Ensure your WebSocket URL is correctly formatted
### Authentication Issues
- Make sure you have the necessary authentication cookies if required
- Verify that you have permission to access the specified conversation
### Event Handling Issues
- Check that you're correctly parsing the event data
- Verify that your event handlers are properly registered

View File

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

View File

@@ -1,4 +1,4 @@
# Local LLM with SGLang or vLLM
# Local LLMs
:::warning
When using a Local LLM, OpenHands may have limited functionality.
@@ -7,10 +7,91 @@ It is highly recommended that you use GPUs to serve local models for optimal exp
## News
- 2025/05/21: We collaborated with Mistral AI and released [Devstral Small](https://mistral.ai/news/devstral) that achieves [46.8% on SWE-Bench Verified](https://github.com/SWE-bench/experiments/pull/228)!
- 2025/03/31: We released an open model OpenHands LM v0.1 32B that achieves 37.1% on SWE-Bench Verified
([blog](https://www.all-hands.dev/blog/introducing-openhands-lm-32b----a-strong-open-coding-agent-model), [model](https://huggingface.co/all-hands/openhands-lm-32b-v0.1)).
## Download the Model from Huggingface
## Quickstart: Running OpenHands on Your Macbook
### Serve the model on your Macbook
We recommend using [LMStudio](https://lmstudio.ai/) for serving these models locally.
1. Download [LM Studio](https://lmstudio.ai/) and install it
2. Download the model:
- Option 1: Directly download the LLM from [this link](https://lmstudio.ai/model/devstral-small-2505-mlx) or by searching for the name `Devstral-Small-2505` in LM Studio
- Option 2: Download a LLM in GGUF format. For example, to download [Devstral Small 2505 GGUF](https://huggingface.co/mistralai/Devstral-Small-2505_gguf), using `huggingface-cli download mistralai/Devstral-Small-2505_gguf --local-dir mistralai/Devstral-Small-2505_gguf`. Then in bash terminal, run `lms import {model_name}` in the directory where you've downloaded the model checkpoint (e.g. run `lms import devstralQ4_K_M.gguf` in `mistralai/Devstral-Small-2505_gguf`)
3. Open LM Studio application, you should first switch to `power user` mode, and then open the developer tab:
![image](./screenshots/1_select_power_user.png)
4. Then click `Select a model to load` on top of the application:
![image](./screenshots/2_select_model.png)
5. And choose the model you want to use, holding `option` on mac to enable advanced loading options:
![image](./screenshots/3_select_devstral.png)
6. You should then pick an appropriate context window for OpenHands based on your hardware configuration (larger than 32768 is recommended for using OpenHands, but too large may cause you to run out of memory); Flash attention is also recommended if it works on your machine.
![image](./screenshots/4_set_context_window.png)
7. And you should start the server (if it is not already in `Running` status), un-toggle `Serve on Local Network` and remember the port number of the LMStudio URL (`1234` is the port number for `http://127.0.0.1:1234` in this example):
![image](./screenshots/5_copy_url.png)
8. Finally, you can click the `copy` button near model name to copy the model name (`imported-models/uncategorized/devstralq4_k_m.gguf` in this example):
![image](./screenshots/6_copy_to_get_model_name.png)
### Start OpenHands with locally served model
Check [the installation guide](https://docs.all-hands.dev/modules/usage/installation) to make sure you have all the prerequisites for running OpenHands.
```bash
export LMSTUDIO_MODEL_NAME="imported-models/uncategorized/devstralq4_k_m.gguf" # <- Replace this with the model name you copied from LMStudio
export LMSTUDIO_URL="http://host.docker.internal:1234" # <- Replace this with the port from LMStudio
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik
mkdir -p ~/.openhands-state && echo '{"language":"en","agent":"CodeActAgent","max_iterations":null,"security_analyzer":null,"confirmation_mode":false,"llm_model":"lm_studio/'$LMSTUDIO_MODEL_NAME'","llm_api_key":"dummy","llm_base_url":"'$LMSTUDIO_URL/v1'","remote_runtime_resource_factor":null,"github_token":null,"enable_default_condenser":true,"user_consents_to_analytics":true}' > ~/.openhands-state/settings.json
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.39-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.39
```
Once your server is running -- you can visit `http://localhost:3000` in your browser to use OpenHands with local Devstral model:
```
Digest: sha256:e72f9baecb458aedb9afc2cd5bc935118d1868719e55d50da73190d3a85c674f
Status: Image is up to date for docker.all-hands.dev/all-hands-ai/openhands:0.39
Starting OpenHands...
Running OpenHands as root
14:22:13 - openhands:INFO: server_config.py:50 - Using config class None
INFO: Started server process [8]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:3000 (Press CTRL+C to quit)
```
## Advanced: Serving LLM on GPUs
### Download model checkpoints
:::note
The model checkpoints downloaded here should NOT be in GGUF format.
:::
For example, to download [OpenHands LM 32B v0.1](https://huggingface.co/all-hands/openhands-lm-32b-v0.1):
@@ -18,9 +99,7 @@ For example, to download [OpenHands LM 32B v0.1](https://huggingface.co/all-hand
huggingface-cli download all-hands/openhands-lm-32b-v0.1 --local-dir all-hands/openhands-lm-32b-v0.1
```
## Create an OpenAI-Compatible Endpoint With a Model Serving Framework
### Serving with SGLang
### Create an OpenAI-Compatible Endpoint With SGLang
- Install SGLang following [the official documentation](https://docs.sglang.ai/start/install.html).
- Example launch command for OpenHands LM 32B (with at least 2 GPUs):
@@ -35,7 +114,7 @@ SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 python3 -m sglang.launch_server \
--api-key mykey --context-length 131072
```
### Serving with vLLM
### Create an OpenAI-Compatible Endpoint with vLLM
- Install vLLM following [the official documentation](https://docs.vllm.ai/en/latest/getting_started/installation.html).
- Example launch command for OpenHands LM 32B (with at least 2 GPUs):
@@ -49,7 +128,7 @@ vllm serve all-hands/openhands-lm-32b-v0.1 \
--enable-prefix-caching
```
## Run and Configure OpenHands
## Advanced: Run and Configure OpenHands
### Run OpenHands

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

View File

@@ -0,0 +1,23 @@
# Organization and User Microagents
## Purpose
Organizations and users can define microagents that apply to all repositories belonging to the organization or user.
## Usage
These microagents can be [any type of microagent](./microagents-overview#microagent-types) and will be loaded
accordingly. However, they are applied to all repositories belonging to the organization or user.
Add a `.openhands` repository under the organization or user and create a `microagents` directory and place the
microagents in that directory.
## Example
General microagent file example for organization `Great-Co` located inside the `.openhands` repository:
`microagents/org-microagent.md`:
```
* Use type hints and error boundaries; validate inputs at system boundaries and fail with meaningful error messages.
* Document interfaces and public APIs; use implementation comments only for non-obvious logic.
* Follow the same naming convention for variables, classes, constants, etc. already used in each repository.
```

View File

@@ -7,7 +7,7 @@ They provide expert guidance, automate common tasks, and ensure consistent pract
Currently OpenHands supports the following types of microagents:
- [General Repository Microagents](./microagents-repo): General guidelines for OpenHands about the repository.
- [General Microagents](./microagents-repo): General guidelines for OpenHands about the repository.
- [Keyword-Triggered Microagents](./microagents-keyword): Guidelines activated by specific keywords in prompts.
To customize OpenHands' behavior, create a .openhands/microagents/ directory in the root of your repository and
@@ -24,7 +24,7 @@ Example repository structure:
some-repository/
└── .openhands/
└── microagents/
└── repo.md # General repository guidelines
└── repo.md # General guidelines
└── trigger_this.md # Microagent triggered by specific keywords
└── trigger_that.md # Microagent triggered by specific keywords
```
@@ -34,7 +34,7 @@ some-repository/
Each microagent file may include frontmatter that provides additional information. In some cases, this frontmatter
is required:
| Microagent Type | Required |
|----------------------------------|----------|
| `General Repository Microagents` | No |
| `Keyword-Triggered Microagents` | Yes |
| Microagent Type | Required |
|---------------------------------|----------|
| `General Microagents` | No |
| `Keyword-Triggered Microagents` | Yes |

View File

@@ -1,4 +1,4 @@
# General Repository Microagents
# General Microagents
## Purpose
@@ -20,7 +20,7 @@ Frontmatter should be enclosed in triple dashes (---) and may include the follow
## Example
General repository microagent file example located at `.openhands/microagents/repo.md`:
General microagent file example located at `.openhands/microagents/repo.md`:
```
This project is a TODO application that allows users to track TODO items.
@@ -28,4 +28,4 @@ To set it up, you can run `npm run build`.
Always make sure the tests are passing before committing changes. You can run the tests by running `npm run test`.
```
[See more examples of general repository microagents here.](https://github.com/All-Hands-AI/OpenHands/tree/main/.openhands/microagents)
[See more examples of general microagents here.](https://github.com/All-Hands-AI/OpenHands/tree/main/.openhands/microagents)

View File

@@ -13,14 +13,16 @@ files on your machine. Only use this runtime in controlled environments or when
Before using the Local Runtime, ensure that:
1. You can run OpenHands using the [Development workflow](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
2. tmux is available on your system.
2. For Linux and Mac, tmux is available on your system.
3. For Windows, PowerShell is available on your system.
- Only [CLI mode](../how-to/cli-mode) and [headless mode](../how-to/headless-mode) are supported in Windows with Local Runtime.
## Configuration
To use the Local Runtime, besides required configurations like the LLM provider, model and API key, you'll need to set
the following options via environment variables or the [config.toml file](https://github.com/All-Hands-AI/OpenHands/blob/main/config.template.toml) when starting OpenHands:
Via environment variables:
Via environment variables (please use PowerShell syntax for Windows PowerShell):
```bash
# Required
@@ -65,4 +67,4 @@ The Local Runtime is particularly useful for:
- CI/CD pipelines where Docker is not available.
- Testing and development of OpenHands itself.
- Environments where container usage is restricted.
- Environments where container usage is restricted (e.g. native Windows).

View File

@@ -27,7 +27,7 @@
"@docusaurus/tsconfig": "^3.7.0",
"@docusaurus/types": "^3.5.1",
"swagger-cli": "^4.0.4",
"swagger-ui-dist": "^5.21.0",
"swagger-ui-dist": "^5.22.0",
"typescript": "~5.8.3"
},
"engines": {
@@ -18730,9 +18730,9 @@
}
},
"node_modules/swagger-ui-dist": {
"version": "5.21.0",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.21.0.tgz",
"integrity": "sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg==",
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.22.0.tgz",
"integrity": "sha512-8YlCSxiyb8uPFa7qoB1lRHYr1PBbT1NuV9RvQdFFPFPudRBTPf9coU5jl02KhzvrtmTEw4jXRgb0kg8pJvVuWQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {

View File

@@ -36,7 +36,7 @@
"@docusaurus/tsconfig": "^3.7.0",
"@docusaurus/types": "^3.5.1",
"swagger-cli": "^4.0.4",
"swagger-ui-dist": "^5.21.0",
"swagger-ui-dist": "^5.22.0",
"typescript": "~5.8.3"
},
"browserslist": {

View File

@@ -24,19 +24,40 @@ const sidebars: SidebarsConfig = {
items: [
{
type: 'doc',
label: 'Openhands Cloud',
label: 'Getting Started',
id: 'usage/cloud/openhands-cloud',
},
{
type: 'category',
label: 'Installation',
items: [
{
type: 'doc',
label: 'GitHub Installation',
id: 'usage/cloud/github-installation',
},
{
type: 'doc',
label: 'GitLab Installation',
id: 'usage/cloud/gitlab-installation',
},
],
},
{
type: 'doc',
label: 'Cloud UI',
id: 'usage/cloud/cloud-ui',
},
{
type: 'doc',
label: 'Cloud Issue Resolver',
id: 'usage/cloud/cloud-issue-resolver',
},
{
type: 'doc',
label: 'Cloud API',
id: 'usage/cloud/cloud-api',
},
{
type: 'doc',
label: 'Cloud GitHub Resolver',
id: 'usage/cloud/cloud-github-resolver',
},
],
},
{
@@ -70,7 +91,7 @@ const sidebars: SidebarsConfig = {
},
{
type: 'doc',
label: 'General Repository Microagents',
label: 'General Microagents',
id: 'usage/prompting/microagents-repo',
},
{
@@ -78,6 +99,11 @@ const sidebars: SidebarsConfig = {
label: 'Keyword-Triggered Microagents',
id: 'usage/prompting/microagents-keyword',
},
{
type: 'doc',
label: 'Organization and User Microagents',
id: 'usage/prompting/microagents-org',
},
{
type: 'doc',
label: 'Global Microagents',
@@ -267,6 +293,11 @@ const sidebars: SidebarsConfig = {
label: 'Evaluation',
id: 'usage/how-to/evaluation-harness',
},
{
type: 'doc',
label: 'WebSocket Connection',
id: 'usage/how-to/websocket-connection',
},
],
},
{

View File

@@ -876,6 +876,11 @@
"type": "string",
"nullable": true
},
"conversation_instructions": {
"type": "string",
"nullable": true,
"description": "Optional instructions the agent must follow throughout the conversation while addressing the user's initial task"
},
"image_urls": {
"type": "array",
"items": {

View File

@@ -42,6 +42,37 @@ api_key = "XXX"
temperature = 0.0
```
### Configuring Condensers for Evaluation
For benchmarks that support condenser configuration (like SWE-Bench), you can define multiple condenser configurations in your `config.toml` file. A condenser is responsible for managing conversation history to maintain context while staying within token limits - you can learn more about how it works [here](https://www.all-hands.dev/blog/openhands-context-condensensation-for-more-efficient-ai-agents):
```toml
# LLM-based summarizing condenser for evaluation
[condenser.summarizer_for_eval]
type = "llm"
llm_config = "haiku" # Reference to an LLM config to use for summarization
keep_first = 2 # Number of initial events to always keep
max_size = 100 # Maximum size of history before triggering summarization
# Recent events condenser for evaluation
[condenser.recent_for_eval]
type = "recent"
keep_first = 2 # Number of initial events to always keep
max_events = 50 # Maximum number of events to keep in history
```
You can then specify which condenser configuration to use when running evaluation scripts, for example:
```bash
EVAL_CONDENSER=summarizer_for_eval \
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 500 100 1 princeton-nlp/SWE-bench_Verified test
```
The name is up to you, but should match a name defined in your `config.toml` file. The last argument in the command specifies the condenser configuration to use. In this case, `summarizer_for_eval` is used, which refers to the LLM-based summarizing condenser as defined above.
If no condenser configuration is specified, the 'noop' condenser will be used by default, which keeps the full conversation history.
```
For other configurations specific to evaluation, such as `save_trajectory_path`, these are typically set in the `get_config` function of the respective `run_infer.py` file for each benchmark.
## Supported Benchmarks

View File

@@ -45,7 +45,7 @@ For example, for instance ID `django_django-11011`, it will try to pull our pre-
This image will be used create an OpenHands runtime image where the agent will operate on.
```bash
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split] [n_runs] [mode]
# Example
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 500 100 1 princeton-nlp/SWE-bench_Verified test
@@ -69,13 +69,20 @@ default, it is set to 1.
- `dataset`, a huggingface dataset name. e.g. `princeton-nlp/SWE-bench`, `princeton-nlp/SWE-bench_Lite`, `princeton-nlp/SWE-bench_Verified`, or `princeton-nlp/SWE-bench_Multimodal`, specifies which dataset to evaluate on.
- `dataset_split`, split for the huggingface dataset. e.g., `test`, `dev`. Default to `test`.
- `n_runs`, e.g. `3`, is the number of times to run the evaluation. Default is 1.
- `mode`, e.g. `swt`, `swt-ci`, or `swe`, specifies the evaluation mode. Default is `swe`.
> [!CAUTION]
> Setting `num_workers` larger than 1 is not officially tested, YMMV.
There is also one optional environment variable you can set.
There are also optional environment variables you can set:
```bash
export USE_HINT_TEXT=true # if you want to use hint text in the evaluation. Default to false. Ignore this if you are not sure.
# Use hint text in the evaluation (default: false)
export USE_HINT_TEXT=true # Ignore this if you are not sure.
# Specify a condenser configuration for memory management (default: NoOpCondenser)
export EVAL_CONDENSER=summarizer_for_eval # Name of the condenser config group in config.toml
```
Let's say you'd like to run 10 instances using `llm.eval_gpt4_1106_preview` and CodeActAgent,
@@ -151,6 +158,8 @@ The script now accepts optional arguments:
- `instance_id`: Specify a single instance to evaluate (optional)
- `dataset_name`: The name of the dataset to use (default: `"princeton-nlp/SWE-bench_Lite"`)
- `split`: The split of the dataset to use (default: `"test"`)
- `environment`: The environment to use for patch evaluation (default: `"local"`). You can set it to
`"modal"` to use [official SWE-Bench support](https://github.com/swe-bench/SWE-bench/blob/main/docs/assets/evaluation.md#%EF%B8%8F-evaluation-with-modal) for running evaluation on Modal.
For example, to evaluate a specific instance with a custom dataset and split:

View File

@@ -44,6 +44,8 @@ from openhands.core.config import (
get_llm_config_arg,
get_parser,
)
from openhands.core.config.utils import get_condenser_config_arg
from openhands.core.config.condenser_config import NoOpCondenserConfig
from openhands.core.logger import openhands_logger as logger
from openhands.core.main import create_runtime, run_controller
from openhands.critic import AgentFinishedCritic
@@ -261,6 +263,7 @@ def get_config(
enable_jupyter=False,
enable_browsing=RUN_WITH_BROWSING,
enable_llm_editor=False,
enable_mcp=False,
condenser=metadata.condenser_config,
enable_prompt_extensions=False,
)
@@ -755,6 +758,7 @@ if __name__ == '__main__':
choices=['swe', 'swt', 'swt-ci'],
help="mode to run the evaluation, either 'swe', 'swt', or 'swt-ci'",
)
args, _ = parser.parse_known_args()
# NOTE: It is preferable to load datasets from huggingface datasets and perform post-processing
@@ -791,6 +795,19 @@ if __name__ == '__main__':
if llm_config is None:
raise ValueError(f'Could not find LLM config: --llm_config {args.llm_config}')
# Get condenser config from environment variable
condenser_name = os.environ.get('EVAL_CONDENSER')
if condenser_name:
condenser_config = get_condenser_config_arg(condenser_name)
if condenser_config is None:
raise ValueError(
f'Could not find Condenser config: EVAL_CONDENSER={condenser_name}'
)
else:
# If no specific condenser config is provided via env var, default to NoOpCondenser
condenser_config = NoOpCondenserConfig()
logger.debug('No Condenser config provided via EVAL_CONDENSER, using NoOpCondenser.')
details = {'mode': args.mode}
_agent_cls = openhands.agenthub.Agent.get_cls(args.agent_cls)
@@ -805,6 +822,7 @@ if __name__ == '__main__':
args.eval_note,
args.eval_output_dir,
details=details,
condenser_config=condenser_config,
)
output_file = os.path.join(metadata.eval_output_dir, 'output.jsonl')

View File

@@ -16,11 +16,19 @@ fi
INSTANCE_ID=$2
DATASET_NAME=${3:-"princeton-nlp/SWE-bench_Lite"}
SPLIT=${4:-"test"}
ENVIRONMENT=${5:-"local"}
echo "INSTANCE_ID: $INSTANCE_ID"
echo "DATASET_NAME: $DATASET_NAME"
echo "SPLIT: $SPLIT"
if [[ "$ENVIRONMENT" != "local" && "$ENVIRONMENT" != "modal" ]]; then
echo "Error: ENVIRONMENT must be either 'local' or 'modal'"
exit 1
fi
echo "ENVIRONMENT: $ENVIRONMENT"
PROCESS_FILEPATH=$(realpath $PROCESS_FILEPATH)
FILE_DIR=$(dirname $PROCESS_FILEPATH)
FILE_NAME=$(basename $PROCESS_FILEPATH)
@@ -78,6 +86,12 @@ echo "=============================================================="
RUN_ID=$(date +"%Y%m%d_%H%M%S")
N_PROCESS=4
MODAL_FLAG=""
if [[ "$ENVIRONMENT" == "modal" ]]; then
MODAL_FLAG="--modal true"
fi
if [ -z "$INSTANCE_ID" ]; then
echo "Running SWE-bench evaluation on the whole input file..."
# Default to SWE-Bench-lite
@@ -90,7 +104,8 @@ if [ -z "$INSTANCE_ID" ]; then
--timeout 3600 \
--cache_level instance \
--max_workers $N_PROCESS \
--run_id $RUN_ID
--run_id $RUN_ID \
$MODAL_FLAG
# get the "model_name_or_path" from the first line of the SWEBENCH_FORMAT_JSONL
MODEL_NAME_OR_PATH=$(jq -r '.model_name_or_path' $SWEBENCH_FORMAT_JSONL | head -n 1)
@@ -137,5 +152,6 @@ else
--instance_ids $INSTANCE_ID \
--cache_level instance \
--max_workers $N_PROCESS \
--run_id $RUN_ID
--run_id $RUN_ID \
$MODAL_FLAG
fi

View File

@@ -14,6 +14,7 @@ SPLIT=$8
N_RUNS=$9
MODE=${10}
if [ -z "$NUM_WORKERS" ]; then
NUM_WORKERS=1
echo "Number of workers not specified, use default $NUM_WORKERS"
@@ -51,6 +52,12 @@ if [ -z "$MODE" ]; then
echo "MODE not specified, use default $MODE"
fi
if [ -n "$EVAL_CONDENSER" ]; then
echo "Using Condenser Config: $EVAL_CONDENSER"
else
echo "No Condenser Config provided via EVAL_CONDENSER, use default (NoOpCondenser)."
fi
export RUN_WITH_BROWSING=$RUN_WITH_BROWSING
echo "RUN_WITH_BROWSING: $RUN_WITH_BROWSING"
@@ -65,6 +72,7 @@ echo "MAX_ITER: $MAX_ITER"
echo "NUM_WORKERS: $NUM_WORKERS"
echo "COMMIT_HASH: $COMMIT_HASH"
echo "MODE: $MODE"
echo "EVAL_CONDENSER: $EVAL_CONDENSER"
# Default to NOT use Hint
if [ -z "$USE_HINT_TEXT" ]; then
@@ -88,6 +96,10 @@ fi
if [ "$MODE" != "swe" ]; then
EVAL_NOTE="${EVAL_NOTE}-${MODE}"
fi
# Add condenser config to eval note if provided
if [ -n "$EVAL_CONDENSER" ]; then
EVAL_NOTE="${EVAL_NOTE}-${EVAL_CONDENSER}"
fi
function run_eval() {
local eval_note="${1}"
@@ -101,6 +113,8 @@ function run_eval() {
--split $SPLIT \
--mode $MODE"
if [ -n "$EVAL_LIMIT" ]; then
echo "EVAL_LIMIT: $EVAL_LIMIT"
COMMAND="$COMMAND --eval-n-limit $EVAL_LIMIT"

View File

@@ -0,0 +1,172 @@
# Visual SWE-Bench Evaluation with Docker Image
This folder contains the evaluation harness that we built on top of the original [Visual SWE-Bench benchmark](https://multi-swe-bench.github.io/#/) ([paper](https://arxiv.org/abs/2412.17315)).
The evaluation consists of three steps:
1. Environment setup: [install python environment](../../README.md#development-environment), [configure LLM config](../../README.md#configure-openhands-and-your-llm), and [pull docker](#openhands-visual-swe-bench-instance-level-docker-support).
2. [Run inference](#run-inference-on-visual-swe-bench-instances): Generate a edit patch for each Github issue.
3. [Evaluate patches using Visual SWE-Bench docker](#evaluate-generated-patches).
## Setup Environment and LLM Configuration
Please follow instruction [here](../../README.md#setup) to setup your local development environment and LLM.
## OpenHands Visual SWE-Bench Instance-level Docker Support
OpenHands now support using the official evaluation docker for both **[inference](#run-inference-on-visual-swe-bench-instances) and [evaluation](#evaluate-generated-patches)**.
This is now the default behavior.
## Run Inference on Visual SWE-Bench Instances
Make sure your Docker daemon is running, and you have ample disk space for the [instance-level docker image](#openhands-visual-swe-bench-instance-level-docker-support).
When the `run_infer.sh` script is started, it will automatically pull the relevant Visual SWE-Bench images. For example, for instance ID `networkx__networkx-6503`, it will try to pull our pre-build docker image `sweb.eval.x86_64.networkx_s_networkx-6503` from DockerHub. This image will be used create an OpenHands runtime image where the agent will operate on.
```bash
./evaluation/benchmarks/visual_swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers]
# Example
./evaluation/benchmarks/visual_swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 133 30 1
```
where `model_config` is mandatory, and the rest are optional.
- `model_config`, e.g. `eval_gpt4_1106_preview`, is the config group name for your
LLM settings, as defined in your `config.toml`.
- `git-version`, e.g. `HEAD`, is the git commit hash of the OpenHands version you would
like to evaluate. It could also be a release tag like `0.6.2`.
- `agent`, e.g. `CodeActAgent`, is the name of the agent for benchmarks, defaulting
to `CodeActAgent`.
- `eval_limit`, e.g. `10`, limits the evaluation to the first `eval_limit` instances. By
default, the script evaluates the entire Visual SWE-bench set (133 issues). Note:
in order to use `eval_limit`, you must also set `agent`.
- `max_iter`, e.g. `20`, is the maximum number of iterations for the agent to run. By
default, it is set to 30.
- `num_workers`, e.g. `3`, is the number of parallel workers to run the evaluation. By
default, it is set to 1.
There are also two optional environment variables you can set.
```bash
export USE_HINT_TEXT=true # if you want to use hint text in the evaluation. Default to false. Ignore this if you are not sure.
export USE_INSTANCE_IMAGE=true # if you want to use instance-level docker images. Default to true
```
Let's say you'd like to run 10 instances using `llm.eval_gpt4_1106_preview` and CodeActAgent,
then your command would be:
```bash
./evaluation/benchmarks/visual_swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 10
```
### Specify a subset of tasks to run infer
If you would like to specify a list of tasks you'd like to benchmark on, you could
create a `config.toml` under `./evaluation/benchmarks/visual_swe_bench/` folder, and put a list
attribute named `selected_ids`, e.g.
```toml
selected_ids = ['astropy__astropy-13838', 'matplotlib__matplotlib-21617', 'plotly__plotly.py-1966']
```
Then only these tasks (rows whose `instance_id` is in the above list) will be evaluated.
In this case, `eval_limit` option applies to tasks that are in the `selected_ids` list.
After running the inference, you will obtain a `output.jsonl` (by default it will be saved to `evaluation/evaluation_outputs`).
## Evaluate Generated Patches
### Download Docker Images
**(Recommended for reproducibility)** If you have extra local space (e.g., 200GB), you can try pull the instance-level docker images we've prepared by running:
```bash
evaluation/benchmarks/visual_swe_bench/scripts/docker/pull_all_eval_docker.sh instance
```
If you want to save disk space a bit, while speeding up the image pre-build process, you can pull the environment-level docker images:
```bash
evaluation/benchmarks/visual_swe_bench/scripts/docker/pull_all_eval_docker.sh env
```
If you want to evaluate on the full SWE-Bench test set:
```bash
evaluation/benchmarks/visual_swe_bench/scripts/docker/pull_all_eval_docker.sh instance full
```
### Run evaluation
With `output.jsonl` file, you can run `eval_infer.sh` to evaluate generated patches, and produce a fine-grained report.
**This evaluation is performed using the official dockerized evaluation announced.**
> If you want to evaluate existing results, you should first run this to clone existing outputs
>
>```bash
>git clone https://huggingface.co/spaces/OpenHands/evaluation evaluation/evaluation_outputs
>```
NOTE, you should have already pulled the instance-level OR env-level docker images following [this section](#openhands-visual-swe-bench-instance-level-docker-support).
Then you can run the following:
```bash
./evaluation/benchmarks/visual_swe_bench/scripts/eval_infer.sh $YOUR_OUTPUT_JSONL [instance_id]
# Example
./evaluation/benchmarks/visual_swe_bench/scripts/eval_infer.sh evaluation/evaluation_outputs/outputs/luolin101__Visual-SWE-bench-test/CodeActAgent/gpt-4-1106-preview_maxiter_50_N_v1.0/output.jsonl
```
The script now accepts optional arguments:
- `instance_id`: Specify a single instance to evaluate (optional)
For example, to evaluate a specific instance with a custom dataset and split:
```bash
./evaluation/benchmarks/visual_swe_bench/scripts/eval_infer.sh $YOUR_OUTPUT_JSONL instance_123
```
> You can also pass in a JSONL with SWE-Bench format to `./evaluation/benchmarks/visual_swe_bench/scripts/eval_infer.sh`, where each line is a JSON of `{"model_patch": "XXX", "model_name_or_path": "YYY", "instance_id": "ZZZ"}`.
The final results will be saved to `evaluation/evaluation_outputs/outputs/visual_swe_bench/CodeActAgent/gpt-4-1106-preview_maxiter_50_N_v1.0/` with the following files/directory:
- `README.md`: a report showing what are the instances that passed, failed, etc.
- `report.json`: a JSON file that contains keys like `"resolved_ids"` pointing to instance IDs that are resolved by the agent.
- `logs/`: a directory of test logs
## Visualize Results
First you need to clone `https://huggingface.co/spaces/OpenHands/evaluation` and add your own running results from openhands into the `outputs` of the cloned repo.
```bash
git clone https://huggingface.co/spaces/OpenHands/evaluation
```
**(optional) setup streamlit environment with conda**:
```bash
cd evaluation
conda create -n streamlit python=3.10
conda activate streamlit
pip install -r requirements.txt
```
**run the visualizer**:
Then, in a separate Python environment with `streamlit` library, you can run the following:
```bash
# Make sure you are inside the cloned `evaluation` repo
conda activate streamlit # if you follow the optional conda env setup above
streamlit app.py --server.port 8501 --server.address 0.0.0.0
```
Then you can access the SWE-Bench trajectory visualizer at `localhost:8501`.
## Submit your evaluation results
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).

View File

@@ -0,0 +1,641 @@
import asyncio
import json
import os
import tempfile
from typing import Any
import pandas as pd
import toml
from datasets import load_dataset
import openhands.agenthub
from evaluation.benchmarks.swe_bench.resource.mapping import (
get_instance_resource_factor,
)
from evaluation.utils.shared import (
EvalException,
EvalMetadata,
EvalOutput,
assert_and_raise,
codeact_user_response,
get_default_sandbox_config_for_eval,
get_metrics,
is_fatal_evaluation_error,
make_metadata,
prepare_dataset,
reset_logger_for_multiprocessing,
run_evaluation,
update_llm_config_for_completions_logging,
)
from openhands.controller.state.state import State
from openhands.core.config import (
AgentConfig,
AppConfig,
get_llm_config_arg,
get_parser,
)
from openhands.core.logger import openhands_logger as logger
from openhands.core.main import create_runtime, run_controller
from openhands.events.action import CmdRunAction, MessageAction
from openhands.events.observation import CmdOutputObservation, ErrorObservation
from openhands.events.serialization.event import event_to_dict
from openhands.runtime.base import Runtime
from openhands.utils.async_utils import call_async_from_sync
from openhands.utils.shutdown_listener import sleep_if_should_continue
USE_HINT_TEXT = os.environ.get('USE_HINT_TEXT', 'false').lower() == 'true'
RUN_WITH_BROWSING = os.environ.get('RUN_WITH_BROWSING', 'false').lower() == 'true'
AGENT_CLS_TO_FAKE_USER_RESPONSE_FN = {
'CodeActAgent': codeact_user_response,
}
def _get_swebench_workspace_dir_name(instance: pd.Series) -> str:
return f'{instance.repo}__{instance.version}'.replace('/', '__')
def get_instruction(instance: pd.Series, metadata: EvalMetadata):
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
# Instruction based on Anthropic's official trajectory
# https://github.com/eschluntz/swe-bench-experiments/tree/main/evaluation/verified/20241022_tools_claude-3-5-sonnet-updated/trajs
instruction = (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a python code repository in the directory {workspace_dir_name}. Consider the following issue description:\n\n"
f'<issue_description>\n'
f'{instance.problem_statement}\n'
'</issue_description>\n\n'
'Can you help me implement the necessary changes to the repository so that the requirements specified in the <issue_description> are met?\n'
"I've already taken care of all changes to any of the test files described in the <issue_description>. This means you DON'T have to modify the testing logic or any of the tests in any way!\n"
"Also the development Python environment is already set up for you (i.e., all dependencies already installed), so you don't need to install other packages.\n"
'Your task is to make the minimal changes to non-test files in the /workspace directory to ensure the <issue_description> is satisfied.\n'
'Follow these steps to resolve the issue:\n'
'1. As a first step, it might be a good idea to explore the repo to familiarize yourself with its structure.\n'
'2. Create a script to reproduce the error and execute it with `python <filename.py>` using the BashTool, to confirm the error\n'
'3. Edit the sourcecode of the repo to resolve the issue\n'
'4. Rerun your reproduce script and confirm that the error is fixed!\n'
'5. Think about edgecases, add comprehensive tests for them in your reproduce script, and run them to make sure your fix handles them as well\n'
f'6. Once you are done with the initial implementation, please carefully re-read the problem description and check the difference between the current code and the base commit {instance["base_commit"]}. Do you think that the issue has been completely and comprehensively solved? Write tests to check the correctness of the solution, specifically focusing on tests that may point out any remaining problems that are not yet solved. Run all of the tests in the repo and check if any of them fail, and if they do fix the code. Repeat this process of carefully reading the problem description and current implementation, testing, and fixing any problems until you are confident that the current implementation is correct. Find and run any tests in the repo that are related to:\n'
' - The issue you are fixing\n'
' - The files you modified\n'
' - The functions you changed\n'
' Make sure all these tests pass with your changes.\n'
"Your thinking should be thorough and so it's fine if it's very long.\n"
)
if RUN_WITH_BROWSING:
instruction += (
'<IMPORTANT!>\nYou SHOULD NEVER attempt to browse the web. </IMPORTANT!>\n'
)
return instruction
# TODO: migrate all swe-bench docker to ghcr.io/openhands
DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/xingyaoww/')
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
def get_instance_docker_image(instance_id: str, official_image: bool = False) -> str:
image_name = 'sweb.eval.x86_64.' + instance_id
image_name = image_name.replace(
'__', '_s_'
) # to comply with docker image naming convention
other_list = [
'plotly__plotly.py-4083',
'plotly__plotly.py-2600',
'plotly__plotly.py-2591',
'plotly__plotly.py-1966',
'networkx__networkx-6503',
'networkx__networkx-6098',
'networkx__networkx-5616',
'networkx__networkx-5354',
'networkx__networkx-5058',
'networkx__networkx-4378',
'networkx__networkx-3764',
'vega__altair-2785',
'vega__altair-1092',
'vega__altair-974',
'vega__altair-830',
'matplotlib__matplotlib-27754',
'matplotlib__matplotlib-26926',
'matplotlib__matplotlib-26788',
'matplotlib__matplotlib-26586',
'sympy__sympy-26941',
'mwaskom__seaborn-3458',
'mwaskom__seaborn-3454',
]
if instance_id in other_list:
return ('docker.io/luolin101/'.rstrip('/') + '/' + image_name).lower()
return (DOCKER_IMAGE_PREFIX.rstrip('/') + '/' + image_name).lower()
def get_config(
instance: pd.Series,
metadata: EvalMetadata,
) -> AppConfig:
# We use a different instance image for the each instance of swe-bench eval
use_official_image = bool(
'verified' in metadata.dataset.lower() or 'lite' in metadata.dataset.lower()
)
base_container_image = get_instance_docker_image(
instance['instance_id'], use_official_image
)
logger.info(
f'Using instance container image: {base_container_image}. '
f'Please make sure this image exists. '
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
)
sandbox_config = get_default_sandbox_config_for_eval()
sandbox_config.base_container_image = base_container_image
sandbox_config.enable_auto_lint = True
sandbox_config.use_host_network = False
# Add platform to the sandbox config to solve issue 4401
sandbox_config.platform = 'linux/amd64'
sandbox_config.remote_runtime_resource_factor = get_instance_resource_factor(
dataset_name=metadata.dataset,
instance_id=instance['instance_id'],
)
config = AppConfig(
default_agent=metadata.agent_class,
run_as_openhands=False,
max_iterations=metadata.max_iterations,
runtime=os.environ.get('RUNTIME', 'docker'),
sandbox=sandbox_config,
# do not mount workspace
workspace_base=None,
workspace_mount_path=None,
)
config.set_llm_config(
update_llm_config_for_completions_logging(
metadata.llm_config, metadata.eval_output_dir, instance['instance_id']
)
)
agent_config = AgentConfig(
enable_jupyter=False,
enable_browsing=RUN_WITH_BROWSING,
enable_llm_editor=False,
condenser=metadata.condenser_config,
enable_prompt_extensions=False,
)
config.set_agent_config(agent_config)
return config
def initialize_runtime(
runtime: Runtime,
instance: pd.Series, # this argument is not required
):
"""Initialize the runtime for the agent.
This function is called before the runtime is used to run the agent.
"""
logger.info('-' * 30)
logger.info('BEGIN Runtime Initialization Fn')
logger.info('-' * 30)
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
obs: CmdOutputObservation
# Set instance id
action = CmdRunAction(
command=f"""echo 'export SWE_INSTANCE_ID={instance['instance_id']}' >> ~/.bashrc && echo 'export PIP_CACHE_DIR=~/.cache/pip' >> ~/.bashrc && echo "alias git='git --no-pager'" >> ~/.bashrc"""
)
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0, f'Failed to export SWE_INSTANCE_ID: {str(obs)}'
)
action = CmdRunAction(command="""export USER=$(whoami); echo USER=${USER} """)
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(obs.exit_code == 0, f'Failed to export USER: {str(obs)}')
# inject the init script
script_dir = os.path.dirname(__file__)
# inject the instance info
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to create /swe_util/eval_data/instances: {str(obs)}',
)
swe_instance_json_name = 'swe-bench-instance.json'
with tempfile.TemporaryDirectory() as temp_dir:
# Construct the full path for the desired file name within the temporary directory
temp_file_path = os.path.join(temp_dir, swe_instance_json_name)
# Write to the file with the desired name within the temporary directory
with open(temp_file_path, 'w') as f:
if not isinstance(instance, dict):
json.dump([instance.to_dict()], f)
else:
json.dump([instance], f)
# Copy the file to the desired location
runtime.copy_to(temp_file_path, '/swe_util/eval_data/instances/')
# inject the instance swe entry
runtime.copy_to(
str(os.path.join(script_dir, 'scripts/setup/instance_swe_entry.sh')),
'/swe_util/',
)
action = CmdRunAction(command='cat ~/.bashrc')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(obs.exit_code == 0, f'Failed to cat ~/.bashrc: {str(obs)}')
action = CmdRunAction(command='source ~/.bashrc')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
if isinstance(obs, ErrorObservation):
logger.error(f'Failed to source ~/.bashrc: {str(obs)}')
assert_and_raise(obs.exit_code == 0, f'Failed to source ~/.bashrc: {str(obs)}')
action = CmdRunAction(command='source /swe_util/instance_swe_entry.sh')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to source /swe_util/instance_swe_entry.sh: {str(obs)}',
)
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to cd to /workspace/{workspace_dir_name}: {str(obs)}',
)
action = CmdRunAction(command='git reset --hard')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(obs.exit_code == 0, f'Failed to git reset --hard: {str(obs)}')
action = CmdRunAction(
command='for remote_name in $(git remote); do git remote remove "${remote_name}"; done'
)
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(obs.exit_code == 0, f'Failed to remove git remotes: {str(obs)}')
action = CmdRunAction(command='which python')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0 and 'testbed' in obs.content,
f'Expected to find python interpreter from testbed, but got: {str(obs)}',
)
logger.info('-' * 30)
logger.info('END Runtime Initialization Fn')
logger.info('-' * 30)
def complete_runtime(
runtime: Runtime,
instance: pd.Series, # this argument is not required, but it is used to get the workspace_dir_name
) -> dict[str, Any]:
"""Complete the runtime for the agent.
This function is called before the runtime is used to run the agent.
If you need to do something in the sandbox to get the correctness metric after
the agent has run, modify this function.
"""
logger.info('-' * 30)
logger.info('BEGIN Runtime Completion Fn')
logger.info('-' * 30)
obs: CmdOutputObservation
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
if obs.exit_code == -1:
# The previous command is still running
# We need to kill previous command
logger.info('The previous command is still running, trying to kill it...')
action = CmdRunAction(command='C-c')
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
# Then run the command again
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to cd to /workspace/{workspace_dir_name}: {str(obs)}',
)
action = CmdRunAction(command='git config --global core.pager ""')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to git config --global core.pager "": {str(obs)}',
)
# First check for any git repositories in subdirectories
action = CmdRunAction(command='find . -type d -name .git -not -path "./.git"')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to find git repositories: {str(obs)}',
)
git_dirs = [p for p in obs.content.strip().split('\n') if p]
if git_dirs:
# Remove all .git directories in subdirectories
for git_dir in git_dirs:
action = CmdRunAction(command=f'rm -rf "{git_dir}"')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to remove git directory {git_dir}: {str(obs)}',
)
# add all files
action = CmdRunAction(command='git add -A')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to git add -A: {str(obs)}',
)
n_retries = 0
git_patch = None
while n_retries < 5:
action = CmdRunAction(
command=f'git diff --no-color --cached {instance["base_commit"]}'
)
action.set_hard_timeout(max(300 + 100 * n_retries, 600))
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
n_retries += 1
if isinstance(obs, CmdOutputObservation):
if obs.exit_code == 0:
git_patch = obs.content.strip()
break
else:
logger.info('Failed to get git diff, retrying...')
sleep_if_should_continue(10)
elif isinstance(obs, ErrorObservation):
logger.error(f'Error occurred: {obs.content}. Retrying...')
sleep_if_should_continue(10)
else:
assert_and_raise(False, f'Unexpected observation type: {str(obs)}')
assert_and_raise(git_patch is not None, 'Failed to get git diff (None)')
logger.info('-' * 30)
logger.info('END Runtime Completion Fn')
logger.info('-' * 30)
return {'git_patch': git_patch}
def process_instance(
instance: pd.Series,
metadata: EvalMetadata,
reset_logger: bool = True,
runtime_failure_count: int = 0,
) -> EvalOutput:
config = get_config(instance, metadata)
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
if reset_logger:
log_dir = os.path.join(metadata.eval_output_dir, 'infer_logs')
reset_logger_for_multiprocessing(logger, instance.instance_id, log_dir)
else:
logger.info(f'Starting evaluation for instance {instance.instance_id}.')
# Increase resource_factor with increasing attempt_id
if runtime_failure_count > 0:
config.sandbox.remote_runtime_resource_factor = min(
config.sandbox.remote_runtime_resource_factor * (2**runtime_failure_count),
8,
)
logger.warning(
f'This is the {runtime_failure_count + 1}th attempt for instance {instance.instance_id}, setting resource factor to {config.sandbox.remote_runtime_resource_factor}'
)
runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
try:
initialize_runtime(runtime, instance)
instruction = get_instruction(instance, metadata)
# Here's how you can run the agent (similar to the `main` function) and get the final task state
state: State | None = asyncio.run(
run_controller(
config=config,
initial_user_action=MessageAction(content=instruction),
runtime=runtime,
fake_user_response_fn=AGENT_CLS_TO_FAKE_USER_RESPONSE_FN[
metadata.agent_class
],
)
)
# if fatal error, throw EvalError to trigger re-run
if is_fatal_evaluation_error(state.last_error):
raise EvalException('Fatal error detected: ' + state.last_error)
# ======= THIS IS SWE-Bench specific =======
# Get git patch
return_val = complete_runtime(runtime, instance)
git_patch = return_val['git_patch']
logger.info(
f'Got git diff for instance {instance.instance_id}:\n--------\n{git_patch}\n--------'
)
finally:
runtime.close()
# ==========================================
# ======= Attempt to evaluate the agent's edits =======
# we use eval_infer.sh to evaluate the agent's edits, not here
# because the agent may alter the environment / testcases
test_result = {
'git_patch': git_patch,
}
# If you are working on some simpler benchmark that only evaluates the final model output (e.g., in a MessageAction)
# You can simply get the LAST `MessageAction` from the returned `state.history` and parse it for evaluation.
if state is None:
raise ValueError('State should not be None.')
# NOTE: this is NO LONGER the event stream, but an agent history that includes delegate agent's events
histories = [event_to_dict(event) for event in state.history]
metrics = get_metrics(state)
# Save the output
output = EvalOutput(
instance_id=instance.instance_id,
instruction=instruction,
instance=instance.to_dict(), # SWE Bench specific
test_result=test_result,
metadata=metadata,
history=histories,
metrics=metrics,
error=state.last_error if state and state.last_error else None,
)
return output
def filter_dataset(dataset: pd.DataFrame, filter_column: str) -> pd.DataFrame:
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.toml')
if os.path.exists(file_path):
with open(file_path, 'r') as file:
data = toml.load(file)
if 'selected_ids' in data:
selected_ids = data['selected_ids']
logger.info(
f'Filtering {len(selected_ids)} tasks from "selected_ids"...'
)
subset = dataset[dataset[filter_column].isin(selected_ids)]
logger.info(f'Retained {subset.shape[0]} tasks after filtering')
return subset
skip_ids = os.environ.get('SKIP_IDS', '').split(',')
if len(skip_ids) > 0:
logger.info(f'Filtering {len(skip_ids)} tasks from "SKIP_IDS"...')
return dataset[~dataset[filter_column].isin(skip_ids)]
return dataset
# A list of instances that are known to be tricky to infer
# (will cause runtime failure even with resource factor = 8)
SWEGYM_EXCLUDE_IDS = [
'dask__dask-10422',
'pandas-dev__pandas-50548',
'pandas-dev__pandas-53672',
'pandas-dev__pandas-54174',
'pandas-dev__pandas-55518',
'pandas-dev__pandas-58383',
'pydata__xarray-6721',
'pytest-dev__pytest-10081',
'pytest-dev__pytest-7236',
]
if __name__ == '__main__':
parser = get_parser()
parser.add_argument(
'--dataset',
type=str,
default='princeton-nlp/SWE-bench',
help='data set to evaluate on, either full-test or lite-test',
)
parser.add_argument(
'--split',
type=str,
default='test',
help='split to evaluate on',
)
args, _ = parser.parse_known_args()
# NOTE: It is preferable to load datasets from huggingface datasets and perform post-processing
# so we don't need to manage file uploading to OpenHands's repo
dataset = load_dataset(args.dataset, split=args.split)
swe_bench_tests = filter_dataset(dataset.to_pandas(), 'instance_id')
logger.info(
f'Loaded dataset {args.dataset} with split {args.split}: {len(swe_bench_tests)} tasks'
)
if 'SWE-Gym' in args.dataset:
swe_bench_tests = swe_bench_tests[
~swe_bench_tests['instance_id'].isin(SWEGYM_EXCLUDE_IDS)
]
logger.info(
f'{len(swe_bench_tests)} tasks left after excluding SWE-Gym excluded tasks'
)
llm_config = None
if args.llm_config:
llm_config = get_llm_config_arg(args.llm_config)
llm_config.log_completions = True
# modify_params must be False for evaluation purpose, for reproducibility and accurancy of results
llm_config.modify_params = False
if llm_config is None:
raise ValueError(f'Could not find LLM config: --llm_config {args.llm_config}')
details = {}
_agent_cls = openhands.agenthub.Agent.get_cls(args.agent_cls)
dataset_descrption = (
args.dataset.replace('/', '__') + '-' + args.split.replace('/', '__')
)
metadata = make_metadata(
llm_config,
dataset_descrption,
args.agent_cls,
args.max_iterations,
args.eval_note,
args.eval_output_dir,
details=details,
)
output_file = os.path.join(metadata.eval_output_dir, 'output.jsonl')
print(f'### OUTPUT FILE: {output_file} ###')
instances = prepare_dataset(swe_bench_tests, output_file, args.eval_n_limit)
if len(instances) > 0 and not isinstance(
instances['PASS_TO_PASS'][instances['PASS_TO_PASS'].index[0]], str
):
for col in ['PASS_TO_PASS', 'FAIL_TO_PASS']:
instances[col] = instances[col].apply(lambda x: str(x))
run_evaluation(
instances,
metadata,
output_file,
args.eval_num_workers,
process_instance,
timeout_seconds=8 * 60 * 60, # 8 hour PER instance should be more than enough
max_retries=5,
)

View File

@@ -0,0 +1,157 @@
xingyaoww/sweb.eval.x86_64.astropy_s_astropy-11693:latest
xingyaoww/sweb.eval.x86_64.astropy_s_astropy-13838:latest
xingyaoww/sweb.eval.x86_64.astropy_s_astropy-14295:latest
xingyaoww/sweb.eval.x86_64.astropy_s_astropy-8292:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-13908:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-13980:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-13983:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-13984:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-14043:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-14623:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-19763:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-20470:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-20518:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-20584:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-20761:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-20826:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-21443:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-21490:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-21550:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-21568:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-21617:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-22865:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-22871:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-22931:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-23047:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-23111:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-23412:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24088:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24177:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24189:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24570:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24691:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24749:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24768:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24849:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24870:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-24971:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25287:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25334:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25340:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25346:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25405:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25499:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25565:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25640:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25667:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25779:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-26078:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-26466:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-2576:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-2846:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-2979:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-3180:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-3187:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-3202:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-3216:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-3217:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-3276:latest
xingyaoww/sweb.eval.x86_64.mwaskom_s_seaborn-3394:latest
xingyaoww/sweb.eval.x86_64.pydata_s_xarray-4182:latest
xingyaoww/sweb.eval.x86_64.pydata_s_xarray-5682:latest
xingyaoww/sweb.eval.x86_64.pylint-dev_s_pylint-4551:latest
xingyaoww/sweb.eval.x86_64.scikit-learn_s_scikit-learn-13087:latest
xingyaoww/sweb.eval.x86_64.scikit-learn_s_scikit-learn-13618:latest
xingyaoww/sweb.eval.x86_64.scikit-learn_s_scikit-learn-14067:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-10048:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-10097:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-10191:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-10435:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-11266:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-11502:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-7615:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-7757:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8028:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8056:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8075:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8120:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8265:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8278:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8620:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8621:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8638:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-8658:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9229:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9230:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9289:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9320:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9350:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9464:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9673:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9698:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9797:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9982:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9987:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9997:latest
xingyaoww/sweb.eval.x86_64.sphinx-doc_s_sphinx-9999:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-11787:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-11788:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-13264:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-13840:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-15151:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-15304:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-15625:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-15976:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-16003:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-17067:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-17115:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-18922:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-21769:latest
xingyaoww/sweb.eval.x86_64.sympy_s_sympy-24723:latest
luolin101/sweb.eval.x86_64.plotly_s_plotly.py-4083:latest
luolin101/sweb.eval.x86_64.plotly_s_plotly.py-2600:latest
luolin101/sweb.eval.x86_64.plotly_s_plotly.py-2591:latest
luolin101/sweb.eval.x86_64.plotly_s_plotly.py-1966:latest
luolin101/sweb.eval.x86_64.networkx_s_networkx-6503:latest
luolin101/sweb.eval.x86_64.networkx_s_networkx-6098:latest
luolin101/sweb.eval.x86_64.networkx_s_networkx-5616:latest
luolin101/sweb.eval.x86_64.networkx_s_networkx-5354:latest
luolin101/sweb.eval.x86_64.networkx_s_networkx-5058:latest
luolin101/sweb.eval.x86_64.networkx_s_networkx-4378:latest
luolin101/sweb.eval.x86_64.networkx_s_networkx-3764:latest
luolin101/sweb.eval.x86_64.vega_s_altair-2785:latest
luolin101/sweb.eval.x86_64.vega_s_altair-1092:latest
luolin101/sweb.eval.x86_64.vega_s_altair-974:latest
luolin101/sweb.eval.x86_64.vega_s_altair-830:latest
luolin101/sweb.eval.x86_64.matplotlib_s_matplotlib-27754:latest
luolin101/sweb.eval.x86_64.matplotlib_s_matplotlib-26926:latest
luolin101/sweb.eval.x86_64.matplotlib_s_matplotlib-26788:latest
luolin101/sweb.eval.x86_64.matplotlib_s_matplotlib-26586:latest
luolin101/sweb.eval.x86_64.sympy_s_sympy-26941:latest
luolin101/sweb.eval.x86_64.mwaskom_s_seaborn-3458:latest
luolin101/sweb.eval.x86_64.mwaskom_s_seaborn-3454:latest
xingyaoww/sweb.eval.x86_64.matplotlib_s_matplotlib-25631:latest
xingyaoww/sweb.env.x86_64.428468730904ff6b4232aa:latest
xingyaoww/sweb.env.x86_64.89a9e6df7ab7bcb9e010c8:latest
xingyaoww/sweb.env.x86_64.15374367de368534f261e3:latest
xingyaoww/sweb.env.x86_64.6b007979cf533f0f3016e8:latest
xingyaoww/sweb.env.x86_64.b382c45e0a94d34ef0fc86:latest
xingyaoww/sweb.env.x86_64.7037e8c448a4b8ebfe9b13:latest
xingyaoww/sweb.env.x86_64.31244378a92e3bcce809ac:latest
xingyaoww/sweb.env.x86_64.efa6065ed5bf204410fd53:latest
xingyaoww/sweb.env.x86_64.a0efca7a0fe6719dbf65c2:latest
xingyaoww/sweb.env.x86_64.502d8fc6ebccd881244091:latest
luolin101/sweb.env.x86_64.eb002359cfcbe2edb56088:latest
xingyaoww/sweb.env.x86_64.d905bb51fb68acc5d4221b:latest
xingyaoww/sweb.env.x86_64.aa92880033da20ca313928:latest
luolin101/sweb.env.x86_64.c6d251a05e0af7688b64fd:latest
xingyaoww/sweb.env.x86_64.c795f4b88616b8462021ed:latest
luolin101/sweb.env.x86_64.1e5a06e76ee016d067d77e:latest
luolin101/sweb.env.x86_64.2e03d8e4d4bd373937a9ef:latest
luolin101/sweb.env.x86_64.4c16026920d27ea78f3b7a:latest
luolin101/sweb.env.x86_64.d15120dfdbda9831e9646b:latest
luolin101/sweb.env.x86_64.c581ba273c3275679773dd:latest
luolin101/sweb.env.x86_64.dc800a1bbe275c5de0c4aa:latest
luolin101/sweb.env.x86_64.59bd7d84a0939c7caba7e6:latest
xingyaoww/sweb.env.x86_64.0d80c7dec81ee2f2f513e2:latest
xingyaoww/sweb.base.x86_64:latest

View File

@@ -0,0 +1,62 @@
#!/bin/bash
set -e
LEVEL=$1
# three levels:
# - base, keyword "sweb.base"
# - env, keyword "sweb.env"
# - instance, keyword "sweb.eval"
SET=$2
if [ -z "$LEVEL" ]; then
echo "Usage: $0 <cache_level> <set>"
echo "cache_level: base, env, or instance"
echo "set: lite, full"
exit 1
fi
if [ -z "$SET" ]; then
echo "Usage: $0 <cache_level> <set>"
echo "cache_level: base, env, or instance"
echo "set: lite, full, default is lite"
SET="lite"
fi
if [ "$SET" == "full" ]; then
IMAGE_FILE="$(dirname "$0")/all-visualswebench-full-instance-images.txt"
else
IMAGE_FILE="$(dirname "$0")/all-visualswebench-full-instance-images.txt"
fi
# Define a pattern based on the level
case $LEVEL in
base)
PATTERN="sweb.base"
;;
env)
PATTERN="sweb.base\|sweb.env"
;;
instance)
PATTERN="sweb.base\|sweb.env\|sweb.eval"
;;
*)
echo "Invalid cache level: $LEVEL"
echo "Valid levels are: base, env, instance"
exit 1
;;
esac
echo "Pulling docker images for [$LEVEL] level"
echo "Pattern: $PATTERN"
echo "Image file: $IMAGE_FILE"
# Read each line from the file, filter by pattern, and pull the docker image
grep "$PATTERN" "$IMAGE_FILE" | while IFS= read -r image; do
echo "Pulling $image into $image"
docker pull $image
# replace _s_ to __ in the image name
renamed_image=$(echo "$image" | sed 's|.*/||; s/_s_/__/g')
docker tag $image $renamed_image
done

View File

@@ -0,0 +1,141 @@
#!/bin/bash
PROCESS_FILEPATH=$1
if [ -z "$PROCESS_FILEPATH" ]; then
echo "Error: PROCESS_FILEPATH is empty. Usage: ./eval_infer.sh <output_file> [instance_id] [dataset_name] [split]"
exit 1
fi
if [ ! -f $PROCESS_FILEPATH ]; then
echo "Error: $PROCESS_FILEPATH is not a file"
exit 1
fi
# If instance_id is empty, it means we want to eval on the whole $PROCESS_FILEPATH
# otherwise, we want to eval on the instance_id
INSTANCE_ID=$2
DATASET_NAME=${3:-"luolin101/Visual-SWE-bench"}
SPLIT=${4:-"test"}
echo "INSTANCE_ID: $INSTANCE_ID"
echo "DATASET_NAME: $DATASET_NAME"
echo "SPLIT: $SPLIT"
PROCESS_FILEPATH=$(realpath $PROCESS_FILEPATH)
FILE_DIR=$(dirname $PROCESS_FILEPATH)
FILE_NAME=$(basename $PROCESS_FILEPATH)
echo "Evaluating $FILE_NAME @ $FILE_DIR"
# ================================================
# detect whether PROCESS_FILEPATH is in OH format or in SWE-bench format
echo "=============================================================="
echo "Detecting whether PROCESS_FILEPATH is in OH format or in SWE-bench format"
echo "=============================================================="
# SWE-bench format is a JSONL where every line has three fields: model_name_or_path, instance_id, and model_patch
function is_swebench_format() {
# Read the first line of the file
read -r first_line < "$PROCESS_FILEPATH"
# Use jq to check if the first line has the required fields
echo "$first_line" | jq -e '. | has("model_name_or_path") and has("instance_id") and has("model_patch")' > /dev/null
if [ $? -ne 0 ]; then
return 1 # Return 1 if the first line does not have the required fields
fi
return 0 # Return 0 if the first line has the required fields
}
# Call the function with the file path
is_swebench_format "$PROCESS_FILEPATH"
IS_SWEBENCH_FORMAT=$?
# Use the result in an if-else statement
if [ $IS_SWEBENCH_FORMAT -eq 0 ]; then
echo "The file IS in SWE-bench format."
SWEBENCH_FORMAT_JSONL=$PROCESS_FILEPATH
else
echo "The file IS NOT in SWE-bench format."
# ==== Convert OH format to SWE-bench format ====
echo "Merged output file with fine-grained report will be saved to $FILE_DIR"
poetry run python3 evaluation/benchmarks/swe_bench/scripts/eval/convert_oh_output_to_swe_json.py $PROCESS_FILEPATH
# replace .jsonl with .swebench.jsonl in filename
SWEBENCH_FORMAT_JSONL=${PROCESS_FILEPATH/.jsonl/.swebench.jsonl}
echo "SWEBENCH_FORMAT_JSONL: $SWEBENCH_FORMAT_JSONL"
# assert that the file exists
if [ ! -f $SWEBENCH_FORMAT_JSONL ]; then
echo "Error: $SWEBENCH_FORMAT_JSONL does not exist. There is probably an error in the conversion process."
exit 1
fi
SWEBENCH_FORMAT_JSONL=$(realpath $SWEBENCH_FORMAT_JSONL)
fi
# ================================================
echo "=============================================================="
echo "Running SWE-bench evaluation"
echo "=============================================================="
RUN_ID=$(date +"%Y%m%d_%H%M%S")
N_PROCESS=16
if [ -z "$INSTANCE_ID" ]; then
echo "Running SWE-bench evaluation on the whole input file..."
# Default to SWE-Bench-lite
# change `--dataset_name` and `--split` to alter dataset
poetry run python -m visualswebench.harness.run_evaluation \
--dataset_name "$DATASET_NAME" \
--split "$SPLIT" \
--predictions_path $SWEBENCH_FORMAT_JSONL \
--timeout 1800 \
--cache_level instance \
--max_workers $N_PROCESS \
--run_id $RUN_ID
# get the "model_name_or_path" from the first line of the SWEBENCH_FORMAT_JSONL
MODEL_NAME_OR_PATH=$(jq -r '.model_name_or_path' $SWEBENCH_FORMAT_JSONL | head -n 1)
echo "MODEL_NAME_OR_PATH: $MODEL_NAME_OR_PATH"
RESULT_OUTPUT_DIR=$(dirname $SWEBENCH_FORMAT_JSONL)
echo "RESULT_OUTPUT_DIR: $RESULT_OUTPUT_DIR"
# move the eval results to the target directory
mkdir -p $RESULT_OUTPUT_DIR
# rm eval_outputs directory if it exists
if [ -d $RESULT_OUTPUT_DIR/eval_outputs ]; then
rm -rf $RESULT_OUTPUT_DIR/eval_outputs
fi
mv logs/run_evaluation/$RUN_ID/$MODEL_NAME_OR_PATH $RESULT_OUTPUT_DIR
mv $RESULT_OUTPUT_DIR/$MODEL_NAME_OR_PATH $RESULT_OUTPUT_DIR/eval_outputs
echo "RUN_ID: $RUN_ID" > $RESULT_OUTPUT_DIR/run_id.txt
# move report file
REPORT_PATH=$MODEL_NAME_OR_PATH.$RUN_ID.json
if [ -f $REPORT_PATH ]; then
# check if $RESULT_OUTPUT_DIR/report.json exists
if [ -f $RESULT_OUTPUT_DIR/report.json ]; then
echo "Report file $RESULT_OUTPUT_DIR/report.json already exists. Overwriting..."
if [ -f $RESULT_OUTPUT_DIR/report.json.bak ]; then
rm $RESULT_OUTPUT_DIR/report.json.bak
fi
mv $RESULT_OUTPUT_DIR/report.json $RESULT_OUTPUT_DIR/report.json.bak
fi
mv $REPORT_PATH $RESULT_OUTPUT_DIR/report.json
fi
poetry run python evaluation/benchmarks/swe_bench/scripts/eval/update_output_with_eval.py $PROCESS_FILEPATH
else
echo "Running SWE-bench evaluation on the instance_id: $INSTANCE_ID"
poetry run python -m visualswebench.harness.run_evaluation \
--dataset_name "$DATASET_NAME" \
--split "$SPLIT" \
--predictions_path $SWEBENCH_FORMAT_JSONL \
--timeout 1800 \
--instance_ids $INSTANCE_ID \
--cache_level instance \
--max_workers $N_PROCESS \
--run_id $RUN_ID
fi

View File

@@ -0,0 +1,117 @@
#!/bin/bash
set -eo pipefail
source "evaluation/utils/version_control.sh"
MODEL_CONFIG=$1
COMMIT_HASH=$2
AGENT=$3
EVAL_LIMIT=$4
MAX_ITER=$5
NUM_WORKERS=$6
DATASET=$7
SPLIT=$8
N_RUNS=$9
if [ -z "$NUM_WORKERS" ]; then
NUM_WORKERS=1
echo "Number of workers not specified, use default $NUM_WORKERS"
fi
checkout_eval_branch
if [ -z "$AGENT" ]; then
echo "Agent not specified, use default CodeActAgent"
AGENT="CodeActAgent"
fi
if [ -z "$MAX_ITER" ]; then
echo "MAX_ITER not specified, use default 100"
MAX_ITER=100
fi
if [ -z "$USE_INSTANCE_IMAGE" ]; then
echo "USE_INSTANCE_IMAGE not specified, use default true"
USE_INSTANCE_IMAGE=true
fi
if [ -z "$RUN_WITH_BROWSING" ]; then
echo "RUN_WITH_BROWSING not specified, use default false"
RUN_WITH_BROWSING=false
fi
if [ -z "$DATASET" ]; then
echo "DATASET not specified, use default luolin101/Visual-SWE-bench"
DATASET="luolin101/Visual-SWE-bench"
fi
if [ -z "$SPLIT" ]; then
echo "SPLIT not specified, use default test"
SPLIT="test"
fi
export USE_INSTANCE_IMAGE=$USE_INSTANCE_IMAGE
echo "USE_INSTANCE_IMAGE: $USE_INSTANCE_IMAGE"
export RUN_WITH_BROWSING=$RUN_WITH_BROWSING
echo "RUN_WITH_BROWSING: $RUN_WITH_BROWSING"
get_openhands_version
echo "AGENT: $AGENT"
echo "OPENHANDS_VERSION: $OPENHANDS_VERSION"
echo "MODEL_CONFIG: $MODEL_CONFIG"
echo "DATASET: $DATASET"
echo "SPLIT: $SPLIT"
# Default to NOT use Hint
if [ -z "$USE_HINT_TEXT" ]; then
export USE_HINT_TEXT=false
fi
echo "USE_HINT_TEXT: $USE_HINT_TEXT"
EVAL_NOTE="$OPENHANDS_VERSION"
# if not using Hint, add -no-hint to the eval note
if [ "$USE_HINT_TEXT" = false ]; then
EVAL_NOTE="$EVAL_NOTE-no-hint"
fi
if [ "$RUN_WITH_BROWSING" = true ]; then
EVAL_NOTE="$EVAL_NOTE-with-browsing"
fi
if [ -n "$EXP_NAME" ]; then
EVAL_NOTE="$EVAL_NOTE-$EXP_NAME"
fi
function run_eval() {
local eval_note=$1
COMMAND="poetry run python evaluation/benchmarks/visual_swe_bench/run_infer.py \
--agent-cls $AGENT \
--llm-config $MODEL_CONFIG \
--max-iterations $MAX_ITER \
--eval-num-workers $NUM_WORKERS \
--eval-note $eval_note \
--dataset $DATASET \
--split $SPLIT"
if [ -n "$EVAL_LIMIT" ]; then
echo "EVAL_LIMIT: $EVAL_LIMIT"
COMMAND="$COMMAND --eval-n-limit $EVAL_LIMIT"
fi
# Run the command
eval $COMMAND
}
unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
if [ -z "$N_RUNS" ]; then
N_RUNS=1
echo "N_RUNS not specified, use default $N_RUNS"
fi
for i in $(seq 1 $N_RUNS); do
current_eval_note="$EVAL_NOTE-run_$i"
echo "EVAL_NOTE: $current_eval_note"
run_eval $current_eval_note
done
checkout_original_branch

View File

@@ -0,0 +1,40 @@
#!/bin/bash
source ~/.bashrc
SWEUTIL_DIR=/swe_util
# FIXME: Cannot read SWE_INSTANCE_ID from the environment variable
# SWE_INSTANCE_ID=django__django-11099
if [ -z "$SWE_INSTANCE_ID" ]; then
echo "Error: SWE_INSTANCE_ID is not set." >&2
exit 1
fi
# Read the swe-bench-test-lite.json file and extract the required item based on instance_id
item=$(jq --arg INSTANCE_ID "$SWE_INSTANCE_ID" '.[] | select(.instance_id == $INSTANCE_ID)' $SWEUTIL_DIR/eval_data/instances/swe-bench-instance.json)
if [[ -z "$item" ]]; then
echo "No item found for the provided instance ID."
exit 1
fi
WORKSPACE_NAME=$(echo "$item" | jq -r '(.repo | tostring) + "__" + (.version | tostring) | gsub("/"; "__")')
echo "WORKSPACE_NAME: $WORKSPACE_NAME"
# Clear the workspace
if [ -d /workspace ]; then
rm -rf /workspace/*
else
mkdir /workspace
fi
# Copy repo to workspace
if [ -d /workspace/$WORKSPACE_NAME ]; then
rm -rf /workspace/$WORKSPACE_NAME
fi
mkdir -p /workspace
cp -r /testbed /workspace/$WORKSPACE_NAME
# Activate instance-specific environment
. /opt/miniconda3/etc/profile.d/conda.sh
conda activate testbed

View File

@@ -10,11 +10,7 @@ describe("ChatMessage", () => {
expect(screen.getByText("Hello, World!")).toBeInTheDocument();
});
it("should render an assistant message", () => {
render(<ChatMessage type="assistant" message="Hello, World!" />);
expect(screen.getByTestId("assistant-message")).toBeInTheDocument();
expect(screen.getByText("Hello, World!")).toBeInTheDocument();
});
it.todo("should render an assistant message");
it.skip("should support code syntax highlighting", () => {
const code = "```js\nconsole.log('Hello, World!')\n```";
@@ -66,10 +62,7 @@ describe("ChatMessage", () => {
it("should apply correct styles to inline code", () => {
render(
<ChatMessage
type="assistant"
message="Here is some `inline code` text"
/>,
<ChatMessage type="agent" message="Here is some `inline code` text" />,
);
const codeElement = screen.getByText("inline code");

View File

@@ -1,11 +1,9 @@
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import { act, screen, waitFor, within } from "@testing-library/react";
import { screen, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { renderWithProviders } from "test-utils";
import type { Message } from "#/message";
import { addUserMessage } from "#/state/chat-slice";
import { SUGGESTIONS } from "#/utils/suggestions";
import * as ChatSlice from "#/state/chat-slice";
import { WsClientProviderStatus } from "#/context/ws-client-provider";
import { ChatInterface } from "#/components/features/chat/chat-interface";
@@ -42,51 +40,10 @@ describe("Empty state", () => {
vi.clearAllMocks();
});
it("should render suggestions if empty", () => {
const { store } = renderWithProviders(<ChatInterface />, {
preloadedState: {
chat: {
messages: [],
systemMessage: {
content: "",
tools: [],
openhands_version: null,
agent_class: null
}
},
},
});
expect(screen.getByTestId("suggestions")).toBeInTheDocument();
act(() => {
store.dispatch(
addUserMessage({
content: "Hello",
imageUrls: [],
timestamp: new Date().toISOString(),
pending: true,
}),
);
});
expect(screen.queryByTestId("suggestions")).not.toBeInTheDocument();
});
it.todo("should render suggestions if empty");
it("should render the default suggestions", () => {
renderWithProviders(<ChatInterface />, {
preloadedState: {
chat: {
messages: [],
systemMessage: {
content: "",
tools: [],
openhands_version: null,
agent_class: null
}
},
},
});
renderWithProviders(<ChatInterface />);
const suggestions = screen.getByTestId("suggestions");
const repoSuggestions = Object.keys(SUGGESTIONS.repo);
@@ -110,21 +67,8 @@ describe("Empty state", () => {
status: WsClientProviderStatus.CONNECTED,
isLoadingMessages: false,
}));
const addUserMessageSpy = vi.spyOn(ChatSlice, "addUserMessage");
const user = userEvent.setup();
const { store } = renderWithProviders(<ChatInterface />, {
preloadedState: {
chat: {
messages: [],
systemMessage: {
content: "",
tools: [],
openhands_version: null,
agent_class: null
}
},
},
});
renderWithProviders(<ChatInterface />);
const suggestions = screen.getByTestId("suggestions");
const displayedSuggestions = within(suggestions).getAllByRole("button");
@@ -133,9 +77,7 @@ describe("Empty state", () => {
await user.click(displayedSuggestions[0]);
// user message loaded to input
expect(addUserMessageSpy).not.toHaveBeenCalled();
expect(screen.queryByTestId("suggestions")).toBeInTheDocument();
expect(store.getState().chat.messages).toHaveLength(0);
expect(input).toHaveValue(displayedSuggestions[0].textContent);
},
);
@@ -149,19 +91,7 @@ describe("Empty state", () => {
isLoadingMessages: false,
}));
const user = userEvent.setup();
const { rerender } = renderWithProviders(<ChatInterface />, {
preloadedState: {
chat: {
messages: [],
systemMessage: {
content: "",
tools: [],
openhands_version: null,
agent_class: null
}
},
},
});
const { rerender } = renderWithProviders(<ChatInterface />);
const suggestions = screen.getByTestId("suggestions");
const displayedSuggestions = within(suggestions).getAllByRole("button");

View File

@@ -20,7 +20,6 @@ describe("AccountSettingsContextMenu", () => {
<AccountSettingsContextMenu
onLogout={onLogoutMock}
onClose={onCloseMock}
isLoggedIn
/>,
);
@@ -35,7 +34,6 @@ describe("AccountSettingsContextMenu", () => {
<AccountSettingsContextMenu
onLogout={onLogoutMock}
onClose={onCloseMock}
isLoggedIn
/>,
);
@@ -45,19 +43,18 @@ describe("AccountSettingsContextMenu", () => {
expect(onLogoutMock).toHaveBeenCalledOnce();
});
test("onLogout should be disabled if the user is not logged in", async () => {
test("logout button is always enabled", async () => {
render(
<AccountSettingsContextMenu
onLogout={onLogoutMock}
onClose={onCloseMock}
isLoggedIn={false}
/>,
);
const logoutOption = screen.getByText("ACCOUNT_SETTINGS$LOGOUT");
await user.click(logoutOption);
expect(onLogoutMock).not.toHaveBeenCalled();
expect(onLogoutMock).toHaveBeenCalledOnce();
});
it("should call onClose when clicking outside of the element", async () => {
@@ -65,7 +62,6 @@ describe("AccountSettingsContextMenu", () => {
<AccountSettingsContextMenu
onLogout={onLogoutMock}
onClose={onCloseMock}
isLoggedIn
/>,
);

View File

@@ -45,6 +45,8 @@ describe("ConversationPanel", () => {
last_updated_at: "2021-10-01T12:00:00Z",
created_at: "2021-10-01T12:00:00Z",
status: "STOPPED" as const,
url: null,
session_api_key: null,
},
{
conversation_id: "2",
@@ -53,6 +55,8 @@ describe("ConversationPanel", () => {
last_updated_at: "2021-10-02T12:00:00Z",
created_at: "2021-10-02T12:00:00Z",
status: "STOPPED" as const,
url: null,
session_api_key: null,
},
{
conversation_id: "3",
@@ -61,6 +65,8 @@ describe("ConversationPanel", () => {
last_updated_at: "2021-10-03T12:00:00Z",
created_at: "2021-10-03T12:00:00Z",
status: "STOPPED" as const,
url: null,
session_api_key: null,
},
];
@@ -143,6 +149,8 @@ describe("ConversationPanel", () => {
last_updated_at: "2021-10-01T12:00:00Z",
created_at: "2021-10-01T12:00:00Z",
status: "STOPPED" as const,
url: null,
session_api_key: null,
},
{
conversation_id: "2",
@@ -151,6 +159,8 @@ describe("ConversationPanel", () => {
last_updated_at: "2021-10-02T12:00:00Z",
created_at: "2021-10-02T12:00:00Z",
status: "STOPPED" as const,
url: null,
session_api_key: null,
},
{
conversation_id: "3",
@@ -159,6 +169,8 @@ describe("ConversationPanel", () => {
last_updated_at: "2021-10-03T12:00:00Z",
created_at: "2021-10-03T12:00:00Z",
status: "STOPPED" as const,
url: null,
session_api_key: null,
},
];

View File

@@ -22,7 +22,7 @@ const renderRepoConnector = () => {
path: "/conversations/:conversationId",
},
{
Component: Outlet,
Component: () => <Outlet />,
path: "/settings",
children: [
{

View File

@@ -11,7 +11,7 @@ import { MOCK_TASKS } from "#/mocks/task-suggestions-handlers";
const renderTaskSuggestions = () => {
const RouterStub = createRoutesStub([
{
Component: TaskSuggestions,
Component: () => <TaskSuggestions />,
path: "/",
},
{

View File

@@ -1,92 +1,11 @@
import { render, screen } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";
import { Messages } from "#/components/features/chat/messages";
import type { Message } from "#/message";
import { renderWithProviders } from "test-utils";
// Mock the useParams hook to provide a conversationId
vi.mock("react-router", async () => {
const actual = await vi.importActual<typeof import("react-router")>("react-router");
return {
...actual,
useParams: () => ({ conversationId: "test-conversation-id" }),
};
});
import { describe, it } from "vitest";
describe("File Operations Messages", () => {
it("should show success indicator for successful file read operation", () => {
const messages: Message[] = [
{
type: "action",
translationID: "read_file_contents",
content: "Successfully read file contents",
success: true,
sender: "assistant",
timestamp: new Date().toISOString(),
},
];
it.todo("should show success indicator for successful file read operation");
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
it.todo("should show failure indicator for failed file read operation");
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();
expect(statusIcon.closest("svg")).toHaveClass("fill-success");
});
it.todo("should show success indicator for successful file edit operation");
it("should show failure indicator for failed file read operation", () => {
const messages: Message[] = [
{
type: "action",
translationID: "read_file_contents",
content: "Failed to read file contents",
success: false,
sender: "assistant",
timestamp: new Date().toISOString(),
},
];
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();
expect(statusIcon.closest("svg")).toHaveClass("fill-danger");
});
it("should show success indicator for successful file edit operation", () => {
const messages: Message[] = [
{
type: "action",
translationID: "edit_file_contents",
content: "Successfully edited file contents",
success: true,
sender: "assistant",
timestamp: new Date().toISOString(),
},
];
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();
expect(statusIcon.closest("svg")).toHaveClass("fill-success");
});
it("should show failure indicator for failed file edit operation", () => {
const messages: Message[] = [
{
type: "action",
translationID: "edit_file_contents",
content: "Failed to edit file contents",
success: false,
sender: "assistant",
timestamp: new Date().toISOString(),
},
];
renderWithProviders(<Messages messages={messages} isAwaitingUserConfirmation={false} />);
const statusIcon = screen.getByTestId("status-icon");
expect(statusIcon).toBeInTheDocument();
expect(statusIcon.closest("svg")).toHaveClass("fill-danger");
});
it.todo("should show failure indicator for failed file edit operation");
});

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