Compare commits

..

240 Commits

Author SHA1 Message Date
openhands 497fd4a02c Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-12 04:04:08 +00:00
openhands 7fac7d6dd0 Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-12 03:03:01 +00:00
openhands 4155b8f801 Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-12 02:39:00 +00:00
openhands e712b013f9 Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-12 02:17:13 +00:00
OpenHands Bot 29b137e9b1 🤖 Auto-fix Python linting issues 2025-05-04 01:07:31 +00:00
Engel Nyst 1292f0c2ea Merge branch 'main' into delegates-cleanup 2025-05-04 03:06:23 +02:00
openhands da8c946078 Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-04 00:44:28 +00:00
openhands 43cef1f969 Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-04 00:14:47 +00:00
Graham Neubig 722711db3b Add OpenHands Cloud API documentation (#8127)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
2025-05-04 00:10:56 +00:00
openhands ab661b485b Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-03 23:39:14 +00:00
openhands 9632914bf0 Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-03 23:10:19 +00:00
Robert Brennan f45f398d81 Small tweaks for mobile styles (#8228) 2025-05-03 21:42:02 +00:00
openhands 3db780ef93 Fix pr #8247: Simplify delegate agents prompt and finish 2025-05-03 21:40:15 +00:00
Engel Nyst 43c16516e8 standardize delegate agents prompt and finish 2025-05-03 23:05:34 +02:00
Rohit Malhotra 0bab3b62f2 (Hotfix): Forbid extraneous params on new conversation route (#8234) 2025-05-03 14:26:38 -06:00
Rohit Malhotra ae990d3cb1 [Refactor]: Split settings and secrets stores (#8213)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-03 14:43:10 -04:00
Xingyao Wang 9babd756e5 Fix settings tab clickable area by extending it beyond just the text (#8240)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-03 17:07:41 +00:00
Engel Nyst 985e20d529 [chore] Run full agent pre-commit (#8235) 2025-05-03 11:24:03 -04:00
Boxuan Li 98cb2e24ee Make tool call json decode error recoverable (#8233) 2025-05-03 15:01:32 +00:00
Chase de175dcc87 bugfix for #8187 (infinite loop when delegating) (#8189) 2025-05-02 22:49:42 +02:00
Robert Brennan 976019ce11 Fix websocket error message handling (#8227)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-02 12:56:36 -04:00
dependabot[bot] 709b6ff39a chore(deps): bump the version-all group with 5 updates (#8226)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 18:14:29 +02:00
Rohit Malhotra 767d092f8f [Fix]: Use str in place of Repository for repository param when creating new conversation (#8159)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-02 11:17:04 -04:00
dependabot[bot] 7244e5df9f chore(deps): bump the version-all group across 1 directory with 12 updates (#8224)
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-02 15:02:11 +00:00
மனோஜ்குமார் பழனிச்சாமி dfbb968ea0 Chore: Update pull_request_template.md (#8118) 2025-05-02 15:53:09 +02:00
Xingyao Wang e4c3bbbc08 Fix: Include RecallObservation in events sent to frontend from ENVIRONMENT source (#8196)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-02 10:18:37 +00:00
Bashwara Undupitiya 6e0fbfeeda refactor: Refactor pause/resume functionality and improve state handling in CLI (#8152) 2025-05-02 12:04:35 +02:00
Ryan H. Tran 03aa5d7456 Upgrade openhands-aci to 0.2.12 (#8220) 2025-05-02 16:54:58 +07:00
Xingyao Wang 6032d2620d feat(MCP): MCP refactor, support stdio, and running MCP server in runtime (#7911)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Calvin Smith <email@cjsmith.io>
2025-05-02 09:43:19 +08:00
Xingyao Wang 0fc86b4063 Fix VS Code URL for remote access (#8191)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-02 09:35:43 +08:00
Rohit Malhotra e39d904a1f [Refactor]: Add typing expectation in FE for provider tokens (#8203)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-01 19:58:46 +00:00
mamoodi 9887813b41 Release 0.36.0 (#8202) 2025-05-01 15:34:46 -04:00
sp.wack d36cde5060 refactor(frontend): useUserRepositories hook (#8207) 2025-05-01 19:01:02 +00:00
dependabot[bot] fc4ad2f8c3 chore(deps): bump the version-all group with 5 updates (#8204)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 18:45:45 +02:00
OpenHands 9e97ea2dd7 Fix issue #8197: Add unit tests for isLikelyDirectory (#8198)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-05-01 16:26:32 +00:00
sp.wack 1ffaae17ff hotfix(backend): Handle errors when executing run actions (#8160) 2025-05-01 20:06:20 +04:00
sp.wack 3edea7c710 hotfix(frontend): Navigate user to /settings/git instead of /settings when their intention is to connect to GitHub (#8200) 2025-05-01 20:05:13 +04:00
Rohit Malhotra 08171eaf59 [Refactor]: Simplify provider info passing (#8138) 2025-05-01 10:49:13 -04:00
Shimada666 5376a54800 Switch to using only npm as package manager (#8201) 2025-05-01 13:12:53 +00:00
Xingyao Wang 14d7449514 Increase conversation limit from 9 to 20 (#8194)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-01 08:49:08 -04:00
Shimada666 735ac72351 Add Lunr search plugin with multi-language support (#8193) 2025-05-01 16:15:56 +04:00
Xingyao Wang e5f25726c0 chore: Update README.md to recommend "claude-3-7-sonnet-20250219" (#8190) 2025-05-01 09:09:07 +02:00
Xingyao Wang 59fc0fe9db Move VSCode settings.json setup from Dockerfile to VSCode plugin initialization (#8192)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-05-01 12:00:43 +08:00
LoneRifle 7ae3494ccc fix(image-input): enforce image types on upload (#8054)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-05-01 10:32:58 +08:00
Qi Liu 3d22520992 [Feat] add multi-swe-bench (#8174)
Co-authored-by: ByteDance User <tiger@bytedance.localdomain>
2025-05-01 00:23:19 +00:00
Tom Deckers cfae2a3607 Use generic token check in order to support Github Apps (#8048)
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
2025-04-30 23:22:14 +00:00
Robert Brennan 906823f898 Add trailing slash to directory paths in UI (#8188)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-30 18:13:10 -05:00
mamoodi 4dcceacc9e Remove Code coverage icon and fix benchmark link in docs (#8186) 2025-04-30 13:07:40 -06:00
mamoodi 9f05237b0d Update global microagents docs with a link to the current list (#8185) 2025-04-30 15:04:16 -04:00
dependabot[bot] 467ee52b05 chore(deps): bump the version-all group with 9 updates (#8180)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-30 17:42:47 +00:00
mamoodi 0d5dbbfa84 Update OpenHands Key Features page (#8179) 2025-04-30 13:22:35 -04:00
mamoodi 9b128f6168 Update microagents docs (#8183) 2025-04-30 12:33:57 -04:00
Robert Brennan 760a14482e Fix ValueError when latest_event_id is undefined (#8168)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Graham Neubig <neubig@gmail.com>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-04-30 12:50:44 +00:00
Ryan H. Tran b5338c69d6 Upgrade openhands-aci to 0.2.11 (#8154) 2025-04-30 02:54:15 +00:00
Hiroki Miyaji c99f031cdb docs: fix broken links (#8169) 2025-04-29 22:31:48 -04:00
mamoodi bcc28a12fe Release 0.35.0 (#8131)
Co-authored-by: Ray Myers <ray.myers@gmail.com>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Chuck Butkus <chuck@all-hands.dev>
2025-04-29 17:45:40 -04:00
Dani c82b3378a6 Fix issue #8145: Correct name for max_tokens for condenser in config.template.toml (#8165) 2025-04-29 20:28:01 +00:00
Ray Myers a6d3db3ce7 Update anyio to 4.9.0 (#8161)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-29 20:05:57 +00:00
SDGLBL 4cbbfd799c fix(memory): Fix empty string content handling in ConversationMemory (#8148)
Co-authored-by: lijie.20 <lijie.20@bytedance.com>
2025-04-29 21:03:13 +02:00
Xingyao Wang 0b728c0c79 [agent]: update system message to prevent the agent being too obsessed with setting up environment (#8007) 2025-04-30 00:10:44 +08:00
Ryosuke Hayashi e35c8ee173 fix OpenAPI schema generation error caused by mappingproxy in models (#8121) 2025-04-29 16:05:02 +00:00
Xingyao Wang 9a9b143620 nit: improve error message when action is not executed (#7029)
Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-30 00:04:11 +08:00
sp.wack 38578bd5f5 hotifx(frontend): Critical fix for black screen (#8158) 2025-04-29 15:56:25 +00:00
dependabot[bot] 7b2c88ae6b chore(deps): bump the version-all group with 4 updates (#8157)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-29 17:46:20 +02:00
dependabot[bot] 0cbf3987f8 chore(deps): bump the version-all group in /frontend with 9 updates (#8155)
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-04-29 15:32:27 +00:00
chuckbutkus d18edc8b30 Move Terms of Service acceptance to dedicated page (#8071)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: tofarr <tofarr@gmail.com>
Co-authored-by: Ray Myers <ray.myers@gmail.com>
Co-authored-by: மனோஜ்குமார் பழனிச்சாமி <smartmanoj42857@gmail.com>
Co-authored-by: Lenshood <lenshood.zxh@gmail.com>
Co-authored-by: OpenHands <opendevin@all-hands.dev>
Co-authored-by: mamoodi <mamoodiha@gmail.com>
Co-authored-by: Graham Neubig <neubig@gmail.com>
2025-04-29 15:12:45 +00:00
Graham Neubig 42eb355a68 Fix OpenRouter context window exceeded error detection (#8150)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-29 10:05:56 -04:00
Xingyao Wang 5fa01ed278 Fix mobile layout for repo picker and suggested tasks (#8137)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-28 21:39:09 -04:00
Xingyao Wang 1f747232cf feat: add agent memory microagents for experiment (#8122) 2025-04-28 19:08:44 -04:00
Engel Nyst 4b1ed30e97 Fix truncation, ensure first user message and log (#8103)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-28 22:43:41 +02:00
Panduka Muditha 998de564cd feat: Add CLI support for agent pause and resume (#8129)
Co-authored-by: Bashwara Undupitiya <bashwarau@verdentra.com>
2025-04-28 16:26:18 -04:00
Engel Nyst 06ce12eff4 Update resolver model (#8124) 2025-04-28 21:07:40 +02:00
sp.wack 88fc26d9b0 frontend: Better diff contrast (#8128) 2025-04-28 22:53:37 +04:00
dependabot[bot] 99233ec153 chore(deps): bump the version-all group with 6 updates (#8125)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-28 20:50:39 +02:00
sp.wack ae9573a503 chore(frontend): Breakdown settings screen (#7929)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-28 22:32:28 +04:00
dependabot[bot] f2725eeb3d chore(deps): bump the version-all group across 1 directory with 8 updates (#8123)
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-04-28 17:18:21 +00:00
Engel Nyst 1b63633030 Simplify microagents (#8114)
Co-authored-by: Robert Brennan <accounts@rbren.io>
2025-04-28 15:00:06 +00:00
Ryan H. Tran 107789b5a8 Add missing last ps1 match output into combined output (#8097) 2025-04-28 21:06:26 +08:00
Panduka Muditha 04bdea5faf feat: Add CLI support for /new, /status and /settings (#8017)
Co-authored-by: Bashwara Undupitiya <bashwarau@verdentra.com>
2025-04-28 08:52:33 -04:00
Engel Nyst 2bad4ea3d2 Litellm emergency fix (#8116) 2025-04-28 08:36:45 +02:00
Rohit Malhotra 1c4c477b3f [Refactor]: Abstract resolver into classes (#7999)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-27 18:52:52 -04:00
Rohit Malhotra 391ba1d988 [Fix]: Move suggest task prompts to BE (#8109)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-27 16:32:15 -04:00
Engel Nyst 70f469b0c1 [chore] run full pre-commit (#8104) 2025-04-27 08:43:26 +02:00
Graham Neubig 8a5c6d3bef Fix long setup scripts failing (#8101)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-26 12:27:54 -04:00
tofarr 998e04e51b Fix for issue where running unit tests resets local settings (#8100)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-04-26 07:24:49 -06:00
Boxuan Li da7041b5e9 Allow cmd execution after running a background command (#8093) 2025-04-26 03:04:05 +00:00
Robert Brennan e4b7b31f48 Add VS Code tab alongside workspace, terminal, and jupyter tabs (#8033)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-25 15:30:50 -07:00
chuckbutkus 587c53f115 Maybe fix for pre-commit errors (#8082)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
Co-authored-by: Graham Neubig <neubig@gmail.com>
2025-04-25 21:10:00 +00:00
mamoodi 4d76f31610 Update Microagents documentation (#7978) 2025-04-25 16:52:55 -04:00
Rohit Malhotra c25a96825c [Fix]: Sort github repos in memory for cloud openhands (#8083)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-04-25 15:16:43 -04:00
OpenHands 16137942eb Fix issue #7888: Update resolver doc to refer to repo.md instead of the old file (#8089)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-04-25 16:13:05 +00:00
dependabot[bot] cf07b151dc chore(deps): bump the version-all group with 5 updates (#8091)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 17:30:17 +02:00
Lenshood ea3787c2ba fix: dev.sh failed due to outdated configuration of Dockerfile (#8058)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-04-25 11:36:53 +08:00
chuckbutkus 956d278138 fix call to convo store get_instance (#8081) 2025-04-25 01:41:00 +00:00
மனோஜ்குமார் பழனிச்சாமி fa186fc433 chore: Use recommended functions (#8056) 2025-04-25 09:39:19 +08:00
Ray Myers 4ef9c72da1 fix - Show error message for too many conversations (#8078) 2025-04-24 19:53:17 -05:00
tofarr c5245a622d Refactor Authentication (#8040)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: rohitvinodmalhotra@gmail.com <rohitvinodmalhotra@gmail.com>
2025-04-24 18:49:41 -06:00
Engel Nyst 9b1aaa53fe Reset the reset (#8079) 2025-04-25 00:59:37 +02:00
Rohit Malhotra 4deffa3907 [Fix]: Don't wipe out secret store on reset route (#8075) 2025-04-24 17:41:46 -04:00
Rohit Malhotra a47c6f3ed1 [Fix]: Log HTTP err type in Git service classes (#8076) 2025-04-24 17:41:36 -04:00
dependabot[bot] 90ece3f8e1 chore(deps): bump the version-all group across 1 directory with 14 updates (#8062)
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-04-24 20:04:33 +00:00
Robert Brennan a948b0fef3 Change log levels from info to debug for various agent controller messages (#8073)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-24 20:00:21 +00:00
Robert Brennan 52848cd3db Improve git handler with better branch management (#8065)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-24 12:34:25 -07:00
mamoodi 62f015370a Update Documentation with new release features (#8045) 2025-04-24 14:58:42 -04:00
sp.wack 7109b057b6 Make tmux optional for development (#8063)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <engel.nyst@gmail.com>
2025-04-24 18:13:33 +00:00
Rohit Malhotra e694fc2d58 [Feat]: Add suggested tasks for Gitlab (#8049) 2025-04-24 13:26:52 -04:00
Robert Brennan 50baf3fd18 Add OpenAPI spec to Docusaurus documentation (#7998)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-24 10:19:33 -07:00
dependabot[bot] dc37f039bf chore(deps): bump the version-all group across 1 directory with 14 updates (#8064)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-24 18:01:39 +02:00
Engel Nyst 91fff77ffe Fix lint (#8060) 2025-04-24 14:34:22 +00:00
sp.wack db01cd39d5 hotfix: Run both BE and FE pre-commits with husky (#8059) 2025-04-24 18:21:41 +04:00
மனோஜ்குமார் பழனிச்சாமி 00865fbb8a fix: reconnect if stream closed (#8055) 2025-04-24 16:05:28 +04:00
Rohit Malhotra 356cd9ff9f (Hotfix): Issue comments on Cloud Resolver (#8053) 2025-04-23 22:50:00 -04:00
Xingyao Wang 78d82408b7 fix: use lower range of tcp port for file viewer (#8051) 2025-04-24 01:51:44 +00:00
Panduka Muditha 3c4ebc3d8a fix: Add error handling for scenarios where tmux is unavailable (#8043)
Co-authored-by: Anuradha Weeraman <anuradha@verdentra.com>
2025-04-23 21:01:06 +02:00
Rohit Malhotra 964478c22f [Feat]: Custom secrets plumbing for BE (#7891)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-23 12:44:25 -04:00
Robert Brennan 00c449d447 Add loading indicator to repository dropdown on home page (#8015)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-23 12:27:49 -04:00
Rohit Malhotra bfd75a1355 (Chore): Rm legacy resolver code (#8001) 2025-04-23 11:34:03 -04:00
Graham Neubig dc91cb263b Add extensive typing to controller directory (#7731)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Ray Myers <ray.myers@gmail.com>
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
2025-04-23 15:33:17 +00:00
Robert Brennan fa559ace86 Add API keys management UI to settings page (#7710)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-23 19:08:32 +04:00
mamoodi 1fd26d196a Release 0.34.0 (#8011) 2025-04-23 11:06:28 -04:00
Robert Brennan 5de62d85fd add an option for a headless backend (#8032) 2025-04-23 04:09:22 +02:00
Chase 5d749aeba7 replace erroneous rstrip() with removesuffix() (#8024) 2025-04-22 22:50:14 +00:00
Chase 693c72d670 remove sse subsection accessor of McpConfig in action_execution_client (#8021) 2025-04-23 00:40:10 +02:00
Engel Nyst 62557d44f2 Use short tool descriptions for o4-mini (#8022) 2025-04-23 00:30:21 +02:00
Robert Brennan 89f8e162da Fix: Don't show status indicator for command timeouts (#8012)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-22 23:30:07 +04:00
Robert Brennan b0a9938e6c Always run git init in SaaS mode regardless of workspace_base setting (#8014)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-22 17:43:20 +00:00
Rohit Malhotra 039fe295a4 Add RateLimitError and handle rate limiting in GitLab and GitHub services (#8003)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-04-22 16:30:41 +00:00
dependabot[bot] 8f3ff1210e chore(deps): bump the version-all group with 6 updates (#8009)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-22 15:16:41 +00:00
Peter Hamilton 5e1e685493 fix: Use SANDBOX_BASE_CONTAINER_IMAGE in resolver workflow (#7956)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-22 16:15:49 +02:00
sp.wack e9f2b72ea5 chore: Better home screen (#7784)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-22 13:15:41 +00:00
Rohit Malhotra 986b90be0a [Fix]: fetch latest token when existing token doesn't exist (#8000) 2025-04-22 03:22:48 +00:00
Robert Brennan bf9f2aa7a5 Initialize git repo in workspace when no GitHub repo is selected (#7904)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-21 18:34:42 -04:00
Engel Nyst b3bd3924a0 Fix and simplify local runtime init (#7997) 2025-04-22 00:24:22 +02:00
Rohit Malhotra 0de50153a0 Add HTTP method option to Git service fetch_data functions (#7996)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-21 18:15:05 -04:00
Xingyao Wang a04024a239 refactor: file viewer server so it is accessible via localhost without authentication (#7987)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-21 22:12:06 +00:00
Rohit Malhotra 1e509a70d4 [Fix]: Dedup token verification logic in resolver (#7967)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-21 20:34:29 +00:00
Engel Nyst 300a59853b Quick fix local runtime (#7991) 2025-04-21 20:28:30 +00:00
Rohit Malhotra 2514b200c5 Fix dictionary changed size during iteration error in EventStream (#7984)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-21 16:21:30 -04:00
Michael Panchenko 52d881c98d Fix issue with "default" in tool schema for gemini-preview (#7964) 2025-04-21 21:21:33 +02:00
Rohit Malhotra 6ac23aea80 [Feat]: Add branch naming convention (#7989) 2025-04-21 18:35:16 +00:00
Xingyao Wang 0412949018 Add agent_class to SystemMessageAction and display in frontend (#7935)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-22 02:08:15 +08:00
Michael Panchenko 5b5adc5c7b Minor refactoring: remove step and task-creation in AgentController (#7981) 2025-04-21 19:28:22 +02:00
dependabot[bot] 0b40f6fac8 chore(deps): bump the version-all group with 7 updates (#7980)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 19:14:58 +02:00
Rohit Malhotra 44d488b718 [Fix]: Building runtime image with unspecified base container img (#7977) 2025-04-21 11:30:22 -04:00
Rohit Malhotra 4f9120ffc6 (Chore): Unsupport resolve all issues in resolver (#7975) 2025-04-21 14:37:53 +00:00
Tetsuuuuuuu 50426edaa1 feat: add argument --base-container-image to resolver (#7612)
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
2025-04-21 10:01:03 -04:00
Xingyao Wang a792f84a83 chore: improve logging for "not a git repository" (#7944) 2025-04-21 16:13:48 +04:00
Alexander Litzenberger cd9d96766c Update documentation on local-llms (#7805)
Co-authored-by: Alex Litzenberger <alex@agot.ai>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2025-04-21 00:20:13 +00:00
Michael Panchenko 14564b25d6 Fix linting (#7965) 2025-04-21 06:34:40 +08:00
Rohit Malhotra 0637b5b912 [Fix]: Replace duplicate enums for providers in resolver (#7954) 2025-04-20 14:06:18 -04:00
Rohit Malhotra 20bf48b693 [Fix]: mismatch between repo object definition between FE and BE (#7953) 2025-04-20 00:28:10 +00:00
Michael Panchenko 5b3270be2d Possibility to disable default tools (#7951) 2025-04-20 02:14:46 +02:00
Tom Deckers ae43744052 Fix Github Enterprise GraphQL URL (#7939)
Co-authored-by: Tom Deckers <tdeckers@cisco.com>
Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
2025-04-19 21:09:00 +00:00
Xingyao Wang b5d7e428d1 Fix #7916: Update Benchmark Score link in README (#7943)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-19 00:27:54 +02:00
Rohit Malhotra d65ea313e8 Add external auth id to /repos route (#7946) 2025-04-18 18:19:36 -04:00
Rohit Malhotra a09ecadba6 (Chore): Rm deprecate /installations route (#7945) 2025-04-18 21:51:08 +00:00
Rohit Malhotra 358166feb2 [Logging]: Add warning logs for gitlab api (#7941) 2025-04-18 21:31:36 +00:00
Kenny Dizi 85e2b73eb4 [Feat] Support o3 and o4 mini (#7898)
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
2025-04-18 21:23:19 +00:00
Rohit Malhotra c18475ddc2 Add public vs private info for repo list (#7937) 2025-04-18 17:07:08 -04:00
Xingyao Wang 06fcf54475 chore: track condeser metadata for llm completion (#7938) 2025-04-19 05:05:31 +08:00
Rohit Malhotra f751f8ab37 [Feat]: Add graphql fetching for GitLab service cls (#7839) 2025-04-18 16:53:49 -04:00
Tei1988 523c6d03c1 fix(resolver): Allow using github.token in Actions and fix base_domain handling (#7934) 2025-04-18 20:50:59 +00:00
Rohit Malhotra 0e0f043e59 [Feat]: Improve resolver inline pr comment localization (#7932) 2025-04-18 15:56:34 -04:00
Xingyao Wang 91c691d526 [agent] Read-only Agent (#6947)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-19 02:46:24 +08:00
Xingyao Wang c6092291ce chore: make sure Makefile make lint also lint tests (#7933) 2025-04-18 14:01:36 -04:00
Engel Nyst a2c55cfdef Refactor to clean up and move utility/legacy out of the agent (#7917) 2025-04-19 01:53:33 +08:00
Michael Panchenko 76cad626ed Bugfix: make extraction of poetry_venvs_path more robust (#7920) 2025-04-18 17:33:52 +00:00
Xingyao Wang 7c23993344 fix(eval): typo in SWE_Bench evaluation (#7930) 2025-04-19 00:31:08 +08:00
dependabot[bot] b669715416 chore(deps): bump the version-all group across 1 directory with 20 updates (#7925)
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-04-18 16:08:35 +00:00
tofarr 7292122b72 Refactor agent loop initialization for better extensibility (#7926) 2025-04-18 09:44:34 -06:00
dependabot[bot] 992ae15c78 chore(deps): bump the version-all group with 7 updates (#7927)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-18 15:02:41 +00:00
Carlos Freund f2b4772ac2 fix(runtime) Avoid windows reserved port (#7722)
Co-authored-by: Carlos Freund <carlosfreund@gmail.com>
2025-04-18 22:18:46 +08:00
Engel Nyst 9b9b1291fc [chore] Just linting on swe-bench files (#7918) 2025-04-18 22:12:01 +08:00
Xingyao Wang 6171395ef9 Refactor metrics handling to include condenser metrics (#7907)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-17 23:08:35 +00:00
sp.wack d270476d6c hotfix(backend): Exclude open PRs when fetching suggested tasks (#7912) 2025-04-18 03:00:04 +04:00
Xingyao Wang f1f7dca009 refactor(action_execution_client): rename function and add property (#7913) 2025-04-18 06:59:13 +08:00
mamoodi 45f572f268 Update documentation (#7905) 2025-04-17 17:43:18 -04:00
Niels Mündler 4b124d5906 Add inference for SWT-Bench (#7201)
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
Co-authored-by: Graham Neubig <neubig@gmail.com>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Calvin Smith <email@cjsmith.io>
2025-04-17 14:49:42 -06:00
Robert Brennan 988d4aa679 Improved logging for agent controller, including pending action time (#7897)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-17 20:22:38 +00:00
Robert Brennan b452fe273c Restore terminal interactivity while keeping UI changes (#7903)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-17 19:42:03 +00:00
sp.wack 9544b37c8a hotfix(forntend): Wait for runtime to start before fetching git changes for diff view (#7910) 2025-04-17 15:15:03 -04:00
Rohit Malhotra 0491357fef [Refactor]: Collapse initial user message for cloud resolver (#7871)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-17 15:09:28 -04:00
Robert Brennan fedd517a71 Change add funds input to number type that only accepts integers (#7628)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-17 18:56:23 +00:00
Rohit Malhotra 9cbed8802f Update translation from GitHub Settings to Git Settings (#7908)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-17 18:55:28 +00:00
Rohit Malhotra c2e1babd76 Fix failing unit test on main (#7909)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-17 18:43:09 +00:00
Carlos Freund cc8b677f3e fix(metrics) Merge metrics of agent LLM and condenser LLM (#7890)
Co-authored-by: Carlos Freund <carlosfreund@gmail.com>
2025-04-18 01:15:14 +08:00
chuckbutkus 78e3f82de1 Change client name and add IDP hint (#7787)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ray Myers <ray.myers@gmail.com>
Co-authored-by: Calvin Smith <email@cjsmith.io>
Co-authored-by: Calvin Smith <calvin@all-hands.dev>
Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Graham Neubig <neubig@gmail.com>
Co-authored-by: Panduka Muditha <pandukal@verdentra.com>
Co-authored-by: Bashwara Undupitiya <bashwarau@verdentra.com>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
2025-04-17 12:23:12 -04:00
dependabot[bot] 20ca2cd8b9 chore(deps): bump the version-all group across 1 directory with 9 updates (#7902)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 17:45:44 +02:00
mamoodi ea0fcd6002 Change title of button to start new conversation (#7464) 2025-04-17 11:16:33 -04:00
juanmichelini 6bcebd4b9d Jetbrains CI Benchmark (#7811)
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
2025-04-17 15:10:20 +00:00
Xingyao Wang 93e9db3206 Refactor system message handling to use event stream (#7824)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Calvin Smith <email@cjsmith.io>
2025-04-17 22:30:19 +08:00
Ray Myers caf34d83bd chore - remove dummy agent test (#7848) 2025-04-17 08:52:02 -04:00
LoneRifle 49d3cd0863 fix(check-unlocalized-strings): make HTML tag test case-insens (#7892) 2025-04-17 14:26:49 +02:00
sp.wack 34989f8e96 feat: Diff UI (#6934) 2025-04-17 16:12:25 +04:00
Rohit Malhotra 9274664302 [Fix]: Rm unnecessary provider token serializer (#7889) 2025-04-16 21:41:07 +00:00
mamoodi 437f0a0154 Release 0.33.0 (#7882)
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: tofarr <tofarr@gmail.com>
Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: Bashwara Undupitiya <65051545+bashwara@users.noreply.github.com>
2025-04-16 17:03:00 -04:00
Bashwara Undupitiya 9d79bf5fff fix: Update folder security dialog styling (#7886) 2025-04-16 14:33:00 -04:00
Robert Brennan 4c62b1d428 Fix: Ensure consistent tab height when workspace tab is selected (#7885)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-16 17:54:50 +00:00
Rohit Malhotra b2a4b4ed90 [Refactor]: Modularize settings storage logic (#7868)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-16 13:30:13 -04:00
tofarr 9262babc3b Fix for error on close (#7884) 2025-04-16 11:13:58 -06:00
dependabot[bot] 1c80ded753 chore(deps-dev): bump the eslint group across 1 directory with 2 updates (#7790)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-16 19:41:25 +04:00
Xingyao Wang 4de8c4d6b1 Update repo microagent docs with frontend action handling information (#7856)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-16 14:27:31 +00:00
Xingyao Wang 91f2254039 frontend: fix terminal prompt and command styling (#7872)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-16 22:13:15 +08:00
Calvin Smith 66fd156c65 feat: Combining condensers (#7867)
Co-authored-by: Calvin Smith <calvin@all-hands.dev>
2025-04-16 07:09:13 -06:00
Xingyao Wang 4ec16f3c2e microagent: Update github.md to avoid agent marking PR as ready for review (#7873) 2025-04-15 23:56:41 -04:00
Robert Brennan 628003abef Convert terminal to tab, make terminal read only (#7795)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
2025-04-16 11:22:52 +08:00
Xingyao Wang 07e400b73d refactor(mcp): simplify MCP config & fix timeout (#7820)
Co-authored-by: ducphamle2 <ducphamle212@gmail.com>
Co-authored-by: trungbach <trunga2k29@gmail.com>
Co-authored-by: quangdz1704 <Ntq.1704@gmail.com>
Co-authored-by: Duc Pham <44611780+ducphamle2@users.noreply.github.com>
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-16 11:04:21 +08:00
Tom Deckers 7e14a512e0 Add base_domain parameter for GitHub Enterprise support (#7754)
Co-authored-by: Tom Deckers <tdeckers@cisco.com>
Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
2025-04-16 00:00:32 +00:00
Rohit Malhotra d7e8f843ad [Docs]: Add GitLab token setup documentation (#7635)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-15 17:25:25 -04:00
Xingyao Wang e69ae81ad2 Add GPT-4.1 to function calling list (#7866)
Co-authored-by: Juan Michelini <juan@juan.com.uy>
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-15 18:12:15 +02:00
dependabot[bot] 03c5db32e6 chore(deps): bump the version-all group with 8 updates (#7865)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 15:40:04 +00:00
Engel Nyst 5e5bf23f9c [Evaluation] Fix KeyError when the instance failed prematurely (#7864) 2025-04-15 15:19:31 +00:00
Shotaro Sano e0fcd7a61e Fix issue #6098: Prevent duplicate error message display in chat interface (#7858) 2025-04-15 16:21:23 +04:00
Ryan H. Tran e9989d1085 Upgrade openhands-aci to 0.2.10 (#7810) 2025-04-15 18:43:44 +07:00
Xingyao Wang 49c515b252 frontend: Display think action as action rather than text (#7852)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-15 09:09:16 +08:00
Robert Brennan 2d05578c21 Fix links in readme (#7854) 2025-04-15 02:27:25 +04:00
Engel Nyst d05a6f30e1 [Refactor] Rename codeact_* agent options to simple name (#7853) 2025-04-15 00:14:13 +02:00
Calvin Smith 10c81c39fb Fix export conversation button in Safari (#7662)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Calvin Smith <calvin@all-hands.dev>
2025-04-14 15:10:20 -06:00
sumeetkumar1701 2d599349ef fix:Transmitting accurate head parameter in cross-repository pull requests. (#7788) 2025-04-14 17:57:15 +00:00
mamoodi 33caf5c6ca Update feature template to add note about adding reaction (#7847) 2025-04-14 13:56:04 -04:00
Ciocanel Razvan a9850766a7 Allow input for pr_type openhands-resolver.yml (#7619)
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
2025-04-14 17:53:58 +00:00
OpenHands 77e2416def Fix issue #7826: [Bug]: Chat input box is too small (#7827) 2025-04-14 12:19:38 -05:00
蔡政特 02af9865ec fix: Runtime local docker environment HTTPStatusError (#7648)
Co-authored-by: Robert Brennan <accounts@rbren.io>
2025-04-14 15:41:54 +00:00
dependabot[bot] 75ca2aa6b1 chore(deps): bump the version-all group with 10 updates (#7846)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 17:16:27 +02:00
mamoodi d820661592 Update docs on why we use sandbox user (#7845) 2025-04-14 11:01:35 -04:00
Robert Brennan 1ff351a4f1 Add OpenHands Cloud to README, other minor tweaks (#7844) 2025-04-14 14:01:52 +00:00
OpenHands 78b8e58561 Fix issue #7837: [Bug]: Unit tests for tool use support (#7838)
Co-authored-by: Engel Nyst <engel.nyst@gmail.com>
2025-04-14 15:45:37 +02:00
tofarr fddbfce51a Fix for race condition in cache (#7812) 2025-04-12 07:43:34 -06:00
Rohit Malhotra 20d3766451 [Fix]: Use better auth header for GitLab microagent (#7828) 2025-04-11 20:09:28 -04:00
sp.wack 72b5e18898 fix(backend): Return 400 if trying to open a binary file (#7825) 2025-04-11 22:47:57 +00:00
Rohit Malhotra 03b8b8c19a (Chore): Rm single provider legacy code (#7821)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-11 18:21:35 +00:00
Panduka Muditha 7c2f1b075e feat: CLI enhancements to support /init, /help and /exit (#7801)
Co-authored-by: Bashwara Undupitiya <bashwarau@verdentra.com>
2025-04-11 14:13:41 -04:00
Graham Neubig 883da1b28c Add extensive typing to openhands/runtime/plugins directory (#7726)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-12 02:02:53 +08:00
Engel Nyst bb98d94b35 [evaluation] fix missing metadata (#7819) 2025-04-11 16:58:59 +00:00
sp.wack d114c45135 chore: Improve pre-commit (#7818) 2025-04-11 20:55:26 +04:00
Calvin Smith 36e092e0ac fix: Disable prompt caching in default condenser (#7781)
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Calvin Smith <calvin@all-hands.dev>
Co-authored-by: Xingyao Wang <xingyao@all-hands.dev>
2025-04-11 10:09:23 -06:00
Ray Myers e2bb69908a chore - Rebuild docker image in fork CI instead of using artifacts (#7809) 2025-04-11 11:06:46 -05:00
Ray Myers cd33c5eac7 Revert "chore - User docker cache mount for vscode server archive (#7… (#7817) 2025-04-11 16:04:50 +00:00
dependabot[bot] 0f8a139fb5 chore(deps): bump the version-all group with 5 updates (#7814)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 17:06:59 +02:00
Xingyao Wang ced4ee3038 Fix: Display accumulated token usage in frontend metrics (#7803)
Co-authored-by: openhands <openhands@all-hands.dev>
2025-04-11 22:38:47 +08:00
598 changed files with 42951 additions and 23621 deletions
@@ -12,3 +12,6 @@ assignees: ''
**Describe the UX or technical implementation you have in mind**
**Additional context**
### If you find this feature request or enhancement useful, make sure to add a 👍 to the issue
+3 -3
View File
@@ -1,12 +1,12 @@
- [ ] This change is worth documenting at https://docs.all-hands.dev/
- [ ] Include this change in the Release Notes. If checked, you **must** provide an **end-user friendly** description for your change below
**End-user friendly description of the problem this fixes or functionality that this introduces.**
**End-user friendly description of the problem this fixes or functionality this introduces.**
---
**Give a summary of what the PR does, explaining any non-trivial design decisions.**
**Summarize what the PR does, explaining any non-trivial design decisions.**
---
**Link of any specific issues this addresses.**
**Link of any specific issues this addresses:**
-53
View File
@@ -1,53 +0,0 @@
# Workflow that uses the DummyAgent to run a simple task
name: Run E2E test with dummy agent
# Always run on "main"
# Always run on PRs
on:
push:
branches:
- main
pull_request:
# If triggered by a PR, it will be in the same group. However, each commit on main will be in its own unique group
concurrency:
group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Install tmux
run: sudo apt-get update && sudo apt-get install -y tmux
- name: Setup Node.js
uses: useblacksmith/setup-node@v5
with:
node-version: '22.x'
- name: Install poetry via pipx
run: pipx install poetry
- name: Set up Python
uses: useblacksmith/setup-python@v6
with:
python-version: '3.12'
cache: 'poetry'
- name: Install Python dependencies using Poetry
run: poetry install --without evaluation
- name: Build Environment
run: make build
- name: Run tests
run: |
set -e
SANDBOX_FORCE_REBUILD_RUNTIME=True poetry run python3 openhands/core/main.py -t "do a flip" -d ./workspace/ -c DummyAgent
- name: Check exit code
run: |
if [ $? -ne 0 ]; then
echo "Test failed"
exit 1
else
echo "Test passed"
fi
+30 -25
View File
@@ -174,20 +174,19 @@ jobs:
build-args: ${{ env.DOCKER_BUILD_ARGS }}
context: containers/runtime
provenance: false
# Forked repos can't push to GHCR, so we need to upload the image as an artifact
# Forked repos can't push to GHCR, so we just build in order to populate the cache for rebuilding
- name: Build runtime image ${{ matrix.base_image.image }} for fork
if: github.event.pull_request.head.repo.fork
uses: useblacksmith/build-push-action@v1
with:
tags: ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
outputs: type=docker,dest=/tmp/runtime-${{ matrix.base_image.tag }}.tar
context: containers/runtime
- name: Upload runtime image for fork
- name: Upload runtime source for fork
if: github.event.pull_request.head.repo.fork
uses: actions/upload-artifact@v4
with:
name: runtime-${{ matrix.base_image.tag }}
path: /tmp/runtime-${{ matrix.base_image.tag }}.tar
name: runtime-src-${{ matrix.base_image.tag }}
path: containers/runtime
verify_hash_equivalence_in_runtime_and_app:
name: Verify Hash Equivalence in Runtime and Docker images
@@ -258,17 +257,23 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
# Forked repos can't push to GHCR, so we need to download the image as an artifact
- name: Download runtime image for fork
- name: Download runtime source for fork
if: github.event.pull_request.head.repo.fork
uses: actions/download-artifact@v4
with:
name: runtime-${{ matrix.base_image.tag }}
path: /tmp
- name: Load runtime image for fork
if: github.event.pull_request.head.repo.fork
name: runtime-src-${{ matrix.base_image.tag }}
path: containers/runtime
- name: Lowercase Repository Owner
run: |
docker load --input /tmp/runtime-${{ matrix.base_image.tag }}.tar
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
# Forked repos can't push to GHCR, so we need to rebuild using cache
- name: Build runtime image ${{ matrix.base_image.image }} for fork
if: github.event.pull_request.head.repo.fork
uses: useblacksmith/build-push-action@v1
with:
load: true
tags: ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
context: containers/runtime
- name: Cache Poetry dependencies
uses: useblacksmith/cache@v5
with:
@@ -287,9 +292,6 @@ jobs:
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies POETRY_GROUP=main,test,runtime INSTALL_PLAYWRIGHT=0
- name: Lowercase Repository Owner
run: |
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Run docker runtime tests
run: |
# We install pytest-xdist in order to run tests across CPUs
@@ -327,17 +329,23 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
# Forked repos can't push to GHCR, so we need to download the image as an artifact
- name: Download runtime image for fork
- name: Download runtime source for fork
if: github.event.pull_request.head.repo.fork
uses: actions/download-artifact@v4
with:
name: runtime-${{ matrix.base_image.tag }}
path: /tmp
- name: Load runtime image for fork
if: github.event.pull_request.head.repo.fork
name: runtime-src-${{ matrix.base_image.tag }}
path: containers/runtime
- name: Lowercase Repository Owner
run: |
docker load --input /tmp/runtime-${{ matrix.base_image.tag }}.tar
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
# Forked repos can't push to GHCR, so we need to rebuild using cache
- name: Build runtime image ${{ matrix.base_image.image }} for fork
if: github.event.pull_request.head.repo.fork
uses: useblacksmith/build-push-action@v1
with:
load: true
tags: ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
context: containers/runtime
- name: Cache Poetry dependencies
uses: useblacksmith/cache@v5
with:
@@ -356,9 +364,6 @@ jobs:
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies POETRY_GROUP=main,test,runtime INSTALL_PLAYWRIGHT=0
- name: Lowercase Repository Owner
run: |
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Run runtime tests
run: |
# We install pytest-xdist in order to run tests across CPUs
+9 -4
View File
@@ -16,10 +16,15 @@ on:
type: string
default: "main"
description: "Target branch to pull and create PR against"
pr_type:
required: false
type: string
default: "draft"
description: "The PR type that is going to be created (draft, ready)"
LLM_MODEL:
required: false
type: string
default: "anthropic/claude-3-5-sonnet-20241022"
default: "anthropic/claude-3-7-sonnet-20250219"
LLM_API_VERSION:
required: false
type: string
@@ -174,7 +179,7 @@ jobs:
echo "MAX_ITERATIONS=${{ inputs.max_iterations || 50 }}" >> $GITHUB_ENV
echo "SANDBOX_ENV_GITHUB_TOKEN=${{ secrets.PAT_TOKEN || github.token }}" >> $GITHUB_ENV
echo "SANDBOX_ENV_BASE_CONTAINER_IMAGE=${{ inputs.base_container_image }}" >> $GITHUB_ENV
echo "SANDBOX_BASE_CONTAINER_IMAGE=${{ inputs.base_container_image }}" >> $GITHUB_ENV
# Set branch variables
echo "TARGET_BRANCH=${{ inputs.target_branch || 'main' }}" >> $GITHUB_ENV
@@ -280,9 +285,9 @@ jobs:
cd /tmp && python -m openhands.resolver.send_pull_request \
--issue-number ${{ env.ISSUE_NUMBER }} \
--target-branch ${{ env.TARGET_BRANCH }} \
--pr-type draft \
--pr-type ${{ inputs.pr_type || 'draft' }} \
--reviewer ${{ github.actor }} | tee pr_result.txt && \
grep "draft created" pr_result.txt | sed 's/.*\///g' > pr_number.txt
grep "PR created" pr_result.txt | sed 's/.*\///g' > pr_number.txt
else
cd /tmp && python -m openhands.resolver.send_pull_request \
--issue-number ${{ env.ISSUE_NUMBER }} \
+17
View File
@@ -54,3 +54,20 @@ Frontend:
## Template for Github Pull Request
If you are starting a pull request (PR), please follow the template in `.github/pull_request_template.md`.
## Implementation Details
These details may or may not be useful for your current task.
### Frontend
#### Action Handling:
- Actions are defined in `frontend/src/types/action-type.ts`
- The `HANDLED_ACTIONS` array in `frontend/src/state/chat-slice.ts` determines which actions are displayed as collapsible UI elements
- To add a new action type to the UI:
1. Add the action type to the `HANDLED_ACTIONS` array
2. Implement the action handling in `addAssistantAction` function in chat-slice.ts
3. Add a translation key in the format `ACTION_MESSAGE$ACTION_NAME` to the i18n files
- Actions with `thought` property are displayed in the UI based on their action type:
- Regular actions (like "run", "edit") display the thought as a separate message
- Special actions (like "think") are displayed as collapsible elements only
+1 -1
View File
@@ -118,7 +118,7 @@ poetry run pytest ./tests/unit/test_*.py
To reduce build time (e.g., if no changes were made to the client-runtime component), you can use an existing Docker container image by
setting the SANDBOX_RUNTIME_CONTAINER_IMAGE environment variable to the desired Docker image.
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.32-nikolaik`
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.36-nikolaik`
## Develop inside Docker container
+14 -1
View File
@@ -39,6 +39,7 @@ ifeq ($(INSTALL_DOCKER),)
@$(MAKE) -s check-docker
endif
@$(MAKE) -s check-poetry
@$(MAKE) -s check-tmux
@echo "$(GREEN)Dependencies checked successfully.$(RESET)"
check-system:
@@ -101,6 +102,18 @@ check-docker:
exit 1; \
fi
check-tmux:
@echo "$(YELLOW)Checking tmux installation...$(RESET)"
@if command -v tmux > /dev/null; then \
echo "$(BLUE)$(shell tmux -V) is already installed.$(RESET)"; \
else \
echo "$(YELLOW)╔════════════════════════════════════════════════════════════════════════════╗$(RESET)"; \
echo "$(YELLOW)║ OPTIONAL: tmux is not installed. ║$(RESET)"; \
echo "$(YELLOW)║ Some advanced terminal features may not work without tmux. ║$(RESET)"; \
echo "$(YELLOW)║ You can install it if needed, but it's not required for development. ║$(RESET)"; \
echo "$(YELLOW)╚════════════════════════════════════════════════════════════════════════════╝$(RESET)"; \
fi
check-poetry:
@echo "$(YELLOW)Checking Poetry installation...$(RESET)"
@if command -v poetry > /dev/null; then \
@@ -175,7 +188,7 @@ install-pre-commit-hooks:
lint-backend:
@echo "$(YELLOW)Running linters...$(RESET)"
@poetry run pre-commit run --files openhands/**/* agenthub/**/* evaluation/**/* --show-diff-on-failure --config $(PRE_COMMIT_CONFIG_PATH)
@poetry run pre-commit run --files openhands/**/* evaluation/**/* tests/**/* --show-diff-on-failure --config $(PRE_COMMIT_CONFIG_PATH)
lint-frontend:
@echo "$(YELLOW)Running linters for frontend...$(RESET)"
+27 -23
View File
@@ -9,7 +9,6 @@
<div align="center">
<a href="https://github.com/All-Hands-AI/OpenHands/graphs/contributors"><img src="https://img.shields.io/github/contributors/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Contributors"></a>
<a href="https://github.com/All-Hands-AI/OpenHands/stargazers"><img src="https://img.shields.io/github/stars/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Stargazers"></a>
<a href="https://codecov.io/github/All-Hands-AI/OpenHands?branch=main"><img alt="CodeCov" src="https://img.shields.io/codecov/c/github/All-Hands-AI/OpenHands?style=for-the-badge&color=blue"></a>
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE"><img src="https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="MIT License"></a>
<br/>
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community"></a>
@@ -18,7 +17,7 @@
<br/>
<a href="https://docs.all-hands.dev/modules/usage/getting-started"><img src="https://img.shields.io/badge/Documentation-000?logo=googledocs&logoColor=FFE165&style=for-the-badge" alt="Check out the documentation"></a>
<a href="https://arxiv.org/abs/2407.16741"><img src="https://img.shields.io/badge/Paper%20on%20Arxiv-000?logoColor=FFE165&logo=arxiv&style=for-the-badge" alt="Paper on Arxiv"></a>
<a href="https://huggingface.co/spaces/OpenHands/evaluation"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score"></a>
<a href="https://docs.google.com/spreadsheets/d/1wOUdFCMyY6Nt0AIqF705KN4JKOWgeI4wUGUP60krXXs/edit?gid=0#gid=0"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score"></a>
<hr>
</div>
@@ -27,7 +26,7 @@ Welcome to OpenHands (formerly OpenDevin), a platform for software development a
OpenHands agents can do anything a human developer can: modify code, run commands, browse the web,
call APIs, and yes—even copy code snippets from StackOverflow.
Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or jump to the [Quick Start](#-quick-start).
Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or [sign up for OpenHands Cloud](https://app.all-hands.dev) to get started.
> [!IMPORTANT]
> Using OpenHands for work? We'd love to chat! Fill out
@@ -36,37 +35,50 @@ Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or jump to the [
![App screenshot](./docs/static/img/screenshot.png)
## ⚡ Quick Start
## ☁️ OpenHands Cloud
The easiest way to get started with OpenHands is on [OpenHands Cloud](https://app.all-hands.dev),
which comes with $50 in free credits for new users.
The easiest way to run OpenHands is in Docker.
## 💻 Running OpenHands Locally
OpenHands can also run on your local system using Docker.
See the [Running OpenHands](https://docs.all-hands.dev/modules/usage/installation) guide for
system requirements and more information.
> [!WARNING]
> On a public network? See our [Hardened Docker Installation Guide](https://docs.all-hands.dev/modules/usage/runtimes/docker#hardened-docker-installation)
> to secure your deployment by restricting network binding and implementing additional security measures.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.32
docker.all-hands.dev/all-hands-ai/openhands:0.36
```
> [!WARNING]
> On a public network? See our [Hardened Docker Installation](https://docs.all-hands.dev/modules/usage/runtimes/docker#hardened-docker-installation) guide
> to secure your deployment by restricting network binding and implementing additional security measures.
You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)!
Finally, you'll need a model provider and API key.
[Anthropic's Claude 3.5 Sonnet](https://www.anthropic.com/api) (`anthropic/claude-3-5-sonnet-20241022`)
When you open the application, you'll be asked to choose an LLM provider and add an API key.
[Anthropic's Claude 3.7 Sonnet](https://www.anthropic.com/api) (`anthropic/claude-3-7-sonnet-20250219`)
works best, but you have [many options](https://docs.all-hands.dev/modules/usage/llms).
---
## 💡 Other ways to run OpenHands
> [!CAUTION]
> OpenHands is meant to be run by a single user on their local workstation.
> It is not appropriate for multi-tenant deployments where multiple users share the same instance. There is no built-in authentication, isolation, or scalability.
>
> If you're interested in running OpenHands in a multi-tenant environment, please
> [get in touch with us](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
> for advanced deployment options.
You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem),
run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/modules/usage/how-to/headless-mode),
@@ -75,14 +87,6 @@ or run it on tagged issues with [a github action](https://docs.all-hands.dev/mod
Visit [Running OpenHands](https://docs.all-hands.dev/modules/usage/installation) for more information and setup instructions.
> [!CAUTION]
> OpenHands is meant to be run by a single user on their local workstation.
> It is not appropriate for multi-tenant deployments where multiple users share the same instance. There is no built-in isolation or scalability.
>
> If you're interested in running OpenHands in a multi-tenant environment, please
> [get in touch with us](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
> for advanced deployment options.
If you want to modify the OpenHands source code, check out [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting) can help.
+17 -4
View File
@@ -216,13 +216,26 @@ model = "gpt-4o"
[agent]
# Whether the browsing tool is enabled
codeact_enable_browsing = true
enable_browsing = true
# Whether the LLM draft editor is enabled
codeact_enable_llm_editor = false
enable_llm_editor = false
# Whether the standard editor tool (str_replace_editor) is enabled
# Only has an effect if enable_llm_editor is False
enable_editor = true
# Whether the IPython tool is enabled
codeact_enable_jupyter = true
enable_jupyter = true
# Whether the command tool is enabled
enable_cmd = true
# Whether the think tool is enabled
enable_think = true
# Whether the finish tool is enabled
enable_finish = true
# LLM config group to use
#llm_config = 'your-llm-config-group'
@@ -378,7 +391,7 @@ type = "noop"
#[llm.condenser]
#model = "gpt-4o"
#temperature = 0.1
#max_tokens = 1024
#max_input_tokens = 1024
#################################### Eval ####################################
# Configuration for the evaluation, please refer to the specific evaluation
+3 -3
View File
@@ -61,8 +61,8 @@ RUN add-apt-repository ppa:deadsnakes/ppa \
&& apt-get install -y python3.12 python3.12-venv python3.12-dev python3-pip \
&& ln -s /usr/bin/python3.12 /usr/bin/python
# NodeJS >= 18.17.1
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
# NodeJS >= 22.x
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y nodejs
# Poetry >= 1.8
@@ -108,7 +108,7 @@ WORKDIR /app
# cache build dependencies
RUN \
--mount=type=bind,source=./,target=/app/ \
--mount=type=bind,source=./,target=/app/,rw \
<<EOF
#!/bin/bash
make -s clean
+1 -1
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.32-nikolaik}
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.36-nikolaik}
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:
+1 -1
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.32-nikolaik}
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik}
#- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234} # enable this only if you want a specific non-root sandbox user but you will have to manually adjust permissions of openhands-state for this user
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:
+1
View File
@@ -3,6 +3,7 @@
# Production
/build
/static/swagger-ui
# Generated files
.docusaurus
+17
View File
@@ -36,6 +36,14 @@ const config: Config = {
mermaid: true,
},
themes: ['@docusaurus/theme-mermaid'],
plugins: [
[
require.resolve('docusaurus-lunr-search'),
{
languages: ['en', 'zh', 'fr', 'ja', 'pt']
}
]
],
presets: [
[
'classic',
@@ -75,10 +83,19 @@ const config: Config = {
position: 'left',
label: 'User Guides',
},
{
href: 'https://docs.all-hands.dev/swagger-ui/', // FIXME: this should be a relative path, but docusarus steals the click
label: 'API',
position: 'left',
},
{
type: 'localeDropdown',
position: 'left',
},
{
type: 'search',
position: 'left',
},
{
href: 'https://all-hands.dev',
label: 'Company',
+102
View File
@@ -0,0 +1,102 @@
const fs = require('fs');
const path = require('path');
const swaggerUiDist = require('swagger-ui-dist');
/**
* This script manually sets up Swagger UI for the Docusaurus documentation.
*
* Why we need this approach:
* 1. Docusaurus doesn't have a built-in way to integrate Swagger UI
* 2. We need to copy the necessary files from swagger-ui-dist to our static directory
* 3. We need to create a custom index.html file that points to our OpenAPI spec
* 4. This approach allows us to customize the Swagger UI to match our documentation style
*/
// Get the absolute path to the swagger-ui-dist package
const swaggerUiDistPath = swaggerUiDist.getAbsoluteFSPath();
// Create the target directory if it doesn't exist
const targetDir = path.join(__dirname, 'static', 'swagger-ui');
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
// Copy all files from swagger-ui-dist to our target directory
const files = fs.readdirSync(swaggerUiDistPath);
files.forEach(file => {
const sourcePath = path.join(swaggerUiDistPath, file);
const targetPath = path.join(targetDir, file);
// Skip directories and non-essential files
if (fs.statSync(sourcePath).isDirectory() ||
file === 'package.json' ||
file === 'README.md' ||
file.endsWith('.map')) {
return;
}
fs.copyFileSync(sourcePath, targetPath);
});
// Create a custom index.html file that points to our OpenAPI spec
const indexHtml = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OpenHands API Documentation</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "/openapi.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
// End Swagger UI call region
window.ui = ui;
};
</script>
</body>
</html>
`;
fs.writeFileSync(path.join(targetDir, 'index.html'), indexHtml);
console.log('Swagger UI files generated successfully in static/swagger-ui/');
@@ -354,12 +354,12 @@ Les options de configuration de l'agent sont définies dans les sections `[agent
- Valeur par défaut : `true`
- Description : Si l'appel de fonction est activé
- `codeact_enable_browsing`
- `enable_browsing`
- Type : `bool`
- Valeur par défaut : `false`
- Description : Si le délégué de navigation est activé dans l'espace d'action (fonctionne uniquement avec l'appel de fonction)
- `codeact_enable_llm_editor`
- `enable_llm_editor`
- Type : `bool`
- Valeur par défaut : `false`
- Description : Si l'éditeur LLM est activé dans l'espace d'action (fonctionne uniquement avec l'appel de fonction)
@@ -52,7 +52,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -61,7 +61,7 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.cli
```
@@ -21,14 +21,18 @@ OpenHands fournit un mode Interface Graphique (GUI) convivial pour interagir ave
3. Entrez la `Clé API` correspondante pour le fournisseur choisi.
4. Cliquez sur "Enregistrer" pour appliquer les paramètres.
### Configuration du Jeton GitHub
### Jetons de Contrôle de Version
OpenHands prend en charge plusieurs fournisseurs de contrôle de version. Vous pouvez configurer des jetons pour plusieurs fournisseurs simultanément.
#### Configuration du Jeton GitHub
OpenHands exporte automatiquement un `GITHUB_TOKEN` vers l'environnement shell s'il est disponible. Cela peut se produire de deux manières :
1. **Localement (OSS)** : L'utilisateur saisit directement son jeton GitHub
2. **En ligne (SaaS)** : Le jeton est obtenu via l'authentification OAuth GitHub
#### Configuration d'un Jeton GitHub Local
##### Configuration d'un Jeton GitHub Local
1. **Générer un Personal Access Token (PAT)** :
- Allez dans Paramètres GitHub > Paramètres développeur > Personal Access Tokens > Tokens (classique)
@@ -40,11 +44,11 @@ OpenHands exporte automatiquement un `GITHUB_TOKEN` vers l'environnement shell s
2. **Entrer le Jeton dans OpenHands** :
- Cliquez sur le bouton Paramètres (icône d'engrenage) en haut à droite
- Accédez à la section "GitHub"
- Accédez à la section "Git Provider Settings"
- Collez votre jeton dans le champ "Jeton GitHub"
- Cliquez sur "Enregistrer" pour appliquer les modifications
#### Politiques de Jetons Organisationnels
##### Politiques de Jetons Organisationnels
Si vous travaillez avec des dépôts organisationnels, une configuration supplémentaire peut être nécessaire :
@@ -59,7 +63,7 @@ Si vous travaillez avec des dépôts organisationnels, une configuration supplé
- Si nécessaire, cliquez sur "Activer SSO" à côté de votre organisation
- Terminez le processus d'autorisation SSO
#### Authentification OAuth (Mode En Ligne)
##### Authentification OAuth (Mode En Ligne)
Lorsque vous utilisez OpenHands en mode en ligne, le flux OAuth GitHub :
@@ -74,7 +78,7 @@ Lorsque vous utilisez OpenHands en mode en ligne, le flux OAuth GitHub :
- Autorisez OpenHands à accéder à votre compte GitHub
- Si vous utilisez une organisation, autorisez l'accès à l'organisation si vous y êtes invité
#### Dépannage
##### Dépannage
Problèmes courants et solutions :
@@ -95,6 +99,43 @@ Problèmes courants et solutions :
- Vérifiez la console du navigateur pour tout message d'erreur
- Utilisez le bouton "Tester la connexion" dans les paramètres s'il est disponible
#### Configuration du Jeton GitLab
OpenHands exporte automatiquement un `GITLAB_TOKEN` vers l'environnement shell, uniquement pour les installations locales, s'il est disponible.
##### Configuration d'un Jeton GitLab
1. **Générer un Personal Access Token (PAT)** :
- Sur GitLab, allez dans Paramètres utilisateur > Jetons d'accès
- Créez un nouveau jeton avec les portées suivantes :
- `api` (Accès API)
- `read_user` (Lecture des informations utilisateur)
- `read_repository` (Lecture du dépôt)
- `write_repository` (Écriture du dépôt)
- Définissez une date d'expiration ou laissez vide pour un jeton sans expiration
2. **Entrer le Jeton dans OpenHands** :
- Cliquez sur le bouton Paramètres (icône d'engrenage)
- Accédez à la section `Git Provider Settings`
- Collez votre jeton dans le champ `Jeton GitLab`
- Si vous utilisez GitLab auto-hébergé, entrez l'URL de votre instance GitLab
- Cliquez sur `Enregistrer les modifications` pour appliquer les changements
##### Dépannage
Problèmes courants et solutions :
1. **Jeton Non Reconnu** :
- Assurez-vous que le jeton est correctement enregistré dans les paramètres
- Vérifiez que le jeton n'a pas expiré
- Vérifiez que le jeton a les portées requises
- Pour les instances auto-hébergées, vérifiez l'URL correcte de l'instance
2. **Accès Refusé** :
- Vérifiez les permissions d'accès au projet
- Vérifiez si le jeton possède les portées nécessaires
- Pour les dépôts de groupe/organisation, assurez-vous d'avoir les accès appropriés
### Paramètres Avancés
1. Basculez sur `Options Avancées` pour accéder aux paramètres supplémentaires.
@@ -46,7 +46,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -56,6 +56,6 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
```
@@ -13,16 +13,16 @@
La façon la plus simple d'exécuter OpenHands est avec Docker.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.32
docker.all-hands.dev/all-hands-ai/openhands:0.36
```
Vous pouvez également exécuter OpenHands en mode [headless scriptable](https://docs.all-hands.dev/modules/usage/how-to/headless-mode), en tant que [CLI interactive](https://docs.all-hands.dev/modules/usage/how-to/cli-mode), ou en utilisant l'[Action GitHub OpenHands](https://docs.all-hands.dev/modules/usage/how-to/github-action).
@@ -13,7 +13,7 @@ C'est le Runtime par défaut qui est utilisé lorsque vous démarrez OpenHands.
```
docker run # ...
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-v /var/run/docker.sock:/var/run/docker.sock \
# ...
```
@@ -348,12 +348,12 @@ dockerコマンドで使用する場合は、`-e LLM_<option>`として渡しま
- デフォルト値: `true`
- 説明: 関数呼び出しが有効かどうか
- `codeact_enable_browsing`
- `enable_browsing`
- 型: `bool`
- デフォルト値: `false`
- 説明: アクションスペースでブラウジングデリゲートが有効かどうか(関数呼び出しでのみ機能)
- `codeact_enable_llm_editor`
- `enable_llm_editor`
- 型: `bool`
- デフォルト値: `false`
- 説明: アクションスペースでLLMエディタが有効かどうか(関数呼び出しでのみ機能)
@@ -34,7 +34,7 @@ Docker で OpenHands を CLI モードで実行するには:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -44,7 +44,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.cli
```
@@ -16,7 +16,11 @@ OpenHandsは、AI アシスタントとやり取りするためのグラフィ
3. 選択したプロバイダーに対応する`API Key`を入力します。
4. `Save Changes`をクリックして設定を適用します。
### GitHubトークンの設定
### バージョン管理トークン
OpenHandsは複数のバージョン管理プロバイダーをサポートしています。複数のプロバイダーのトークンを同時に設定できます。
#### GitHubトークンの設定
OpenHandsは、利用可能な場合、自動的に`GITHUB_TOKEN`をシェル環境にエクスポートします。これは2つの方法で行われます。
@@ -34,7 +38,7 @@ OpenHandsは、利用可能な場合、自動的に`GITHUB_TOKEN`をシェル環
- Minimal Permissions(検索用に**Meta Data = Read-only**を選択し、ブランチ作成用に**Pull Requests = Read and Write**、**Content = Read and Write**を選択します)
2. **OpenHandsにトークンを入力**:
- 設定ボタン(歯車アイコン)をクリックします。
- `GitHub Settings`セクションに移動します。
- `Git Provider Settings`セクションに移動します。
- `GitHub Token`フィールドにトークンを貼り付けます。
- `Save Changes`をクリックして変更を適用します。
</details>
@@ -94,6 +98,46 @@ OpenHandsは、利用可能な場合、自動的に`GITHUB_TOKEN`をシェル環
- 組織を使用している場合は、プロンプトが表示されたら組織へのアクセスを承認します。
</details>
#### GitLabトークンの設定
OpenHandsは、利用可能な場合、ローカルインストールのみ、自動的に`GITLAB_TOKEN`をシェル環境にエクスポートします。
<details>
<summary>GitLabトークンの設定</summary>
1. **Personal Access TokenPAT)の生成**:
- GitLabで、User Settings > Access Tokensに移動します。
- 以下のスコープを持つ新しいトークンを作成します:
- `api`APIアクセス)
- `read_user`(ユーザー情報の読み取り)
- `read_repository`(リポジトリ読み取り)
- `write_repository`(リポジトリ書き込み)
- 有効期限を設定するか、無期限トークンの場合は空白のままにします。
2. **OpenHandsにトークンを入力**:
- 設定ボタン(歯車アイコン)をクリックします。
- `Git Provider Settings`セクションに移動します。
- `GitLab Token`フィールドにトークンを貼り付けます。
- セルフホスト型GitLabを使用している場合は、GitLabインスタンスのURLを入力します。
- `Save Changes`をクリックして変更を適用します。
</details>
<details>
<summary>トラブルシューティング</summary>
一般的な問題と解決策:
- **トークンが認識されない**:
- トークンが設定に正しく保存されていることを確認します。
- トークンの有効期限が切れていないことを確認します。
- トークンに必要なスコープがあることを確認します。
- セルフホスト型インスタンスの場合は、正しいインスタンスURLを確認します。
- **アクセスが拒否された**:
- プロジェクトのアクセス権限を確認します。
- トークンに必要なスコープがあるかどうかを確認します。
- グループ/組織のリポジトリの場合は、適切なアクセス権があることを確認します。
</details>
### 高度な設定
1. 設定ページ内で、`Advanced`オプションを切り替えて追加の設定にアクセスします。
@@ -31,7 +31,7 @@ DockerでOpenHandsをヘッドレスモードで実行するには:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -42,7 +42,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.main -t "write a bash script that prints hi"
```
@@ -13,7 +13,7 @@ OpenHandsがリポジトリで動作する際:
1. リポジトリに`.openhands/microagents/`が存在する場合、そこからリポジトリ固有の指示を読み込みます。
2. 会話のキーワードによってトリガーされる一般的なガイドラインを読み込みます。
現在の[パブリックMicroagents](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)を参照してください。
現在の[パブリックMicroagents](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)を参照してください。
## Microagentのフォーマット
@@ -88,4 +88,4 @@ triggers:
- ビルド時間とイメージサイズを最適化
```
より多くの例については、[現在のパブリックマイクロエージェント](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)をご覧ください。
より多くの例については、[現在のパブリックマイクロエージェント](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)をご覧ください。
@@ -25,7 +25,7 @@ nikolaik の `SANDBOX_RUNTIME_CONTAINER_IMAGE` は、ランタイムサーバー
```bash
docker run # ...
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-v $WORKSPACE_BASE:/opt/workspace_base \
@@ -82,5 +82,5 @@ docker network create openhands-network
# 分離されたネットワークで OpenHands を実行
docker run # ... \
--network openhands-network \
docker.all-hands.dev/all-hands-ai/openhands:0.32
docker.all-hands.dev/all-hands-ai/openhands:0.36
```
@@ -292,17 +292,17 @@ As opções de configuração do agente são definidas nas seções `[agent]` e
- Padrão: `true`
- Descrição: Se a chamada de função está habilitada
- `codeact_enable_browsing`
- `enable_browsing`
- Tipo: `bool`
- Padrão: `false`
- Descrição: Se o delegado de navegação está habilitado no espaço de ação (funciona apenas com chamada de função)
- `codeact_enable_llm_editor`
- `enable_llm_editor`
- Tipo: `bool`
- Padrão: `false`
- Descrição: Se o editor LLM está habilitado no espaço de ação (funciona apenas com chamada de função)
- `codeact_enable_jupyter`
- `enable_jupyter`
- Tipo: `bool`
- Padrão: `false`
- Descrição: Se o Jupyter está habilitado no espaço de ação
@@ -35,7 +35,7 @@ Para executar o OpenHands no modo CLI com Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -45,7 +45,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.cli
```
@@ -17,7 +17,11 @@ O OpenHands fornece um modo de Interface Gráfica do Usuário (GUI) para interag
3. Insira a `Chave de API` correspondente para o provedor escolhido.
4. Clique em `Salvar Alterações` para aplicar as configurações.
### Configuração do Token do GitHub
### Tokens de Controle de Versão
O OpenHands suporta múltiplos provedores de controle de versão. Você pode configurar tokens para vários provedores simultaneamente.
#### Configuração do Token do GitHub
O OpenHands exporta automaticamente um `GITHUB_TOKEN` para o ambiente shell se ele estiver disponível. Isso pode acontecer de duas maneiras:
@@ -35,7 +39,7 @@ O OpenHands exporta automaticamente um `GITHUB_TOKEN` para o ambiente shell se e
- Minimal Permissions (Selecione **Meta Data = Read-only** para pesquisa, **Pull Requests = Read and Write**, **Content = Read and Write** para criação de branches)
2. **Insira o Token no OpenHands**:
- Clique no botão Settings (ícone de engrenagem).
- Navegue até a seção `GitHub Settings`.
- Navegue até a seção `Git Provider Settings`.
- Cole seu token no campo `GitHub Token`.
- Clique em `Save Changes` para aplicar as alterações.
</details>
@@ -95,6 +99,46 @@ O OpenHands exporta automaticamente um `GITHUB_TOKEN` para o ambiente shell se e
- Se estiver usando uma organização, autorize o acesso à organização se solicitado.
</details>
#### Configuração do Token do GitLab
O OpenHands exporta automaticamente um `GITLAB_TOKEN` para o ambiente shell, apenas para instalações locais, se ele estiver disponível.
<details>
<summary>Configurando um Token do GitLab</summary>
1. **Gere um Personal Access Token (PAT)**:
- No GitLab, vá para User Settings > Access Tokens.
- Crie um novo token com os seguintes escopos:
- `api` (Acesso à API)
- `read_user` (Leitura de informações do usuário)
- `read_repository` (Leitura do repositório)
- `write_repository` (Escrita no repositório)
- Defina uma data de expiração ou deixe em branco para um token sem expiração.
2. **Insira o Token no OpenHands**:
- Clique no botão Settings (ícone de engrenagem).
- Navegue até a seção `Git Provider Settings`.
- Cole seu token no campo `GitLab Token`.
- Se estiver usando GitLab auto-hospedado, insira a URL da sua instância GitLab.
- Clique em `Save Changes` para aplicar as alterações.
</details>
<details>
<summary>Solução de Problemas</summary>
Problemas comuns e soluções:
- **Token Não Reconhecido**:
- Certifique-se de que o token esteja salvo corretamente nas configurações.
- Verifique se o token não expirou.
- Verifique se o token possui os escopos necessários.
- Para instâncias auto-hospedadas, verifique a URL correta da instância.
- **Acesso Negado**:
- Verifique as permissões de acesso ao projeto.
- Verifique se o token possui os escopos necessários.
- Para repositórios de grupo/organização, certifique-se de ter o acesso adequado.
</details>
### Configurações Avançadas
1. Dentro da página Settings, ative as opções `Advanced` para acessar configurações adicionais.
@@ -32,7 +32,7 @@ Para executar o OpenHands no modo Headless com Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -43,7 +43,7 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.main -t "escreva um script bash que imprima oi"
```
@@ -58,17 +58,17 @@
A maneira mais fácil de executar o OpenHands é no Docker.
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.32
docker.all-hands.dev/all-hands-ai/openhands:0.36
```
Você encontrará o OpenHands em execução em http://localhost:3000!
@@ -13,7 +13,7 @@ Quando o OpenHands trabalha com um repositório, ele:
1. Carrega instruções específicas do repositório de `.openhands/microagents/`, se presentes no repositório.
2. Carrega diretrizes gerais acionadas por palavras-chave nas conversas.
Veja os [Microagentes Públicos](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) atuais.
Veja os [Microagentes Públicos](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents) atuais.
## Formato do Microagente
@@ -4,7 +4,7 @@
Microagentes públicos são diretrizes especializadas acionadas por palavras-chave para todos os usuários do OpenHands.
Eles são definidos em arquivos markdown no diretório
[`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge).
[`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents).
Microagentes públicos:
- Monitoram comandos recebidos em busca de suas palavras-chave de acionamento.
@@ -15,7 +15,7 @@ Microagentes públicos:
## Microagentes Públicos Atuais
Para mais informações sobre microagentes específicos, consulte seus arquivos de documentação individuais no
diretório [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge/).
diretório [`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/).
### Agente GitHub
**Arquivo**: `github.md`
@@ -59,7 +59,7 @@ yes | npm install package-name
## Contribuindo com um Microagente Público
Você pode criar seus próprios microagentes públicos adicionando novos arquivos markdown ao
diretório [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge/).
diretório [`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/).
### Melhores Práticas para Microagentes Públicos
@@ -81,7 +81,7 @@ Antes de criar um microagente público, considere:
#### 2. Crie o Arquivo
Crie um novo arquivo markdown em [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge/)
Crie um novo arquivo markdown em [`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/)
com um nome descritivo (por exemplo, `docker.md` para um agente focado em Docker).
Atualize o arquivo com o frontmatter necessário [de acordo com o formato exigido](./microagents-overview#microagent-format)
@@ -149,5 +149,5 @@ Lembre-se de:
- Otimizar para tempo de build e tamanho da imagem
```
Veja os [microagentes públicos atuais](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) para
Veja os [microagentes públicos atuais](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents) para
mais exemplos.
@@ -13,7 +13,7 @@ Este é o Runtime padrão que é usado quando você inicia o OpenHands. Você po
```
docker run # ...
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-v /var/run/docker.sock:/var/run/docker.sock \
# ...
```
@@ -349,17 +349,17 @@ Agent 配置选项在 `config.toml` 文件的 `[agent]` 和 `[agent.<agent_name>
- 默认值: `true`
- 描述: 是否启用函数调用
- `codeact_enable_browsing`
- `enable_browsing`
- 类型: `bool`
- 默认值: `false`
- 描述: 是否在 action space 中启用浏览代理(仅适用于函数调用)
- `codeact_enable_llm_editor`
- `enable_llm_editor`
- 类型: `bool`
- 默认值: `false`
- 描述: 是否在 action space 中启用 LLM 编辑器(仅适用于函数调用)
- `codeact_enable_jupyter`
- `enable_jupyter`
- 类型: `bool`
- 默认值: `false`
- 描述: 是否在 action space 中启用 Jupyter
@@ -50,7 +50,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -59,7 +59,7 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.cli
```
@@ -19,14 +19,18 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
3. 输入所选提供商对应的 `API Key`
4. 点击"保存"应用设置。
### GitHub Token 设置
### 版本控制令牌
OpenHands 支持多个版本控制提供商。您可以同时配置多个提供商的令牌。
#### GitHub Token 设置
如果可用,OpenHands 会自动将 `GITHUB_TOKEN` 导出到 shell 环境中。这可以通过两种方式实现:
1. **本地(OSS**:用户直接输入他们的 GitHub token
2. **在线(SaaS**:通过 GitHub OAuth 身份验证获取 token
#### 设置本地 GitHub Token
##### 设置本地 GitHub Token
1. **生成个人访问令牌(PAT**
- 转到 GitHub 设置 > 开发者设置 > 个人访问令牌 > 令牌(经典)
@@ -38,11 +42,11 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
2. **在 OpenHands 中输入令牌**
- 点击右上角的设置按钮(齿轮图标)
- 导航到"GitHub"部分
- 导航到"Git Provider Settings"部分
- 将令牌粘贴到"GitHub Token"字段中
- 点击"保存"应用更改
#### 组织令牌策略
##### 组织令牌策略
如果您使用组织仓库,可能需要额外的设置:
@@ -57,7 +61,7 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
- 如果需要,点击组织旁边的"启用 SSO"
- 完成 SSO 授权过程
#### OAuth 身份验证(在线模式)
##### OAuth 身份验证(在线模式)
在在线模式下使用 OpenHands 时,GitHub OAuth 流程:
@@ -72,7 +76,7 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
- 授权 OpenHands 访问您的 GitHub 帐户
- 如果使用组织,在出现提示时授权组织访问
#### 故障排除
##### 故障排除
常见问题和解决方案:
@@ -93,6 +97,43 @@ OpenHands 提供了一个用户友好的图形用户界面(GUI)模式,用
- 检查浏览器控制台中是否有任何错误消息
- 如果可用,使用设置中的"测试连接"按钮
#### GitLab Token 设置
OpenHands 会自动将 `GITLAB_TOKEN` 导出到 shell 环境中,仅适用于本地安装,如果它可用的话。
##### 设置 GitLab Token
1. **生成个人访问令牌(PAT**
- 在 GitLab 中,转到用户设置 > 访问令牌
- 创建具有以下范围的新令牌:
- `api`API 访问)
- `read_user`(读取用户信息)
- `read_repository`(读取仓库)
- `write_repository`(写入仓库)
- 设置过期日期或留空以获取永不过期的令牌
2. **在 OpenHands 中输入令牌**
- 点击设置按钮(齿轮图标)
- 导航到 `Git Provider Settings` 部分
- 将令牌粘贴到 `GitLab Token` 字段中
- 如果使用自托管 GitLab,请输入您的 GitLab 实例 URL
- 点击 `Save Changes` 应用更改
##### 故障排除
常见问题和解决方案:
1. **令牌无法识别**
- 确保令牌已正确保存在设置中
- 检查令牌是否已过期
- 验证令牌是否具有所需的范围
- 对于自托管实例,验证正确的实例 URL
2. **访问被拒绝**
- 验证项目访问权限
- 检查令牌是否具有必要的范围
- 对于组/组织仓库,确保您拥有适当的访问权限
### 高级设置
1. 切换`高级选项`以访问其他设置。
@@ -47,7 +47,7 @@ LLM_API_KEY="sk_test_12345"
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -57,6 +57,6 @@ docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
```
@@ -11,16 +11,16 @@
在 Docker 中运行 OpenHands 是最简单的方式。
```bash
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.32
docker.all-hands.dev/all-hands-ai/openhands:0.36
```
你也可以在可脚本化的[无头模式](https://docs.all-hands.dev/modules/usage/how-to/headless-mode)下运行 OpenHands,作为[交互式 CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode),或使用 [OpenHands GitHub Action](https://docs.all-hands.dev/modules/usage/how-to/github-action)。
@@ -11,7 +11,7 @@
```
docker run # ...
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-v /var/run/docker.sock:/var/run/docker.sock \
# ...
```
+8
View File
@@ -0,0 +1,8 @@
{
"label": "OpenHands Cloud",
"position": 9,
"link": {
"type": "generated-index",
"description": "Documentation for OpenHands Cloud features and services."
}
}
+177
View File
@@ -0,0 +1,177 @@
# OpenHands Cloud API
OpenHands Cloud provides a REST API that allows you to programmatically interact with the service. This is useful if you easily want to kick off your own jobs from your programs in a flexible way.
This guide explains how to obtain an API key and use the API to start conversations.
For more detailed information about the API, refer to the [OpenHands API Reference](https://docs.all-hands.dev/swagger-ui/).
## Obtaining an API Key
To use the OpenHands Cloud API, you'll need to generate an API key:
1. Log in to your [OpenHands Cloud](https://app.all-hands.dev) account
2. Navigate to the [Settings page](https://app.all-hands.dev/settings)
3. Locate the "API Keys" section
4. Click "Generate New Key"
5. Give your key a descriptive name (e.g., "Development", "Production")
6. Copy the generated API key and store it securely - it will only be shown once
![API Key Generation](/img/docs/api-key-generation.png)
## API Usage
### Starting a New Conversation
To start a new conversation with OpenHands performing a task, you'll need to make a POST request to the conversation endpoint.
#### Request Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `initial_user_msg` | string | Yes | The initial message to start the conversation |
| `repository` | string | No | Git repository name to provide context in the format `owner/repo`. You must have access to the repo. |
#### Examples
<details>
<summary>cURL</summary>
```bash
curl -X POST "https://app.all-hands.dev/api/conversations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"initial_user_msg": "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so.",
"repository": "yourusername/your-repo"
}'
```
</details>
<details>
<summary>Python (with requests)</summary>
```python
import requests
api_key = "YOUR_API_KEY"
url = "https://app.all-hands.dev/api/conversations"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
data = {
"initial_user_msg": "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so.",
"repository": "yourusername/your-repo"
}
response = requests.post(url, headers=headers, json=data)
conversation = response.json()
print(f"Conversation Link: https://app.all-hands.dev/conversations/{conversation['id']}")
print(f"Status: {conversation['status']}")
```
</details>
<details>
<summary>TypeScript/JavaScript (with fetch)</summary>
```typescript
const apiKey = "YOUR_API_KEY";
const url = "https://app.all-hands.dev/api/conversations";
const headers = {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
};
const data = {
initial_user_msg: "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so.",
repository: "yourusername/your-repo"
};
async function startConversation() {
try {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(data)
});
const conversation = await response.json();
console.log(`Conversation Link: https://app.all-hands.dev/conversations/${conversation.id}`);
console.log(`Status: ${conversation.status}`);
return conversation;
} catch (error) {
console.error("Error starting conversation:", error);
}
}
startConversation();
```
</details>
#### Response
The API will return a JSON object with details about the created conversation:
```json
{
"status": "ok",
"conversation_id": "abc1234",
}
```
You may also receive an `AuthenticationError` if:
1. You provided an invalid API key
2. You provided the wrong repo name
3. You don't have access to the repo
### Retrieving Conversation Status
You can check the status of a conversation by making a GET request to the conversation endpoint.
#### Endpoint
```
GET https://app.all-hands.dev/api/conversations/{conversation_id}
```
#### Example
<details>
<summary>cURL</summary>
```bash
curl -X GET "https://app.all-hands.dev/api/conversations/{conversation_id}" \
-H "Authorization: Bearer YOUR_API_KEY"
```
</details>
#### Response
The response is formatted as follows:
```json
{
"conversation_id":"abc1234",
"title":"Update README.md",
"created_at":"2025-04-29T15:13:51.370706Z",
"last_updated_at":"2025-04-29T15:13:57.199210Z",
"status":"RUNNING",
"selected_repository":"yourusername/your-repo",
"trigger":"gui"
}
```
## Rate Limits
The API has a limit of 10 simultaneous conversations per account. If you need a higher limit for your use case, please contact us at [contact@all-hands.dev](mailto:contact@all-hands.dev).
If you exceed this limit, the API will return a 429 Too Many Requests response.
+20 -10
View File
@@ -6,20 +6,26 @@ OpenHands Cloud is the cloud hosted version of OpenHands by All Hands AI.
OpenHands Cloud can be accessed at https://app.all-hands.dev/.
You can also interact with OpenHands Cloud programmatically using the [API](./cloud-api).
## Getting Started
After visiting OpenHands Cloud, you will be asked to connect with your GitHub account:
1. After reading and accepting the terms of service, click `Connect to GitHub`.
After visiting OpenHands Cloud, you will be asked to connect with your GitHub or GitLab account:
1. After reading and accepting the terms of service, click `Log in with GitHub` or `Log in with GitLab`.
2. Review the permissions requested by OpenHands and then click `Authorize OpenHands AI`.
- OpenHands will require some permissions from your GitHub account. To read more about these permissions,
you can click the `Learn more` link on the GitHub authorize page.
- OpenHands will require some permissions from your GitHub or GitLab account. To read more about these permissions:
- GitHub: You can click the `Learn more` link on the GitHub authorize page.
- GitLab: You can expand each permission request on the GitLab authorize page.
## Repository Access
### Adding Repository Access
### GitHub
#### Adding Repository Access
You can grant OpenHands specific repository access:
1. Click the `Select a GitHub project` dropdown, select `Add more repositories...`.
1. Click `Add GitHub repos` on the Home page.
2. Select the organization, then choose the specific repositories to grant OpenHands access to.
<details>
<summary>Permission Details for Repository Access</summary>
@@ -42,11 +48,15 @@ You can grant OpenHands specific repository access:
3. Click on `Install & Authorize`.
### Modifying Repository Access
#### Modifying Repository Access
You can modify repository access at any time by:
* Using the same `Select a GitHub project > Add more repositories` workflow, or
* Visiting the Settings page and selecting `Configure GitHub Repositories` under the `GitHub Settings` section.
You can modify GitHub repository access at any time by:
* Using the same `Add GitHub repos` workflow, or
* Visiting the Settings page and selecting `Configure GitHub Repositories` under the `Git Settings` section.
### GitLab
When using your GitLab account, OpenHands will automatically have access to your repositories.
## Conversation Persistence
+3 -3
View File
@@ -291,17 +291,17 @@ The agent configuration options are defined in the `[agent]` and `[agent.<agent_
- Default: `true`
- Description: Whether function calling is enabled
- `codeact_enable_browsing`
- `enable_browsing`
- Type: `bool`
- Default: `false`
- Description: Whether browsing delegate is enabled in the action space (only works with function calling)
- `codeact_enable_llm_editor`
- `enable_llm_editor`
- Type: `bool`
- Default: `false`
- Description: Whether LLM editor is enabled in the action space (only works with function calling)
- `codeact_enable_jupyter`
- `enable_jupyter`
- Type: `bool`
- Default: `false`
- Description: Whether Jupyter is enabled in the action space
@@ -1,18 +1,17 @@
# Repository Customization
You can customize how OpenHands works with your repository by creating a
You can customize how OpenHands interacts with your repository by creating a
`.openhands` directory at the root level.
## Microagents
You can use microagents to extend the OpenHands prompts with information
about your project and how you want OpenHands to work. See
[Repository Microagents](../prompting/microagents-repo) for more information.
Microagents allow you to extend OpenHands prompts with information specific to your project and define how OpenHands
should function. See [Microagents Overview](../prompting/microagents-overview) for more information.
## Setup Script
You can add `.openhands/setup.sh`, which will be run every time OpenHands begins
working with your repository. This is a good place to install dependencies, set
environment variables, etc.
You can add a `.openhands/setup.sh` file, which will run every time OpenHands begins working with your repository.
This is an ideal location for installing dependencies, setting environment variables, and performing other setup tasks.
For example:
```bash
+5 -2
View File
@@ -35,7 +35,7 @@ To run OpenHands in CLI mode with Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -45,8 +45,11 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.cli
```
This command will start an interactive session in Docker where you can input tasks and receive responses from OpenHands.
The `-e SANDBOX_USER_ID=$(id -u)` is passed to the Docker command to ensure the sandbox user matches the host users
permissions. This prevents the agent from creating root-owned files in the mounted workspace.
@@ -1,7 +1,8 @@
# Custom Sandbox
:::note
This guide is for users that would like to use their own custom Docker image for the runtime, e.g. with certain tools or programming languages pre-installed
This guide is for users that would like to use their own custom Docker image for the runtime. For example
with certain tools or programming languages pre-installed.
:::
The sandbox is where the agent performs its tasks. Instead of running commands directly on your computer
+40 -17
View File
@@ -18,11 +18,14 @@ OpenHands provides a Graphical User Interface (GUI) mode for interacting with th
3. Enter the corresponding `API Key` for your chosen provider.
4. Click `Save Changes` to apply the settings.
### GitHub Token Setup
### Version Control Tokens
OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it is available. This can happen in two ways:
OpenHands supports multiple version control providers. You can configure tokens for multiple providers simultaneously.
#### GitHub Token Setup
OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if provided:
**Local Installation**: The user directly inputs their GitHub token.
<details>
<summary>Setting Up a GitHub Token</summary>
@@ -36,9 +39,8 @@ OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it
- Minimal Permissions ( Select `Meta Data = Read-only` read for search, `Pull Requests = Read and Write` and `Content = Read and Write` for branch creation)
2. **Enter Token in OpenHands**:
- Click the Settings button (gear icon).
- Navigate to the `GitHub Settings` section.
- Paste your token in the `GitHub Token` field.
- Click `Save Changes` to apply the changes.
- Click `Save` to apply the changes.
</details>
<details>
@@ -79,21 +81,43 @@ OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it
- Check the browser console for any error messages.
</details>
**OpenHands Cloud**: The token is obtained through GitHub OAuth authentication.
#### GitLab Token Setup
OpenHands automatically exports a `GITLAB_TOKEN` to the shell environment if provided:
<details>
<summary>OAuth Authentication</summary>
<summary>Setting Up a GitLab Token</summary>
When using OpenHands Cloud, the GitHub OAuth flow requests the following permissions:
- Repository access (read/write)
- Workflow management
- Organization read access
1. **Generate a Personal Access Token (PAT)**:
- On GitLab, go to User Settings > Access Tokens.
- Create a new token with the following scopes:
- `api` (API access)
- `read_user` (Read user information)
- `read_repository` (Read repository)
- `write_repository` (Write repository)
- Set an expiration date or leave it blank for a non-expiring token.
2. **Enter Token in OpenHands**:
- Click the Settings button (gear icon).
- Paste your token in the `GitLab Token` field.
- Enter your GitLab instance URL if using self-hosted GitLab.
- Click `Save` to apply the changes.
</details>
To authenticate OpenHands:
- Click `Sign in with GitHub` when prompted.
- Review the requested permissions.
- Authorize OpenHands to access your GitHub account.
- If using an organization, authorize organization access if prompted.
<details>
<summary>Troubleshooting</summary>
Common issues and solutions:
- **Token Not Recognized**:
- Ensure the token is properly saved in settings.
- Check that the token hasn't expired.
- Verify the token has the required scopes.
- For self-hosted instances, verify the correct instance URL.
- **Access Denied**:
- Verify project access permissions.
- Check if the token has the necessary scopes.
- For group/organization repositories, ensure you have proper access.
</details>
### Advanced Settings
@@ -112,7 +136,6 @@ OpenHands automatically exports a `GITHUB_TOKEN` to the shell environment if it
## Tips for Effective Use
- Be specific in your requests to get the most accurate and helpful responses, as described in the [prompting best practices](../prompting/prompting-best-practices).
- Use the workspace panel to explore your project structure.
- Use one of the recommended models, as described in the [LLMs section](usage/llms/llms.md).
Remember, the GUI mode of OpenHands is designed to make your interaction with the AI assistant as smooth and intuitive
+5 -2
View File
@@ -32,7 +32,7 @@ To run OpenHands in Headless mode with Docker:
```bash
docker run -it \
--pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
@@ -43,10 +43,13 @@ docker run -it \
-v ~/.openhands-state:/.openhands-state \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
docker.all-hands.dev/all-hands-ai/openhands:0.32 \
docker.all-hands.dev/all-hands-ai/openhands:0.36 \
python -m openhands.core.main -t "write a bash script that prints hi"
```
The `-e SANDBOX_USER_ID=$(id -u)` is passed to the Docker command to ensure the sandbox user matches the host users
permissions. This prevents the agent from creating root-owned files in the mounted workspace.
## Advanced Headless Configurations
To view all available configuration options for headless mode, run the Python command with the `--help` flag.
+3 -3
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.32-nikolaik
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik
docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.32-nikolaik \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.36-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \
docker.all-hands.dev/all-hands-ai/openhands:0.32
docker.all-hands.dev/all-hands-ai/openhands:0.36
```
You'll find OpenHands running at http://localhost:3000!
+10 -9
View File
@@ -6,23 +6,24 @@
- Displays the conversation between the user and OpenHands.
- OpenHands explains its actions in this panel.
### Workspace
- Browse project files and directories.
- Use the `Open in VS Code` option to:
* Modify files
* Upload and download files
### Changes
- Shows the file changes performed by OpenHands.
### VS Code
- Embedded VS Code for browsing and modifying files.
- Can also be used to upload and download files.
### Terminal
- A space for OpenHands and users to run terminal commands.
### Jupyter
- Shows all Python commands that were executed by OpenHands.
- Particularly handy when using OpenHands to perform data visualization tasks.
### App
- Shows the web server when OpenHands runs an application.
- Displays the web server when OpenHands runs an application.
- Users can interact with the running application.
### Browser
- Used by OpenHands to browse websites.
- The browser is non-interactive.
### Terminal
- A space for OpenHands and users to run terminal commands.
+2
View File
@@ -17,6 +17,8 @@ Based on these findings and community feedback, the following models have been v
- [gemini/gemini-2.5-pro](https://blog.google/technology/google-deepmind/gemini-model-thinking-updates-march-2025/)
- [deepseek/deepseek-chat](https://api-docs.deepseek.com/)
- [openai/o3-mini](https://openai.com/index/openai-o3-mini/)
- [openai/o3](https://openai.com/index/introducing-o3-and-o4-mini/)
- [openai/o4-mini](https://openai.com/index/introducing-o3-and-o4-mini/)
- [all-hands/openhands-lm-32b-v0.1](https://www.all-hands.dev/blog/introducing-openhands-lm-32b----a-strong-open-coding-agent-model) -- available through [OpenRouter](https://openrouter.ai/all-hands/openhands-lm-32b-v0.1)
+4 -4
View File
@@ -15,7 +15,7 @@ It is highly recommended that you use GPUs to serve local models for optimal exp
For example, to download [OpenHands LM 32B v0.1](https://huggingface.co/all-hands/openhands-lm-32b-v0.1):
```bash
huggingface-cli download all-hands/openhands-lm-32b-v0.1 --local-dir my_folder/openhands-lm-32b-v0.1
huggingface-cli download all-hands/openhands-lm-32b-v0.1 --local-dir all-hands/openhands-lm-32b-v0.1
```
## Create an OpenAI-Compatible Endpoint With a Model Serving Framework
@@ -27,7 +27,7 @@ huggingface-cli download all-hands/openhands-lm-32b-v0.1 --local-dir my_folder/o
```bash
SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 python3 -m sglang.launch_server \
--model my_folder/openhands-lm-32b-v0.1 \
--model all-hands/openhands-lm-32b-v0.1 \
--served-model-name openhands-lm-32b-v0.1 \
--port 8000 \
--tp 2 --dp 1 \
@@ -41,7 +41,7 @@ SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 python3 -m sglang.launch_server \
- Example launch command for OpenHands LM 32B (with at least 2 GPUs):
```bash
vllm serve my_folder/openhands-lm-32b-v0.1 \
vllm serve all-hands/openhands-lm-32b-v0.1 \
--host 0.0.0.0 --port 8000 \
--api-key mykey \
--tensor-parallel-size 2 \
@@ -67,7 +67,7 @@ Ensure `config.toml` exists by running `make setup-config` which will create one
workspace_base="/path/to/your/workspace"
[llm]
embedding_model="local"
model="openhands-lm-32b-v0.1"
ollama_base_url="http://localhost:8000"
```
+96
View File
@@ -0,0 +1,96 @@
# Model Context Protocol (MCP)
:::note
This page outlines how to configure and use the Model Context Protocol (MCP) in OpenHands, allowing you to extend the agent's capabilities with custom tools.
:::
## Overview
Model Context Protocol (MCP) is a mechanism that allows OpenHands to communicate with external tool servers. These servers can provide additional functionality to the agent, such as specialized data processing, external API access, or custom tools. MCP is based on the open standard defined at [modelcontextprotocol.io](https://modelcontextprotocol.io).
## Configuration
MCP configuration is defined in the `[mcp]` section of your `config.toml` file.
### Configuration Example
```toml
[mcp]
# SSE Servers - External servers that communicate via Server-Sent Events
sse_servers = [
# Basic SSE server with just a URL
"http://example.com:8080/mcp",
# SSE server with API key authentication
{url="https://secure-example.com/mcp", api_key="your-api-key"}
]
# Stdio Servers - Local processes that communicate via standard input/output
stdio_servers = [
# Basic stdio server
{name="fetch", command="uvx", args=["mcp-server-fetch"]},
# Stdio server with environment variables
{
name="data-processor",
command="python",
args=["-m", "my_mcp_server"],
env={
"DEBUG": "true",
"PORT": "8080"
}
}
]
```
## Configuration Options
### SSE Servers
SSE servers are configured using either a string URL or an object with the following properties:
- `url` (required)
- Type: `str`
- Description: The URL of the SSE server
- `api_key` (optional)
- Type: `str`
- Default: `None`
- Description: API key for authentication with the SSE server
### Stdio Servers
Stdio servers are configured using an object with the following properties:
- `name` (required)
- Type: `str`
- Description: A unique name for the server
- `command` (required)
- Type: `str`
- Description: The command to run the server
- `args` (optional)
- Type: `list of str`
- Default: `[]`
- Description: Command-line arguments to pass to the server
- `env` (optional)
- Type: `dict of str to str`
- Default: `{}`
- Description: Environment variables to set for the server process
## How MCP Works
When OpenHands starts, it:
1. Reads the MCP configuration from `config.toml`
2. Connects to any configured SSE servers
3. Starts any configured stdio servers
4. Registers the tools provided by these servers with the agent
The agent can then use these tools just like any built-in tool. When the agent calls an MCP tool:
1. OpenHands routes the call to the appropriate MCP server
2. The server processes the request and returns a response
3. OpenHands converts the response to an observation and presents it to the agent
@@ -0,0 +1,38 @@
# Keyword-Triggered Microagents
## Purpose
Keyword-triggered microagents provide OpenHands with specific instructions that are activated when certain keywords
appear in the prompt. This is useful for tailoring behavior based on particular tools, languages, or frameworks.
## Usage
These microagents are only loaded when a prompt includes one of the trigger words.
## Frontmatter Syntax
Frontmatter is required for keyword-triggered microagents. It must be placed at the top of the file,
above the guidelines.
Enclose the frontmatter in triple dashes (---) and include the following fields:
| Field | Description | Required | Default |
|------------|--------------------------------------------------|----------|------------------|
| `triggers` | A list of keywords that activate the microagent. | Yes | None |
| `agent` | The agent this microagent applies to. | No | 'CodeActAgent' |
## Example
Keyword-triggered microagent file example located at `.openhands/microagents/yummy.md`:
```
---
triggers:
- yummyhappy
- happyyummy
---
The user has said the magic word. Respond with "That was delicious!"
```
[See examples of microagents triggered by keywords in the official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)
@@ -1,31 +1,40 @@
# Microagents Overview
Microagents are specialized prompts that enhance OpenHands with domain-specific knowledge, repository-specific context
and task-specific workflows. They help by providing expert guidance, automating common tasks, and ensuring
consistent practices across projects.
Microagents are specialized prompts that enhance OpenHands with domain-specific knowledge.
They provide expert guidance, automate common tasks, and ensure consistent practices across projects.
## Microagent Categories
## Microagent Types
Currently OpenHands supports two categories of microagents:
Currently OpenHands supports the following types of microagents:
- [Repository-specific Microagents](./microagents-repo): Repository-specific context and guidelines for OpenHands.
- [Public Microagents](./microagents-public): General guidelines triggered by keywords for all OpenHands users.
- [General Repository Microagents](./microagents-repo): General guidelines for OpenHands about the repository.
- [Keyword-Triggered Microagents](./microagents-keyword): Guidelines activated by specific keywords in prompts.
A microagent is classified as repository-specific or public depending on its location:
To customize OpenHands' behavior, create a .openhands/microagents/ directory in the root of your repository and
add `<microagent_name>.md` files inside.
- Repository-specific microagents are located in a repository's `.openhands/microagents/` directory
- Public microagents are located in the official OpenHands repository inside the `/microagents` folder
:::note
Loaded microagents take up space in the context window.
These microagents, alongside user messages, inform OpenHands about the task and the environment.
:::
When OpenHands works with a repository, it:
Example repository structure:
1. Loads **repository-specific** microagents from `.openhands/microagents/` if present in the repository.
2. Loads **public knowledge** microagents triggered by keywords in conversations
3. Loads **public tasks** microagents when explicitly requested by the user
```
some-repository/
└── .openhands/
└── microagents/
└── repo.md # General repository guidelines
└── trigger_this.md # Microagent triggered by specific keywords
└── trigger_that.md # Microagent triggered by specific keywords
```
You can check out the existing public microagents at the [official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/).
## Microagents Frontmatter Requirements
## Microagent Format
Each microagent file may include frontmatter that provides additional information. In some cases, this frontmatter
is required:
All microagents use markdown files with YAML frontmatter that have special instructions to help OpenHands activate them.
Check out the [syntax documentation](./microagents-syntax) for a comprehensive guide on how to configure your microagents.
| Microagent Type | Required |
|----------------------------------|----------|
| `General Repository Microagents` | No |
| `Keyword-Triggered Microagents` | Yes |
@@ -1,35 +1,17 @@
# Public Microagents
# Global Microagents
## Overview
Public microagents provide specialized context and capabilities for all OpenHands users, regardless of their repository configuration. Unlike repository-specific microagents, public microagents are globally available across all repositories.
Global microagents are [keyword-triggered microagents](./microagents-keyword) that apply to all OpenHands users. A list of the current
global microagents can be found [in the OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents).
Public microagents come in two types:
## Contributing a Global Microagent
- **Knowledge microagents**: Automatically activated when keywords in conversations match their triggers
- **Task microagents**: Explicitly invoked by users to guide through specific workflows
Both types follow the same syntax and structure as repository-specific microagents, using markdown files with YAML frontmatter that define their behavior and capabilities. They are located in the official OpenHands repository under:
- [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) for knowledge microagents
- [`microagents/tasks/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks) for task microagents
Public microagents:
- Monitor incoming commands for their trigger words.
- Activate when relevant triggers are detected.
- Apply their specialized knowledge and capabilities.
- Follow their specific guidelines and restrictions.
When loading public microagents, OpenHands scans the official repository's microagents directories recursively, processing all markdown files except README.md. The system categorizes each microagent based on its `type` field in the YAML frontmatter, regardless of its exact file location within the knowledge or tasks directories.
## Contributing a Public Microagent
You can create public microagents and share with the community by opening a pull request to the official repository.
You can create global microagents and share with the community by opening a pull request to the official repository.
See the [CONTRIBUTING.md](https://github.com/All-Hands-AI/OpenHands/blob/main/CONTRIBUTING.md) for specific instructions on how to contribute to OpenHands.
### Public Microagents Best Practices
### Global Microagents Best Practices
- **Clear Scope**: Keep the microagent focused on a specific domain or task.
- **Explicit Instructions**: Provide clear, unambiguous guidelines.
@@ -37,11 +19,11 @@ See the [CONTRIBUTING.md](https://github.com/All-Hands-AI/OpenHands/blob/main/CO
- **Safety First**: Include necessary warnings and constraints.
- **Integration Awareness**: Consider how the microagent interacts with other components.
### Steps to Contribute a Public Microagent
### Steps to Contribute a Global Microagent
#### 1. Plan the Public Microagent
#### 1. Plan the Global Microagent
Before creating a public microagent, consider:
Before creating a global microagent, consider:
- What specific problem or use case will it address?
- What unique capabilities or knowledge should it have?
@@ -51,23 +33,19 @@ Before creating a public microagent, consider:
#### 2. Create File
Create a new Markdown file with a descriptive name in the appropriate directory:
[`microagents/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents)
- [`microagents/knowledge/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge) for knowledge microagents
- [`microagents/tasks/`](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks) for task microagents
#### 3. Testing the Global Microagent
Ensure it follows the correct [syntax](./microagents-syntax.md) and [best practices](./microagents-syntax.md#markdown-content-best-practices).
#### 3. Testing the Public Microagent
- Test the agent with various prompts
- Verify trigger words activate the agent correctly
- Ensure instructions are clear and comprehensive
- Check for potential conflicts and overlaps with existing agents
- Test the agent with various prompts.
- Verify trigger words activate the agent correctly.
- Ensure instructions are clear and comprehensive.
- Check for potential conflicts and overlaps with existing agents.
#### 4. Submission Process
Submit a pull request with:
- The new microagent file
- Updated documentation if needed
- Description of the agent's purpose and capabilities
- The new microagent file.
- Updated documentation if needed.
- Description of the agent's purpose and capabilities.
+18 -104
View File
@@ -1,117 +1,31 @@
# Repository-specific Microagents
# General Repository Microagents
## Overview
## Purpose
OpenHands can be customized to work more effectively with specific repositories by providing repository-specific context and guidelines.
General guidelines for OpenHands to work more effectively with the repository.
This section explains how to optimize OpenHands for your project.
## Usage
## Creating Repository Microagents
These microagents are always loaded as part of the context.
You can customize OpenHands' behavior for your repository by creating a `.openhands/microagents/` directory in your repository's root.
## Frontmatter Syntax
You can enhance OpenHands' performance by adding custom microagents to your repository:
The frontmatter for this type of microagent is optional.
1. For overall repository-specific instructions, create a `.openhands/microagents/repo.md` file
2. For reusable domain knowledge triggered by keywords, add multiple `.md` files to `.openhands/microagents/knowledge/`
3. For common workflows and tasks, create multiple `.md` files to `.openhands/microagents/tasks/`
Frontmatter should be enclosed in triple dashes (---) and may include the following fields:
Check out the [best practices](./microagents-syntax.md#markdown-content-best-practices) for formatting the content of your custom microagent.
| Field | Description | Required | Default |
|-----------|-----------------------------------------|----------|----------------|
| `agent` | The agent this microagent applies to | No | 'CodeActAgent' |
Keep in mind that loaded microagents take up space in the context window. It's crucial to strike a balance between the additional context provided by microagents and the instructions provided in the user's inputs.
Note that you can use OpenHands to create new microagents. The public microagent [`add_agent`](https://github.com/All-Hands-AI/OpenHands/blob/main/microagents/knowledge/add_agent.md) is loaded to all OpenHands instance and can support you on this.
## Types of Microagents
OpenHands supports three primary types of microagents, each with specific purposes and features to enhance agent performance:
- [repository](#repository-microagents)
- [knowledge](#knowledge-microagents)
- [tasks](#tasks-microagents)
The standard directory structure within a repository is:
- One main `repo.md` file containing repository-specific instructions
- Additional `Knowledge` agents in `.openhands/microagents/knowledge/` directory
- Additional `Task` agents in `.openhands/microagents/tasks/` directory
When processing the `.openhands/microagents/` directory, OpenHands will recursively scan all subfolders and process any `.md` files (except `README.md`) it finds. The system determines the microagent type based on the `type` field in the YAML frontmatter, not by the file's location. However, for organizational clarity, it's recommended to follow the standard directory structure.
### Repository Microagents
The `Repository` microagent is loaded specifically from `.openhands/microagents/repo.md` and serves as the main
repository-specific instruction file. This single file is automatically loaded whenever OpenHands works with that repository
without requiring any keyword matching or explicit call from the user.
OpenHands does not support multiple `repo.md` files in different locations or multiple microagents with type `repo`.
If you need to organize different types of repository information, the recommended approach is to use a single `repo.md` file with well-structured sections rather than trying to create multiple microagents with the type `repo`.
The best practice is to include project-specific instructions, team practices, coding standards, and architectural guidelines that are relevant for **all** prompts in that repository.
Example structure:
## Example
General repository microagent file example located at `.openhands/microagents/repo.md`:
```
your-repository/
└── .openhands/
└── microagents/
└── repo.md # Repository-specific instructions
This project is a TODO application that allows users to track TODO items.
To set it up, you can run `npm run build`.
Always make sure the tests are passing before committing changes. You can run the tests by running `npm run test`.
```
[See the example in the official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/blob/main/.openhands/microagents/repo.md?plain=1)
### Knowledge Microagents
Knowledge microagents provide specialized domain expertise:
- Recommended to be located in `.openhands/microagents/knowledge/`
- Triggered by specific keywords in conversations
- Contain expertise on tools, languages, frameworks, and common practices
Use knowledge microagents to trigger additional context relevant to specific technologies, tools, or workflows. For example, mentioning "git" in your conversation will automatically trigger git-related expertise to help with Git operations.
Examples structure:
```
your-repository/
└── .openhands/
└── microagents/
└── knowledge/
└── git.md
└── docker.md
└── python.md
└── ...
└── repo.md
```
You can find several real examples of `Knowledge` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)
### Tasks Microagents
Task microagents guide users through interactive workflows:
- Recommended to be located in `.openhands/microagents/tasks/`
- Provide step-by-step processes for common development tasks
- Accept inputs and adapt to different scenarios
- Ensure consistent outcomes for complex operations
Task microagents are a convenient way to store multi-step processes you perform regularly. For instance, you can create a `update_pr_description.md` microagent to automatically generate better pull request descriptions based on code changes.
Examples structure:
```
your-repository/
└── .openhands/
└── microagents/
└── tasks/
└── update_pr_description.md
└── address_pr_comments.md
└── get_test_to_pass.md
└── ...
└── knowledge/
└── ...
└── repo.md
```
You can find several real examples of `Tasks` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks)
[See more examples of general repository microagents here.](https://github.com/All-Hands-AI/OpenHands/tree/main/.openhands/microagents)
@@ -1,128 +0,0 @@
# Microagents Syntax
Microagents are defined using markdown files with YAML frontmatter that specify their behavior, triggers, and capabilities.
Find below a comprehensive description of the frontmatter syntax and other details about how to use each type of microagent available at OpenHands.
## Frontmatter Schema
Every microagent requires a YAML frontmatter section at the beginning of the file, enclosed by triple dashes (`---`). The fields are:
| Field | Description | Required | Used By |
| ---------- | -------------------------------------------------- | ------------------------ | ---------------- |
| `name` | Unique identifier for the microagent | Yes | All types |
| `type` | Type of microagent: `repo`, `knowledge`, or `task` | Yes | All types |
| `version` | Version number (Semantic versioning recommended) | Yes | All types |
| `agent` | The agent type (typically `CodeActAgent`) | Yes | All types |
| `author` | Creator of the microagent | No | All types |
| `triggers` | List of keywords that activate the microagent | Yes for knowledge agents | Knowledge agents |
| `inputs` | Defines required user inputs for task execution | Yes for task agents | Task agents |
## Core Fields
### `agent`
**Purpose**: Specifies which agent implementation processes the microagent (typically `CodeActAgent`).
- Defines a single agent responsible for processing the microagent
- Must be available in the OpenHands system (see the [agent hub](https://github.com/All-Hands-AI/OpenHands/tree/main/openhands/agenthub))
- If the specified agent is not active, the microagent will not be used
### `triggers`
**Purpose**: Defines keywords that activate the `knowledge` microagent.
**Example**:
```yaml
triggers:
- kubernetes
- k8s
- docker
- security
- containers cluster
```
**Key points**:
- Can include both single words and multi-word phrases
- Case-insensitive matching is typically used
- More specific triggers (like "docker compose") prevent false activations
- Multiple triggers increase the chance of activation in relevant contexts
- Unique triggers like "flarglebargle" can be used for testing or special functionality
- Triggers should be carefully chosen to avoid unwanted activations or conflicts with other microagents
- Common terms used in many conversations may cause the microagent to be activated too frequently
When using multiple triggers, the microagent will be activated if any of the trigger words or phrases appear in the
conversation.
### `inputs`
**Purpose**: Defines parameters required from the user when a `task` microagent is activated.
**Schema**:
```yaml
inputs:
- name: INPUT_NAME # Used with {{ INPUT_NAME }}
description: 'Description of what this input is for'
required: true # Optional, defaults to true
```
**Key points**:
- The `name` and `description` properties are required for each input
- The `required` property is optional and defaults to `true`
- Input values are referenced in the microagent body using double curly braces (e.g., `{{ INPUT_NAME }}`)
- All inputs defined will be collected from the user before the task microagent executes
**Variable Usage**: Reference input values using double curly braces `{{ INPUT_NAME }}`.
## Example Formats
### Repository Microagent
Repository microagents provide context and guidelines for a specific repository.
- Located at: `.openhands/microagents/repo.md`
- Automatically loaded when working with the repository
- Only one per repository
The `Repository` microagent is loaded specifically from `.openhands/microagents/repo.md` and serves as the main
repository-specific instruction file. This single file is automatically loaded whenever OpenHands works with that repository
without requiring any keyword matching or explicit call from the user.
[See the example in the official OpenHands repository](https://github.com/All-Hands-AI/OpenHands/blob/main/.openhands/microagents/repo.md?plain=1)
### Knowledge Microagent
Provides specialized domain expertise triggered by keywords.
You can find several real examples of `Knowledge` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/knowledge)
### Task Microagent
When explicitly asked by the user, will guide through interactive workflows with specific inputs.
You can find several real examples of `Tasks` microagents in the [offical OpenHands repository](https://github.com/All-Hands-AI/OpenHands/tree/main/microagents/tasks)
## Markdown Content Best Practices
After the frontmatter, compose the microagent body using Markdown syntax. Examples of elements you can include are:
- Clear, concise instructions outlining the microagent's purpose and responsibilities
- Specific guidelines and constraints the microagent should adhere to
- Relevant code snippets and practical examples to illustrate key points
- Step-by-step procedures for task agents, guiding users through workflows
**Design Tips**:
- Keep microagents focused with a clear purpose
- Provide specific guidelines rather than general advice
- Use distinctive triggers for knowledge agents
- Keep content concise to minimize context window usage
- Break large microagents into smaller, focused ones
Aim for clarity, brevity, and practicality in your writing. Use formatting like bullet points, code blocks, and emphasis to enhance readability and comprehension.
Remember that balancing microagents details with user input space is important for maintaining effective interactions.
+2 -2
View File
@@ -35,8 +35,8 @@ A useful feature is the ability to connect to your local filesystem. To mount yo
Be careful! There's nothing stopping the OpenHands agent from deleting or modifying
any files that are mounted into its workspace.
This setup can cause some issues with file permissions (hence the `SANDBOX_USER_ID` variable)
but seems to work well on most systems.
The `-e SANDBOX_USER_ID=$(id -u)` is passed to the Docker command to ensure the sandbox user matches the host users
permissions. This prevents the agent from creating root-owned files in the mounted workspace.
## Hardened Docker Installation
@@ -20,3 +20,18 @@ Try these in order:
* If using Docker Desktop, ensure `Settings > Advanced > Allow the default Docker socket to be used` is enabled.
* Depending on your configuration you may need `Settings > Resources > Network > Enable host networking` enabled in Docker Desktop.
* Reinstall Docker Desktop.
### Permission Error
**Description**
On initial prompt, an error is seen with `Permission Denied` or `PermissionError`.
**Resolution**
* Check if the `~/.openhands-state` is owned by `root`. If so, you can:
* Change the directory's ownership: `sudo chown <user>:<user> ~/.openhands-state`.
* or update permissions on the directory: `sudo chmod 777 ~/.openhands-state`
* or delete it if you dont need previous data. OpenHands will recreate it. You'll need to re-enter LLM settings.
* If mounting a local directory, ensure your `WORKSPACE_BASE` has the necessary permissions for the user running
OpenHands.
+1534 -19
View File
File diff suppressed because it is too large Load Diff
+11 -4
View File
@@ -4,23 +4,27 @@
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"start": "node generate-swagger-ui.js && docusaurus start",
"build": "node generate-swagger-ui.js && docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
"typecheck": "tsc",
"generate-swagger-ui": "node generate-swagger-ui.js"
},
"// Note": "The OpenAPI spec is stored in docs/static/openapi.json so it's accessible at /openapi.json in the deployed site",
"dependencies": {
"@docusaurus/core": "^3.7.0",
"@docusaurus/plugin-content-pages": "^3.7.0",
"@docusaurus/preset-classic": "^3.7.0",
"@docusaurus/theme-mermaid": "^3.7.0",
"@mdx-js/react": "^3.1.0",
"@node-rs/jieba": "^2.0.1",
"clsx": "^2.0.0",
"docusaurus-lunr-search": "^3.6.0",
"prism-react-renderer": "^2.4.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
@@ -31,6 +35,8 @@
"@docusaurus/module-type-aliases": "^3.5.1",
"@docusaurus/tsconfig": "^3.7.0",
"@docusaurus/types": "^3.5.1",
"swagger-cli": "^4.0.4",
"swagger-ui-dist": "^5.21.0",
"typescript": "~5.8.3"
},
"browserslist": {
@@ -47,5 +53,6 @@
},
"engines": {
"node": ">=18.0"
}
},
"packageManager": "npm@10.5.0"
}
+10 -6
View File
@@ -27,7 +27,11 @@ const sidebars: SidebarsConfig = {
label: 'Openhands Cloud',
id: 'usage/cloud/openhands-cloud',
},
{
type: 'doc',
label: 'Cloud API',
id: 'usage/cloud/cloud-api',
},
{
type: 'doc',
label: 'Cloud GitHub Resolver',
@@ -66,18 +70,18 @@ const sidebars: SidebarsConfig = {
},
{
type: 'doc',
label: 'Repository-specific',
label: 'General Repository Microagents',
id: 'usage/prompting/microagents-repo',
},
{
type: 'doc',
label: 'Public',
id: 'usage/prompting/microagents-public',
label: 'Keyword-Triggered Microagents',
id: 'usage/prompting/microagents-keyword',
},
{
type: 'doc',
label: 'Syntax',
id: 'usage/prompting/microagents-syntax',
label: 'Global Microagents',
id: 'usage/prompting/microagents-public',
},
],
},
@@ -45,7 +45,6 @@ export function HomepageHeader() {
<div align="center" className="header-links">
<a href="https://github.com/All-Hands-AI/OpenHands/graphs/contributors"><img src="https://img.shields.io/github/contributors/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Contributors" /></a>
<a href="https://github.com/All-Hands-AI/OpenHands/stargazers"><img src="https://img.shields.io/github/stars/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Stargazers" /></a>
<a href="https://codecov.io/github/All-Hands-AI/OpenHands?branch=main"><img alt="CodeCov" src="https://img.shields.io/codecov/c/github/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" /></a>
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE"><img src="https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="MIT License" /></a>
<br/>
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community" /></a>
@@ -53,7 +52,7 @@ export function HomepageHeader() {
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/CREDITS.md"><img src="https://img.shields.io/badge/Project-Credits-blue?style=for-the-badge&color=FFE165&logo=github&logoColor=white" alt="Credits" /></a>
<br/>
<a href="https://arxiv.org/abs/2407.16741"><img src="https://img.shields.io/badge/Paper%20on%20Arxiv-000?logoColor=FFE165&logo=arxiv&style=for-the-badge" alt="Paper on Arxiv" /></a>
<a href="https://huggingface.co/spaces/OpenHands/evaluation"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score" /></a>
<a href="https://docs.google.com/spreadsheets/d/1wOUdFCMyY6Nt0AIqF705KN4JKOWgeI4wUGUP60krXXs/edit?gid=0#gid=0"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score" /></a>
</div>
</div>
</div>
+15
View File
@@ -0,0 +1,15 @@
# Static Files for OpenHands Documentation
This directory contains static files that are copied directly to the build output of the Docusaurus documentation.
## OpenAPI Specification
The `openapi.json` file in this directory is the OpenAPI specification for the OpenHands API. It is copied to the build output and is accessible at `/openapi.json` in the deployed site.
This file is used by the Swagger UI interface, which is accessible at `/swagger-ui/` in the deployed site.
## Why is the OpenAPI spec in the static directory?
The OpenAPI specification is placed in the static directory so that it's accessible at a predictable URL in the deployed site. This allows the Swagger UI to reference it directly.
We only need one copy of the OpenAPI spec file, which is this one in the static directory.
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 144 KiB

+2086
View File
File diff suppressed because it is too large Load Diff
-9831
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -131,9 +131,9 @@ def get_config(
)
)
agent_config = AgentConfig(
codeact_enable_jupyter=False,
codeact_enable_browsing=RUN_WITH_BROWSING,
codeact_enable_llm_editor=False,
enable_jupyter=False,
enable_browsing=RUN_WITH_BROWSING,
enable_llm_editor=False,
)
config.set_agent_config(agent_config)
return config
@@ -79,8 +79,8 @@ def get_config(
agent_config.enable_prompt_extensions = False
agent_config = AgentConfig(
function_calling=False,
codeact_enable_jupyter=True,
codeact_enable_browsing_delegate=True,
enable_jupyter=True,
enable_browsing=True,
)
config.set_agent_config(agent_config)
return config
@@ -0,0 +1 @@
config.yaml
@@ -0,0 +1,35 @@
# CI Builds Repair Benchmark Integration
This module integrates the CI Builds Repair benchmark developed by [JetBrains-Research](https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair/ci-builds-repair-benchmark).
For more information, refer to the [GitHub repository](https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair/ci-builds-repair-benchmark) and the associated [research paper](https://arxiv.org/abs/2406.11612).
See notice below for details
## Setup
Before running any scripts, make sure to configure the benchmark by setting up `config.yaml`.
This benchmark pushes to JetBrains' private GitHub repository. You will to request a `token_gh` provided by their team, to run this benchmark.
## Inference
To run inference with your model:
```bash
./evaluation/benchmarks/lca_ci_build_repair/scripts/run_infer.sh llm.yourmodel
```
## Evaluation
To evaluate the predictions:
```bash
./evaluation/benchmarks/lca_ci_build_repair/scripts/eval_infer.sh predictions_path_containing_output
```
## Results
The benchmark contains 68 instances, we skip instances #126 and #145, and only run 66 instances due to dockerization errors.
Due to running in live GitHub machines, the benchmark is sensitive to the date it is run. Even the golden patches in the dataset might present failures due to updates.
For example, on 2025-04-09, running the benchmark against the golden patches gave 57/67 successes, with 1 job left in the waiting list.
On 2025-04-10, running the benchmark full with OH and no oracle, 37 succeeded. That is 54% of the complete set of 68 instances and 64% of the 57 that succeed with golden patches.
@@ -0,0 +1,11 @@
LCA_PATH: path #where to clone lca-ci rep
model_name: OpenHands
benchmark_owner: ICML-25-BenchName-builds-repair
token_gh: your_token
#for lca-ci-repo
repos_folder: /path/to/repos # here the cloned repos would be stored
out_folder: /out/folder # here the result files would be stored
data_cache_dir: /data/cache/dir/ # here the cached dataset would be stored
username_gh: username-gh # your GitHub username
# test_username: test_user # username that would be displayed in the benchmark. Optional. If ommitted, username_gh would be used
language: Python # dataset language (now only Python is available)
@@ -0,0 +1,242 @@
"""Implements evaluation on JetBrains CI builds repair baselines
Please see https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair
and https://huggingface.co/datasets/JetBrains-Research/lca-ci-builds-repair
TODOs:
- Add more flags
"""
import json
import os
from pathlib import Path
import ruamel.yaml
from evaluation.utils.shared import (
EvalMetadata,
get_default_sandbox_config_for_eval,
make_metadata,
)
from openhands.core.config import (
AppConfig,
LLMConfig,
get_parser,
load_app_config,
)
from openhands.core.logger import openhands_logger as logger
from openhands.core.main import create_runtime
from openhands.events.action import CmdRunAction
from openhands.events.observation import CmdOutputObservation
from openhands.runtime.base import Runtime
from openhands.utils.async_utils import call_async_from_sync
def get_config(
metadata: EvalMetadata,
) -> AppConfig:
sandbox_config = get_default_sandbox_config_for_eval()
sandbox_config.base_container_image = 'python:3.12-bookworm'
config = AppConfig(
default_agent=metadata.agent_class,
run_as_openhands=False,
runtime='docker',
max_iterations=metadata.max_iterations,
sandbox=sandbox_config,
# do not mount workspace
workspace_base=None,
workspace_mount_path=None,
)
config.set_llm_config(metadata.llm_config)
agent_config = config.get_agent_config(metadata.agent_class)
agent_config.enable_prompt_extensions = False
return config
config = load_app_config()
def load_bench_config():
script_dir = os.path.dirname(
os.path.abspath(__file__)
) # Get the absolute path of the script
config_path = os.path.join(script_dir, 'config.yaml')
yaml = ruamel.yaml.YAML(typ='rt')
with open(config_path, 'r') as file:
return yaml.load(file)
bench_config = load_bench_config()
def run_eval(
runtime: Runtime,
):
"""Run the evaluation and create report"""
logger.info(f"{'-' * 50} BEGIN Runtime Initialization Fn {'-' * 50}")
obs: CmdOutputObservation
lca_path = bench_config['LCA_PATH']
lca_ci_path = os.path.join(
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
)
model_name = bench_config['model_name']
action = CmdRunAction(command=f'mkdir {lca_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
action = CmdRunAction(command=f'cd {lca_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
lca_repo_url = 'https://github.com/juanmichelini/lca-baselines'
action = CmdRunAction(command=f'git clone {lca_repo_url}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
action = CmdRunAction(command=f'cd {lca_ci_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
action = CmdRunAction(command='git switch open-hands-integration')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
script_dir = os.path.dirname(
os.path.abspath(__file__)
) # Get the absolute path of the script
config_path = os.path.join(script_dir, 'config.yaml')
runtime.copy_to(config_path, lca_ci_path)
token_gh = bench_config['token_gh']
commandf = f'export TOKEN_GH={token_gh}'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
action = CmdRunAction(command='poetry install')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
# Set up the task environment
commandf = f'poetry run python run_eval_jobs.py --model-name "{model_name}" --config-path "{lca_ci_path}/config.yaml" --job-ids-file "/tmp/output_lca.jsonl" --result-filename "testfile.jsonl" > /tmp/single_output.txt'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(f'run_eval_jobs.py gave {obs.content} !')
# assert obs.exit_code == 0
commandf = 'cat /tmp/single_output.txt'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(f' {commandf} gave {obs.content}!')
testfile_path = os.path.join(bench_config['out_folder'], 'testfile.jsonl')
commandf = f'cat {testfile_path}'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
report_str = obs.content
logger.info(f"{'-' * 50} END Runtime Initialization Fn {'-' * 50}")
return report_str
def process_predictions(predictions_path: str):
output_path = Path(predictions_path)
if output_path.suffix != '.jsonl':
raise ValueError('output_path must end in .jsonl')
output_lca_path = output_path.with_name(output_path.stem + '_lca.jsonl')
with output_path.open() as infile, output_lca_path.open('w') as outfile:
for line in infile:
data = json.loads(line)
json.dump(data.get('test_result'), outfile)
outfile.write('\n')
return str(output_lca_path)
if __name__ == '__main__':
parser = get_parser()
parser.add_argument(
'-s',
'--eval-split',
type=str,
default='test',
choices=['test'],
help='data split to evaluate on, must be test',
)
parser.add_argument(
'--predictions-path',
type=str,
help='Path to the directory containing the output.jsonl with the predictions.',
)
args, _ = parser.parse_known_args()
data_split = args.eval_split
llm_config = LLMConfig(model='dummy_model')
metadata = make_metadata(
llm_config,
f'jetbrains-lca-ci--{data_split}',
args.agent_cls,
args.max_iterations,
args.eval_note,
args.predictions_path,
)
# prepare image
config = get_config(metadata)
runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
logger.info('Converting output.jsonl into output_lca.jsonl')
predictions_lca_path = process_predictions(
os.path.join(args.predictions_path, 'output.jsonl')
)
runtime.copy_to(predictions_lca_path, '/tmp')
# get results
results_str = run_eval(runtime)
results_path = os.path.join(args.predictions_path, 'results.jsonl')
with open(results_path, 'w') as file:
file.write(results_str)
logger.info(f'Saved results to {results_path}')
# make a summary
resolved_instances = []
unresolved_instances = []
for line in results_str.strip().splitlines():
data = json.loads(line)
conclusion = data.get('conclusion')
if conclusion == 'success':
resolved_instances.append(data)
elif conclusion == 'failure':
unresolved_instances.append(data)
completed_instances = resolved_instances + unresolved_instances
report = {
'success': len(resolved_instances),
'failure': len(unresolved_instances),
'resolved_instances': resolved_instances,
'unresolved_instances': unresolved_instances,
'completed_instances': completed_instances,
}
print(f'Results: {report}')
report_path = os.path.join(args.predictions_path, 'report.jsonl')
with open(report_path, 'w') as out_f:
out_f.write(json.dumps(report) + '\n')
logger.info(f'Saved report of results in swebench format to {report_path}')
@@ -0,0 +1,406 @@
"""Implements inference on JetBrains CI builds repair baselines
Please see https://github.com/JetBrains-Research/lca-baselines/tree/main/ci-builds-repair
and https://huggingface.co/datasets/JetBrains-Research/lca-ci-builds-repair
TODOs:
- Add EXP_NAME
"""
import asyncio
import json
import os
from typing import Any
import pandas as pd
import ruamel.yaml
from datasets import load_dataset
from evaluation.utils.shared import (
EvalMetadata,
EvalOutput,
codeact_user_response,
compatibility_for_eval_history_pairs,
get_default_sandbox_config_for_eval,
make_metadata,
prepare_dataset,
reset_logger_for_multiprocessing,
run_evaluation,
)
from openhands.controller.state.state import State
from openhands.core.config import (
AppConfig,
get_llm_config_arg,
get_parser,
load_app_config,
)
from openhands.core.logger import openhands_logger as logger
from openhands.core.main import create_runtime, run_controller
from openhands.events.action import CmdRunAction, MessageAction
from openhands.events.observation import CmdOutputObservation
from openhands.runtime.base import Runtime
from openhands.utils.async_utils import call_async_from_sync
def get_config(
metadata: EvalMetadata,
) -> AppConfig:
sandbox_config = get_default_sandbox_config_for_eval()
sandbox_config.base_container_image = 'python:3.12-bookworm'
config = AppConfig(
default_agent=metadata.agent_class,
run_as_openhands=False,
runtime='docker',
max_iterations=metadata.max_iterations,
sandbox=sandbox_config,
# do not mount workspace
workspace_base=None,
workspace_mount_path=None,
)
config.set_llm_config(metadata.llm_config)
agent_config = config.get_agent_config(metadata.agent_class)
agent_config.enable_prompt_extensions = False
return config
config = load_app_config()
def load_bench_config():
script_dir = os.path.dirname(
os.path.abspath(__file__)
) # Get the absolute path of the script
config_path = os.path.join(script_dir, 'config.yaml')
yaml = ruamel.yaml.YAML(typ='rt')
with open(config_path, 'r') as file:
return yaml.load(file)
bench_config = load_bench_config()
AGENT_CLS_TO_FAKE_USER_RESPONSE_FN = {
'CodeActAgent': codeact_user_response,
}
AGENT_CLS_TO_INST_SUFFIX = {
'CodeActAgent': 'When you think you have completed the task, please finish the interaction using the "finish" tool.\n'
}
def initialize_runtime(
runtime: Runtime,
instance: pd.Series,
):
"""Initialize the runtime for the agent.
This function is called before the runtime is used to run the agent.
"""
logger.info(f"{'-' * 50} BEGIN Runtime Initialization Fn {'-' * 50}")
obs: CmdOutputObservation
lca_path = bench_config['LCA_PATH']
lca_ci_path = os.path.join(
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
)
repo_name = instance['repo_name']
repos_path = bench_config['repos_folder']
repo_owner = instance['repo_owner']
repo_path = os.path.join(repos_path, f'{repo_owner}__{repo_name}')
model_name = bench_config['model_name']
action = CmdRunAction(command=f'mkdir {lca_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
action = CmdRunAction(command=f'cd {lca_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
lca_repo_url = 'https://github.com/juanmichelini/lca-baselines'
action = CmdRunAction(command=f'git clone {lca_repo_url}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
action = CmdRunAction(command=f'cd {lca_ci_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
action = CmdRunAction(command='git switch open-hands-integration')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
script_dir = os.path.dirname(
os.path.abspath(__file__)
) # Get the absolute path of the script
config_path = os.path.join(script_dir, 'config.yaml')
with open(config_path, 'r') as file:
config_as_text = file.read()
commandf = f"echo '{config_as_text}' > config.yaml"
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
token_gh = bench_config['token_gh']
commandf = f'export TOKEN_GH={token_gh}'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
action = CmdRunAction(command='poetry install')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
# Set up the task environment
commandf = f'poetry run python run_get_datapoint.py --model-name {model_name} --id {instance["id"]} > branch_name.txt'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
if obs.exit_code != 0:
print(f'run_get_datapoint.py failed at {instance["id"]} with {obs.content}')
assert obs.exit_code == 0
commandf = 'cat branch_name.txt'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
bench_config['user_branch_name'] = obs.content
# Navigate to the task's code path
action = CmdRunAction(command=f'cd {repo_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(f"{'-' * 50} END Runtime Initialization Fn {'-' * 50}")
def complete_runtime(
runtime: Runtime,
instance: pd.Series,
) -> dict[str, Any]:
"""Complete the runtime for the agent.
This function is called before the runtime is used to run the agent.
If you need to do something in the sandbox to get the correctness metric after
the agent has run, modify this function.
"""
logger.info(f"{'-' * 50} BEGIN Runtime Completion Fn {'-' * 50}")
obs: CmdOutputObservation
model_name = bench_config['model_name']
lca_path = bench_config['LCA_PATH']
lca_ci_path = os.path.join(
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
)
user_branch_name = bench_config['user_branch_name']
token_gh = bench_config['token_gh']
commandf = f'export TOKEN_GH={token_gh}'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
# Navigate to the lca-baseslines scripts path
action = CmdRunAction(command=f'cd {lca_ci_path}')
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
assert obs.exit_code == 0
commandf = f'poetry run python run_push_datapoint.py --id {instance["id"]} --model-name {model_name} --user-branch-name {user_branch_name} > single_output.json'
logger.info(f'Running push script: {commandf}')
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
# assert obs.exit_code == 0
commandf = 'cat single_output.json'
action = CmdRunAction(command=commandf)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
result = json.loads(obs.content)
logger.info(f"{'-' * 50} END Runtime Completion Fn {'-' * 50}")
return result
def process_instance(instance: Any, metadata: EvalMetadata, reset_logger: bool = True):
config = get_config(metadata)
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
if reset_logger:
log_dir = os.path.join(metadata.eval_output_dir, 'infer_logs')
reset_logger_for_multiprocessing(logger, instance['instance_id'], log_dir)
else:
logger.info(f'Starting evaluation for instance {instance["instance_id"]}.')
repo_name = instance['repo_name']
repo_workflow = instance['workflow_path']
repo_logs = instance['logs']
repos_path = bench_config['repos_folder']
repo_owner = instance['repo_owner']
repo_path = os.path.join(repos_path, f'{repo_owner}__{repo_name}')
# Prepare the task instruction
instruction_no_oracle = f"""
<uploaded_files>
{repo_path}
</uploaded_files>
I've uploaded a python code repository in the directory {repo_path}, Consider the following issue:
<issue_description>
The repository must pass the CI workflow {repo_workflow}.
but it gave the following error
{repo_logs}
</issue_description>
Can you help me implement the necessary changes to the repository so that the requirements specified in the <issue_description> are met?
I've already taken care of all changes to any of the test files described in the <issue_description>. This means you DON'T have to modify the testing logic or any of the tests in any way!
Also the development Python environment is already set up for you (i.e., all dependencies already installed), so you don't need to install other packages.
Your task is to make the minimal changes to non-test files in the {repo_path} directory to ensure the <issue_description> is satisfied.
Follow these phases to resolve the issue:
Phase 1. READING: read the problem and reword it in clearer terms
1.1 If there are code or config snippets. Express in words any best practices or conventions in them.
1.2 Hightlight message errors, method names, variables, file names, stack traces, and technical details.
1.3 Explain the problem in clear terms.
1.4 Enumerate the steps to reproduce the problem.
1.5 Hightlight any best practices to take into account when testing and fixing the issue
Phase 2. RUNNING: install and run the tests on the repository
2.1 Follow the readme
2.2 Install the environment and anything needed
2.2 Iterate and figure out how to run the tests
Phase 3. EXPLORATION: find the files that are related to the problem and possible solutions
3.1 Use `grep` to search for relevant methods, classes, keywords and error messages.
3.2 Identify all files related to the problem statement.
3.3 Propose the methods and files to fix the issue and explain why.
3.4 From the possible file locations, select the most likely location to fix the issue.
Phase 4. TEST CREATION: before implementing any fix, create a script to reproduce and verify the issue.
4.1 Look at existing test files in the repository to understand the test format/structure.
4.2 Create a minimal reproduction script that reproduces the located issue.
4.3 Run the reproduction script to confirm you are reproducing the issue.
4.4 Adjust the reproduction script as necessary.
Phase 5. FIX ANALYSIS: state clearly the problem and how to fix it
5.1 State clearly what the problem is.
5.2 State clearly where the problem is located.
5.3 State clearly how the test reproduces the issue.
5.4 State clearly the best practices to take into account in the fix.
5.5 State clearly how to fix the problem.
Phase 6. FIX IMPLEMENTATION: Edit the source code to implement your chosen solution.
6.1 Make minimal, focused changes to fix the issue.
Phase 7. VERIFICATION: Test your implementation thoroughly.
7.1 Run your reproduction script to verify the fix works.
7.2 Add edge cases to your test script to ensure comprehensive coverage.
7.3 Run existing tests related to the modified code to ensure you haven't broken anything. Run any tests in the repository related to:
7.2.1 The issue you are fixing
7.2.2 The files you modified
7.2.3 The functions you changed
7.4 If any tests fail, revise your implementation until all tests pass
Phase 8. REVIEW: Carefully re-read the problem description and compare your changes with the base commit {instance["sha_fail"]}.
8.1 Ensure you've fully addressed all requirements.
Once all phases are done, announce: 'Agent Task Complete'.
Be thorough in your exploration, testing, and reasoning. It's fine if your thinking process is lengthy - quality and completeness are more important than brevity.
"""
runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
initialize_runtime(runtime, instance)
# Run the agent
state: State | None = asyncio.run(
run_controller(
config=config,
initial_user_action=MessageAction(content=instruction_no_oracle),
runtime=runtime,
fake_user_response_fn=AGENT_CLS_TO_FAKE_USER_RESPONSE_FN.get(
metadata.agent_class
),
)
)
assert state is not None
metrics = state.metrics.get() if state.metrics else {}
test_result = complete_runtime(runtime, instance)
# history is now available as a stream of events, rather than list of pairs of (Action, Observation)
# for compatibility with the existing output format, we can remake the pairs here
# remove when it becomes unnecessary
histories = compatibility_for_eval_history_pairs(state.history)
# Save the output
output = EvalOutput(
instance_id=instance['instance_id'],
# instance=instance.to_dict(orient='recorods'),
instruction=instruction_no_oracle,
metadata=metadata,
history=histories,
test_result=test_result,
metrics=metrics,
)
return output
if __name__ == '__main__':
parser = get_parser()
parser.add_argument(
'-s',
'--eval-split',
type=str,
default='test',
choices=['test'],
help='data split to evaluate on, must be test',
)
args, _ = parser.parse_known_args()
data_split = args.eval_split
bench = load_dataset(
'JetBrains-Research/lca-ci-builds-repair', split=data_split
).to_pandas()
# todo: see why 126 is giving problems on inference
# todo: see why 145 is giving problems on eval
bench = bench[bench['id'] != 126]
bench = bench[bench['id'] != 145]
# bench = bench.iloc[0:56]
# add column instnace_id for compatibility with oh repo, old id column must be kept for lca repo
bench['instance_id'] = bench['id'].astype(str)
llm_config = None
if args.llm_config:
llm_config = get_llm_config_arg(args.llm_config)
# modify_params must be False for evaluation purpose, for reproducibility and accurancy of results
llm_config.modify_params = False
if llm_config is None:
raise ValueError(f'Could not find LLM config: --llm_config {args.llm_config}')
metadata = make_metadata(
llm_config,
f'jetbrains-lca-ci--{data_split}',
args.agent_cls,
args.max_iterations,
args.eval_note,
args.eval_output_dir,
)
output_file = os.path.join(metadata.eval_output_dir, 'output.jsonl')
instances = prepare_dataset(bench, output_file, args.eval_n_limit)
run_evaluation(
instances, metadata, output_file, args.eval_num_workers, process_instance
)
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -eo pipefail
source "evaluation/utils/version_control.sh"
PROCESS_FILEPATH=$1
if [ -z "$PROCESS_FILEPATH" ]; then
echo "Error: PROCESS_FILEPATH is empty. Usage: ./eval_infer.sh <output_file> [instance_id] [dataset_name] [split]"
exit 1
fi
get_openhands_version
PROCESS_FILEPATH=$(realpath $PROCESS_FILEPATH)
echo "OPENHANDS_VERSION: $OPENHANDS_VERSION"
echo "PROCESS_FILEPATH: $PROCESS_FILEPATH"
EVAL_NOTE="$OPENHANDS_VERSION"
if [ -n "$EXP_NAME" ]; then
EVAL_NOTE="$EVAL_NOTE-$EXP_NAME"
fi
function run_eval() {
COMMAND="poetry run python ./evaluation/benchmarks/lca_ci_build_repair/eval_infer.py \
--predictions-path $PROCESS_FILEPATH "
echo "RUNNING: $COMMAND"
# Run the command
eval $COMMAND
}
unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
run_eval
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -eo pipefail
source "evaluation/utils/version_control.sh"
MODEL_CONFIG=$1
get_openhands_version
echo "OPENHANDS_VERSION: $OPENHANDS_VERSION"
echo "MODEL_CONFIG: $MODEL_CONFIG"
EVAL_NOTE="$OPENHANDS_VERSION"
if [ -n "$EXP_NAME" ]; then
EVAL_NOTE="$EVAL_NOTE-$EXP_NAME"
fi
function run_eval() {
COMMAND="poetry run python ./evaluation/benchmarks/lca_ci_build_repair/run_infer.py \
--llm-config $MODEL_CONFIG "
# Run the command
eval $COMMAND
}
#unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
run_eval
@@ -0,0 +1,60 @@
"""Installs LCA CI Build Repair benchmark with scripts for OH integration."""
import os
import shutil
import subprocess
import yaml
def setup():
# Read config.yaml
print('Reading config.yaml')
script_dir = os.path.dirname(
os.path.abspath(__file__)
) # Get the absolute path of the script
config_path = os.path.join(script_dir, 'config.yaml')
with open(config_path, 'r') as f:
config = yaml.safe_load(f)
lca_path = config['LCA_PATH']
lca_ci_path = os.path.join(
lca_path, 'lca-baselines', 'ci-builds-repair', 'ci-builds-repair-benchmark'
)
repo_url = 'https://github.com/juanmichelini/lca-baselines'
# Clone the repository to LCA_CI_PATH
print(f'Cloning lca-baselines repository from {repo_url} into {lca_path}')
result = subprocess.run(
['git', 'clone', repo_url], cwd=lca_path, capture_output=True, text=True
)
if result.returncode != 0:
print(f'Warning cloning repository: {result.stderr}')
# Clone the repository to LCA_CI_PATH
print('Switching branches')
result = subprocess.run(
['git', 'switch', 'open-hands-integration'],
cwd=lca_ci_path,
capture_output=True,
text=True,
)
if result.returncode != 0:
print(f'Warning switching repository: {result.stderr}')
# Move and rename config_lca.yaml (overwrite if exists)
lca_ci_config_path = os.path.join(lca_ci_path, 'config.yaml')
print(f'Copying config.yaml to {lca_ci_config_path}')
shutil.copy(config_path, lca_ci_config_path)
# Run poetry install in LCA_CI_PATH
print(f"Running 'poetry install' in {lca_ci_path}")
result = subprocess.run(
['poetry', 'install'], cwd=lca_ci_path, capture_output=True, text=True
)
if result.returncode != 0:
print(f'Warning during poetry install: {result.stderr}')
if __name__ == '__main__':
setup()
@@ -0,0 +1,65 @@
# Multi-swe-bench Evaluation with OpenHands
## LLM Setup
Please follow [here](../../README.md#setup).
## Dataset Preparing
Please download the [**Multi-SWE-Bench** dataset](https://huggingface.co/datasets/bytedance-research/Multi-SWE-Bench).
And change the dataset following [script](scripts/data/data_change.py).
```bash
python evaluation/benchmarks/multi_swe_bench/scripts/data/data_change.py
```
## Docker image download
Please download the multi-swe-bench dokcer images from [here](https://github.com/multi-swe-bench/multi-swe-bench?tab=readme-ov-file#run-evaluation).
## Generate patch
Please edit the [script](infer.sh) and run it.
```bash
bash evaluation/benchmarks/multi_swe_bench/infer.sh
```
Script variable explanation:
- `models`, e.g. `llm.eval_gpt4_1106_preview`, is the config group name for your
LLM settings, as defined in your `config.toml`.
- `git-version`, e.g. `HEAD`, is the git commit hash of the OpenHands version you would
like to evaluate. It could also be a release tag like `0.6.2`.
- `agent`, e.g. `CodeActAgent`, is the name of the agent for benchmarks, defaulting to `CodeActAgent`.
- `eval_limit`, e.g. `10`, limits the evaluation to the first `eval_limit` instances. By
default, the script evaluates the (500 issues), which will no exceed the maximum of the dataset number.
- `max_iter`, e.g. `20`, is the maximum number of iterations for the agent to run. By
default, it is set to 50.
- `num_workers`, e.g. `3`, is the number of parallel workers to run the evaluation. By
default, it is set to 1.
- `language`, the language of your evaluating dataset.
- `dataset`, the absolute position of the dataset jsonl.
The results will be generated in evaluation/evaluation_outputs/outputs/XXX/CodeActAgent/YYY/output.jsonl, you can refer to the [example](examples/output.jsonl).
## Runing evaluation
First, install [multi-swe-bench](https://github.com/multi-swe-bench/multi-swe-bench).
```bash
pip install multi-swe-bench
```
Second, convert the output.jsonl to patch.jsonl with [script](scripts/eval/convert.py), you can refer to the [example](examples/patch.jsonl).
```bash
python evaluation/benchmarks/multi_swe_bench/scripts/eval/convert.py
```
Finally, evaluate with multi-swe-bench.
The config file config.json can be refer to the [example](examples/config.json) or [github](https://github.com/multi-swe-bench/multi-swe-bench/tree/main?tab=readme-ov-file#configuration-file-example).
```bash
python -m multi_swe_bench.harness.run_evaluation --config config.json
```
@@ -0,0 +1,456 @@
import json
import os
import subprocess
import tempfile
import time
from functools import partial
import pandas as pd
from swebench.harness.grading import get_eval_report
from swebench.harness.run_evaluation import (
APPLY_PATCH_FAIL,
APPLY_PATCH_PASS,
)
from swebench.harness.test_spec import SWEbenchInstance, TestSpec, make_test_spec
from swebench.harness.utils import load_swebench_dataset
from tqdm import tqdm
from evaluation.benchmarks.swe_bench.resource.mapping import (
get_instance_resource_factor,
)
from evaluation.benchmarks.swe_bench.run_infer import get_instance_docker_image
from evaluation.utils.shared import (
EvalMetadata,
EvalOutput,
get_default_sandbox_config_for_eval,
prepare_dataset,
reset_logger_for_multiprocessing,
run_evaluation,
)
from openhands.core.config import (
AppConfig,
LLMConfig,
get_parser,
)
from openhands.core.logger import openhands_logger as logger
from openhands.core.main import create_runtime
from openhands.events.action import CmdRunAction
from openhands.events.observation import CmdOutputObservation
from openhands.utils.async_utils import call_async_from_sync
# TODO: migrate all swe-bench docker to ghcr.io/openhands
DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/xingyaoww/')
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
def process_git_patch(patch):
if not isinstance(patch, str):
return ''
if not patch.strip():
# skip empty patches
return ''
patch = patch.replace('\r\n', '\n')
# There might be some weird characters at the beginning of the patch
# due to some OpenHands inference command outputs
# FOR EXAMPLE:
# git diff --no-color --cached 895f28f9cbed817c00ab68770433170d83132d90
# 0
# diff --git a/django/db/models/sql/.backup.query.py b/django/db/models/sql/.backup.query.py
# new file mode 100644
# index 0000000000..fc13db5948
# We "find" the first line that starts with "diff" and then we remove lines before it
lines = patch.split('\n')
for i, line in enumerate(lines):
if line.startswith('diff --git'):
patch = '\n'.join(lines[i:])
break
patch = patch.rstrip() + '\n' # Make sure the last line ends with a newline
return patch
def get_config(metadata: EvalMetadata, instance: pd.Series) -> AppConfig:
# We use a different instance image for the each instance of swe-bench eval
base_container_image = get_instance_docker_image(instance['instance_id'])
logger.info(
f'Using instance container image: {base_container_image}. '
f'Please make sure this image exists. '
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
)
sandbox_config = get_default_sandbox_config_for_eval()
sandbox_config.base_container_image = base_container_image
sandbox_config.remote_runtime_resource_factor = get_instance_resource_factor(
dataset_name=metadata.dataset,
instance_id=instance['instance_id'],
)
config = AppConfig(
run_as_openhands=False,
runtime=os.environ.get('RUNTIME', 'docker'),
sandbox=sandbox_config,
# do not mount workspace
workspace_base=None,
workspace_mount_path=None,
)
return config
def process_instance(
instance: pd.Series,
metadata: EvalMetadata,
reset_logger: bool = True,
log_dir: str | None = None,
runtime_failure_count: int = 0,
) -> EvalOutput:
"""
Evaluate agent performance on a SWE-bench problem instance.
Note that this signature differs from the expected input to `run_evaluation`. Use
`functools.partial` to provide optional arguments before passing to the evaluation harness.
Args:
log_dir (str | None, default=None): Path to directory where log files will be written. Must
be provided if `reset_logger` is set.
Raises:
AssertionError: if the `reset_logger` flag is set without a provided log directory.
"""
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
if reset_logger:
assert (
log_dir is not None
), "Can't reset logger without a provided log directory."
os.makedirs(log_dir, exist_ok=True)
reset_logger_for_multiprocessing(logger, instance.instance_id, log_dir)
else:
logger.info(f'Starting evaluation for instance {instance.instance_id}.')
config = get_config(metadata, instance)
instance_id = instance.instance_id
model_patch = instance['model_patch']
test_spec: TestSpec = instance['test_spec']
logger.info(f'Starting evaluation for instance {instance_id}.')
if 'test_result' not in instance.keys():
instance['test_result'] = {}
instance['test_result']['report'] = {
'empty_generation': False,
'resolved': False,
'failed_apply_patch': False,
'error_eval': False,
'test_timeout': False,
}
if model_patch == '':
instance['test_result']['report']['empty_generation'] = True
return EvalOutput(
instance_id=instance_id,
test_result=instance['test_result'],
metadata=metadata,
)
# Increase resource_factor with increasing attempt_id
if runtime_failure_count > 0:
config.sandbox.remote_runtime_resource_factor = min(
config.sandbox.remote_runtime_resource_factor * (2**runtime_failure_count),
8,
)
logger.warning(
f'This is the {runtime_failure_count + 1}th attempt for instance {instance.instance_id}, setting resource factor to {config.sandbox.remote_runtime_resource_factor}'
)
try:
runtime = create_runtime(config)
call_async_from_sync(runtime.connect)
# Get patch and save it to /tmp/patch.diff
with tempfile.TemporaryDirectory() as temp_dir:
# Patch file
patch_file_path = os.path.join(temp_dir, 'patch.diff')
with open(patch_file_path, 'w') as f:
f.write(model_patch)
runtime.copy_to(patch_file_path, '/tmp')
# Eval script
eval_script_path = os.path.join(temp_dir, 'eval.sh')
with open(eval_script_path, 'w') as f:
f.write(test_spec.eval_script)
runtime.copy_to(eval_script_path, '/tmp')
# Set +x
action = CmdRunAction(command='chmod +x /tmp/eval.sh')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert obs.exit_code == 0
# Apply patch
exec_command = (
'cd /testbed && '
"(git apply -v /tmp/patch.diff && echo 'APPLY_PATCH_PASS' || "
"(echo 'Failed to apply patch with git apply, trying with patch command...' && "
"(patch --batch --fuzz=5 -p1 -i /tmp/patch.diff && echo 'APPLY_PATCH_PASS' || "
"echo 'APPLY_PATCH_FAIL')))"
)
action = CmdRunAction(command=exec_command)
action.set_hard_timeout(600)
obs = runtime.run_action(action)
assert isinstance(obs, CmdOutputObservation)
apply_patch_output = obs.content
assert isinstance(apply_patch_output, str)
instance['test_result']['apply_patch_output'] = apply_patch_output
if 'APPLY_PATCH_FAIL' in apply_patch_output:
logger.info(f'[{instance_id}] {APPLY_PATCH_FAIL}:\n{apply_patch_output}')
instance['test_result']['report']['failed_apply_patch'] = True
return EvalOutput(
instance_id=instance_id,
test_result=instance['test_result'],
metadata=metadata,
)
elif 'APPLY_PATCH_PASS' in apply_patch_output:
logger.info(f'[{instance_id}] {APPLY_PATCH_PASS}:\n{apply_patch_output}')
# Run eval script in background and save output to log file
log_file = '/tmp/eval_output.log'
action = CmdRunAction(command=f'/tmp/eval.sh > {log_file} 2>&1 & echo $!')
action.set_hard_timeout(300) # Short timeout just to get the process ID
obs = runtime.run_action(action)
if isinstance(obs, CmdOutputObservation) and obs.exit_code == 0:
pid = obs.content.split()[-1].strip()
logger.info(
f'[{instance_id}] Evaluation process started with PID: {pid}'
)
# Poll for completion
start_time = time.time()
timeout = 1800 # 30 minutes
while True:
seconds_elapsed = time.time() - start_time
if seconds_elapsed > timeout:
logger.info(
f'[{instance_id}] Evaluation timed out after {timeout} seconds'
)
instance['test_result']['report']['test_timeout'] = True
break
check_action = CmdRunAction(
command=f'ps -p {pid} > /dev/null; echo $?'
)
check_action.set_hard_timeout(300)
check_obs = runtime.run_action(check_action)
if (
isinstance(check_obs, CmdOutputObservation)
and check_obs.content.split()[-1].strip() == '1'
):
logger.info(
f'[{instance_id}] Evaluation process completed after {seconds_elapsed} seconds'
)
break
logger.info(
f'[{instance_id}] [{seconds_elapsed:.0f}s] Evaluation still running, waiting...'
)
time.sleep(30) # Wait for 30 seconds before checking again
# Read the log file
cat_action = CmdRunAction(command=f'cat {log_file}')
cat_action.set_hard_timeout(300)
cat_obs = runtime.run_action(cat_action)
# Grade answer
if isinstance(cat_obs, CmdOutputObservation) and cat_obs.exit_code == 0:
test_output = cat_obs.content
assert isinstance(test_output, str)
instance['test_result']['test_output'] = test_output
# Get report from test output
logger.info(f'[{instance_id}] Grading answer...')
with tempfile.TemporaryDirectory() as temp_dir:
# Create a directory structure that matches the expected format
# NOTE: this is a hack to make the eval report format consistent
# with the original SWE-Bench eval script
log_dir = os.path.join(temp_dir, 'logs', instance_id.lower())
os.makedirs(log_dir, exist_ok=True)
test_output_path = os.path.join(log_dir, 'test_output.txt')
with open(test_output_path, 'w') as f:
f.write(test_output)
try:
_report = get_eval_report(
test_spec=test_spec,
prediction={
'model_patch': model_patch,
'instance_id': instance_id,
},
log_path=test_output_path,
include_tests_status=True,
)
report = _report[instance_id]
logger.info(
f"[{instance_id}] report: {report}\nResult for {instance_id}: resolved: {report['resolved']}"
)
instance['test_result']['report']['resolved'] = report[
'resolved'
]
except Exception as e:
logger.error(
f'[{instance_id}] Error when getting eval report: {e}'
)
instance['test_result']['report']['resolved'] = False
instance['test_result']['report']['error_eval'] = True
else:
logger.info(f'[{instance_id}] Error when starting eval:\n{obs.content}')
instance['test_result']['report']['error_eval'] = True
return EvalOutput(
instance_id=instance_id,
test_result=instance['test_result'],
metadata=metadata,
)
else:
logger.info(
f'[{instance_id}] Unexpected output when applying patch:\n{apply_patch_output}'
)
raise RuntimeError(
instance_id,
f'Unexpected output when applying patch:\n{apply_patch_output}',
logger,
)
finally:
runtime.close()
if __name__ == '__main__':
parser = get_parser()
parser.add_argument(
'--input-file',
type=str,
help='Path to input predictions file',
required=True,
)
parser.add_argument(
'--dataset',
type=str,
default='princeton-nlp/SWE-bench',
help='data set to evaluate on, either full-test or lite-test',
)
parser.add_argument(
'--split',
type=str,
default='test',
help='split to evaluate on',
)
args, _ = parser.parse_known_args()
# Load SWE-Bench dataset
full_dataset: list[SWEbenchInstance] = load_swebench_dataset(
args.dataset, args.split
)
instance_id_to_instance = {
instance['instance_id']: instance for instance in full_dataset
}
logger.info(
f'Loaded dataset {args.dataset} with split {args.split} to run inference on.'
)
# Load predictions
assert args.input_file.endswith('.jsonl'), 'Input file must be a jsonl file.'
required_fields = ['instance_id', 'model_patch', 'test_result']
with open(args.input_file) as f:
predictions = pd.DataFrame.from_records(
[
{k: v for k, v in json.loads(line).items() if k in required_fields}
for line in tqdm(f, desc='Loading predictions')
]
)
assert (
'instance_id' in predictions.columns
), 'Input file must contain instance_id column.'
if 'model_patch' not in predictions.columns and (
'test_result' in predictions.columns
and 'model_patch' in predictions['test_result'].iloc[0]
):
raise ValueError(
'Input file must contain model_patch column OR test_result column with model_patch field.'
)
assert len(predictions['instance_id'].unique()) == len(
predictions
), 'instance_id column must be unique.'
if 'model_patch' not in predictions.columns:
predictions['model_patch'] = predictions['test_result'].apply(
lambda x: x.get('git_patch', '')
)
assert {'instance_id', 'model_patch'}.issubset(
set(predictions.columns)
), 'Input file must contain instance_id and model_patch columns.'
# Process model_patch
predictions['model_patch'] = predictions['model_patch'].apply(process_git_patch)
# Merge predictions with dataset
predictions['instance'] = predictions['instance_id'].apply(
lambda x: instance_id_to_instance[x]
)
predictions['test_spec'] = predictions['instance'].apply(make_test_spec)
# Prepare dataset
output_file = args.input_file.replace('.jsonl', '.swebench_eval.jsonl')
instances = prepare_dataset(predictions, output_file, args.eval_n_limit)
# If possible, load the relevant metadata to avoid issues with `run_evaluation`.
metadata: EvalMetadata | None = None
metadata_filepath = os.path.join(os.path.dirname(args.input_file), 'metadata.json')
if os.path.exists(metadata_filepath):
with open(metadata_filepath, 'r') as metadata_file:
data = metadata_file.read()
metadata = EvalMetadata.model_validate_json(data)
else:
# Initialize with a dummy metadata when file doesn't exist
metadata = EvalMetadata(
agent_class='dummy_agent', # Placeholder agent class
llm_config=LLMConfig(model='dummy_model'), # Minimal LLM config
max_iterations=1, # Minimal iterations
eval_output_dir=os.path.dirname(
args.input_file
), # Use input file dir as output dir
start_time=time.strftime('%Y-%m-%d %H:%M:%S'), # Current time
git_commit=subprocess.check_output(['git', 'rev-parse', 'HEAD'])
.decode('utf-8')
.strip(), # Current commit
dataset=args.dataset, # Dataset name from args
)
# The evaluation harness constrains the signature of `process_instance_func` but we need to
# pass extra information. Build a new function object to avoid issues with multiprocessing.
process_instance_func = partial(
process_instance, log_dir=output_file.replace('.jsonl', '.logs')
)
run_evaluation(
instances,
metadata=metadata,
output_file=output_file,
num_workers=args.eval_num_workers,
process_instance_func=process_instance_func,
)
# Load evaluated predictions & print number of resolved predictions
evaluated_predictions = pd.read_json(output_file, lines=True)
fields = ['resolved', 'failed_apply_patch', 'error_eval', 'empty_generation']
def count_report_field(row, field):
return row['test_result']['report'][field]
report = {}
for field in fields:
count = evaluated_predictions.apply(
count_report_field, args=(field,), axis=1
).sum()
report[field] = count
logger.info(
f'# {field}: {count} / {len(evaluated_predictions)}. ({count / len(evaluated_predictions):.2%})'
)
@@ -0,0 +1,24 @@
{
"mode": "evaluation",
"workdir": "./data/workdir",
"patch_files": [
"./data/patches/<your_patch_file>.jsonl"
],
"dataset_files": [
"./data/patches/<to_evaluate_dataset_file>.jsonl"
],
"force_build": false,
"output_dir": "./data/dataset",
"specifics": [],
"skips": [],
"repo_dir": "./data/repos",
"need_clone": false,
"global_env": [],
"clear_env": true,
"stop_on_error": true,
"max_workers": 8,
"max_workers_build_image": 8,
"max_workers_run_instance": 8,
"log_dir": "./data/logs",
"log_level": "DEBUG"
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
{"org": "ponylang", "repo": "ponyc", "number": "4595", "fix_patch": "diff --git a/src/libponyc/ast/parser.c b/src/libponyc/ast/parser.c\nindex 9852922f..2c37d6b8 100644\n--- a/src/libponyc/ast/parser.c\n+++ b/src/libponyc/ast/parser.c\n@@ -693,6 +693,7 @@ DEF(idseqsingle);\n AST_NODE(TK_LET);\n TOKEN(\"variable name\", TK_ID);\n AST_NODE(TK_NONE); // Type\n+ SET_FLAG(AST_FLAG_IN_PARENS);\n DONE();\n \n // idseq"}
{"org": "ponylang", "repo": "ponyc", "number": "4593", "fix_patch": "diff --git a/packages/cli/command_parser.pony b/packages/cli/command_parser.pony\nindex a5acce8e..fa97808b 100644\n--- a/packages/cli/command_parser.pony\n+++ b/packages/cli/command_parser.pony\n@@ -100,6 +100,7 @@ class CommandParser\n | let cs: CommandSpec box =>\n return CommandParser._sub(cs, this).\n _parse_command(tokens, options, args, envsmap, opt_stop)\n+// Correctly handle parent default options\n end\n else\n return SyntaxError(token, \"unknown command\")"}
{"org": "ponylang", "repo": "ponyc", "number": "4588", "fix_patch": "diff --git a/src/libponyc/expr/match.c b/src/libponyc/expr/match.c\nindex 7d16066f..c2ec7056 100644\n--- a/src/libponyc/expr/match.c\n+++ b/src/libponyc/expr/match.c\n@@ -314,8 +314,10 @@ static ast_t* make_pattern_type(pass_opt_t* opt, ast_t* pattern)\n case TK_DONTCAREREF:\n case TK_MATCH_CAPTURE:\n case TK_MATCH_DONTCARE:\n+ if (ast_id(pattern_type) == TK_ISO) pattern_type = set_cap_and_ephemeral(pattern_type, TK_TRN, TK_EPHEMERAL);\n return pattern_type;\n \n+\n case TK_TUPLE:\n {\n ast_t* pattern_child = ast_child(pattern);"}
@@ -0,0 +1,32 @@
#!/bin/bash
BASE_SCRIPT="./evaluation/benchmarks/multi_swe_bench/scripts/run_infer.sh"
MODELS=("aaa" "bbb" "ccc" "ddd" "fff")
GIT_VERSION="HEAD"
AGENT_NAME="CodeActAgent"
EVAL_LIMIT="500"
MAX_ITER="50"
NUM_WORKERS="1"
LANGUAGE="XXX"
DATASET="XXX"
for MODEL in "${MODELS[@]}"; do
echo "=============================="
echo "Running benchmark for MODEL: $MODEL"
echo "=============================="
$BASE_SCRIPT \
"$MODEL" \
"$GIT_VERSION" \
"$AGENT_NAME" \
"$EVAL_LIMIT" \
"$MAX_ITER" \
"$NUM_WORKERS" \
"$DATASET" \
"$LANGUAGE"
echo "Completed $MODEL"
done
@@ -0,0 +1,39 @@
"""Mapping instance_id to resource_factor.
Different instances may have different resource requirements.
e.g., some instances may require more memory/CPU to run inference.
This file tracks the resource requirements of different instances.
"""
import json
import os
from openhands.core.logger import openhands_logger as logger
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
DEFAULT_RUNTIME_RESOURCE_FACTOR = int(
os.environ.get('DEFAULT_RUNTIME_RESOURCE_FACTOR', 1)
)
# dataset to resource mapping
_global_resource_mapping: dict[str, dict[str, float]] = {}
def get_resource_mapping(dataset_name: str) -> dict[str, float]:
if dataset_name not in _global_resource_mapping:
file_path = os.path.join(CUR_DIR, f'{dataset_name}.json')
if not os.path.exists(file_path):
logger.warning(f'Resource mapping for {dataset_name} not found.')
return None
with open(file_path, 'r') as f:
_global_resource_mapping[dataset_name] = json.load(f)
logger.info(f'Loaded resource mapping for {dataset_name}')
return _global_resource_mapping[dataset_name]
def get_instance_resource_factor(dataset_name: str, instance_id: str) -> int:
resource_mapping = get_resource_mapping(dataset_name)
if resource_mapping is None:
return DEFAULT_RUNTIME_RESOURCE_FACTOR
return int(resource_mapping.get(instance_id, DEFAULT_RUNTIME_RESOURCE_FACTOR))
@@ -0,0 +1,847 @@
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, FileReadAction, 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'
USE_INSTANCE_IMAGE = os.environ.get('USE_INSTANCE_IMAGE', 'true').lower() == 'true'
RUN_WITH_BROWSING = os.environ.get('RUN_WITH_BROWSING', 'false').lower() == 'true'
# TODO: migrate all swe-bench docker to ghcr.io/openhands
# TODO: 适应所有的语言
DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', '')
LANGUAGE = os.environ.get('LANGUAGE', 'python')
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
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)
# Prepare instruction
# 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
instructions = {
'python': (
'<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"
),
'java': (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a Java 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 Java 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 Java class to reproduce the error and execute it by first compiling with `javac <classname>.java` and then running with `java <classname>` 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 or class and confirm that the error is fixed!\n"
"5. Think about edgecases, add comprehensive tests for them in your reproduce class or script, and run them to make sure your fix handles these cases 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 or classes 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"
),
'go': (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a Go 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 Go 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 or a function to reproduce the error and execute it with `go run <filename.go>` 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"
),
'c': (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a C 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 C 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 by compiling your C code (for example, using `gcc <filename.c> -o <executable>`) and then running the executable 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"
),
'cpp': (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a C++ 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 C++ 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 or adapt a small executable (e.g., a main file or a test driver) to reproduce the issue. Build and run it (for example, by using `g++ -o reproduce reproduce.cpp && ./reproduce` via 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"
),
'javascript': (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a Javascript 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 Javascript 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 `node <filename.js>` 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"
),
'typescript': (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a Typescript 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 Typescript 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 `ts-node <filename.ts>` 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"
),
'rust': (
'<uploaded_files>\n'
f'/workspace/{workspace_dir_name}\n'
'</uploaded_files>\n'
f"I've uploaded a Rust 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 Rust 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 reproduction script (or binary) that triggers the error and execute it with `cargo run --bin <filename>` 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"
),
}
instruction = instructions.get(LANGUAGE.lower())
if instruction and RUN_WITH_BROWSING:
instruction += (
'<IMPORTANT!>\n'
'You SHOULD NEVER attempt to browse the web. '
'</IMPORTANT!>\n'
)
return instruction
# TODO: 适应所有的语言
# def get_instance_docker_image(instance_id: str) -> str:
# image_name = 'sweb.eval.x86_64.' + instance_id
# if LANGUAGE == 'python':
# image_name = image_name.replace(
# '__', '_s_'
# ) # to comply with docker image naming convention
# return (DOCKER_IMAGE_PREFIX.rstrip('/') + '/' + image_name).lower()
# else:
# return image_name.lower() ##加载本地的
def get_instance_docker_image(instance: pd.Series):
if LANGUAGE == 'python':
image_name = 'sweb.eval.x86_64.' + instance['instance_id']
image_name = image_name.replace(
'__', '_s_'
) # to comply with docker image naming convention
return (DOCKER_IMAGE_PREFIX.rstrip('/') + '/' + image_name).lower()
else:
container_name = instance.get('repo', '').lower()
container_name = container_name.replace('/', '_m_')
instance_id = instance.get('instance_id', '')
tag_suffix = instance_id.split('-')[-1] if instance_id else ''
container_tag = f'pr-{tag_suffix}'
# pdb.set_trace()
return f'mswebench/{container_name}:{container_tag}'
# return "kong/insomnia:pr-8284"
# return "'sweb.eval.x86_64.local_insomnia"
# return "local_insomnia_why"
# return "local/kong-insomnia:pr-8117"
def get_config(
instance: pd.Series,
metadata: EvalMetadata,
) -> AppConfig:
SWE_BENCH_CONTAINER_IMAGE = 'ghcr.io/opendevin/eval-swe-bench:full-v1.2.1'
if USE_INSTANCE_IMAGE:
# We use a different instance image for the each instance of swe-bench eval
# base_container_image = get_instance_docker_image(instance['instance_id'])
base_container_image = get_instance_docker_image(instance)
logger.info(
f'Using instance container image: {base_container_image}. '
f'Please make sure this image exists. '
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
)
else:
base_container_image = SWE_BENCH_CONTAINER_IMAGE
logger.info(f'Using swe-bench container image: {base_container_image}')
sandbox_config = get_default_sandbox_config_for_eval()
sandbox_config.base_container_image = base_container_image
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
REPO_NAME = instance['repo'].split('/')[-1]
# 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 && echo 'export REPO_NAME={REPO_NAME}' >> ~/.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)}'
)
# pdb.set_trace()
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)}')
if USE_INSTANCE_IMAGE:
# inject the init script
script_dir = os.path.dirname(__file__)
# inject the instance info
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
action.set_hard_timeout(600)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to create /swe_util/eval_data/instances: {str(obs)}',
)
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)}',
)
else:
action = CmdRunAction(command='source /swe_util/swe_entry.sh')
action.set_hard_timeout(1800)
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
assert_and_raise(
obs.exit_code == 0,
f'Failed to source /swe_util/swe_entry.sh: {str(obs)}',
)
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
action.set_hard_timeout(600)
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)}')
##TODO:这里看看需不需要判断其他语言的环境
# 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)}',
)
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)}',
)
##删除二进制文件
action = CmdRunAction(
command="""
for file in $(git status --porcelain | grep -E "^(M| M|\\?\\?|A| A)" | cut -c4-); do
if [ -f "$file" ] && (file "$file" | grep -q "executable" || git check-attr binary "$file" | grep -q "binary: set"); then
git rm -f "$file" 2>/dev/null || rm -f "$file"
echo "Removed: $file"
fi
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(
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
f'Failed to remove binary files: {str(obs)}',
)
# pdb.set_trace()
n_retries = 0
git_patch = None
while n_retries < 5:
action = CmdRunAction(
command=f'git diff --no-color --cached {instance["base_commit"]} > patch.diff'
)
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)}')
action = FileReadAction(path='patch.diff')
action.set_hard_timeout(max(300 + 100 * n_retries, 600))
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
git_patch = obs.content
# pdb.set_trace()
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}'
)
# pdb.set_trace()
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
###remove binary diffs
def remove_binary_diffs(patch_text):
lines = patch_text.splitlines()
cleaned_lines = []
block = []
is_binary_block = False
for line in lines:
if line.startswith('diff --git '):
if block and not is_binary_block:
cleaned_lines.extend(block)
block = [line]
is_binary_block = False
elif 'Binary files' in line:
is_binary_block = True
block.append(line)
else:
block.append(line)
if block and not is_binary_block:
cleaned_lines.extend(block)
return '\n'.join(cleaned_lines)
git_patch = remove_binary_diffs(git_patch)
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
if __name__ == '__main__':
# pdb.set_trace()
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)
# dataset = load_dataset(args.dataset)
dataset = load_dataset('json', data_files=args.dataset)
dataset = dataset[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'
)
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['FAIL_TO_PASS'][instances['FAIL_TO_PASS'].index[0]], str
):
for col in ['PASS_TO_PASS', 'FAIL_TO_PASS']:
instances[col] = instances[col].apply(lambda x: str(x))
# if LANGUAGE == "java": ##TODO:适配多语言的版本
# for col in ['issue_numbers', 'created_at']:
# instances[col] = instances[col].apply(lambda x: str(x))
run_evaluation(
instances,
metadata,
output_file,
args.eval_num_workers,
process_instance,
timeout_seconds=120 * 60, # 2 hour PER instance should be more than enough
max_retries=5,
)
@@ -0,0 +1,36 @@
import json
input_file = 'XXX.jsonl'
output_file = 'YYY.jsonl'
with open(input_file, 'r', encoding='utf-8') as fin, open(
output_file, 'w', encoding='utf-8'
) as fout:
for line in fin:
line = line.strip()
if not line:
continue
data = json.loads(line)
item = data
# 提取原始数据
org = item.get('org', '')
repo = item.get('repo', '')
number = str(item.get('number', ''))
new_item = {}
new_item['repo'] = f'{org}/{repo}'
new_item['instance_id'] = f'{org}__{repo}-{number}'
new_item['problem_statement'] = (
item['resolved_issues'][0].get('title', '')
+ '\n'
+ item['resolved_issues'][0].get('body', '')
)
new_item['FAIL_TO_PASS'] = []
new_item['PASS_TO_PASS'] = []
new_item['base_commit'] = item['base'].get('sha', '')
new_item['version'] = '0.1' # depends
output_data = new_item
fout.write(json.dumps(output_data, ensure_ascii=False) + '\n')
@@ -0,0 +1,24 @@
import json
import re
IN_FILE = 'output.jsonl'
OUT_FILE = 'patch.jsonl'
def main():
with open(IN_FILE, 'r') as fin:
with open(OUT_FILE, 'w') as fout:
for line in fin:
data = json.loads(line)
groups = re.match(r'(.*)__(.*)-(.*)', data['instance_id'])
patch = {
'org': groups.group(1),
'repo': groups.group(2),
'number': groups.group(3),
'fix_patch': data['test_result']['git_patch'],
}
fout.write(json.dumps(patch) + '\n')
if __name__ == '__main__':
main()
+155
View File
@@ -0,0 +1,155 @@
#!/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
LANGUAGE=$8
# N_RUNS=$10
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 princeton-nlp/SWE-bench_Lite"
DATASET="princeton-nlp/SWE-bench_Lite"
fi
if [ -z "$LANGUAGE" ]; then
echo "LANUGUAGE not specified, use default python"
LANGUAGE="python"
fi
if [ -z "$SPLIT" ]; then
echo "LANUGUAGE not specified, use default python"
SPLIT="train"
fi
##TODO:适配多语言的版本
# if [ -z "$SPLIT" ]; then
# if [ "$LANGUAGE" = "python" ]; then
# echo "SPLIT is test as LANUGUAGE is python"
# SPLIT="test"
# elif [ "$LANGUAGE" = "java" ]; then
# echo "SPLIT is java_verified as LANUGUAGE is java"
# SPLIT="java_verified"
# fi
# fi
if [ -z "$EVAL_DOCKER_IMAGE_PREFIX" ]; then
if [ "$LANGUAGE" = "python" ]; then
echo "EVAL_DOCKER_IMAGE_PREFIX is docker.io/xingyaoww/ as default as LANUGUAGE is python"
EVAL_DOCKER_IMAGE_PREFIX="docker.io/xingyaoww/"
elif [ "$LANGUAGE" = "java" ]; then
echo "EVAL_DOCKER_IMAGE_PREFIX is java_verified as LANUGUAGE is java"
EVAL_DOCKER_IMAGE_PREFIX=""
fi
fi
export EVAL_DOCKER_IMAGE_PREFIX=$EVAL_DOCKER_IMAGE_PREFIX
echo "EVAL_DOCKER_IMAGE_PREFIX: $EVAL_DOCKER_IMAGE_PREFIX"
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"
export LANGUAGE=$LANGUAGE
echo "LANGUAGE: $LANGUAGE"
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/multi_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
# Skip runs if the run number is in the SKIP_RUNS list
# read from env variable SKIP_RUNS as a comma separated list of run numbers
SKIP_RUNS=(${SKIP_RUNS//,/ })
for i in $(seq 1 $N_RUNS); do
if [[ " ${SKIP_RUNS[@]} " =~ " $i " ]]; then
echo "Skipping run $i"
continue
fi
current_eval_note="$EVAL_NOTE-run_$i"
echo "EVAL_NOTE: $current_eval_note"
run_eval $current_eval_note
done
checkout_original_branch
@@ -0,0 +1,54 @@
"""This script compares gold patches with OpenHands-generated patches and check whether
OpenHands found the right (set of) files to modify.
"""
import argparse
import json
import re
def extract_modified_files(patch):
modified_files = set()
file_pattern = re.compile(r'^diff --git a/(.*?) b/')
for line in patch.split('\n'):
match = file_pattern.match(line)
if match:
modified_files.add(match.group(1))
return modified_files
def process_report(oh_output_file):
succ = 0
fail = 0
for line in open(oh_output_file):
line = json.loads(line)
instance_id = line['instance_id']
gold_patch = line['swe_instance']['patch']
generated_patch = line['git_patch']
gold_modified_files = extract_modified_files(gold_patch)
# swe-bench lite only: a gold patch always contains exactly one file
assert len(gold_modified_files) == 1
generated_modified_files = extract_modified_files(generated_patch)
# Check if all files in gold_patch are also in generated_patch
all_files_in_generated = gold_modified_files.issubset(generated_modified_files)
if all_files_in_generated:
succ += 1
else:
fail += 1
print(
f'{instance_id}: file mismatch, gold = {gold_modified_files}, generated = {generated_modified_files}'
)
print(
f'\nSUMMARY: {succ} out of {succ + fail} instances found correct files to edit, success rate = {succ / float(succ + fail)}'
)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--oh_output_file', help='Path to the OH output file')
args = parser.parse_args()
process_report(args.oh_output_file)
@@ -0,0 +1,45 @@
#!/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
if [ -z "$REPO_NAME" ]; then
echo "Error: REPO_NAME 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 /home/$REPO_NAME /workspace/$WORKSPACE_NAME
# Activate instance-specific environment
# . /opt/miniconda3/etc/profile.d/conda.sh
# conda activate testbed
@@ -0,0 +1,27 @@
#!/bin/bash
set -e
EVAL_WORKSPACE="evaluation/benchmarks/swe_bench/eval_workspace"
mkdir -p $EVAL_WORKSPACE
# 1. Prepare REPO
echo "==== Prepare SWE-bench repo ===="
OH_SWE_BENCH_REPO_PATH="https://github.com/All-Hands-AI/SWE-bench.git"
OH_SWE_BENCH_REPO_BRANCH="eval"
git clone -b $OH_SWE_BENCH_REPO_BRANCH $OH_SWE_BENCH_REPO_PATH $EVAL_WORKSPACE/OH-SWE-bench
# 2. Prepare DATA
echo "==== Prepare SWE-bench data ===="
EVAL_IMAGE=ghcr.io/all-hands-ai/eval-swe-bench:builder_with_conda
EVAL_WORKSPACE=$(realpath $EVAL_WORKSPACE)
chmod +x $EVAL_WORKSPACE/OH-SWE-bench/swebench/harness/prepare_data.sh
if [ -d $EVAL_WORKSPACE/eval_data ]; then
rm -r $EVAL_WORKSPACE/eval_data
fi
docker run \
-v $EVAL_WORKSPACE:/workspace \
-w /workspace \
-u $(id -u):$(id -g) \
-e HF_DATASETS_CACHE="/tmp" \
--rm -it $EVAL_IMAGE \
bash -c "cd OH-SWE-bench/swebench/harness && /swe_util/miniforge3/bin/conda run -n swe-bench-eval ./prepare_data.sh && mv eval_data /workspace/"
@@ -0,0 +1,96 @@
#!/bin/bash
set -e
# assert user name is `root`
if [ "$USER" != "root" ]; then
echo "Error: This script is intended to be run by the 'root' user only." >&2
exit 1
fi
source ~/.bashrc
SWEUTIL_DIR=/swe_util
# Create logs directory
LOG_DIR=/openhands/logs
mkdir -p $LOG_DIR && chmod 777 $LOG_DIR
# 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-test-lite.json)
if [[ -z "$item" ]]; then
echo "No item found for the provided instance ID."
exit 1
fi
CONDA_ENV_NAME=$(echo "$item" | jq -r '.repo + "__" + .version | gsub("/"; "__")')
echo "CONDA_ENV_NAME: $CONDA_ENV_NAME"
SWE_TASK_DIR=/openhands/swe_tasks
mkdir -p $SWE_TASK_DIR
# Dump test_patch to /workspace/test.patch
echo "$item" | jq -r '.test_patch' > $SWE_TASK_DIR/test.patch
# Dump patch to /workspace/gold.patch
echo "$item" | jq -r '.patch' > $SWE_TASK_DIR/gold.patch
# Dump the item to /workspace/instance.json except for the "test_patch" and "patch" fields
echo "$item" | jq 'del(.test_patch, .patch)' > $SWE_TASK_DIR/instance.json
# Clear the workspace
rm -rf /workspace/*
# Copy repo to workspace
if [ -d /workspace/$CONDA_ENV_NAME ]; then
rm -rf /workspace/$CONDA_ENV_NAME
fi
cp -r $SWEUTIL_DIR/eval_data/testbeds/$CONDA_ENV_NAME /workspace
# Reset swe-bench testbed and install the repo
. $SWEUTIL_DIR/miniforge3/etc/profile.d/conda.sh
conda config --set changeps1 False
conda config --append channels conda-forge
conda activate swe-bench-eval
mkdir -p $SWE_TASK_DIR/reset_testbed_temp
mkdir -p $SWE_TASK_DIR/reset_testbed_log_dir
SWE_BENCH_DIR=/swe_util/OH-SWE-bench
output=$(
export PYTHONPATH=$SWE_BENCH_DIR && \
cd $SWE_BENCH_DIR && \
python swebench/harness/reset_swe_env.py \
--swe_bench_tasks $SWEUTIL_DIR/eval_data/instances/swe-bench-test.json \
--temp_dir $SWE_TASK_DIR/reset_testbed_temp \
--testbed /workspace \
--conda_path $SWEUTIL_DIR/miniforge3 \
--instance_id $SWE_INSTANCE_ID \
--log_dir $SWE_TASK_DIR/reset_testbed_log_dir \
--timeout 900 \
--verbose
)
REPO_PATH=$(echo "$output" | awk -F': ' '/repo_path:/ {print $2}')
TEST_CMD=$(echo "$output" | awk -F': ' '/test_cmd:/ {print $2}')
echo "Repo Path: $REPO_PATH"
echo "Test Command: $TEST_CMD"
echo "export SWE_BENCH_DIR=\"$SWE_BENCH_DIR\"" >> ~/.bashrc
echo "export REPO_PATH=\"$REPO_PATH\"" >> ~/.bashrc
echo "export TEST_CMD=\"$TEST_CMD\"" >> ~/.bashrc
if [[ "$REPO_PATH" == "None" ]]; then
echo "Error: Failed to retrieve repository path. Tests may not have passed or output was not as expected." >&2
exit 1
fi
# Activate instance-specific environment
. $SWEUTIL_DIR/miniforge3/etc/profile.d/conda.sh
conda activate $CONDA_ENV_NAME
set +e
+58 -1
View File
@@ -2,6 +2,8 @@
This folder contains the evaluation harness that we built on top of the original [SWE-Bench benchmark](https://www.swebench.com/) ([paper](https://arxiv.org/abs/2310.06770)).
**UPDATE (4/8/2025): We now support running SWT-Bench evaluation! For more details, checkout [the corresponding section](#SWT-Bench-Evaluation).**
**UPDATE (03/27/2025): We now support SWE-Bench multimodal evaluation! Simply use "princeton-nlp/SWE-bench_Multimodal" as the dataset name in the `run_infer.sh` script to evaluate on multimodal instances.**
**UPDATE (2/18/2025): We now support running SWE-Gym using the same evaluation harness here. For more details, checkout [this README](./SWE-Gym.md).**
@@ -141,7 +143,7 @@ With `output.jsonl` file, you can run `eval_infer.sh` to evaluate generated patc
./evaluation/benchmarks/swe_bench/scripts/eval_infer.sh $YOUR_OUTPUT_JSONL [instance_id] [dataset_name] [split]
# Example
./evaluation/benchmarks/swe_bench/scripts/eval_infer.sh evaluation/evaluation_outputs/outputs/swe_bench/CodeActAgent/gpt-4-1106-preview_maxiter_50_N_v1.0/output.jsonl
./evaluation/benchmarks/swe_bench/scripts/eval_infer.sh evaluation/evaluation_outputs/outputs/princeton-nlp__SWE-bench_Lite/CodeActAgent/gpt-4-1106-preview_maxiter_50_N_v1.0/output.jsonl
```
The script now accepts optional arguments:
@@ -182,3 +184,58 @@ To clean-up all existing runtimes that you've already started, run:
```bash
ALLHANDS_API_KEY="YOUR-API-KEY" ./evaluation/utils/scripts/cleanup_remote_runtime.sh
```
## SWT-Bench Evaluation
[SWT-Bench](https://swtbench.com/) ([paper](https://arxiv.org/abs/2406.12952)) is a benchmark for evaluating the capability of LLMs at creating unit tests. It is performed on the same instances as SWE-Bench, but requires a separate evaluation harness to capture coverage and issue reproduction. We therefore detail below how to leverage the inference script in this folder to run inference on SWT-Bench and how to use the SWT-Bench evaluation harness to evaluate them.
### Run inference on SWT-Bench
To run inference on SWT-Bench, you can use the same `run_infer.sh` script as described for evaluation on plain SWE-Bench. The only differences is that you need to specify the `mode` parameter to `swt` or `swt-ci` when running the script. For example, to run inference on SWT-Bench Verified, run the following command:
```bash
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [swe-dataset] test 1 swt
# Example - This runs evaluation on CodeActAgent for 500 instances on "SWT-bench_Verified"'s test set (corresponding to SWE-bench_Verified), with max 100 iteration per instances, with 1 number of workers running in parallel
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4o-2024-11-20 HEAD CodeActAgent 500 100 1 princeton-nlp/SWE-bench_Verified test 1 swt
```
The two modes `swt` and `swt-ci` have the following effect:
- `swt`: This mode will change the prompt to instruct the agent to generate reproducing test cases instead of resolving the issue.
- `swt-ci`: In addition to the changes by `swt`, this mode sets up the CI environment by i) pre-installing the environment in the docker image, such that the test framework can be executed without errors and ii) telling the model the exact command to run the test framework.
### Run evaluation for SWT-bench
The evaluation of these results is done leveraging [the SWT-Bench evaluation harness](https://github.com/logic-star-ai/swt-bench/tree/master).
#### Extracting results into SWT-Bench harness format
In order to run evaluation of the obtained inference results in the SWT-Bench harness, we transform the results to a format that the SWT-Bench evaluation harness expects.
```bash
python3 evaluation/benchmarks/swe_bench/scripts/swtbench/convert.py --prediction_file [output.jsonl] > [output_swt.jsonl]
# Example
python3 evaluation/benchmarks/swe_bench/scripts/swtbench/convert.py --prediction_file "evaluation/evaluation_outputs/outputs/princeton-nlp__SWE-bench_Verified-test/CodeActAgent/gpt-4o-2024-11-20_maxiter_100_N_v0.31.0-no-hint-swt-run_1/output.jsonl" > OpenHands-gpt-4o-2024-11-20.jsonl
```
#### Running the results in SWT-Bench
Next, we run the [SWT-Bench evaluation harness](https://github.com/logic-star-ai/swt-bench/tree/master) with these results.
First set-up and validate the setup as described in the harness [here](https://github.com/logic-star-ai/swt-bench/tree/master?tab=readme-ov-file#-set-up).
Then, run the evaluation with the following command:
```bash
# Example
python3 -m src.main \
--dataset_name princeton-nlp/SWE-bench_Verified \
--predictions_path <pathTo>/OpenHands-gpt-4o-2024-11-20.jsonl \
--max_workers 12 \
--run_id OpenHands-CodeAct-gpt-4o-2024-11-20 --patch_types vanilla --build_mode api
```
The results of the evaluation can be obtained by running the reporting script of the harness.
```bash
# Example
python -m src.report run_instance_swt_logs/OpenHands-CodeAct-gpt-4o-2024-11-20/OpenHands__CodeActAgent__gpt-4o-2024-11-20 --dataset verified
```

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