Compare commits

..

220 Commits

Author SHA1 Message Date
Xingyao Wang 1e398d6362 Merge commit '1d052818ae51856c13e6d468ab79673747440ae5' into xw/diff-edit 2024-09-25 15:02:02 +00:00
mamoodi 1d052818ae Set runtime container image so it doesn't need to be rebuilt (#4035) 2024-09-25 05:20:45 +02:00
tofarr ee284bae8f Fix server lock up on session init (#4007) 2024-09-24 15:49:30 -06:00
Xingyao Wang 1b1d8f0b02 [eval] Use imap_unorderd for parallizing evaluation (#4040) 2024-09-24 20:47:27 +00:00
tobitege c32cec7f89 (enh) send status messages to UI during startup (#3771)
Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Robert Brennan <contact@rbren.io>
Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com>
2024-09-24 18:46:58 +00:00
Robert Brennan 7b2b1eff57 fix up settings saves (#4037) 2024-09-24 18:18:19 +00:00
dependabot[bot] 2f1b537471 chore(deps): bump minio from 7.2.8 to 7.2.9 (#4034)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-24 18:07:24 +02:00
dependabot[bot] f2a71eb388 chore(deps): bump boto3 from 1.35.24 to 1.35.25 (#4027)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-24 18:06:52 +02:00
dependabot[bot] 63c5d74169 chore(deps-dev): bump openai from 1.47.0 to 1.47.1 (#4033)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-24 18:06:20 +02:00
dependabot[bot] 5d77aec90b chore(deps): bump litellm from 1.47.1 to 1.48.0 (#4032)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-24 18:05:50 +02:00
Xingyao Wang a66e738957 [eval] use mp Pool instead ProcessPoolExecutor (#4025) 2024-09-24 23:59:06 +08:00
dependabot[bot] 582f07f9c9 chore(deps-dev): bump @types/node from 22.5.5 to 22.6.1 in /frontend (#4028)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-24 19:51:39 +04:00
sp.wack 83b7fcc3ed hotfix(frontend): Clear base URL when advanced options is unselected (#4016) 2024-09-24 19:49:39 +04:00
RajWorking 8f565c8740 Updated ErrorObservation for EditAction 2024-09-24 15:42:25 +00:00
Xingyao Wang df28a7a5b9 bump codeact to 1.10 2024-09-24 15:40:05 +00:00
RajWorking 4743eb4c35 Moved create_dataset to be used implicitly by EditAction. 2024-09-24 15:40:05 +00:00
RajWorking 4a6898bbda added new line to regex of diff blocks 2024-09-24 15:40:04 +00:00
RajWorking a4ddac4f2c minor bug fixes 2024-09-24 15:40:00 +00:00
RajWorking 33422f1a4a [Feat] Added FileEditAction to enable edits using diff format. 2024-09-24 15:39:09 +00:00
Graham Neubig dc418e7b71 Update README.md for runtime (#4015) 2024-09-24 02:50:15 +02:00
mamoodi dd3d1497f6 Add clearer OpenHands Configuration logs (#4011) 2024-09-23 18:42:00 -04:00
Xingyao Wang 8ea2d61ff2 [llm] Add app name for OpenRouter (#4010) 2024-09-24 00:26:07 +02:00
Graham Neubig 73ded7de10 Make drop_params default in llm_config (#4012) 2024-09-23 16:57:10 -04:00
dependabot[bot] 3f6aa0d1f1 chore(deps-dev): bump ruff from 0.6.6 to 0.6.7 (#4001)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 20:15:54 +02:00
dependabot[bot] 2556767ccb chore(deps-dev): bump @types/react from 18.3.7 to 18.3.8 in /frontend (#3974)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:43:16 -04:00
tobitege fbef93b762 Refactor config.py file into package (own folder with separate files) (#3987) 2024-09-23 12:42:54 -04:00
dependabot[bot] 3a93fd4c64 chore(deps): bump vite from 5.4.6 to 5.4.7 in /frontend (#3994)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:39:24 -04:00
dependabot[bot] a12e8cf06a chore(deps): bump json-repair from 0.29.2 to 0.29.4 (#4000)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:38:49 -04:00
dependabot[bot] 69479852ff chore(deps-dev): bump llama-index from 0.11.10 to 0.11.12 (#3999)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:38:40 -04:00
dependabot[bot] 7024e973d4 chore(deps): bump browsergym from 0.6.4 to 0.7.0 (#3998)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:38:28 -04:00
dependabot[bot] a260cc8dc8 chore(deps): bump boto3 from 1.35.23 to 1.35.24 (#3997)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:38:13 -04:00
dependabot[bot] 7e53c96b14 chore(deps-dev): bump openai from 1.46.1 to 1.47.0 (#4002)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 18:38:02 +02:00
dependabot[bot] 96b23d2e4c chore(deps): bump jose from 5.9.2 to 5.9.3 in /frontend (#3993)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:37:52 -04:00
dependabot[bot] b97aa10b66 chore(deps): bump litellm from 1.46.8 to 1.47.1 (#4003)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 18:36:58 +02:00
Aavash Baral b61455042f fix: models cut off in Settings UI (#3900) (#3991) 2024-09-23 10:54:00 -04:00
Ikko Eltociear Ashimine c84495830e [eval] update swe_bench/README.md (#3990) 2024-09-23 11:03:09 +02:00
Xingyao Wang 3435f1e5d8 Store the file edit backup file in /tmp (#3958) 2024-09-23 06:32:24 +08:00
Xingyao Wang 714e46f29a [eval] save eventstream & llm completions for SWE-Bench run_infer (#3923) 2024-09-22 04:39:13 +00:00
mamoodi e0608af0b3 Add OpenRouter provider docs (#3986) 2024-09-21 20:57:25 -04:00
Xingyao Wang 402a03cb9a change top_p default value to 1.0 (#3983) 2024-09-21 18:00:18 +00:00
tobitege 01462e11d7 (fix) CodeActAgent/LLM: react on should_exit flag (user cancellation) (#3968) 2024-09-20 23:49:45 +02:00
Engel Nyst ebd93977cd Update local ollama doc (#3966) 2024-09-20 21:56:38 +02:00
mamoodi ef189d52a5 Remove ollama reference from documentation for now (#3959) 2024-09-20 14:48:48 -04:00
mamoodi 3c77cc80dc Release 0.9.4 (#3982) 2024-09-20 20:05:01 +02:00
dependabot[bot] 31b189c9af chore(deps-dev): bump ruff from 0.6.5 to 0.6.6 (#3976)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-20 18:44:25 +02:00
dependabot[bot] a7630c399a chore(deps): bump boto3 from 1.35.22 to 1.35.23 (#3977)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-20 18:43:40 +02:00
dependabot[bot] 86521c971b chore(deps): bump litellm from 1.46.6 to 1.46.8 (#3975)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-20 18:40:40 +02:00
tobitege 6682e0f1dd (fix) CodeActAgent: use content of AgentDelegateObservation (#3970)
Co-authored-by: Ryan H. Tran <descience.thh10@gmail.com>
2024-09-20 18:31:11 +02:00
dependabot[bot] 031b91457a chore(deps): bump pandas from 2.2.2 to 2.2.3 (#3978)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-20 16:21:52 +00:00
Xingyao Wang b13ed017d8 [eval] add git patch post-processing for SWE-Bench eval_infer (#3980) 2024-09-20 15:33:53 +00:00
Robert Brennan 72ca1690a7 Wait for runtime to be ready in __init__ (#3963) 2024-09-20 17:31:30 +02:00
tobitege 45066f19dc (fix) restore sudo-capability after recent changes (#3964) 2024-09-19 23:08:13 +02:00
dependabot[bot] 809903bad4 chore(deps-dev): bump chromadb from 0.5.5 to 0.5.7 (#3951)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:35:25 +02:00
dependabot[bot] 071f1f0e13 chore(deps): bump google-cloud-aiplatform from 1.67.0 to 1.67.1 (#3952)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:33:59 +02:00
dependabot[bot] 08a505406b chore(deps): bump litellm from 1.46.4 to 1.46.6 (#3953)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:33:08 +02:00
dependabot[bot] 1756b85675 chore(deps): bump browsergym from 0.6.3 to 0.6.4 (#3954)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:31:46 +02:00
dependabot[bot] e8ab8f1146 chore(deps): bump boto3 from 1.35.21 to 1.35.22 (#3955)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:28:24 +02:00
dependabot[bot] a6ea4c2a60 chore(deps-dev): bump sympy from 1.13.2 to 1.13.3 (#3956)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:27:51 +02:00
dependabot[bot] 1e7f398376 chore(deps-dev): bump openai from 1.46.0 to 1.46.1 (#3957)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:27:14 +02:00
niliy01 0f6fb0f80e (enh) unify the log output in docker build process (#3961)
Signed-off-by: niliy <WannaTen@users.noreply.github.com>
2024-09-19 19:19:16 +02:00
dependabot[bot] bd1f0f1671 chore(deps): bump monaco-editor from 0.51.0 to 0.52.0 in /frontend (#3950)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 21:12:38 +04:00
tobitege 2842efa0e8 ChatMessage: get timestamp out of direct view (#3948) 2024-09-19 15:40:20 +02:00
tobitege 620526b8b4 agent_controller: in PAUSED state reduce delegate logspam from delegate (#3946) 2024-09-19 14:34:38 +02:00
tofarr 31dbd3d02e Fix google cloud session manager (#3942) 2024-09-19 06:28:10 -06:00
tofarr dd7174e559 Fix broken cli (#3941) 2024-09-18 19:15:09 -06:00
Engel Nyst 8fdfece059 Refactor messages serialization (#3832)
Co-authored-by: Robert Brennan <accounts@rbren.io>
2024-09-18 23:48:58 +02:00
tofarr ad0b549d8b Feat Tightening up Timeouts and interrupt conditions. (#3926) 2024-09-18 20:50:42 +00:00
Engel Nyst 47f60b8275 Don't send gemini settings when the llm is not gemini (#3940) 2024-09-18 20:12:58 +00:00
Xingyao Wang 5d7f2fd4ae [eval] Allow evaluation of SWE-Bench patches on RemoteRuntime (#3927)
Co-authored-by: Boxuan Li <liboxuan@connect.hku.hk>
Co-authored-by: Graham Neubig <neubig@gmail.com>
2024-09-18 16:07:34 -04:00
dependabot[bot] 22e885736b chore(deps-dev): bump openai from 1.45.1 to 1.46.0 (#3929)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 20:22:42 +02:00
dependabot[bot] f9589a552e chore(deps): bump google-cloud-aiplatform from 1.66.0 to 1.67.0 (#3934)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 20:22:32 +02:00
dependabot[bot] 043fb2771d chore(deps): bump @nextui-org/react from 2.4.6 to 2.4.8 in /frontend (#3888)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 17:50:52 +00:00
dependabot[bot] b95740cc55 chore(deps-dev): bump tailwindcss from 3.4.11 to 3.4.12 in /frontend (#3928)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 21:38:26 +04:00
Robert Brennan c864715b43 Fix UID management for ubuntu users (#3937) 2024-09-18 16:29:39 +00:00
Robert Brennan a7f1bca586 fix documentation links (#3936) 2024-09-18 12:21:30 -04:00
tobitege b4408b41c9 (feat) LLM class: add safety_settings for Gemini; improve max_output_tokens defaulting (#3925) 2024-09-18 11:51:23 -04:00
Engel Nyst e3be71f523 Fix init order with threading (#3935) 2024-09-18 15:26:51 +00:00
dependabot[bot] dbe767325f chore(deps): bump boto3 from 1.35.20 to 1.35.21 (#3930)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 17:13:25 +02:00
dependabot[bot] ec0fe35d48 chore(deps): bump fastapi from 0.114.2 to 0.115.0 (#3932)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 17:12:48 +02:00
dependabot[bot] 883f36b005 chore(deps): bump browsergym from 0.6.0 to 0.6.3 (#3931)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 17:11:59 +02:00
dependabot[bot] dc6b4b7296 chore(deps): bump litellm from 1.46.1 to 1.46.4 (#3933)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 15:06:39 +00:00
dependabot[bot] fe0a8eb036 chore(deps-dev): bump ruff from 0.6.4 to 0.6.5 (#3894)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 14:20:26 +00:00
tobitege c3117e8c39 (feat) add --version to cli (#3924) 2024-09-18 09:44:51 -04:00
Qiang Li f7ebc1cf1f chore: Add docker files for developing inside container. (#3911) 2024-09-17 23:19:01 +02:00
mamoodi 8a419b5c45 Reorder sidebar doc by bringing LLMs higher up (#3922) 2024-09-17 14:26:13 -04:00
dependabot[bot] 9787a31ba1 chore(deps-dev): bump @types/react from 18.3.6 to 18.3.7 in /frontend (#3920)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 11:57:33 -04:00
dependabot[bot] 31296624d1 chore(deps): bump vite from 5.4.5 to 5.4.6 in /frontend (#3919)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 11:57:23 -04:00
dependabot[bot] 656222f416 chore(deps): bump boto3 from 1.35.19 to 1.35.20 (#3915)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 11:29:15 -04:00
dependabot[bot] a4e61faf56 chore(deps-dev): bump llama-index from 0.11.9 to 0.11.10 (#3916)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 11:29:06 -04:00
dependabot[bot] f4657edc48 chore(deps): bump litellm from 1.46.0 to 1.46.1 (#3917)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 15:21:32 +00:00
Engel Nyst ef09f0fe37 Small fix in readme (#3912) 2024-09-17 14:33:25 +00:00
Xingyao Wang f996b31d64 [eval] Fix multi-processing bug (again^3) & allow set EXP_NAME for each run_infer (#3907)
Co-authored-by: Boxuan Li <liboxuan@connect.hku.hk>
2024-09-17 14:07:58 +00:00
mamoodi fa0d9cfa42 Add providers section in documentation and put current docs under it (#3905) 2024-09-17 08:52:13 -04:00
niliy01 07a094e701 (enh) Update Docker pull data in place (#3910)
Signed-off-by: Yi Lin <teroincn@gmail.com>
2024-09-17 10:22:07 +02:00
tobitege 52c5abccbf (enh) Dockerfile.j2: improve env vars for bash and activate in .bashrc (#3871) 2024-09-17 08:49:04 +02:00
dependabot[bot] 29b0e62cd7 chore(deps): bump react-i18next from 15.0.1 to 15.0.2 in /frontend (#3889) 2024-09-17 11:04:48 +08:00
dependabot[bot] 2a10ff1374 chore(deps): bump litellm from 1.44.28 to 1.46.0 (#3896)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 20:56:22 +02:00
dependabot[bot] 592c9580d2 chore(deps-dev): bump @types/node from 22.5.4 to 22.5.5 in /frontend (#3890)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 18:29:25 +00:00
niliy01 804674bb9f refactor the logic in agent_controller to imporve readability (#3873)
Signed-off-by: Yi Lin <teroincn@gmail.com>
2024-09-16 14:13:52 -04:00
Engel Nyst 41a54378dc Add delegates events to eval trajectories (#3881) 2024-09-16 14:10:42 -04:00
mamoodi 9d4eb7d19d Minor tweaks to getting started guide (#3901) 2024-09-16 13:53:46 -04:00
dependabot[bot] d886bf7e2b chore(deps-dev): bump postcss from 8.4.45 to 8.4.47 in /frontend (#3886)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 11:17:33 -05:00
dependabot[bot] dcede97f68 chore(deps-dev): bump openai from 1.45.0 to 1.45.1 (#3887)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 11:17:11 -05:00
dependabot[bot] 531aec404a chore(deps): bump jose from 5.8.0 to 5.9.2 in /frontend (#3891)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: yufansong <yufan@risingwave-labs.com>
2024-09-16 11:16:26 -05:00
dependabot[bot] b7e050eaf6 chore(deps): bump fastapi from 0.114.1 to 0.114.2 (#3892)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 11:15:59 -05:00
dependabot[bot] 1cc1016768 chore(deps-dev): bump @types/react from 18.3.5 to 18.3.6 in /frontend (#3893)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: yufansong <yufan@risingwave-labs.com>
2024-09-16 11:15:45 -05:00
dependabot[bot] d3c2a022b3 chore(deps-dev): bump llama-index-embeddings-ollama from 0.3.0 to 0.3.1 (#3895)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: yufansong <yufan@risingwave-labs.com>
2024-09-16 11:15:26 -05:00
dependabot[bot] 88abf1b5d8 chore(deps): bump boto3 from 1.35.18 to 1.35.19 (#3897)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: yufansong <yufan@risingwave-labs.com>
2024-09-16 11:15:09 -05:00
mamoodi 834296f7b4 Missed adding Groq to sidebar so it shows up (#3885) 2024-09-16 11:31:53 -04:00
Graham Neubig 243cb492aa Run pre-commit on all files (#3884) 2024-09-16 11:07:08 -04:00
mamoodi f11e767eb5 Remove Cleanup stage in runtime tests (#3861)
Co-authored-by: tobitege <10787084+tobitege@users.noreply.github.com>
2024-09-16 10:14:49 -04:00
tofarr 0db664986d Tightened up the logic on retries. (#3882) 2024-09-16 07:28:06 -06:00
tobitege a33f61c025 (feat) Show messages' timestamp in UI (#3869) 2024-09-16 05:41:29 +02:00
tobitege a45b20a406 (fix) runtime: tweak _wait_until_alive tenacity and exception handling (#3878) 2024-09-16 04:24:58 +02:00
Engel Nyst f6709d08ef Add docs for Groq and for OpenAI proxies (#3877) 2024-09-15 23:08:37 +00:00
Xingyao Wang 2b3925278d [eval] refactor process instance logic into update_progress (#3875) 2024-09-15 18:47:15 -04:00
tobitege ecf4aed28b (fix) Update logs after run_action (EventStreamRuntime) (#3870) 2024-09-15 18:50:10 +02:00
mamoodi a97ef34139 documentation changes associated with UI changes and more consistency (#3866) 2024-09-14 17:22:15 -04:00
tobitege 554636cf2a (fix) Fix runtime (RT) tests and split tests in 2 actions (openhands/root) (#3791)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2024-09-14 21:51:30 +02:00
tobitege 57390eb26b (enh) docker pull (if not found locally) with progress info (#3682) 2024-09-14 06:26:42 +02:00
Engel Nyst 379f2b6f23 Fix queue length on Macs (#3867) 2024-09-14 01:11:29 +00:00
Graham Neubig 26cc1670ad Adds OpenAI o-1 models to frontend (#3868)
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2024-09-13 23:53:24 +00:00
dependabot[bot] cbeae3e612 chore(deps): bump browsergym from 0.5.1 to 0.6.0 (#3860)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 22:43:17 +02:00
dependabot[bot] 434951af23 chore(deps): bump boto3 from 1.35.17 to 1.35.18 (#3858)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 17:25:49 +00:00
dependabot[bot] 900d819394 chore(deps): bump vite from 5.4.4 to 5.4.5 in /frontend (#3862)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 11:53:30 -04:00
Xingyao Wang 3a1b8c093b [eval] yet another eval fixes on multi-processing (#3854)
Co-authored-by: Graham Neubig <neubig@gmail.com>
2024-09-13 15:51:22 +00:00
dependabot[bot] cea6b6e30e chore(deps-dev): bump llama-index from 0.11.8 to 0.11.9 (#3859)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 15:19:06 +00:00
dependabot[bot] 0233cd7848 chore(deps): bump litellm from 1.44.24 to 1.44.28 (#3856)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 15:13:34 +00:00
dependabot[bot] 95edc1b5cf chore(deps): bump google-generativeai from 0.8.0 to 0.8.1 (#3855)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 15:06:24 +00:00
tobitege 6111f530c2 (fix) StuckDetector: syntax error loops were not detected (#3663)
Co-authored-by: mamoodi <mamoodiha@gmail.com>
2024-09-13 16:53:52 +02:00
Xingyao Wang 78c5f58adc refactor & improve retry for the reliability of RemoteRuntime & evaluation (#3846) 2024-09-13 07:37:07 -04:00
dependabot[bot] 7506b20087 chore(deps): bump boto3 from 1.35.16 to 1.35.17 (#3841)
Bumps [boto3](https://github.com/boto/boto3) from 1.35.16 to 1.35.17.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.16...1.35.17)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 10:07:05 +00:00
mamoodi bff9296d68 Make the publish PyPi manual to fit current release process (#3851) 2024-09-12 20:53:19 -04:00
mamoodi 4b5240cdf7 Release 0.9.3 (#3850) 2024-09-12 20:51:34 -04:00
Robert Brennan 9ef79cbe22 fix advanced settings issue (#3849) 2024-09-12 22:00:31 +00:00
Robert Brennan 1f13d80ddc fix saves (#3848) 2024-09-12 21:47:02 +00:00
Robert Brennan 58de5221f5 fix file access (#3847) 2024-09-12 15:30:21 -04:00
Robert Brennan 9bbb35ec18 minor settings fixes (#3809)
* minor settings fixes

* useMemo

* fix code
2024-09-12 19:08:18 +00:00
Xingyao Wang 797f02ff6f rename huggingface evaluation benchmark (#3845) 2024-09-12 18:50:26 +00:00
Xingyao Wang 47d9621742 [eval] SWE-Bench eval usability fixes (#3836)
* [eval] increase timeout for swebench eval init/complete

* allow CmdRunAction to optionally block when .timeout is setted

* fix unit test for serialization

* fix unit tests for security analyzer

* fix integration tests

* add more timeout

* only check P2P when instances are non-empty;
convert P2P and F2P columns to string instead of list

---------

Co-authored-by: Graham Neubig <neubig@gmail.com>
2024-09-12 16:33:51 +00:00
dependabot[bot] 8c12f5b67d chore(deps-dev): bump tailwindcss from 3.4.10 to 3.4.11 in /frontend (#3838)
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.10 to 3.4.11.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.11/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.10...v3.4.11)

---
updated-dependencies:
- dependency-name: tailwindcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-12 11:38:21 -04:00
dependabot[bot] 6132a58367 chore(deps-dev): bump husky from 9.1.5 to 9.1.6 in /frontend (#3839)
Bumps [husky](https://github.com/typicode/husky) from 9.1.5 to 9.1.6.
- [Release notes](https://github.com/typicode/husky/releases)
- [Commits](https://github.com/typicode/husky/compare/v9.1.5...v9.1.6)

---
updated-dependencies:
- dependency-name: husky
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-12 11:38:15 -04:00
Xingyao Wang 2fe2f4c530 [eval] increase timeout for SWEBench eval init/complete (#3829)
* [eval] increase timeout for swebench eval init/complete

* allow CmdRunAction to optionally block when .timeout is setted

* fix unit test for serialization

* fix unit tests for security analyzer

* fix integration tests

* add more timeout
2024-09-12 15:20:58 +00:00
tofarr 4d8f812f88 chore: update the icons from OpenDevin to OpenHands (#3835)
* chore: update the icons from OpenDevin to OpenHands

* Update logo
2024-09-12 14:19:31 +00:00
tofarr e5cb80d59d docs: Update steps for running integration tests in a local environment (#3830)
* docs: Update steps for running integration tests in a local environment
2024-09-12 03:22:53 -06:00
sp.wack ee9bea393f feat(frontend): Update settings to include base URL (#3755)
* Update settings to include base URL

* Fix tests
2024-09-11 21:57:19 -04:00
dependabot[bot] 940de86caa chore(deps): bump browsergym from 0.4.3 to 0.5.1 (#3833)
Bumps browsergym from 0.4.3 to 0.5.1.

---
updated-dependencies:
- dependency-name: browsergym
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2024-09-12 03:55:21 +02:00
Frank Xu fe5ecb6da8 add url info in browsing observation (#3815)
* add url info in browsing observation

* fix integration tests for url

---------

Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2024-09-12 02:46:39 +02:00
mamoodi 41b8f3e4a7 Fail the Runtime tests check if the previous jobs were cancelled or failed (#3825)
* Fail the Runtime tests check if the previous jobs were cancelled or failed

* Check only for failures

* Add test exit

* Test cancel

* fix conditions

* fix condition again

* Try another way

* Now test success
2024-09-11 16:40:00 -04:00
dependabot[bot] 93ecd82e61 chore(deps): bump google-cloud-aiplatform from 1.65.0 to 1.66.0 (#3828)
Bumps [google-cloud-aiplatform](https://github.com/googleapis/python-aiplatform) from 1.65.0 to 1.66.0.
- [Release notes](https://github.com/googleapis/python-aiplatform/releases)
- [Changelog](https://github.com/googleapis/python-aiplatform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/python-aiplatform/compare/v1.65.0...v1.66.0)

---
updated-dependencies:
- dependency-name: google-cloud-aiplatform
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 18:52:35 +02:00
dependabot[bot] 052149ccf3 chore(deps-dev): bump llama-index from 0.11.6 to 0.11.8 (#3827)
Bumps [llama-index](https://github.com/run-llama/llama_index) from 0.11.6 to 0.11.8.
- [Release notes](https://github.com/run-llama/llama_index/releases)
- [Changelog](https://github.com/run-llama/llama_index/blob/main/CHANGELOG.md)
- [Commits](https://github.com/run-llama/llama_index/compare/v0.11.6...v0.11.8)

---
updated-dependencies:
- dependency-name: llama-index
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 18:51:05 +02:00
dependabot[bot] 3aba722a59 chore(deps-dev): bump evaluate from 0.4.2 to 0.4.3 (#3818)
Bumps [evaluate](https://github.com/huggingface/evaluate) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/huggingface/evaluate/releases)
- [Commits](https://github.com/huggingface/evaluate/compare/v0.4.2...v0.4.3)

---
updated-dependencies:
- dependency-name: evaluate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 18:47:22 +02:00
dependabot[bot] 4738640f4e chore(deps): bump datasets from 2.21.0 to 3.0.0 (#3821)
Bumps [datasets](https://github.com/huggingface/datasets) from 2.21.0 to 3.0.0.
- [Release notes](https://github.com/huggingface/datasets/releases)
- [Commits](https://github.com/huggingface/datasets/compare/2.21.0...3.0.0)

---
updated-dependencies:
- dependency-name: datasets
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 18:46:23 +02:00
dependabot[bot] bf6f7b9943 chore(deps): bump google-generativeai from 0.7.2 to 0.8.0 (#3822)
Bumps [google-generativeai](https://github.com/google/generative-ai-python) from 0.7.2 to 0.8.0.
- [Release notes](https://github.com/google/generative-ai-python/releases)
- [Changelog](https://github.com/google-gemini/generative-ai-python/blob/main/RELEASE.md)
- [Commits](https://github.com/google/generative-ai-python/compare/v0.7.2...v0.8.0)

---
updated-dependencies:
- dependency-name: google-generativeai
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 18:35:33 +02:00
dependabot[bot] 0f20965999 chore(deps): bump fastapi from 0.114.0 to 0.114.1 (#3823)
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.114.0 to 0.114.1.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.114.0...0.114.1)

---
updated-dependencies:
- dependency-name: fastapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 16:21:08 +00:00
dependabot[bot] e6034b301b chore(deps): bump vite from 5.4.3 to 5.4.4 in /frontend (#3817)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.3 to 5.4.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.4/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 19:19:49 +03:00
dependabot[bot] 9e50b88f9f chore(deps): bump litellm from 1.44.23 to 1.44.24 (#3826)
Bumps [litellm](https://github.com/BerriAI/litellm) from 1.44.23 to 1.44.24.
- [Release notes](https://github.com/BerriAI/litellm/releases)
- [Commits](https://github.com/BerriAI/litellm/compare/v1.44.23...v1.44.24)

---
updated-dependencies:
- dependency-name: litellm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 16:10:43 +00:00
dependabot[bot] fd0ecdd4e0 chore(deps): bump boto3 from 1.35.15 to 1.35.16 (#3824)
Bumps [boto3](https://github.com/boto/boto3) from 1.35.15 to 1.35.16.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.15...1.35.16)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 16:08:19 +00:00
Robert Brennan c6105f264f Improvements to file list UI (#3794)
* move filematching logic into server

* wait until ready before returning

* show loading message instead of empty

* logspam

* delint

* fix type

* add a few more default ignores
2024-09-11 09:44:37 -04:00
Engel Nyst 93f271579c Revert "chore(deps): bump numpy from 1.26.4 to 2.1.1 (#3713)" (#3816)
This reverts commit 5100d12cea.
2024-09-11 12:29:32 +02:00
Boxuan Li 1976763152 Fix wrong mention of Devin in localLLMs.md (#3814) 2024-09-11 07:49:33 +02:00
Engel Nyst 516ca701d4 Update local-llms.md (#3811) 2024-09-11 01:08:20 +02:00
mamoodi f3b2085f9b Reduce runtime tests duration by running them across CPUs (#3779)
* Reduce runtime tests duration by running them across CPUs

* fix hardcoded image name

* test two cpus

* Test folder change

* Up the CPU to 4 again to test

* Change to 3 CPUs

* Down to 2

* Add param to remove all openhands containers

* Add comment

* Add reruns just in case

* Fix ordering of if
2024-09-10 14:31:17 -04:00
Cole Murray 97a03faf33 Add Handling of Cache Prompt When Formatting Messages (#3773)
* Add Handling of Cache Prompt When Formatting Messages

* Fix Value for Cache Control

* Fix Value for Cache Control

* Update openhands/core/message.py

Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>

* Fix lint error

* Serialize Messages if Propt Caching Is Enabled

* Remove formatting message change

---------

Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: tobitege <10787084+tobitege@users.noreply.github.com>
2024-09-10 16:34:41 +00:00
dependabot[bot] 06ed142191 chore(deps): bump json-repair from 0.29.1 to 0.29.2 (#3800)
Bumps [json-repair](https://github.com/mangiucugna/json_repair) from 0.29.1 to 0.29.2.
- [Release notes](https://github.com/mangiucugna/json_repair/releases)
- [Commits](https://github.com/mangiucugna/json_repair/compare/v0.29.1...v0.29.2)

---
updated-dependencies:
- dependency-name: json-repair
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 16:18:36 +00:00
dependabot[bot] dbd0786345 chore(deps-dev): bump pytest from 8.3.2 to 8.3.3 (#3801)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.2 to 8.3.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.2...8.3.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 16:17:30 +00:00
dependabot[bot] 3bc9a485b8 chore(deps-dev): bump openai from 1.44.0 to 1.44.1 (#3802)
Bumps [openai](https://github.com/openai/openai-python) from 1.44.0 to 1.44.1.
- [Release notes](https://github.com/openai/openai-python/releases)
- [Changelog](https://github.com/openai/openai-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/openai/openai-python/compare/v1.44.0...v1.44.1)

---
updated-dependencies:
- dependency-name: openai
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 16:16:32 +00:00
dependabot[bot] 2b845d9568 chore(deps): bump i18next from 23.15.0 to 23.15.1 in /frontend (#3805)
Bumps [i18next](https://github.com/i18next/i18next) from 23.15.0 to 23.15.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.15.0...v23.15.1)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 23:57:59 +08:00
dependabot[bot] d7e0db0b35 chore(deps-dev): bump typescript from 5.5.4 to 5.6.2 in /frontend (#3804)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.5.4 to 5.6.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.5.4...v5.6.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 23:57:49 +08:00
dependabot[bot] 508681691a chore(deps-dev): bump typescript from 5.5.4 to 5.6.2 in /docs (#3806)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.5.4 to 5.6.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.5.4...v5.6.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 23:57:41 +08:00
tobitege 1c9b4ad78a fix regression in fork artifact upload in ghcr_runtime (#3807) 2024-09-10 17:36:36 +02:00
dependabot[bot] ecb1b9b2a0 chore(deps): bump boto3 from 1.35.14 to 1.35.15 (#3798)
Bumps [boto3](https://github.com/boto/boto3) from 1.35.14 to 1.35.15.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.14...1.35.15)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 17:29:56 +02:00
dependabot[bot] e4f8708656 chore(deps): bump litellm from 1.44.22 to 1.44.23 (#3799)
Bumps [litellm](https://github.com/BerriAI/litellm) from 1.44.22 to 1.44.23.
- [Release notes](https://github.com/BerriAI/litellm/releases)
- [Commits](https://github.com/BerriAI/litellm/compare/v1.44.22...v1.44.23)

---
updated-dependencies:
- dependency-name: litellm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 17:25:41 +02:00
dependabot[bot] 822de89394 chore(deps): bump browsergym from 0.3.4 to 0.4.3 (#3762)
* chore(deps): bump browsergym from 0.3.4 to 0.4.3

Bumps browsergym from 0.3.4 to 0.4.3.

---
updated-dependencies:
- dependency-name: browsergym
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* integration tests updated to browsergym

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
2024-09-10 17:24:40 +02:00
Robert Brennan c5e89be6de fix runtime tags (#3790) 2024-09-09 20:03:48 +00:00
dependabot[bot] 386688da5f chore(deps): bump fastapi from 0.113.0 to 0.114.0 (#3783)
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.113.0 to 0.114.0.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.113.0...0.114.0)

---
updated-dependencies:
- dependency-name: fastapi
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 15:23:34 -04:00
dependabot[bot] 6c01d25976 chore(deps): bump boto3 from 1.35.13 to 1.35.14 (#3784)
Bumps [boto3](https://github.com/boto/boto3) from 1.35.13 to 1.35.14.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.13...1.35.14)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 15:23:26 -04:00
dependabot[bot] 05e2b0c352 chore(deps-dev): bump openai from 1.43.1 to 1.44.0 (#3787)
Bumps [openai](https://github.com/openai/openai-python) from 1.43.1 to 1.44.0.
- [Release notes](https://github.com/openai/openai-python/releases)
- [Changelog](https://github.com/openai/openai-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/openai/openai-python/compare/v1.43.1...v1.44.0)

---
updated-dependencies:
- dependency-name: openai
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 15:23:16 -04:00
dependabot[bot] 5066468c36 chore(deps-dev): bump build from 1.2.1 to 1.2.2 (#3785)
Bumps [build](https://github.com/pypa/build) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/pypa/build/releases)
- [Changelog](https://github.com/pypa/build/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/build/compare/1.2.1...1.2.2)

---
updated-dependencies:
- dependency-name: build
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 15:23:04 -04:00
dependabot[bot] 9349009074 chore(deps): bump litellm from 1.44.19 to 1.44.22 (#3786)
Bumps [litellm](https://github.com/BerriAI/litellm) from 1.44.19 to 1.44.22.
- [Release notes](https://github.com/BerriAI/litellm/releases)
- [Commits](https://github.com/BerriAI/litellm/compare/v1.44.19...v1.44.22)

---
updated-dependencies:
- dependency-name: litellm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 15:22:52 -04:00
tobitege 5ffff742de Regression fixes: LLM logging; client readiness (EventStreamRuntime) (#3776)
* Regression fixes: LLM logging; client readiness (EventStreamRuntime)

* fix llm.async_completion_wrapper bad edit in previous commit

* regen couple of mock files

* client: always log initialized status
2024-09-09 21:02:43 +02:00
dependabot[bot] 50dc17c65c chore(deps): bump i18next from 23.14.0 to 23.15.0 in /frontend (#3788)
Bumps [i18next](https://github.com/i18next/i18next) from 23.14.0 to 23.15.0.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.14.0...v23.15.0)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 19:31:27 +03:00
Robert Brennan f4d6b3262d fix runtime image (#3782) 2024-09-09 09:55:48 -04:00
Robert Brennan cb3168da12 Redesign settings modal (#3751)
* add advanced options switch

* remove logic for custom models

* remove extra span

* consolidate row

* no more toast

* remove default subtitle

* fix title tags

* remove getSettingsDifference

* delint

* delint

* fix select buttons

* delete test

* fix test

* fix test

* fix labels

* remove model-id tests

* fix labels

* fix labels

* rename var

* fix test

* fix more tests

* change some mocks

* more fixes

* one more fix

* remove some mocks

* rename things

* one more test

* ahhhhh

* change required settings

* fix test

* delint

* fix build
2024-09-09 09:02:58 -04:00
tobitege 2b7517e542 (enh) add caching@v4 action in workflows (#3780)
* dummy test change

* regen yml: 1st install python 3.11, then poetry

* fix caching for poetry; old entry for python was rather useless

* fix steps order (cache before poetry)

* add poetry caching to ghcr_runtime; fix fork conditions

* ghcr_runtime: more caching actions; condition fixes

* fix interim action error (order of steps)

* cache@v4 instead of v3

* fixed interim typo for 2 fork conditions

* runtime/test_env_vars: compacted multiple tests into one to reduce time

* ugh if fork condition changes again
2024-09-09 10:49:49 +02:00
Cole Murray dadada18ce Add Anthropic Models to Cache Prompt (#3775)
* Add Anthropic Models to Cache Prompt

* Update Cache Prompt Active Check for Partial String Matching
2024-09-08 22:09:14 +00:00
Robert Brennan ab3851593d Support interactive commands (#3653)
* hacky solution for interactive commands

* add more behavior

* debug

* fix continue functionality

* remove prints

* refactor a bit

* reduce test sleep

* fix python version

* fix pre-commit issue

* Regenerate integration tests

* Update openhands/runtime/client/client.py

* revert some prompt stuff

* several integration mock files regenerated

* execute_action: remove duplicate exception logging

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: tobitege <10787084+tobitege@users.noreply.github.com>
2024-09-08 21:45:51 +02:00
dependabot[bot] 5100d12cea chore(deps): bump numpy from 1.26.4 to 2.1.1 (#3713)
Bumps [numpy](https://github.com/numpy/numpy) from 1.26.4 to 2.1.1.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v1.26.4...v2.1.1)

---
updated-dependencies:
- dependency-name: numpy
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 15:52:27 -04:00
mamoodi a9cf7e6ee6 docs: fix cli and headless commands (#3768) 2024-09-06 15:52:11 -04:00
sp.wack 8392a3fb6b Remove unwanted (large) keys when sharing feedback (#3766) 2024-09-06 22:45:18 +03:00
dependabot[bot] c376b81505 chore(deps): bump fastapi from 0.112.3 to 0.113.0 (#3760)
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.112.3 to 0.113.0.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.112.3...0.113.0)

---
updated-dependencies:
- dependency-name: fastapi
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 19:33:12 +02:00
dependabot[bot] 8440604dd1 chore(deps-dev): bump ruff from 0.6.3 to 0.6.4 (#3763)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.3 to 0.6.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.3...0.6.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 19:31:58 +02:00
dependabot[bot] a4d75cd190 chore(deps-dev): bump llama-index from 0.11.5 to 0.11.6 (#3761)
Bumps [llama-index](https://github.com/run-llama/llama_index) from 0.11.5 to 0.11.6.
- [Release notes](https://github.com/run-llama/llama_index/releases)
- [Changelog](https://github.com/run-llama/llama_index/blob/main/CHANGELOG.md)
- [Commits](https://github.com/run-llama/llama_index/compare/v0.11.5...v0.11.6)

---
updated-dependencies:
- dependency-name: llama-index
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 19:31:01 +02:00
dependabot[bot] 4db929b986 chore(deps): bump litellm from 1.44.17 to 1.44.19 (#3764)
Bumps [litellm](https://github.com/BerriAI/litellm) from 1.44.17 to 1.44.19.
- [Release notes](https://github.com/BerriAI/litellm/releases)
- [Commits](https://github.com/BerriAI/litellm/compare/v1.44.17...v1.44.19)

---
updated-dependencies:
- dependency-name: litellm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 19:30:20 +02:00
dependabot[bot] b6b38fcd37 chore(deps-dev): bump openai from 1.43.0 to 1.43.1 (#3765)
Bumps [openai](https://github.com/openai/openai-python) from 1.43.0 to 1.43.1.
- [Release notes](https://github.com/openai/openai-python/releases)
- [Changelog](https://github.com/openai/openai-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/openai/openai-python/compare/v1.43.0...v1.43.1)

---
updated-dependencies:
- dependency-name: openai
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 19:29:02 +02:00
dependabot[bot] d619be96d1 chore(deps): bump boto3 from 1.35.12 to 1.35.13 (#3759)
Bumps [boto3](https://github.com/boto/boto3) from 1.35.12 to 1.35.13.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.12...1.35.13)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 18:09:36 +02:00
dependabot[bot] 6f44ea0115 chore(deps): bump json-repair from 0.28.4 to 0.29.1 (#3745)
Bumps [json-repair](https://github.com/mangiucugna/json_repair) from 0.28.4 to 0.29.1.
- [Release notes](https://github.com/mangiucugna/json_repair/releases)
- [Commits](https://github.com/mangiucugna/json_repair/compare/v0.28.4...v0.29.1)

---
updated-dependencies:
- dependency-name: json-repair
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 18:08:17 +02:00
Robert Brennan 0f118df910 Docs: fix "architecture" and "llms" sections (#3749)
* fix llm docs

* fix architecture
2024-09-06 09:51:45 -04:00
Jiayi Pan 43c4a7fff4 Allow Generalized SWE-Bench format for evaluation (#3752)
* allow generalized swe-bench format

* Update run_infer.py

* fix linter

---------

Co-authored-by: Xingyao Wang <xingyao6@illinois.edu>
2024-09-06 13:05:00 +00:00
tobitege 57187417b7 revert enabling litellm verbose mode from testing (#3750) 2024-09-05 20:12:04 +00:00
tobitege 03b5b03bb2 (enh) CodeActAgent: improve logging; sensible retry defaults in config (#3729)
* CodeActAgent: improve logging; sensible retry defaults for completion errors

* CodeActAgent: reduce completion error message sent to UI

* tweak values; docs+config template changes

* fix format_messages; log exception in codeactagent again
2024-09-05 18:14:15 +00:00
dependabot[bot] 681276f27c chore(deps): bump google-cloud-aiplatform from 1.64.0 to 1.65.0 (#3747)
Bumps [google-cloud-aiplatform](https://github.com/googleapis/python-aiplatform) from 1.64.0 to 1.65.0.
- [Release notes](https://github.com/googleapis/python-aiplatform/releases)
- [Changelog](https://github.com/googleapis/python-aiplatform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/python-aiplatform/compare/v1.64.0...v1.65.0)

---
updated-dependencies:
- dependency-name: google-cloud-aiplatform
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 13:31:15 -04:00
niliy01 82a154f7e7 (feat) making prompt caching optional instead of enabled default (#3689)
* (feat) making prompt caching optional instead of enabled default

At present, only the Claude models support prompt caching as a experimental feature, therefore, this feature should be implemented as an optional setting rather than being enabled by default.

Signed-off-by: Yi Lin <teroincn@gmail.com>

* handle the conflict

* fix unittest mock return value

* fix lint error in whitespace

---------

Signed-off-by: Yi Lin <teroincn@gmail.com>
2024-09-05 18:52:26 +02:00
dependabot[bot] 5b7ab28511 chore(deps): bump vite from 5.4.2 to 5.4.3 in /frontend (#3721)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.2 to 5.4.3.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:54:09 -04:00
dependabot[bot] ca3f39e918 chore(deps-dev): bump postcss from 8.4.44 to 8.4.45 in /frontend (#3722)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.44 to 8.4.45.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.44...8.4.45)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:53:50 -04:00
dependabot[bot] 6c2630e506 chore(deps-dev): bump @types/node from 22.5.2 to 22.5.4 in /frontend (#3740)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.2 to 22.5.4.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:53:38 -04:00
dependabot[bot] 260e41486e chore(deps-dev): bump llama-index from 0.11.4 to 0.11.5 (#3741)
Bumps [llama-index](https://github.com/run-llama/llama_index) from 0.11.4 to 0.11.5.
- [Release notes](https://github.com/run-llama/llama_index/releases)
- [Changelog](https://github.com/run-llama/llama_index/blob/main/CHANGELOG.md)
- [Commits](https://github.com/run-llama/llama_index/compare/v0.11.4...v0.11.5)

---
updated-dependencies:
- dependency-name: llama-index
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:53:28 -04:00
dependabot[bot] 9b0fb8f81a chore(deps): bump boto3 from 1.35.11 to 1.35.12 (#3742)
Bumps [boto3](https://github.com/boto/boto3) from 1.35.11 to 1.35.12.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.11...1.35.12)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:53:22 -04:00
dependabot[bot] cd360ef6aa chore(deps): bump litellm from 1.44.15 to 1.44.17 (#3743)
Bumps [litellm](https://github.com/BerriAI/litellm) from 1.44.15 to 1.44.17.
- [Release notes](https://github.com/BerriAI/litellm/releases)
- [Commits](https://github.com/BerriAI/litellm/compare/v1.44.15...v1.44.17)

---
updated-dependencies:
- dependency-name: litellm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:53:15 -04:00
dependabot[bot] 5bb46525a4 chore(deps): bump fastapi from 0.112.2 to 0.112.3 (#3744)
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.112.2 to 0.112.3.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.112.2...0.112.3)

---
updated-dependencies:
- dependency-name: fastapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:53:08 -04:00
dependabot[bot] f80e4a9e5d chore(deps): bump anthropic from 0.34.1 to 0.34.2 (#3746)
Bumps [anthropic](https://github.com/anthropics/anthropic-sdk-python) from 0.34.1 to 0.34.2.
- [Release notes](https://github.com/anthropics/anthropic-sdk-python/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-python/compare/v0.34.1...v0.34.2)

---
updated-dependencies:
- dependency-name: anthropic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 11:52:59 -04:00
mamoodi 60c5fd41ec Update docs on LLM providers for consistency (#3738)
* Update docs on LLM providers for consistency

* Update headless command

* minor tweaks based on feedback

---------

Co-authored-by: Robert Brennan <contact@rbren.io>
Co-authored-by: Robert Brennan <accounts@rbren.io>
2024-09-05 15:10:28 +00:00
Xingyao Wang 688068a44e Fix issues for running RemoteRuntime in parallel on SWE-Bench (#3716)
* feat: add SWE-bench fullset support

* fix instance image list

* update eval script and documentation

* increase timeout for remote runtime

* add push script

* handle the case when ret push is an generator

* update pbar

* set SWE-Bench default to run SWE-Bench lite

* add script to cleanup remote runtime

* fix the cases when tag is too long

* update README

* update readme for cleanup

* rename od to oh

* Update evaluation/swe_bench/README.md

Co-authored-by: Graham Neubig <neubig@gmail.com>

* Update evaluation/swe_bench/README.md

Co-authored-by: Graham Neubig <neubig@gmail.com>

* Update evaluation/swe_bench/scripts/cleanup_remote_runtime.sh

Co-authored-by: Graham Neubig <neubig@gmail.com>

* Update evaluation/swe_bench/scripts/cleanup_remote_runtime.sh

Co-authored-by: Graham Neubig <neubig@gmail.com>

* Update evaluation/swe_bench/scripts/cleanup_remote_runtime.sh

Co-authored-by: Graham Neubig <neubig@gmail.com>

* gets API key and Runtime from env var

---------

Co-authored-by: Graham Neubig <neubig@gmail.com>
2024-09-05 10:34:31 +08:00
Robert Brennan ee158feb15 Documentation updates (#3733)
* update badges

* fix badges

* better badges

* move credits

* more badge work

* add gh logo

* update some copy

* update logo

* fix height

* update text

* emdash

* remove cruft

* move title

* update links

* add hr

* white logo

* move some stuff to getting-started

* revert logo

* more copy changes

* minor tweaks

* fix sidebar

* explicit sidebar

* words

* fix tag

* fix how-to

* more docs work

* update styles

* fix up custom sandbox docs

* change eval title

* fix up getting-started

* fix getting started

* update to 0.9.2

* update screenshot

* add company link

* fix dark mode

* minor fixes

* update image

* update headless and cli docs

* update readme

* fix links

* revert package

* rename links

* fix links

* fix link

* chagne to claude
2024-09-04 21:22:52 +00:00
dependabot[bot] ec25abd98b chore(deps): bump boto3 from 1.35.10 to 1.35.11 (#3724)
Bumps [boto3](https://github.com/boto/boto3) from 1.35.10 to 1.35.11.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.10...1.35.11)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: tofarr <tofarr@gmail.com>
2024-09-04 12:49:11 -07:00
leo bb28dea51f Add documentation for CLI mode (#3706)
* Add documentation for CLI mode

Fixes #3703

Add documentation for CLI mode in OpenHands.

* **New Documentation**: Add `docs/modules/usage/how-to/cli-mode.md` to document CLI mode.
  - Include instructions on starting an interactive OpenHands session via the command line.
  - Explain the difference between CLI mode and headless mode.
  - Provide examples of CLI commands and expected outputs.
* **Update Existing Documentation**: Modify `docs/modules/usage/how-to/headless-mode.md`.
  - Clarify the difference between headless mode and CLI mode.
  - Add a reference to the new CLI mode documentation.

* Update cli-mode.md

* Update headless-mode.md

---------

Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: tofarr <tofarr@gmail.com>
2024-09-04 15:38:57 -04:00
Robert Brennan 2a99aa6679 Cosmetic README updates (#3728)
* update badges

* fix badges

* better badges

* move credits

* more badge work

* add gh logo

* update some copy

* update logo

* fix height

* update text

* emdash

* remove cruft

* move title

* update links

* add hr

* white logo

* move some stuff to getting-started

* revert logo

* more copy changes

* minor tweaks

* words

* fix getting started

* update to 0.9.2

* update screenshot

* minor fixes
2024-09-04 19:38:28 +00:00
mamoodi add4653335 Release 0.9.2 (#3727) 2024-09-04 14:31:54 -04:00
Robert Brennan 2557c18fb1 specify runtime image (#3726) 2024-09-04 12:03:26 -04:00
tobitege bc31fb15fe (fix) CodeActAgent: fix issues with vision support in prompts (#3665)
* CodeActAgent: fix message prep if prompt caching is not supported

* fix python version in regen tests workflow

* fix in conftest "mock_completion" method

* add disable_vision to LLMConfig; revert change in message parsing in llm.py

* format messages in several files for completion

* refactored message(s) formatting (llm.py); added vision_is_active()

* fix a unit test

* regenerate: added LOG_TO_FILE and FORCE_REGENERATE env flags

* try to fix path to logs folder in workflow

* llm: prevent index error

* try FORCE_USE_LLM in regenerate

* tweaks everywhere...

* fix 2 random unit test errors :(

* added FORCE_REGENERATE_TESTS=true to regenerate CLI

* fix test_lint_file_fail_typescript again

* double-quotes for env vars in workflow; llm logger set to debug

* fix typo in regenerate

* regenerate iterations now 20; applied iteration counter fix by Li

* regenerate: pass FORCE_REGENERATE flag into env

* fixes for int tests. several mock files updated.

* browsing_agent: fix response_parser.py adding ) to empty response

* test_browse_internet: fix skipif and revert obsolete mock files

* regenerate: fi bracketing for http server start/kill conditions

* disable test_browse_internet for CodeAct*Agents; mock files updated after merge

* missed to include more mock files earlier

* reverts after review feedback from Li

* forgot one

* browsing agent test, partial fixes and updated mock files

* test_browse_internet works in my WSL now!

* adapt unit test test_prompt_caching.py

* add DEBUG to regenerate workflow command

* convert regenerate workflow params to inputs

* more integration test mock files updated

* more files

* test_prompt_caching: restored test_prompt_caching_headers purpose

* file_ops: fix potential exception, like "cross device copy"; fixed mock files accordingly

* reverts/changes wrt feedback from xingyao

* updated docs and config template

* code cleanup wrt review feedback
2024-09-04 17:58:30 +02:00
368 changed files with 20896 additions and 7463 deletions
+1 -1
View File
@@ -1 +1 @@
The files in this directory configure a development container for GitHub Codespaces.
The files in this directory configure a development container for GitHub Codespaces.
+139 -43
View File
@@ -1,5 +1,5 @@
# Workflow that builds, tests and then pushes the runtime docker images to the ghcr.io repository
name: Build, Test and Publish Runtime Image
name: Build, Test and Publish RT Image
# Only run one workflow of the same group at a time.
# There can be at most one running and one pending job in a concurrency group at any time.
@@ -38,10 +38,6 @@ jobs:
base_image:
- image: 'nikolaik/python-nodejs:python3.11-nodejs22'
tag: nikolaik
- image: 'python:3.11-bookworm'
tag: python
- image: 'node:22-bookworm'
tag: node
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -70,85 +66,162 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Install poetry via pipx
run: pipx install poetry
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'poetry'
- name: Cache Poetry dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pypoetry
~/.virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Install poetry via pipx
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies
- name: Create source distribution and Dockerfile
run: poetry run python3 openhands/runtime/utils/runtime_build.py --base_image ${{ matrix.base_image.image }} --build_folder containers/runtime --force_rebuild
- name: Build and push runtime image ${{ matrix.base_image.image }}
if: "!github.event.pull_request.head.repo.fork"
if: github.event.pull_request.head.repo.fork != true
run: |
./containers/build.sh runtime ${{ github.repository_owner }} --push ${{ matrix.base_image.tag }}
# Forked repos can't push to GHCR, so we need to upload the image as an artifact
- name: Build runtime image ${{ matrix.base_image.image }} for fork
if: "github.event.pull_request.head.repo.fork"
if: github.event.pull_request.head.repo.fork
uses: docker/build-push-action@v6
with:
tags: ghcr.io/all-hands-ai/runtime:${{ github.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
if: "github.event.pull_request.head.repo.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
# Run unit tests with the EventStream runtime Docker images
test_runtime:
name: Test Runtime
runs-on: ubuntu-latest
# Run unit tests with the EventStream runtime Docker images as root
test_runtime_root:
name: RT Unit Tests (Root)
needs: [ghcr_build_runtime]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
base_image: ['nikolaik', 'python', 'node']
base_image: ['nikolaik']
steps:
- uses: actions/checkout@v4
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
swap-storage: true
# Forked repos can't push to GHCR, so we need to download the image as an artifact
- name: Download runtime image for fork
if: "github.event.pull_request.head.repo.fork"
if: github.event.pull_request.head.repo.fork
uses: actions/download-artifact@v4
with:
name: runtime-${{ matrix.base_image }}
path: /tmp
- name: Load runtime image for fork
if: "github.event.pull_request.head.repo.fork"
if: github.event.pull_request.head.repo.fork
run: |
docker load --input /tmp/runtime-${{ matrix.base_image }}.tar
- name: Install poetry via pipx
run: pipx install poetry
- name: Cache Poetry dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pypoetry
~/.virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'poetry'
- name: Install poetry via pipx
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies
- name: Run runtime tests
run: |
# We install pytest-xdist in order to run tests across CPUs
poetry run pip install pytest-xdist
# Install to be able to retry on failures for flaky tests
poetry run pip install pytest-rerunfailures
image_name=ghcr.io/${{ github.repository_owner }}/runtime:${{ github.sha }}-${{ matrix.base_image }}
image_name=$(echo $image_name | tr '[:upper:]' '[:lower:]')
SKIP_CONTAINER_LOGS=true \
TEST_RUNTIME=eventstream \
SANDBOX_USER_ID=$(id -u) \
SANDBOX_BASE_CONTAINER_IMAGE=$image_name \
SANDBOX_RUNTIME_CONTAINER_IMAGE=$image_name \
TEST_IN_CI=true \
poetry run pytest --cov=agenthub --cov=openhands --cov-report=xml -s ./tests/runtime
RUN_AS_OPENHANDS=false \
poetry run pytest -n 3 -raR --reruns 1 --reruns-delay 3 --cov=agenthub --cov=openhands --cov-report=xml -s ./tests/runtime
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# Run unit tests with the EventStream runtime Docker images as openhands user
test_runtime_oh:
name: RT Unit Tests (openhands)
runs-on: ubuntu-latest
needs: [ghcr_build_runtime]
strategy:
matrix:
base_image: ['nikolaik']
steps:
- uses: actions/checkout@v4
# Forked repos can't push to GHCR, so we need to download the image as an artifact
- name: Download runtime image for fork
if: github.event.pull_request.head.repo.fork
uses: actions/download-artifact@v4
with:
name: runtime-${{ matrix.base_image }}
path: /tmp
- name: Load runtime image for fork
if: github.event.pull_request.head.repo.fork
run: |
docker load --input /tmp/runtime-${{ matrix.base_image }}.tar
- name: Cache Poetry dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pypoetry
~/.virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install poetry via pipx
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies
- name: Run runtime tests
run: |
# We install pytest-xdist in order to run tests across CPUs
poetry run pip install pytest-xdist
# Install to be able to retry on failures for flaky tests
poetry run pip install pytest-rerunfailures
image_name=ghcr.io/${{ github.repository_owner }}/runtime:${{ github.sha }}-${{ matrix.base_image }}
image_name=$(echo $image_name | tr '[:upper:]' '[:lower:]')
SKIP_CONTAINER_LOGS=true \
TEST_RUNTIME=eventstream \
SANDBOX_USER_ID=$(id -u) \
SANDBOX_RUNTIME_CONTAINER_IMAGE=$image_name \
TEST_IN_CI=true \
RUN_AS_OPENHANDS=true \
poetry run pytest -n 3 -raR --reruns 1 --reruns-delay 3 --cov=agenthub --cov=openhands --cov-report=xml -s ./tests/runtime
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
env:
@@ -156,33 +229,41 @@ jobs:
# Run integration tests with the eventstream runtime Docker image
runtime_integration_tests_on_linux:
name: Runtime Integration Tests on Linux
name: RT Integration Tests (Linux)
runs-on: ubuntu-latest
needs: [ghcr_build_runtime]
strategy:
fail-fast: false
matrix:
base_image: ['nikolaik', 'python', 'node']
base_image: ['nikolaik']
steps:
- uses: actions/checkout@v4
# Forked repos can't push to GHCR, so we need to download the image as an artifact
- name: Download runtime image for fork
if: "github.event.pull_request.head.repo.fork"
if: github.event.pull_request.head.repo.fork
uses: actions/download-artifact@v4
with:
name: runtime-${{ matrix.base_image }}
path: /tmp
- name: Load runtime image for fork
if: "github.event.pull_request.head.repo.fork"
if: github.event.pull_request.head.repo.fork
run: |
docker load --input /tmp/runtime-${{ matrix.base_image }}.tar
- name: Install poetry via pipx
run: pipx install poetry
- name: Cache Poetry dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pypoetry
~/.virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'poetry'
- name: Install poetry via pipx
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies
- name: Run integration tests
@@ -192,7 +273,7 @@ jobs:
TEST_RUNTIME=eventstream \
SANDBOX_USER_ID=$(id -u) \
SANDBOX_BASE_CONTAINER_IMAGE=$image_name \
SANDBOX_RUNTIME_CONTAINER_IMAGE=$image_name \
TEST_IN_CI=true \
TEST_ONLY=true \
./tests/integration/regenerate.sh
@@ -201,11 +282,26 @@ jobs:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# Checks that all runtime tests have passed
all_runtime_tests_passed:
# The two following jobs (named identically) are to check whether all the runtime tests have passed as the
# "All Runtime Tests Passed" is a required job for PRs to merge
# Due to this bug: https://github.com/actions/runner/issues/2566, we want to create a job that runs when the
# prerequisites have been cancelled or failed so merging is disallowed, otherwise Github considers "skipped" as "success"
runtime_tests_check_success:
name: All Runtime Tests Passed
if: ${{ !cancelled() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
runs-on: ubuntu-latest
needs: [test_runtime, runtime_integration_tests_on_linux]
needs: [test_runtime_root, test_runtime_oh, runtime_integration_tests_on_linux]
steps:
- name: All tests passed
run: echo "All runtime tests have passed successfully!"
runtime_tests_check_fail:
name: All Runtime Tests Passed
if: ${{ cancelled() || contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
runs-on: ubuntu-latest
needs: [test_runtime_root, test_runtime_oh, runtime_integration_tests_on_linux]
steps:
- name: Some tests failed
run: |
echo "Some runtime tests failed or were cancelled"
exit 1
+11 -3
View File
@@ -22,13 +22,21 @@ jobs:
python-version: ['3.11']
steps:
- uses: actions/checkout@v4
- name: Install poetry via pipx
run: pipx install poetry
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'poetry'
- name: Cache Poetry dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pypoetry
~/.virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Install poetry via pipx
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: poetry install --without evaluation,llama-index
- name: Install & Start Docker
+9 -4
View File
@@ -1,9 +1,14 @@
name: Release workflow
# Publishes the OpenHands PyPi package
name: Publish PyPi Package
# Triggered manually
on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+*"
workflow_dispatch:
inputs:
reason:
description: 'Reason for manual trigger'
required: true
default: ''
jobs:
release:
@@ -3,6 +3,23 @@ name: Regenerate Integration Tests
on:
workflow_dispatch:
inputs:
debug:
description: 'Enable debug mode'
type: boolean
default: true
log_to_file:
description: 'Enable logging to file'
type: boolean
default: true
force_regenerate_tests:
description: 'Force regeneration of tests'
type: boolean
default: false
force_use_llm:
description: 'Force use of LLM'
type: boolean
default: false
jobs:
regenerate_integration_tests:
@@ -12,21 +29,32 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install poetry via pipx
run: pipx install poetry
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'poetry'
python-version: "3.11"
- name: Cache Poetry dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pypoetry
~/.virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Install poetry via pipx
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: poetry install --without evaluation,llama-index
run: make install-python-dependencies
- name: Build Environment
run: make build
- name: Regenerate integration tests
run: ./tests/integration/regenerate.sh
run: |
DEBUG=${{ inputs.debug }} \
LOG_TO_FILE=${{ inputs.log_to_file }} \
FORCE_REGENERATE_TESTS=${{ inputs.force_regenerate_tests }} \
FORCE_USE_LLM=${{ inputs.force_use_llm }} \
./tests/integration/regenerate.sh
- name: Commit changes
run: |
if git diff --quiet --exit-code; then
@@ -37,5 +65,6 @@ jobs:
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add .
git commit -m "Regenerate integration tests"
# run it twice in case pre-commit makes changes
git commit -am "Regenerate integration tests" || git commit -am "Regenerate integration tests"
git push
+1
View File
@@ -228,3 +228,4 @@ runtime_*.tar
# docker build
containers/runtime/Dockerfile
containers/runtime/project.tar.gz
containers/runtime/code
+25
View File
@@ -97,3 +97,28 @@ Please refer to [this README](./tests/integration/README.md) for details.
### 9. Add or update dependency
1. Add your dependency in `pyproject.toml` or use `poetry add xxx`
2. Update the poetry.lock file via `poetry lock --no-update`
## Develop inside Docker container
TL;DR
```bash
make docker-dev
```
See more details [here](./containers/dev/README.md)
If you are just interested in running `OpenHands` without installing all the required tools on your host.
```bash
make docker-run
```
If you do not have `make` on your host, run:
```bash
cd ./containers/dev
./dev.sh
```
You do need [Docker](https://docs.docker.com/engine/install/) installed on your host though.
+32 -4
View File
@@ -2,8 +2,9 @@ SHELL=/bin/bash
# Makefile for OpenHands project
# Variables
BACKEND_HOST ?= "127.0.0.1"
BACKEND_PORT = 3000
BACKEND_HOST = "127.0.0.1:$(BACKEND_PORT)"
BACKEND_HOST_PORT = "$(BACKEND_HOST):$(BACKEND_PORT)"
FRONTEND_PORT = 3001
DEFAULT_WORKSPACE_DIR = "./workspace"
DEFAULT_MODEL = "gpt-4o"
@@ -189,12 +190,12 @@ build-frontend:
# Start backend
start-backend:
@echo "$(YELLOW)Starting backend...$(RESET)"
@poetry run uvicorn openhands.server.listen:app --port $(BACKEND_PORT) --reload --reload-exclude "workspace/*"
@poetry run uvicorn openhands.server.listen:app --host $(BACKEND_HOST) --port $(BACKEND_PORT) --reload --reload-exclude "workspace/*"
# Start frontend
start-frontend:
@echo "$(YELLOW)Starting frontend...$(RESET)"
@cd frontend && VITE_BACKEND_HOST=$(BACKEND_HOST) VITE_FRONTEND_PORT=$(FRONTEND_PORT) npm run start
@cd frontend && VITE_BACKEND_HOST=$(BACKEND_HOST_PORT) VITE_FRONTEND_PORT=$(FRONTEND_PORT) npm run start
# Common setup for running the app (non-callable)
_run_setup:
@@ -204,7 +205,7 @@ _run_setup:
fi
@mkdir -p logs
@echo "$(YELLOW)Starting backend server...$(RESET)"
@poetry run uvicorn openhands.server.listen:app --port $(BACKEND_PORT) &
@poetry run uvicorn openhands.server.listen:app --host $(BACKEND_HOST) --port $(BACKEND_PORT) &
@echo "$(YELLOW)Waiting for the backend to start...$(RESET)"
@until nc -z localhost $(BACKEND_PORT); do sleep 0.1; done
@echo "$(GREEN)Backend started successfully.$(RESET)"
@@ -216,6 +217,20 @@ run:
@cd frontend && echo "$(BLUE)Starting frontend with npm...$(RESET)" && npm run start -- --port $(FRONTEND_PORT)
@echo "$(GREEN)Application started successfully.$(RESET)"
# Run the app (in docker)
docker-run: WORKSPACE_BASE ?= $(PWD)/workspace
docker-run:
@if [ -f /.dockerenv ]; then \
echo "Running inside a Docker container. Exiting..."; \
exit 0; \
else \
echo "$(YELLOW)Running the app in Docker $(OPTIONS)...$(RESET)"; \
export WORKSPACE_BASE=${WORKSPACE_BASE}; \
export SANDBOX_USER_ID=$(shell id -u); \
export DATE=$(shell date +%Y%m%d%H%M%S); \
docker compose up $(OPTIONS); \
fi
# Run the app (WSL mode)
run-wsl:
@echo "$(YELLOW)Running the app in WSL mode...$(RESET)"
@@ -280,6 +295,16 @@ setup-config-prompts:
fi
# Develop in container
docker-dev:
@if [ -f /.dockerenv ]; then \
echo "Running inside a Docker container. Exiting..."; \
exit 0; \
else \
echo "$(YELLOW)Build and run in Docker $(OPTIONS)...$(RESET)"; \
./containers/dev/dev.sh $(OPTIONS); \
fi
# Clean up all caches
clean:
@echo "$(YELLOW)Cleaning up caches...$(RESET)"
@@ -298,7 +323,10 @@ help:
@echo " $(GREEN)start-frontend$(RESET) - Start the frontend server for the OpenHands project."
@echo " $(GREEN)run$(RESET) - Run the OpenHands application, starting both backend and frontend servers."
@echo " Backend Log file will be stored in the 'logs' directory."
@echo " $(GREEN)docker-dev$(RESET) - Build and run the OpenHands application in Docker."
@echo " $(GREEN)docker-run$(RESET) - Run the OpenHands application, starting both backend and frontend servers in Docker."
@echo " $(GREEN)help$(RESET) - Display this help message, providing information on available targets."
# Phony targets
.PHONY: build check-dependencies check-python check-npm check-docker check-poetry install-python-dependencies install-frontend-dependencies install-pre-commit-hooks lint start-backend start-frontend run run-wsl setup-config setup-config-prompts help
.PHONY: docker-dev docker-run
+32 -72
View File
@@ -1,72 +1,49 @@
<a name="readme-top"></a>
<!--
*** Thanks for checking out the Best-README-Template. If you have a suggestion
*** that would make this better, please fork the repo and create a pull request
*** or simply open an issue with the tag "enhancement".
*** Don't forget to give the project a star!
*** Thanks again! Now go create something AMAZING! :D
-->
<div align="center">
<img src="./docs/static/img/logo.png" alt="Logo" width="200">
<h1 align="center">OpenHands: Code Less, Make More</h1>
</div>
<!-- PROJECT SHIELDS -->
<!--
*** I'm using markdown "reference style" links for readability.
*** Reference links are enclosed in brackets [ ] instead of parentheses ( ).
*** See the bottom of this document for the declaration of the reference variables
*** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.
*** https://www.markdownguide.org/basic-syntax/#reference-style-links
-->
<p align="center">
<a href="https://trendshift.io/repositories/8648">
<img src="https://trendshift.io/api/badge/repositories/8648" alt="GitHub Trend" style="display: block; margin: auto;">
</a>
</p>
<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/network/members"><img src="https://img.shields.io/github/forks/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Forks"></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://github.com/All-Hands-AI/OpenHands/issues"><img src="https://img.shields.io/github/issues/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Issues"></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>
<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=blue" alt="Credits"></a>
<br/>
<a href="https://join.slack.com/t/opendevin/shared_invite/zt-2oikve2hu-UDxHeo8nsE69y6T7yFX_BA"><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>
<a href="https://discord.gg/ESHStjSjD4"><img src="https://img.shields.io/badge/Discord-Join%20Us-purple?logo=discord&logoColor=white&style=for-the-badge" alt="Join our Discord community"></a>
<a href="https://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"></a>
</div>
<!-- PROJECT LOGO -->
<div align="center">
<img src="./docs/static/img/logo.png" alt="Logo" width="200" height="200">
<h1 align="center">OpenHands: Code Less, Make More</h1>
<a href="https://docs.all-hands.dev/modules/usage/intro"><img src="https://img.shields.io/badge/Documentation-OpenHands-blue?logo=googledocs&logoColor=white&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-red?logo=arxiv&style=for-the-badge" alt="Paper on Arxiv"></a>
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/CREDITS.md"><img src="https://img.shields.io/badge/Project-Credits-blue?style=for-the-badge&color=FFE165&logo=github&logoColor=white" alt="Credits"></a>
<br/>
<a href="https://huggingface.co/spaces/OpenDevin/evaluation"><img src="https://img.shields.io/badge/Evaluation-Benchmark%20on%20HF%20Space-green?logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark"></a>
<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>
<hr>
</div>
<hr>
Welcome to OpenHands (formerly OpenDevin), a platform for software development agents powered by AI.
Welcome to OpenHands, a platform for autonomous software engineers, powered by AI and LLMs (previously called "OpenDevin").
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.
OpenHands agents collaborate with human developers to write code, fix bugs, and ship features.
Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or jump to the [Quick Start](#-quick-start).
![App screenshot](./docs/static/img/screenshot.png)
## ⚡ Getting Started
OpenHands works best with Docker version 26.0.0+ (Docker Desktop 4.31.0+).
You must be using Linux, Mac OS, or WSL on Windows.
## ⚡ Quick Start
To start OpenHands in a docker container, run the following commands in your terminal:
The easiest way to run OpenHands is in Docker. You can change `WORKSPACE_BASE` below to
point OpenHands to existing code that you'd like to modify.
> [!WARNING]
> When you run the following command, files in `./workspace` may be modified or deleted.
See the [Getting Started](https://docs.all-hands.dev/modules/usage/getting-started) guide for
system requirements and more information.
```bash
WORKSPACE_BASE=$(pwd)/workspace
docker run -it \
--pull=always \
export WORKSPACE_BASE=$(pwd)/workspace
docker run -it --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.9-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-v $WORKSPACE_BASE:/opt/workspace_base \
@@ -77,29 +54,23 @@ docker run -it \
ghcr.io/all-hands-ai/openhands:0.9
```
> [!NOTE]
> This command pulls the `0.9` tag, which represents the most recent stable release of OpenHands. You have other options as well:
> - For a specific release version, use `ghcr.io/all-hands-ai/openhands:<OpenHands_version>` (replace <OpenHands_version> with the desired version number).
> - For the most up-to-date development version, use `ghcr.io/all-hands-ai/openhands:main`. This version may be **(unstable!)** and is recommended for testing or development purposes only.
>
> Choose the tag that best suits your needs based on stability requirements and desired features.
You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)!
You'll find OpenHands running at [http://localhost:3000](http://localhost:3000) with access to `./workspace`. To have OpenHands operate on your code, place it in `./workspace`.
OpenHands will only have access to this workspace folder. The rest of your system will not be affected as it runs in a secured docker sandbox.
You can also run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/modules/usage/how-to/headless-mode),
or as an [interactive CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode).
Upon opening OpenHands, you must select the appropriate `Model` and enter the `API Key` within the settings that should pop up automatically. These can be set at any time by selecting
the `Settings` button (gear icon) in the UI. If the required `Model` does not exist in the list, you can manually enter it in the text box.
Visit [Getting Started](https://docs.all-hands.dev/modules/usage/getting-started) for more information and setup instructions.
For the development workflow, see [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
If you want to modify the OpenHands source code, check out [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
Are you having trouble? Check out our [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting).
Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting) can help.
## 🚀 Documentation
## 📖 Documentation
To learn more about the project, and for tips on using OpenHands,
**check out our [documentation](https://docs.all-hands.dev/modules/usage/intro)**.
**check out our [documentation](https://docs.all-hands.dev/modules/usage/getting-started)**.
There you'll find resources on how to use different LLM providers (like ollama and Anthropic's Claude),
There you'll find resources on how to use different LLM providers,
troubleshooting resources, and advanced configuration options.
## 🤝 How to Contribute
@@ -134,17 +105,6 @@ Let's make software engineering better together!
Distributed under the MIT License. See [`LICENSE`](./LICENSE) for more information.
[contributors-shield]: https://img.shields.io/github/contributors/All-Hands-AI/OpenHands?style=for-the-badge
[contributors-url]: https://github.com/All-Hands-AI/OpenHands/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/All-Hands-AI/OpenHands?style=for-the-badge
[forks-url]: https://github.com/All-Hands-AI/OpenHands/network/members
[stars-shield]: https://img.shields.io/github/stars/All-Hands-AI/OpenHands?style=for-the-badge
[stars-url]: https://github.com/All-Hands-AI/OpenHands/stargazers
[issues-shield]: https://img.shields.io/github/issues/All-Hands-AI/OpenHands?style=for-the-badge
[issues-url]: https://github.com/All-Hands-AI/OpenHands/issues
[license-shield]: https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge
[license-url]: https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE
## 🙏 Acknowledgements
OpenHands is built by a large number of contributors, and every contribution is greatly appreciated! We also build upon other open source projects, and we are deeply thankful for their work.
+13 -4
View File
@@ -65,10 +65,15 @@ In order to accomplish my goal I need to send the information asked back to the
"""
def get_prompt(error_prefix: str, cur_axtree_txt: str, prev_action_str: str) -> str:
def get_prompt(
error_prefix: str, cur_url: str, cur_axtree_txt: str, prev_action_str: str
) -> str:
prompt = f"""\
{error_prefix}
# Current Page URL:
{cur_url}
# Current Accessibility Tree:
{cur_axtree_txt}
@@ -139,6 +144,7 @@ class BrowsingAgent(Agent):
"""
messages: list[Message] = []
prev_actions = []
cur_url = ''
cur_axtree_txt = ''
error_prefix = ''
last_obs = None
@@ -179,6 +185,9 @@ class BrowsingAgent(Agent):
self.error_accumulator += 1
if self.error_accumulator > 5:
return MessageAction('Too many errors encountered. Task failed.')
cur_url = last_obs.url
try:
cur_axtree_txt = flatten_axtree_to_str(
last_obs.axtree_object,
@@ -204,11 +213,11 @@ class BrowsingAgent(Agent):
messages.append(Message(role='system', content=[TextContent(text=system_msg)]))
prompt = get_prompt(error_prefix, cur_axtree_txt, prev_action_str)
prompt = get_prompt(error_prefix, cur_url, cur_axtree_txt, prev_action_str)
messages.append(Message(role='user', content=[TextContent(text=prompt)]))
logger.debug(prompt)
response = self.llm.completion(
messages=[message.model_dump() for message in messages],
messages=self.llm.format_messages_for_llm(messages),
temperature=0.0,
stop=[')```', ')\n```'],
)
+2 -2
View File
@@ -57,7 +57,7 @@ class Flags:
@classmethod
def from_dict(self, flags_dict):
"""Helper for JSON serializble requirement."""
"""Helper for JSON serializable requirement."""
if isinstance(flags_dict, Flags):
return flags_dict
@@ -354,7 +354,7 @@ and executed by a program, make sure to follow the formatting instructions.
self._prompt += '\n'.join(
[
f"""\
- [{msg['role']}] {msg['message']}"""
- [{msg['role']}], {msg['message']}"""
for msg in chat_messages
]
)
+2 -2
View File
@@ -24,9 +24,9 @@ class BrowsingResponseParser(ResponseParser):
if action_str is None:
return ''
action_str = action_str.strip()
if not action_str.endswith('```'):
if action_str and not action_str.endswith('```'):
action_str = action_str + ')```'
logger.info(action_str)
logger.debug(action_str)
return action_str
def parse_action(self, action_str: str) -> Action:
+31 -1
View File
@@ -6,6 +6,7 @@ from openhands.events.action import (
AgentDelegateAction,
AgentFinishAction,
CmdRunAction,
FileEditAction,
IPythonRunCellAction,
MessageAction,
)
@@ -16,6 +17,7 @@ class CodeActResponseParser(ResponseParser):
- CmdRunAction(command) - bash command to run
- IPythonRunCellAction(code) - IPython code to run
- AgentDelegateAction(agent, inputs) - delegate action for (sub)task
- FileEditAction(diff_block) - Search/Replace block to edit.
- MessageAction(content) - Message action to run (e.g. ask for clarification)
- AgentFinishAction() - end the interaction
"""
@@ -28,6 +30,7 @@ class CodeActResponseParser(ResponseParser):
CodeActActionParserCmdRun(),
CodeActActionParserIPythonRunCell(),
CodeActActionParserAgentDelegate(),
CodeActActionParserFileEdit(),
]
self.default_parser = CodeActActionParserMessage()
@@ -39,7 +42,7 @@ class CodeActResponseParser(ResponseParser):
action = response.choices[0].message.content
if action is None:
return ''
for lang in ['bash', 'ipython', 'browse']:
for lang in ['bash', 'ipython', 'edit', 'browse']:
if f'<execute_{lang}>' in action and f'</execute_{lang}>' not in action:
action += f'</execute_{lang}>'
return action
@@ -158,6 +161,33 @@ class CodeActActionParserAgentDelegate(ActionParser):
return AgentDelegateAction(agent='BrowsingAgent', inputs={'task': task})
class CodeActActionParserFileEdit(ActionParser):
"""Parser action:
- FileEditAction(diff_block) - Search/Replace block to edit.
"""
def __init__(
self,
):
self.diff_block = None
def check_condition(self, action_str: str) -> bool:
self.diff_block = re.search(
r'<execute_edit>(.*)</execute_edit>', action_str, re.DOTALL
)
return self.diff_block is not None
def parse(self, action_str: str) -> Action:
assert (
self.diff_block is not None
), 'self.diff_block should not be None when parse is called'
thought = action_str.replace(self.diff_block.group(0), '').strip()
return FileEditAction(
diff_block=self.diff_block.group(1).strip(),
thought=thought,
)
class CodeActActionParserMessage(ActionParser):
"""Parser action:
- MessageAction(content) - Message action to run (e.g. ask for clarification)
+50 -24
View File
@@ -1,21 +1,26 @@
import os
from itertools import islice
from agenthub.codeact_agent.action_parser import CodeActResponseParser
from openhands.controller.agent import Agent
from openhands.controller.state.state import State
from openhands.core.config import AgentConfig
from openhands.core.exceptions import OperationCancelled
from openhands.core.logger import openhands_logger as logger
from openhands.core.message import ImageContent, Message, TextContent
from openhands.events.action import (
Action,
AgentDelegateAction,
AgentFinishAction,
CmdRunAction,
FileEditAction,
IPythonRunCellAction,
MessageAction,
)
from openhands.events.observation import (
AgentDelegateObservation,
CmdOutputObservation,
FileEditObservation,
IPythonRunCellObservation,
UserRejectObservation,
)
@@ -33,7 +38,7 @@ from openhands.utils.prompt import PromptManager
class CodeActAgent(Agent):
VERSION = '1.9'
VERSION = '1.10'
"""
The Code Act Agent is a minimalist agent.
The agent works by passing the model a list of action-observation pairs and prompting the model to take the next step.
@@ -101,6 +106,8 @@ class CodeActAgent(Agent):
return f'{action.thought}\n<execute_ipython>\n{action.code}\n</execute_ipython>'
elif isinstance(action, AgentDelegateAction):
return f'{action.thought}\n<execute_browse>\n{action.inputs["task"]}\n</execute_browse>'
elif isinstance(action, FileEditAction):
return f'{action.thought}\n<execute_edit>\n{action.diff_block}\n</execute_edit>'
elif isinstance(action, MessageAction):
return action.content
elif isinstance(action, AgentFinishAction) and action.source == 'agent':
@@ -110,6 +117,7 @@ class CodeActAgent(Agent):
def get_action_message(self, action: Action) -> Message | None:
if (
isinstance(action, AgentDelegateAction)
or isinstance(action, FileEditAction)
or isinstance(action, CmdRunAction)
or isinstance(action, IPythonRunCellAction)
or isinstance(action, MessageAction)
@@ -117,7 +125,11 @@ class CodeActAgent(Agent):
):
content = [TextContent(text=self.action_to_str(action))]
if isinstance(action, MessageAction) and action.images_urls:
if (
self.llm.vision_is_active()
and isinstance(action, MessageAction)
and action.images_urls
):
content.append(ImageContent(image_urls=action.images_urls))
return Message(
@@ -127,14 +139,15 @@ class CodeActAgent(Agent):
def get_observation_message(self, obs: Observation) -> Message | None:
max_message_chars = self.llm.config.max_message_chars
obs_prefix = 'OBSERVATION:\n'
if isinstance(obs, CmdOutputObservation):
text = 'OBSERVATION:\n' + truncate_content(obs.content, max_message_chars)
text = obs_prefix + truncate_content(obs.content, max_message_chars)
text += (
f'\n[Command {obs.command_id} finished with exit code {obs.exit_code}]'
)
return Message(role='user', content=[TextContent(text=text)])
elif isinstance(obs, IPythonRunCellObservation):
text = 'OBSERVATION:\n' + obs.content
text = obs_prefix + obs.content
# replace base64 images with a placeholder
splitted = text.split('\n')
for i, line in enumerate(splitted):
@@ -145,17 +158,21 @@ class CodeActAgent(Agent):
text = '\n'.join(splitted)
text = truncate_content(text, max_message_chars)
return Message(role='user', content=[TextContent(text=text)])
elif isinstance(obs, FileEditObservation):
text = obs_prefix + truncate_content(obs.content, max_message_chars)
return Message(role='user', content=[TextContent(text=text)])
elif isinstance(obs, AgentDelegateObservation):
text = 'OBSERVATION:\n' + truncate_content(
str(obs.outputs), max_message_chars
text = obs_prefix + truncate_content(
obs.outputs['content'] if 'content' in obs.outputs else '',
max_message_chars,
)
return Message(role='user', content=[TextContent(text=text)])
elif isinstance(obs, ErrorObservation):
text = 'OBSERVATION:\n' + truncate_content(obs.content, max_message_chars)
text = obs_prefix + truncate_content(obs.content, max_message_chars)
text += '\n[Error occurred in processing last action]'
return Message(role='user', content=[TextContent(text=text)])
elif isinstance(obs, UserRejectObservation):
text = 'OBSERVATION:\n' + truncate_content(obs.content, max_message_chars)
text = obs_prefix + truncate_content(obs.content, max_message_chars)
text += '\n[Last action has been rejected by the user]'
return Message(role='user', content=[TextContent(text=text)])
else:
@@ -178,6 +195,7 @@ class CodeActAgent(Agent):
- CmdRunAction(command) - bash command to run
- IPythonRunCellAction(code) - IPython code to run
- AgentDelegateAction(agent, inputs) - delegate action for (sub)task
- FileEditAction(diff_block) - Search/Replace block to edit.
- MessageAction(content) - Message action to run (e.g. ask for clarification)
- AgentFinishAction() - end the interaction
"""
@@ -188,26 +206,31 @@ class CodeActAgent(Agent):
# prepare what we want to send to the LLM
messages = self._get_messages(state)
params = {
'messages': [message.model_dump() for message in messages],
'messages': self.llm.format_messages_for_llm(messages),
'stop': [
'</execute_ipython>',
'</execute_bash>',
'</execute_browse>',
'</execute_edit>',
],
'temperature': 0.0,
}
if self.llm.supports_prompt_caching:
if self.llm.is_caching_prompt_active():
params['extra_headers'] = {
'anthropic-beta': 'prompt-caching-2024-07-31',
}
# TODO: move exception handling to agent_controller
try:
response = self.llm.completion(**params)
except Exception:
except OperationCancelled as e:
raise e
except Exception as e:
logger.error(f'{e}')
error_message = '{}: {}'.format(type(e).__name__, str(e).split('\n')[0])
return AgentFinishAction(
thought='Agent encountered an error while processing the last action. Please try again.'
thought=f'Agent encountered an error while processing the last action.\nError: {error_message}\nPlease try again.'
)
return self.action_parser.parse(response)
@@ -219,7 +242,7 @@ class CodeActAgent(Agent):
content=[
TextContent(
text=self.prompt_manager.system_message,
cache_prompt=self.llm.supports_prompt_caching, # Cache system prompt
cache_prompt=self.llm.is_caching_prompt_active(), # Cache system prompt
)
],
),
@@ -228,7 +251,7 @@ class CodeActAgent(Agent):
content=[
TextContent(
text=self.prompt_manager.initial_user_message,
cache_prompt=self.llm.supports_prompt_caching, # if the user asks the same query,
cache_prompt=self.llm.is_caching_prompt_active(), # if the user asks the same query,
)
],
),
@@ -247,14 +270,14 @@ class CodeActAgent(Agent):
if message:
# handle error if the message is the SAME role as the previous message
# litellm.exceptions.BadRequestError: litellm.BadRequestError: OpenAIException - Error code: 400 - {'detail': 'Only supports u/a/u/a/u...'}
# there should not have two consecutive messages from the same role
# there shouldn't be two consecutive messages from the same role
if messages and messages[-1].role == message.role:
messages[-1].content.extend(message.content)
else:
messages.append(message)
# Add caching to the last 2 user messages
if self.llm.supports_prompt_caching:
if self.llm.is_caching_prompt_active():
user_turns_processed = 0
for message in reversed(messages):
if message.role == 'user' and user_turns_processed < 2:
@@ -263,14 +286,17 @@ class CodeActAgent(Agent):
].cache_prompt = True # Last item inside the message content
user_turns_processed += 1
# the latest user message is important:
# The latest user message is important:
# we want to remind the agent of the environment constraints
latest_user_message = next(
(
m
for m in reversed(messages)
if m.role == 'user'
and any(isinstance(c, TextContent) for c in m.content)
islice(
(
m
for m in reversed(messages)
if m.role == 'user'
and any(isinstance(c, TextContent) for c in m.content)
),
1,
),
None,
)
+34 -7
View File
@@ -5,8 +5,13 @@ The assistant can use a Python environment with <execute_ipython>, e.g.:
print("Hello World!")
</execute_ipython>
The assistant can execute bash commands wrapped with <execute_bash>, e.g. <execute_bash> ls </execute_bash>.
The assistant is not allowed to run interactive commands. For commands that may run indefinitely,
the output should be redirected to a file and the command run in the background, e.g. <execute_bash> python3 app.py > server.log 2>&1 & </execute_bash>
If a bash command returns exit code `-1`, this means the process is not yet finished.
The assistant must then send a second <execute_bash>. The second <execute_bash> can be empty
(which will retrieve any additional logs), or it can contain text to be sent to STDIN of the running process,
or it can contain the text `ctrl+c` to interrupt the process.
For commands that may run indefinitely, the output should be redirected to a file and the command run
in the background, e.g. <execute_bash> python3 app.py > server.log 2>&1 & </execute_bash>
If a command execution result says "Command timed out. Sending SIGINT to the process",
the assistant should retry running the command in the background.
{% endset %}
@@ -14,22 +19,44 @@ the assistant should retry running the command in the background.
The assistant can browse the Internet with <execute_browse> and </execute_browse>.
For example, <execute_browse> Tell me the usa's president using google search </execute_browse>.
Or <execute_browse> Tell me what is in http://example.com </execute_browse>.
{% endset %}
{% set EDIT_DIFF_PREFIX %}
The assistant can edit files with <execute_edit> and </execute_edit>. Each change must be described with a SEARCH/REPLACE block.
Every SEARCH section must EXACTLY MATCH the existing file content, character for character, including all comments, docstrings, etc. SEARCH/REPLACE blocks will replace all matching occurrences. Include enough lines to make the SEARCH blocks uniquely match the lines to change.
Keep SEARCH/REPLACE blocks as concise as possible. Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
To move code within a file, use 2 SEARCH/REPLACE blocks: 1 to delete it from its current location, 1 to insert it in the new location.
If you want to put code in a new file, use a SEARCH/REPLACE block with: a new file path, an empty `SEARCH` section and the new file's contents in the `REPLACE` section.
Every SEARCH/REPLACE block must use this format:
1. The FULL file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc.
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE
For example,
<execute_edit>
demo.py
<<<<<<< SEARCH
print("hello")
=======
print("goodbye")
>>>>>>> REPLACE
</execute_edit>
{% endset %}
{% set PIP_INSTALL_PREFIX %}
The assistant can install Python packages using the %pip magic command in an IPython environment by using the following syntax: <execute_ipython> %pip install [package needed] </execute_ipython> and should always import packages and define variables before starting to use them.
{% endset %}
{% set SYSTEM_PREFIX = MINIMAL_SYSTEM_PREFIX + BROWSING_PREFIX + PIP_INSTALL_PREFIX %}
{% set SYSTEM_PREFIX = MINIMAL_SYSTEM_PREFIX + BROWSING_PREFIX + EDIT_DIFF_PREFIX + PIP_INSTALL_PREFIX %}
{% set COMMAND_DOCS %}
Apart from the standard Python library, the assistant can also use the following functions (already imported) in <execute_ipython> environment:
{{ agent_skills_docs }}
IMPORTANT:
- `open_file` only returns the first 100 lines of the file by default! The assistant MUST use `scroll_down` repeatedly to read the full file BEFORE making edits!
- The assistant shall adhere to THE `edit_file_by_replace`, `append_file` and `insert_content_at_line` FUNCTIONS REQUIRING PROPER INDENTATION. If the assistant would like to add the line ' print(x)', it must fully write the line out, with all leading spaces before the code!
- Indentation is important and code that is not indented correctly will fail and require fixing before it can be run.
- Any code issued should be less than 50 lines to avoid context being cut off!
- After EVERY `create_file` the method `append_file` shall be used to write the FIRST content!
- For `edit_file_by_replace` NEVER provide empty parameters!
- For `edit_file_by_replace` the file must be read fully before any replacements!
{% endset %}
{% set SYSTEM_SUFFIX %}
Responses should be concise.
+26 -58
View File
@@ -4,23 +4,12 @@
USER: Create a list of numbers from 1 to 10, and display them in a web page at port 5000.
ASSISTANT:
Sure! Let me create a Python file `app.py`:
<execute_ipython>
create_file('app.py')
</execute_ipython>
USER:
OBSERVATION:
[File: /workspace/app.py (1 lines total)]
(this is the beginning of the file)
1|
(this is the end of the file)
[File app.py created.]
ASSISTANT:
Now I will write the Python code for starting a web server and save it to the file `app.py`:
<execute_ipython>
EDITED_CODE="""from flask import Flask
Sure! Let me write the Python code for starting a web server and save it to a new Python file `app.py`:
<execute_edit>
app.py
<<<<<<< SEARCH
=======
from flask import Flask
app = Flask(__name__)
@app.route('/')
@@ -29,30 +18,17 @@ def index():
return str(numbers)
if __name__ == '__main__':
app.run(port=5000)"""
app.run(port=5000)
>>>>>>> REPLACE
</execute_edit>
insert_content_at_line(
'app.py',
1,
EDITED_CODE,
)
</execute_ipython>
USER:
OBSERVATION:
(this is the beginning of the file)
1|from flask import Flask
2|app = Flask(__name__)
3|
4|@app.route('/')
5|def index():
6| numbers = list(range(1, 11))
7| return str(numbers)
8|
9|if __name__ == '__main__':
10| app.run(port=5000)
(this is the end of the file)
[File updated (edited at line 1). Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary.]
I updated the file app.py by
appending:
from flask import Flask
app = Flask(__name__)
ASSISTANT:
I have created a Python file `app.py` that will display a list of numbers from 1 to 10 when you run it. Let me run the Python file for you:
@@ -177,30 +153,22 @@ USER:
ASSISTANT:
I should edit the file to display the numbers in a table format. I should include correct indentation. Let me update the file:
<execute_ipython>
edit_file_by_replace(
'app.py',
to_replace=" return str(numbers)",
new_content=" return '<table>' + ''.join([f'<tr><td>{i}</td></tr>' for i in numbers]) + '</table>'",
)
</execute_ipython>
<execute_edit>
app.py
<<<<<<< SEARCH
return str(numbers)
=======
return '<table>' + ''.join([f'<tr><td>{i}</td></tr>' for i in numbers]) + '</table>'
>>>>>>> REPLACE
</execute_edit>
USER:
Observation:
[File: /workspace/app.py (10 lines total after edit)]
(this is the beginning of the file)
1|from flask import Flask
2|app = Flask(__name__)
3|
4|@app.route('/')
5|def index():
6| numbers = list(range(1, 11))
7| return '<table>' + ''.join([f'<tr><td>{i}</td></tr>' for i in numbers]) + '</table>'
8|
9|if __name__ == '__main__':
10| app.run(port=5000)
(this is the end of the file)
[File updated (edited at line 7). Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary.]
I updated the file app.py by
replacing:
return str(numbers)
with:
return '<table>' + ''.join([f'<tr><td>{i}</td></tr>' for i in numbers]) + '</table>'
ASSISTANT:
Running the updated file:
@@ -94,7 +94,11 @@ class CodeActSWEAgent(Agent):
):
content = [TextContent(text=self.action_to_str(action))]
if isinstance(action, MessageAction) and action.images_urls:
if (
self.llm.vision_is_active()
and isinstance(action, MessageAction)
and action.images_urls
):
content.append(ImageContent(image_urls=action.images_urls))
return Message(
@@ -156,9 +160,8 @@ class CodeActSWEAgent(Agent):
# prepare what we want to send to the LLM
messages: list[Message] = self._get_messages(state)
response = self.llm.completion(
messages=[message.model_dump() for message in messages],
messages=self.llm.format_messages_for_llm(messages),
stop=[
'</execute_ipython>',
'</execute_bash>',
+5 -2
View File
@@ -73,10 +73,13 @@ class MicroAgent(Agent):
latest_user_message=last_user_message,
)
content = [TextContent(text=prompt)]
if last_image_urls:
if self.llm.vision_is_active() and last_image_urls:
content.append(ImageContent(image_urls=last_image_urls))
message = Message(role='user', content=content)
resp = self.llm.completion(messages=[message.model_dump()])
resp = self.llm.completion(
messages=self.llm.format_messages_for_llm(message),
temperature=0.0,
)
action_resp = resp['choices'][0]['message']['content']
action = parse_response(action_resp)
return action
+2 -2
View File
@@ -46,8 +46,8 @@ class PlannerAgent(Agent):
state, self.llm.config.max_message_chars
)
content = [TextContent(text=prompt)]
if image_urls:
if self.llm.vision_is_active() and image_urls:
content.append(ImageContent(image_urls=image_urls))
message = Message(role='user', content=content)
resp = self.llm.completion(messages=[message.model_dump()])
resp = self.llm.completion(messages=self.llm.format_messages_for_llm(message))
return self.response_parser.parse(resp)
+22
View File
@@ -0,0 +1,22 @@
#
services:
openhands:
build:
context: ./
dockerfile: ./containers/app/Dockerfile
image: openhands:latest
container_name: openhands-app-${DATE:-}
environment:
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.9-nikolaik}
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:
- "3000:3000"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${WORKSPACE_BASE:-$PWD/workspace}:/opt/workspace_base
pull_policy: build
stdin_open: true
tty: true
+21 -10
View File
@@ -126,21 +126,29 @@ embedding_model = ""
# Model to use
model = "gpt-4o"
# Number of retries to attempt
#num_retries = 5
# Number of retries to attempt when an operation fails with the LLM.
# Increase this value to allow more attempts before giving up
#num_retries = 8
# Retry maximum wait time
#retry_max_wait = 60
# Maximum wait time (in seconds) between retry attempts
# This caps the exponential backoff to prevent excessively long
#retry_max_wait = 120
# Retry minimum wait time
#retry_min_wait = 3
# Minimum wait time (in seconds) between retry attempts
# This sets the initial delay before the first retry
#retry_min_wait = 15
# Retry multiplier for exponential backoff
# Multiplier for exponential backoff calculation
# The wait time increases by this factor after each failed attempt
# A value of 2.0 means each retry waits twice as long as the previous one
#retry_multiplier = 2.0
# Drop any unmapped (unsupported) params without causing an exception
#drop_params = false
# Using the prompt caching feature provided by the LLM
#caching_prompt = false
# Base URL for the OLLAMA API
#ollama_base_url = ""
@@ -151,14 +159,17 @@ model = "gpt-4o"
#timeout = 0
# Top p for the API
#top_p = 0.5
#top_p = 1.0
[llm.gpt3]
# If model is vision capable, this option allows to disable image processing (useful for cost reduction).
#disable_vision = true
[llm.gpt4o-mini]
# API key to use
api_key = "your-api-key"
# Model to use
model = "gpt-3.5"
model = "gpt-4o-mini"
#################################### Agent ###################################
# Configuration for agents (group name starts with 'agent')
+124
View File
@@ -0,0 +1,124 @@
# syntax=docker/dockerfile:1
###
FROM ubuntu:22.04 AS dind
# https://docs.docker.com/engine/install/ubuntu/
RUN apt-get update && apt-get install -y \
ca-certificates \
curl \
&& install -m 0755 -d /etc/apt/keyrings \
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc \
&& chmod a+r /etc/apt/keyrings/docker.asc \
&& echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
RUN apt-get update && apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean \
&& apt-get autoremove -y
###
FROM dind AS openhands
ENV DEBIAN_FRONTEND=noninteractive
#
RUN apt-get update && apt-get install -y \
bash \
build-essential \
curl \
git \
git-lfs \
software-properties-common \
make \
netcat \
sudo \
wget \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean \
&& apt-get autoremove -y
# https://github.com/cli/cli/blob/trunk/docs/install_linux.md
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& apt-get update && apt-get -y install \
gh \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean \
&& apt-get autoremove -y
# Python 3.11
RUN add-apt-repository ppa:deadsnakes/ppa \
&& apt-get update \
&& apt-get install -y python3.11 python3.11-venv python3.11-dev python3-pip \
&& ln -s /usr/bin/python3.11 /usr/bin/python
# NodeJS >= 18.17.1
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y nodejs
# Poetry >= 1.8
RUN curl -fsSL https://install.python-poetry.org | python3.11 - \
&& ln -s ~/.local/bin/poetry /usr/local/bin/poetry
#
RUN <<EOF
#!/bin/bash
printf "#!/bin/bash
set +x
uname -a
docker --version
gh --version | head -n 1
git --version
#
python --version
echo node `node --version`
echo npm `npm --version`
poetry --version
netcat -h 2>&1 | head -n 1
" > /version.sh
chmod a+x /version.sh
EOF
###
FROM openhands AS dev
RUN apt-get update && apt-get install -y \
dnsutils \
file \
iproute2 \
jq \
lsof \
ripgrep \
silversearcher-ag \
vim \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean \
&& apt-get autoremove -y
WORKDIR /app
# cache build dependencies
RUN \
--mount=type=bind,source=./,target=/app/ \
<<EOF
#!/bin/bash
make -s clean
make -s check-dependencies
make -s install-python-dependencies
# NOTE
# node_modules are .dockerignore-d therefore not mountable
# make -s install-frontend-dependencies
EOF
#
CMD ["bash"]
+54
View File
@@ -0,0 +1,54 @@
# Develop in Docker
Install [Docker](https://docs.docker.com/engine/install/) on your host machine and run:
```bash
make docker-dev
# same as:
cd ./containers/dev
./dev.sh
```
It could take some time if you are running for the first time as Docker will pull all the tools required for building OpenHands. The next time you run again, it should be instant.
## Build and run
If everything goes well, you should be inside a container after Docker finishes building the `openhands:dev` image similar to the following:
```bash
Build and run in Docker ...
root@93fc0005fcd2:/app#
```
You may now proceed with the normal [build and run](../../Development.md) workflow as if you were on the host.
## Make changes
The source code on the host is mounted as `/app` inside docker. You may edit the files as usual either inside the Docker container or on your host with your favorite IDE/editors.
The following are also mapped as readonly from your host:
```yaml
# host credentials
- $HOME/.git-credentials:/root/.git-credentials:ro
- $HOME/.gitconfig:/root/.gitconfig:ro
- $HOME/.npmrc:/root/.npmrc:ro
```
## VSCode
Alternatively, if you use VSCode, you could also [attach to the running container](https://code.visualstudio.com/docs/devcontainers/attach-container).
See details for [developing in docker](https://code.visualstudio.com/docs/devcontainers/containers) or simply ask `OpenHands` ;-)
## Rebuild dev image
You could optionally pass additional options to the build script.
```bash
make docker-dev OPTIONS="--build"
# or
./containers/dev/dev.sh --build
```
See [docker compose run](https://docs.docker.com/reference/cli/docker/compose/run/) for more options.
+38
View File
@@ -0,0 +1,38 @@
#
services:
dev:
privileged: true
build:
context: ${OPENHANDS_WORKSPACE:-../../}
dockerfile: ./containers/dev/Dockerfile
image: openhands:dev
container_name: openhands-dev
environment:
- 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.9-nikolaik}
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:
- "3000:3000"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${WORKSPACE_BASE:-$PWD/workspace}:/opt/workspace_base
# source code
- ${OPENHANDS_WORKSPACE:-../../}:/app
# host credentials
- $HOME/.git-credentials:/root/.git-credentials:ro
- $HOME/.gitconfig:/root/.gitconfig:ro
- $HOME/.npmrc:/root/.npmrc:ro
# cache
- cache-data:/root/.cache
pull_policy: never
stdin_open: true
tty: true
##
volumes:
cache-data:
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
set -o pipefail
function get_docker() {
echo "Docker is required to build and run OpenHands."
echo "https://docs.docker.com/get-started/get-docker/"
exit 1
}
function check_tools() {
command -v docker &>/dev/null || get_docker
}
function exit_if_indocker() {
if [ -f /.dockerenv ]; then
echo "Running inside a Docker container. Exiting..."
exit 1
fi
}
#
exit_if_indocker
check_tools
##
OPENHANDS_WORKSPACE=$(git rev-parse --show-toplevel)
cd "$OPENHANDS_WORKSPACE/containers/dev/" || exit 1
##
export BACKEND_HOST="0.0.0.0"
#
export SANDBOX_USER_ID=$(id -u)
export WORKSPACE_BASE=${WORKSPACE_BASE:-$OPENHANDS_WORKSPACE/workspace}
docker compose run --rm --service-ports "$@" dev
##
+5 -4
View File
@@ -1,11 +1,12 @@
# Dynamic constructed Dockerfile
# Dynamically constructed Dockerfile
This folder builds runtime image (sandbox), which will use a `Dockerfile` that is dynamically generated depends on the `base_image` AND a [Python source distribution](https://docs.python.org/3.10/distutils/sourcedist.html) that's based on the current commit of `openhands`.
This folder builds a runtime image (sandbox), which will use a dynamically generated `Dockerfile`
that depends on the `base_image` **AND** a [Python source distribution](https://docs.python.org/3.10/distutils/sourcedist.html) that is based on the current commit of `openhands`.
The following command will generate Dockerfile for `ubuntu:22.04` and the source distribution `.tar` into `containers/runtime`.
The following command will generate a `Dockerfile` file for `nikolaik/python-nodejs:python3.11-nodejs22` (the default base image), an updated `config.sh` and the runtime source distribution files/folders into `containers/runtime`:
```bash
poetry run python3 openhands/runtime/utils/runtime_build.py \
--base_image ubuntu:22.04 \
--base_image nikolaik/python-nodejs:python3.11-nodejs22 \
--build_folder containers/runtime
```
+13 -8
View File
@@ -4,8 +4,8 @@ import { themes as prismThemes } from "prism-react-renderer";
const config: Config = {
title: "OpenHands",
tagline: "An Open Platform for AI Software Developers as Generalist Agents",
favicon: "img/logo.png",
tagline: "Code Less, Make More",
favicon: "img/logo-square.png",
// Set the production url of your site here
url: "https://docs.all-hands.dev",
@@ -73,23 +73,28 @@ const config: Config = {
type: "docSidebar",
sidebarId: "docsSidebar",
position: "left",
label: "Docs",
label: "User Guides",
},
{
type: "docSidebar",
sidebarId: "apiSidebar",
position: "left",
label: "Codebase",
label: "Python API",
},
{
type: 'localeDropdown',
position: 'left',
},
{
href: "https://all-hands.dev",
label: "Company",
position: "right",
},
{
href: "https://github.com/All-Hands-AI/OpenHands",
label: "GitHub",
position: "right",
},
{
type: 'localeDropdown',
position: 'left',
},
],
},
prism: {
@@ -59,10 +59,6 @@ Félicitations !
## Explication technique
Le code pertinent est défini dans [ssh_box.py](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/docker/ssh_box.py) et [image_agnostic_util.py](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/docker/image_agnostic_util.py).
En particulier, ssh_box.py vérifie l'objet config pour ```config.sandbox.base_container_image``` et ensuite tente de récupérer l'image à l'aide de [get_od_sandbox_image](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/docker/image_agnostic_util.py#L72), qui est défini dans image_agnostic_util.py.
Lorsqu'une image personnalisée est utilisée pour la première fois, elle ne sera pas trouvée et donc elle sera construite (à l'exécution ultérieure, l'image construite sera trouvée et renvoyée).
L'image personnalisée est construite avec [_build_sandbox_image()](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/docker/image_agnostic_util.py#L29), qui crée un fichier docker en utilisant votre image personnalisée comme base et configure ensuite l'environnement pour OpenHands, comme ceci:
@@ -41,4 +41,4 @@ ne peut être aussi puissant que les modèles qui le pilotent -- heureusement, l
Certains LLM ont des limites de taux et peuvent nécessiter des réessais. OpenHands réessaiera automatiquement les demandes s'il reçoit une erreur 429 ou une erreur de connexion API.
Vous pouvez définir les variables d'environnement `LLM_NUM_RETRIES`, `LLM_RETRY_MIN_WAIT`, `LLM_RETRY_MAX_WAIT` pour contrôler le nombre de réessais et le temps entre les réessais.
Par défaut, `LLM_NUM_RETRIES` est 5 et `LLM_RETRY_MIN_WAIT`, `LLM_RETRY_MAX_WAIT` sont respectivement de 3 secondes et 60 secondes.
Par défaut, `LLM_NUM_RETRIES` est 8 et `LLM_RETRY_MIN_WAIT`, `LLM_RETRY_MAX_WAIT` sont respectivement de 15 secondes et 120 secondes.
@@ -43,4 +43,4 @@ OpenHands 将向你配置的 LLM 发出许多提示。大多数这些 LLM 都是
一些 LLM 有速率限制,可能需要重试操作。OpenHands 会在收到 429 错误或 API 连接错误时自动重试请求。
你可以设置 `LLM_NUM_RETRIES``LLM_RETRY_MIN_WAIT``LLM_RETRY_MAX_WAIT` 环境变量来控制重试次数和重试之间的时间。
默认情况下,`LLM_NUM_RETRIES`5`LLM_RETRY_MIN_WAIT``LLM_RETRY_MAX_WAIT` 分别为 3 秒和 60 秒。
默认情况下,`LLM_NUM_RETRIES`8`LLM_RETRY_MIN_WAIT``LLM_RETRY_MAX_WAIT` 分别为 15 秒和 120 秒。
@@ -74,7 +74,7 @@ WORKSPACE_DIR="$(pwd)/workspace"
如有需要,可以替换您选择的 `LLM_MODEL`
完成!现在您可以通过 `make run` 启动 Devin 而无需 Docker。现在您应该可以连接到 `http://localhost:3000/`
完成!现在您可以通过 `make run` 启动 OpenHands 而无需 Docker。现在您应该可以连接到 `http://localhost:3000/`
## 选择您的模型
+13 -13
View File
@@ -47,8 +47,8 @@ graph TD
```
1. User Input: The user provides a custom base Docker image
2. Image Building: OpenHands builds a new Docker image (the "OD runtime image") based on the user-provided image. This new image includes OpenHands-specific code, primarily the "runtime client"
3. Container Launch: When OpenHands starts, it launches a Docker container using the OD runtime image
2. Image Building: OpenHands builds a new Docker image (the "OH runtime image") based on the user-provided image. This new image includes OpenHands-specific code, primarily the "runtime client"
3. Container Launch: When OpenHands starts, it launches a Docker container using the OH runtime image
4. Client Initialization: The runtime client initializes inside the container, setting up necessary components like a bash shell and loading any specified plugins
5. Communication: The OpenHands backend (`runtime.py`) communicates with the runtime client over RESTful API, sending actions and receiving observations
6. Action Execution: The runtime client receives actions from the backend, executes them in the sandboxed environment, and sends back observations
@@ -62,7 +62,7 @@ The role of the client:
- It formats and returns observations to the backend, ensuring a consistent interface for processing results
## How OpenHands builds and maintains OD Runtime images
## How OpenHands builds and maintains OH Runtime images
OpenHands' approach to building and managing runtime images ensures efficiency, consistency, and flexibility in creating and maintaining Docker images for both production and development environments.
@@ -80,9 +80,9 @@ OpenHands uses a dual-tagging system for its runtime images to balance reproduci
- This ensures reproducibility; the same hash always means the same image contents
2. Generic tag: `{target_image_repo}:{target_image_tag}`.
Example: `runtime:od_v0.8.3_ubuntu_tag_22.04`
Example: `runtime:oh_v0.9.3_ubuntu_tag_22.04`
- This tag follows the format: `runtime:od_v{OD_VERSION}_{BASE_IMAGE_NAME}_tag_{BASE_IMAGE_TAG}`
- This tag follows the format: `runtime:oh_v{OH_VERSION}_{BASE_IMAGE_NAME}_tag_{BASE_IMAGE_TAG}`
- It represents the latest build for a particular base image and OpenHands version combination
- This tag is updated whenever a new image is built from the same base image, even if the source code changes
@@ -94,11 +94,11 @@ The hash-based tag ensures reproducibility, while the generic tag provides a sta
- Hash-based tag: `{target_image_repo}:{target_image_hash_tag}`.
Example: `runtime:abc123def456`
- Generic tag: `{target_image_repo}:{target_image_tag}`.
Example: `runtime:od_v0.8.3_ubuntu_tag_22.04`
Example: `runtime:oh_v0.9.3_ubuntu_tag_22.04`
2. Build Process:
- a. Convert the base image name to an OD runtime image name
Example: `ubuntu:22.04` -> `runtime:od_v0.8.3_ubuntu_tag_22.04`
- a. Convert the base image name to an OH runtime image name
Example: `ubuntu:22.04` -> `runtime:oh_v0.9.3_ubuntu_tag_22.04`
- b. Generate a build context (Dockerfile and OpenHands source code) and calculate its hash
- c. Check for an existing image with the calculated hash
- d. If not found, check for a recent compatible image to use as a base
@@ -108,7 +108,7 @@ The hash-based tag ensures reproducibility, while the generic tag provides a sta
3. Image Reuse and Rebuilding Logic:
The system follows these steps to determine whether to build a new image or use an existing one from a user-provided (base) image (e.g., `ubuntu:22.04`):
- a. If an image exists with the same hash (e.g., `runtime:abc123def456`), it will be reused as is
- b. If the exact hash is not found, the system will try to rebuild using the latest generic image (e.g., `runtime:od_v0.8.3_ubuntu_tag_22.04`) as a base. This saves time by leveraging existing dependencies
- b. If the exact hash is not found, the system will try to rebuild using the latest generic image (e.g., `runtime:oh_v0.9.3_ubuntu_tag_22.04`) as a base. This saves time by leveraging existing dependencies
- c. If neither the hash-tagged nor the generic-tagged image is found, the system will build the image completely from scratch
4. Caching and Efficiency:
@@ -121,10 +121,10 @@ Here's a flowchart illustrating the build process:
```mermaid
flowchart TD
A[Start] --> B{Convert base image name}
B --> |ubuntu:22.04 -> runtime:od_v0.8.3_ubuntu_tag_22.04| C[Generate build context and hash]
B --> |ubuntu:22.04 -> runtime:oh_v0.9.3_ubuntu_tag_22.04| C[Generate build context and hash]
C --> D{Check for existing image with hash}
D -->|Found runtime:abc123def456| E[Use existing image]
D -->|Not found| F{Check for runtime:od_v0.8.3_ubuntu_tag_22.04}
D -->|Not found| F{Check for runtime:oh_v0.9.3_ubuntu_tag_22.04}
F -->|Found| G[Rebuild based on recent image]
F -->|Not found| H[Build from scratch]
G --> I[Tag with hash and generic tags]
@@ -137,13 +137,13 @@ This approach ensures that:
1. Identical source code and Dockerfile always produce the same image (via hash-based tags)
2. The system can quickly rebuild images when minor changes occur (by leveraging recent compatible images)
3. The generic tag (e.g., `runtime:od_v0.8.3_ubuntu_tag_22.04`) always points to the latest build for a particular base image and OpenHands version combination
3. The generic tag (e.g., `runtime:oh_v0.9.3_ubuntu_tag_22.04`) always points to the latest build for a particular base image and OpenHands version combination
## Runtime Plugin System
The OpenHands Runtime supports a plugin system that allows for extending functionality and customizing the runtime environment. Plugins are initialized when the runtime client starts up.
Check [an example of Jupyter plugin here](https://github.com/All-Hands-AI/OpenHands/blob/9c44d94cef32e6426ebd8deeeb52963153b2348a/openhands/runtime/plugins/jupyter/__init__.py#L30-L63) if you want to implement your own plugin.
Check [an example of Jupyter plugin here](https://github.com/All-Hands-AI/OpenHands/blob/ecf4aed28b0cf7c18d4d8ff554883ba182fc6bdd/openhands/runtime/plugins/jupyter/__init__.py#L21-L55) if you want to implement your own plugin.
*More details about the Plugin system are still under construction - contributions are welcomed!*
+66
View File
@@ -0,0 +1,66 @@
---
sidebar_position: 2
---
# Getting Started
## System Requirements
* Docker version 26.0.0+ or Docker Desktop 4.31.0+
* You must be using Linux or Mac OS
* If you are on Windows, you must use [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)
## Installation
The easiest way to run OpenHands is in Docker. You can change `WORKSPACE_BASE` below to point OpenHands to
existing code that you'd like to modify.
```bash
export WORKSPACE_BASE=$(pwd)/workspace
docker run -it --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.9-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-v $WORKSPACE_BASE:/opt/workspace_base \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
ghcr.io/all-hands-ai/openhands:0.9
```
You can also run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/modules/usage/how-to/headless-mode),
or as an [interactive CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode).
## Setup
After running the command above, you'll find OpenHands running at [http://localhost:3000](http://localhost:3000).
The agent will have access to the `./workspace` folder to do its work. You can copy existing code here, or change `WORKSPACE_BASE` in the
command to point to an existing folder.
Upon launching OpenHands, you'll see a settings modal. You **must** select an `LLM Provider` and `LLM Model` and enter a corresponding `API Key`.
These can be changed at any time by selecting the `Settings` button (gear icon) in the UI.
If the required `LLM Model` does not exist in the list, you can toggle `Advanced Options` and manually enter it with the correct prefix
in the `Custom Model` text box.
The `Advanced Options` also allow you to specify a `Base URL` if required.
<div style={{ display: 'flex', justifyContent: 'center', gap: '20px' }}>
<img src="/img/settings-screenshot.png" alt="settings-modal" width="340" />
<img src="/img/settings-advanced.png" alt="settings-modal" width="335" />
</div>
## Versions
The command above pulls the `0.9` tag, which represents the most recent stable release of OpenHands. You have other options as well:
- For a specific release, use `ghcr.io/all-hands-ai/openhands:$VERSION`, replacing $VERSION with the version number.
- We use semver, and release major, minor, and patch tags. So `0.9` will automatically point to the latest `0.9.x` release, and `0` will point to the latest `0.x.x` release.
- For the most up-to-date development version, you can use `ghcr.io/all-hands-ai/openhands:main`. This version is unstable and is recommended for testing or development purposes only.
You can choose the tag that best suits your needs based on stability requirements and desired features.
For the development workflow, see [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
Are you having trouble? Check out our [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting).
+108
View File
@@ -0,0 +1,108 @@
# CLI Mode
OpenHands can be run in an interactive CLI mode, which allows users to start an interactive session via the command line.
This mode is different from the [headless mode](headless-mode), which is non-interactive and better for scripting.
## With Python
To start an interactive OpenHands session via the command line, follow these steps:
1. Ensure you have followed the [Development setup instructions](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)
2. Run the following command:
```bash
poetry run python -m openhands.core.cli
```
This command will start an interactive session where you can input tasks and receive responses from OpenHands.
You'll need to be sure to set your model, API key, and other settings via environment variables
[or the `config.toml` file](https://github.com/All-Hands-AI/OpenHands/blob/main/config.template.toml).
## With Docker
To run OpenHands in CLI mode with Docker, follow these steps:
1. Set `WORKSPACE_BASE` to the directory you want OpenHands to edit:
```bash
WORKSPACE_BASE=$(pwd)/workspace
```
2. Set `LLM_MODEL` to the model you want to use:
```bash
LLM_MODEL="anthropic/claude-3-5-sonnet-20240620"
```
3. Set `LLM_API_KEY` to your API key:
```bash
LLM_API_KEY="sk_test_12345"
```
4. Run the following Docker command:
```bash
docker run -it \
--pull=always \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
-e LLM_MODEL=$LLM_MODEL \
-v $WORKSPACE_BASE:/opt/workspace_base \
-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) \
ghcr.io/all-hands-ai/openhands:0.9 \
python -m openhands.core.cli
```
This command will start an interactive session in Docker where you can input tasks and receive responses from OpenHands.
## Examples of CLI Commands and Expected Outputs
Here are some examples of CLI commands and their expected outputs:
### Example 1: Simple Task
```bash
How can I help? >> Write a Python script that prints "Hello, World!"
```
Expected Output:
```bash
🤖 Sure! Here is a Python script that prints "Hello, World!":
print("Hello, World!")
```
### Example 2: Bash Command
```bash
How can I help? >> Create a directory named "test_dir"
```
Expected Output:
```bash
🤖 Creating a directory named "test_dir":
mkdir test_dir
```
### Example 3: Error Handling
```bash
How can I help? >> Delete a non-existent file
```
Expected Output:
```bash
🤖 An error occurred. Please try again.
```
@@ -1,26 +1,19 @@
# Create and Use a Custom Docker Sandbox
# Custom Sandbox
The default OpenHands sandbox comes with a [minimal ubuntu configuration](https://github.com/All-Hands-AI/OpenHands/blob/main/containers/sandbox/Dockerfile).
Your use case may need additional software installed by default.
The sandbox is where the agent does its work. Instead of running commands directly on your computer
(which could be dangerous), the agent runs them inside of a Docker container.
The default OpenHands sandbox (`python-nodejs:python3.11-nodejs22`
from [nikolaik/python-nodejs](https://hub.docker.com/r/nikolaik/python-nodejs)) comes with some packages installed such
as python and Node.js but your use case may need additional software installed by default.
There are two ways you can do so:
1. Use an existing image from docker hub. For instance, if you want to have `nodejs` installed, you can do so by using the `node:20` image
1. Use an existing image from docker hub
2. Creating your own custom docker image and using it
If you want to take the first approach, you can skip the `Create Your Docker Image` section.
For a more feature-rich environment, you might consider using pre-built images like **[nikolaik/python-nodejs](https://hub.docker.com/r/nikolaik/python-nodejs)**, which comes with both Python and Node.js pre-installed, along with many other useful tools and libraries, like:
- Node.js: 22.x
- npm: 10.x
- yarn: stable
- Python: latest
- pip: latest
- pipenv: latest
- poetry: latest
- uv: latest
## Setup
Make sure you are able to run OpenHands using the [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md) first.
@@ -79,7 +72,7 @@ Run OpenHands by running ```make run``` in the top level directory.
Navigate to ```localhost:3001``` and check if your desired dependencies are available.
In the case of the example above, running ```node -v``` in the terminal produces ```v20.15.0```
In the case of the example above, running ```node -v``` in the terminal produces ```v20.15.0```.
Congratulations!
@@ -1,4 +1,4 @@
# Contribute to OpenHands Evaluation Harness
# Evaluation
This guide provides an overview of how to integrate your own evaluation benchmark into the OpenHands framework.
@@ -12,7 +12,7 @@ Here's an example configuration file you can use to define and use multiple LLMs
```toml
[llm]
# IMPORTANT: add your API key here, and set the model to the one you want to evaluate
model = "gpt-4o-2024-05-13"
model = "claude-3-5-sonnet-20240620"
api_key = "sk-XXX"
[llm.eval_gpt4_1106_preview_llm]
+22 -52
View File
@@ -1,12 +1,9 @@
# Running in Headless / CLI Mode
# Headless Mode
You can run OpenHands via a CLI, without starting the web application. This makes it easy
to automate tasks with OpenHands. There are 2 main modes of operation:
You can run OpenHands with a single command, without starting the web application.
This makes it easy to write scripts and automate tasks with OpenHands.
* **Headless** : Designed for use with scripts
* **CLI** : Designed for interactive use via a console
As with other modes, the environment is configurable via environment variables or by saving values into [config.toml](https://github.com/All-Hands-AI/OpenHands/blob/main/config.template.toml)
This is different from [CLI Mode](cli-mode), which is interactive, and better for active development.
## With Python
@@ -14,34 +11,36 @@ To run OpenHands in headless mode with Python,
[follow the Development setup instructions](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md),
and then run:
### Headless with Python
```bash
poetry run python -m openhands.core.main -t "write a bash script that prints hi"
```
### CLI with Python
You'll need to be sure to set your model, API key, and other settings via environment variables
[or the `config.toml` file](https://github.com/All-Hands-AI/OpenHands/blob/main/config.template.toml).
## With Docker
1. Set `WORKSPACE_BASE` to the directory you want OpenHands to edit:
```bash
poetry run python -m openhands.core.cli
How can I help? >> write a bash script that prints hi
WORKSPACE_BASE=$(pwd)/workspace
```
## Headless With Docker
To run OpenHands in headless mode with Docker, run:
2. Set `LLM_MODEL` to the model you want to use:
```bash
# Set WORKSPACE_BASE to the directory you want OpenHands to edit
WORKSPACE_BASE=$(pwd)/workspace
LLM_MODEL="anthropic/claude-3-5-sonnet-20240620"
```
# Set LLM_API_KEY to an API key, e.g. for OpenAI or Anthropic
LLM_API_KEY="abcde"
3. Set `LLM_API_KEY` to your API key:
# Set LLM_MODEL to the model you want to use
LLM_MODEL="gpt-4o"
```bash
LLM_API_KEY="sk_test_12345"
```
4. Run the following Docker command:
```bash
docker run -it \
--pull=always \
-e SANDBOX_USER_ID=$(id -u) \
@@ -53,34 +52,5 @@ docker run -it \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
ghcr.io/all-hands-ai/openhands:0.9 \
poetry run python -m openhands.core.main \
-t "Write a bash script that prints Hello World"
```
## CLI With Docker
To run OpenHands in cli mode with Docker, run:
```bash
# Set WORKSPACE_BASE to the directory you want OpenHands to edit
WORKSPACE_BASE=$(pwd)/workspace
# Set LLM_API_KEY to an API key, e.g. for OpenAI or Anthropic
LLM_API_KEY="abcde"
# Set LLM_MODEL to the model you want to use
LLM_MODEL="gpt-4o"
docker run -it \
--pull=always \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_API_KEY=$LLM_API_KEY \
-e LLM_MODEL=$LLM_MODEL \
-v $WORKSPACE_BASE:/opt/workspace_base \
-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) \
ghcr.io/all-hands-ai/openhands:0.9 \
poetry run python -m openhands.core.cli
python -m openhands.core.main -t "write a bash script that prints hi"
```
-5
View File
@@ -1,5 +0,0 @@
---
sidebar_position: 6
---
# 🔎 How To Section
@@ -1,6 +1,6 @@
# Use OpenHands in OpenShift/K8S
# Kubernetes
There are different ways this can be accomplished. This guide goes through one possible way:
There are different ways you might run OpenHands on Kubernetes or OpenShift. This guide goes through one possible way:
1. Create a PV "as a cluster admin" to map workspace_base data and docker directory to the pod through the worker node
2. Create a PVC to be able to mount those PVs to the pod
3. Create a pod which contains two containers; the OpenHands and Sandbox containers
-72
View File
@@ -1,72 +0,0 @@
---
sidebar_position: 1
---
# 💻 OpenHands
OpenHands is an **autonomous AI software engineer** capable of executing complex engineering tasks and collaborating actively with users on software development projects.
This project is fully open-source, so you can use and modify it however you like.
:::tip
Explore the codebase of OpenHands on [GitHub](https://github.com/All-Hands-AI/OpenHands) or join one of our communities!
<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"
alt="Contributors"
/>
</a>
<a href="https://github.com/All-Hands-AI/OpenHands/network/members">
<img
src="https://img.shields.io/github/forks/All-Hands-AI/OpenHands?style=for-the-badge"
alt="Forks"
/>
</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"
alt="Stargazers"
/>
</a>
<a href="https://github.com/All-Hands-AI/OpenHands/issues">
<img
src="https://img.shields.io/github/issues/All-Hands-AI/OpenHands?style=for-the-badge"
alt="Issues"
/>
</a>
<br></br>
<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"
alt="MIT License"
/>
</a>
<br></br>
<a href="https://join.slack.com/t/opendevin/shared_invite/zt-2oikve2hu-UDxHeo8nsE69y6T7yFX_BA">
<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>
<a href="https://discord.gg/ESHStjSjD4">
<img
src="https://img.shields.io/badge/Discord-Join%20Us-purple?logo=discord&logoColor=white&style=for-the-badge"
alt="Join our Discord community"
/>
</a>
:::
## 🛠️ Getting Started
[Check out the getting started guide on Github](https://github.com/All-Hands-AI/OpenHands?tab=readme-ov-file#-getting-started)
[contributors-shield]: https://img.shields.io/github/contributors/All-Hands-AI/OpenHands?style=for-the-badge
[contributors-url]: https://github.com/All-Hands-AI/OpenHands/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/All-Hands-AI/OpenHands?style=for-the-badge
[forks-url]: https://github.com/All-Hands-AI/OpenHands/network/members
[stars-shield]: https://img.shields.io/github/stars/All-Hands-AI/OpenHands?style=for-the-badge
[stars-url]: https://github.com/All-Hands-AI/OpenHands/stargazers
[issues-shield]: https://img.shields.io/github/issues/All-Hands-AI/OpenHands?style=for-the-badge
[issues-url]: https://github.com/All-Hands-AI/OpenHands/issues
[license-shield]: https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge
[license-url]: https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE
+23 -32
View File
@@ -1,55 +1,46 @@
# Azure OpenAI LLM
# Azure
## Completion
OpenHands uses LiteLLM to make calls to Azure's chat models. You can find their documentation on using Azure as a provider [here](https://docs.litellm.ai/docs/providers/azure).
OpenHands uses LiteLLM for completion calls. You can find their documentation on Azure [here](https://docs.litellm.ai/docs/providers/azure)
## Azure OpenAI Configuration
### Azure openai configs
When running the OpenHands Docker image, you'll need to set the following environment variables using `-e`:
When running OpenHands, you'll need to set the following environment variable using `-e` in the
[docker run command](/modules/usage/getting-started#installation):
```
LLM_BASE_URL="<azure-api-base-url>" # e.g. "https://openai-gpt-4-test-v-1.openai.azure.com/"
LLM_API_KEY="<azure-api-key>"
LLM_MODEL="azure/<your-gpt-deployment-name>"
LLM_API_VERSION="<api-version>" # e.g. "2024-02-15-preview"
LLM_API_VERSION="<api-version>" # e.g. "2023-05-15"
```
Example:
```bash
docker run -it \
--pull=always \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_BASE_URL="x.openai.azure.com" \
-e LLM_API_VERSION="2024-02-15-preview" \
-v $WORKSPACE_BASE:/opt/workspace_base \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
ghcr.io/all-hands-ai/openhands:main
docker run -it --pull=always \
-e LLM_API_VERSION="2023-05-15"
...
```
You can set the LLM_MODEL and LLM_API_KEY in the OpenHands UI itself.
Then set the following in the OpenHands UI through the Settings:
:::note
You can find your ChatGPT deployment name on the deployments page in Azure. It could be the same with the chat model name (e.g. 'GPT4-1106-preview'), by default or initially set, but it doesn't have to be the same. Run openhands, and when you load it in the browser, go to Settings and set model as above: "azure/&lt;your-actual-gpt-deployment-name&gt;". If it's not in the list, enter your own text and save it.
You will need your ChatGPT deployment name which can be found on the deployments page in Azure. This is referenced as
&lt;deployment-name&gt; below.
:::
* Enable `Advanced Options`
* `Custom Model` to azure/&lt;deployment-name&gt;
* `Base URL` to your Azure API Base URL (e.g. `https://example-endpoint.openai.azure.com`)
* `API Key` to your Azure API key
## Embeddings
OpenHands uses llama-index for embeddings. You can find their documentation on Azure [here](https://docs.llamaindex.ai/en/stable/api_reference/embeddings/azure_openai/)
OpenHands uses llama-index for embeddings. You can find their documentation on Azure [here](https://docs.llamaindex.ai/en/stable/api_reference/embeddings/azure_openai/).
### Azure openai configs
### Azure OpenAI Configuration
The model used for Azure OpenAI embeddings is "text-embedding-ada-002".
You need the correct deployment name for this model in your Azure account.
When running OpenHands in Docker, set the following environment variables using `-e`:
When running OpenHands, set the following environment variables using `-e` in the
[docker run command](/modules/usage/getting-started#installation):
```
LLM_EMBEDDING_MODEL="azureopenai"
LLM_EMBEDDING_DEPLOYMENT_NAME="<your-embedding-deployment-name>" # e.g. "TextEmbedding...<etc>"
LLM_API_VERSION="<api-version>" # e.g. "2024-02-15-preview"
LLM_EMBEDDING_DEPLOYMENT_NAME="<your-embedding-deployment-name>" # e.g. "TextEmbedding...<etc>"
LLM_API_VERSION="<api-version>" # e.g. "2024-02-15-preview"
```
+16 -14
View File
@@ -1,28 +1,30 @@
# Google Gemini/Vertex LLM
# Google Gemini/Vertex
## Completion
OpenHands uses LiteLLM for completion calls. The following resources are relevant for using OpenHands with Google's LLMs
OpenHands uses LiteLLM to make calls to Google's chat models. You can find their documentation on using Google as a provider:
- [Gemini - Google AI Studio](https://docs.litellm.ai/docs/providers/gemini)
- [VertexAI - Google Cloud Platform](https://docs.litellm.ai/docs/providers/vertex)
### Gemini - Google AI Studio Configs
## Gemini - Google AI Studio Configs
To use Gemini through Google AI Studio when running the OpenHands Docker image, you'll need to set the following environment variables using `-e`:
When running OpenHands, you'll need to set the following in the OpenHands UI through the Settings:
* `LLM Provider` to `Gemini`
* `LLM Model` to the model you will be using.
If the model is not in the list, toggle `Advanced Options`, and enter it in `Custom Model` (e.g. gemini/&lt;model-name&gt; like `gemini/gemini-1.5-pro`).
* `API Key` to your Gemini API key
```
GEMINI_API_KEY="<your-google-api-key>"
LLM_MODEL="gemini/gemini-1.5-pro"
```
## VertexAI - Google Cloud Platform Configs
### Vertex AI - Google Cloud Platform Configs
To use Vertex AI through Google Cloud Platform when running the OpenHands Docker image, you'll need to set the following environment variables using `-e`:
To use Vertex AI through Google Cloud Platform when running OpenHands, you'll need to set the following environment
variables using `-e` in the [docker run command](/modules/usage/getting-started#installation):
```
GOOGLE_APPLICATION_CREDENTIALS="<json-dump-of-gcp-service-account-json>"
VERTEXAI_PROJECT="<your-gcp-project-id>"
VERTEXAI_LOCATION="<your-gcp-location>"
LLM_MODEL="vertex_ai/<desired-llm-model>"
```
Then set the following in the OpenHands UI through the Settings:
* `LLM Provider` to `VertexAI`
* `LLM Model` to the model you will be using.
If the model is not in the list, toggle `Advanced Options`, and enter it in `Custom Model` (e.g. vertex_ai/&lt;model-name&gt;).
+23
View File
@@ -0,0 +1,23 @@
# Groq
OpenHands uses LiteLLM to make calls to chat models on Groq. You can find their documentation on using Groq as a provider [here](https://docs.litellm.ai/docs/providers/groq).
## Configuration
When running OpenHands, you'll need to set the following in the OpenHands UI through the Settings:
* `LLM Provider` to `Groq`
* `LLM Model` to the model you will be using. [Visit here to see the list of
models that Groq hosts](https://console.groq.com/docs/models). If the model is not in the list, toggle
`Advanced Options`, and enter it in `Custom Model` (e.g. groq/&lt;model-name&gt; like `groq/llama3-70b-8192`)
* `API key` to your Groq API key. To find or create your Groq API Key, [see here](https://console.groq.com/keys)
## Using Groq as an OpenAI-Compatible Endpoint
The Groq endpoint for chat completion is [mostly OpenAI-compatible](https://console.groq.com/docs/openai). Therefore, you can access Groq models as you
would access any OpenAI-compatible endpoint. You can set the following in the OpenHands UI through the Settings:
* Enable `Advanced Options`
* `Custom Model` to the prefix `openai/` + the model you will be using (e.g. `openai/llama3-70b-8192`)
* `Base URL` to `https://api.groq.com/openai/v1`
* `API Key` to your Groq API key
+33 -23
View File
@@ -1,57 +1,67 @@
---
sidebar_position: 2
sidebar_position: 3
---
# 🤖 LLM Backends
OpenHands can connect to any LLM supported by LiteLLM. However, it requires a powerful model to work.
The following are verified by the community to work with OpenHands:
* claude-3-5-sonnet
* gemini-1.5-pro / gemini-1.5-flash
* gpt-4 / gpt-4o
* llama-3.1-405b / hermes-3-llama-3.1-405b
* wizardlm-2-8x22b
:::warning
OpenHands will issue many prompts to the LLM you configure. Most of these LLMs cost money, so be sure to set spending
limits and monitor usage.
:::
If you have successfully run OpenHands with specific LLMs not in the list, please add them to the verified list. We
also encourage you to open a PR to share your setup process to help others using the same provider and LLM!
For a full list of the providers and models available, please consult the
[litellm documentation](https://docs.litellm.ai/docs/providers).
## Local and Open Source Models
:::note
Most current local and open source models are not as powerful. When using such models, you may see long
wait times between messages, poor responses, or errors about malformed JSON. OpenHands can only be as powerful as the
models driving it. However, if you do find ones that work, please add them to the verified list above.
## LLM Configuration
:::warning
OpenHands will issue many prompts to the LLM you configure. Most of these LLMs cost money, so be sure to set spending
limits and monitor usage.
:::
The `LLM_MODEL` environment variable controls which model is used in programmatic interactions.
But when using the OpenHands UI, you'll need to choose your model in the settings window.
## LLM Configuration
The following environment variables might be necessary for some LLMs/providers:
The following can be set in the OpenHands UI through the Settings:
* `LLM Provider`
* `LLM Model`
* `API Key`
* `Base URL` (through `Advanced Settings`)
- `LLM_API_KEY`
- `LLM_BASE_URL`
- `LLM_EMBEDDING_MODEL`
- `LLM_EMBEDDING_DEPLOYMENT_NAME`
- `LLM_API_VERSION`
- `LLM_DROP_PARAMS`
There are some settings that may be necessary for some LLMs/providers that cannot be set through the UI. Instead, these
can be set through environment variables passed to the [docker run command](/modules/usage/getting-started#installation)
using `-e`:
* `LLM_API_VERSION`
* `LLM_EMBEDDING_MODEL`
* `LLM_EMBEDDING_DEPLOYMENT_NAME`
* `LLM_DROP_PARAMS`
* `LLM_DISABLE_VISION`
* `LLM_CACHING_PROMPT`
We have a few guides for running OpenHands with specific model providers:
- [OpenAI](llms/openai-llms)
- [ollama](llms/local-llms)
- [Azure](llms/azure-llms)
- [Google](llms/google-llms)
* [Azure](llms/azure-llms)
* [Google](llms/google-llms)
* [Groq](llms/groq)
* [OpenAI](llms/openai-llms)
* [OpenRouter](llms/openrouter)
### API retries and rate limits
Some LLMs have rate limits and may require retries. OpenHands will automatically retry requests if it receives a 429 error or API connection error.
You can set the following environment variables to control the number of retries and the time between retries:
* `LLM_NUM_RETRIES` (Default of 5)
* `LLM_RETRY_MIN_WAIT` (Default of 3 seconds)
* `LLM_RETRY_MAX_WAIT` (Default of 60 seconds)
* `LLM_NUM_RETRIES` (Default of 8)
* `LLM_RETRY_MIN_WAIT` (Default of 15 seconds)
* `LLM_RETRY_MAX_WAIT` (Default of 120 seconds)
+22 -18
View File
@@ -5,7 +5,7 @@ When using a Local LLM, OpenHands may have limited functionality.
:::
Ensure that you have the Ollama server up and running.
For detailed startup instructions, refer to [here](https://github.com/ollama/ollama)
For detailed startup instructions, refer to [here](https://github.com/ollama/ollama).
This guide assumes you've started ollama with `ollama serve`. If you're running ollama differently (e.g. inside docker), the instructions might need to be modified. Please note that if you're running WSL the default ollama configuration blocks requests from docker containers. See [here](#configuring-ollama-service-wsl-en).
@@ -28,17 +28,14 @@ mistral:7b-instruct-v0.2-q4_K_M eb14864c7427 4.4 GB 2 weeks ago
starcoder2:latest f67ae0f64584 1.7 GB 19 hours ago
```
## Start OpenHands
## Run OpenHands with Docker
### Docker
Use the instructions [here](../intro) to start OpenHands using Docker.
### Start OpenHands
Use the instructions [here](../getting-started) to start OpenHands using Docker.
But when running `docker run`, you'll need to add a few more arguments:
```bash
--add-host host.docker.internal:host-gateway \
-e LLM_API_KEY="ollama" \
-e LLM_BASE_URL="http://host.docker.internal:11434" \
-e LLM_OLLAMA_BASE_URL="http://host.docker.internal:11434" \
```
@@ -55,8 +52,6 @@ docker run \
--pull=always \
--add-host host.docker.internal:host-gateway \
-e SANDBOX_USER_ID=$(id -u) \
-e LLM_API_KEY="ollama" \
-e LLM_BASE_URL="http://host.docker.internal:11434" \
-e LLM_OLLAMA_BASE_URL="http://host.docker.internal:11434" \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-v $WORKSPACE_BASE:/opt/workspace_base \
@@ -67,6 +62,16 @@ docker run \
You should now be able to connect to `http://localhost:3000/`
### Configure the Web Application
When running `openhands`, you'll need to set the following in the OpenHands UI through the Settings:
- the model to "ollama/&lt;model-name&gt;"
- the base url to `http://host.docker.internal:11434`
- the API key is optional, you can use any string, such as `ollama`.
## Run OpenHands in Development Mode
### Build from Source
Use the instructions in [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md) to build OpenHands.
@@ -77,23 +82,22 @@ Make sure `config.toml` is there by running `make setup-config` which will creat
workspace_base="./workspace"
[llm]
model="ollama/codellama:7b"
api_key="ollama"
embedding_model="local"
base_url="http://localhost:11434"
ollama_base_url="http://localhost:11434"
```
Replace `LLM_MODEL` of your choice if you need to.
Done! Now you can start OpenHands by: `make run`. You now should be able to connect to `http://localhost:3000/`
Done! Now you can start OpenHands by: `make run` without Docker. You now should be able to connect to `http://localhost:3000/`
## Select your Model
### Configure the Web Application
In the OpenHands UI, click on the Settings wheel in the bottom-left corner.
Then in the `Model` input, enter `ollama/codellama:7b`, or the name of the model you pulled earlier.
If it doesnt show up in a dropdown, thats fine, just type it in. Click Save when youre done.
If it doesnt show up in the dropdown, enable `Advanced Settings` and type it in. Please note: you need the model name as listed by `ollama list`, with the prefix `ollama/`.
In the API Key field, enter `ollama` or any value, since you don't need a particular key.
In the Base URL field, enter `http://localhost:11434`.
And now you're ready to go!
@@ -200,7 +204,7 @@ base_url="http://localhost:1234/v1"
custom_llm_provider="openai"
```
Done! Now you can start Devin by: `make run` without Docker. You now should be able to connect to `http://localhost:3000/`
Done! Now you can start OpenHands by: `make run` without Docker. You now should be able to connect to `http://localhost:3000/`
# Note
+13 -64
View File
@@ -1,75 +1,24 @@
# OpenAI
OpenHands uses [LiteLLM](https://www.litellm.ai/) to make calls to OpenAI's chat models. You can find their full documentation on OpenAI chat calls [here](https://docs.litellm.ai/docs/providers/openai).
OpenHands uses LiteLLM to make calls to OpenAI's chat models. You can find their documentation on using OpenAI as a provider [here](https://docs.litellm.ai/docs/providers/openai).
## Configuration
### Manual Configuration
When running the OpenHands Docker image, you'll need to set the following environment variables:
```sh
LLM_MODEL="openai/<gpt-model-name>" # e.g. "openai/gpt-4o"
LLM_API_KEY="<your-openai-project-api-key>"
```
To see a full list of OpenAI models that LiteLLM supports, please visit https://docs.litellm.ai/docs/providers/openai#openai-chat-completion-models.
To find or create your OpenAI Project API Key, please visit https://platform.openai.com/api-keys.
**Example**:
```sh
export WORKSPACE_BASE=$(pwd)/workspace
docker run -it \
--pull=always \
-e SANDBOX_USER_ID=$(id -u) \
-e LLM_MODEL="openai/<gpt-model-name>" \
-e LLM_API_KEY="<your-openai-project-api-key>" \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-v $WORKSPACE_BASE:/opt/workspace_base \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
ghcr.io/opendevin/opendevin:0.8
```
### UI Configuration
You can also directly set the `LLM_MODEL` and `LLM_API_KEY` in the OpenHands client itself. Follow this guide to get up and running with the OpenHands client.
From there, you can set your model and API key in the settings window.
When running OpenHands, you'll need to set the following in the OpenHands UI through the Settings:
* `LLM Provider` to `OpenAI`
* `LLM Model` to the model you will be using.
[Visit here to see a full list of OpenAI models that LiteLLM supports.](https://docs.litellm.ai/docs/providers/openai#openai-chat-completion-models)
If the model is not in the list, toggle `Advanced Options`, and enter it in `Custom Model` (e.g. openai/&lt;model-name&gt; like `openai/gpt-4o`).
* `API Key` to your OpenAI API key. To find or create your OpenAI Project API Key, [see here](https://platform.openai.com/api-keys).
## Using OpenAI-Compatible Endpoints
Just as for OpenAI Chat completions, we use LiteLLM for OpenAI-compatible endpoints. You can find their full documentation on this topic [here](https://docs.litellm.ai/docs/providers/openai_compatible).
When running the OpenHands Docker image, you'll need to set the following environment variables:
## Using an OpenAI Proxy
```sh
LLM_BASE_URL="<api-base-url>" # e.g. "http://0.0.0.0:3000"
LLM_MODEL="openai/<model-name>" # e.g. "openai/mistral"
LLM_API_KEY="<your-api-key>"
```
**Example**:
```sh
export WORKSPACE_BASE=$(pwd)/workspace
docker run -it \
--pull=always \
-e SANDBOX_USER_ID=$(id -u) \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-e LLM_BASE_URL="<api-base-url>" \
-e LLM_MODEL="openai/<model-name>" \
-e LLM_API_KEY="<your-api-key>" \
-v $WORKSPACE_BASE:/opt/workspace_base \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
ghcr.io/opendevin/opendevin:0.8
```
If you're using an OpenAI proxy, you'll need to set the following in the OpenHands UI through the Settings:
* Enable `Advanced Options`
* `Custom Model` to openai/&lt;model-name&gt; (e.g. `openai/gpt-4o` or openai/&lt;proxy-prefix&gt;/&lt;model-name&gt;)
* `Base URL` to the URL of your OpenAI proxy
* `API Key` to your OpenAI API key
+12
View File
@@ -0,0 +1,12 @@
# OpenRouter
OpenHands uses LiteLLM to make calls to chat models on OpenRouter. You can find their documentation on using OpenRouter as a provider [here](https://docs.litellm.ai/docs/providers/openrouter).
## Configuration
When running OpenHands, you'll need to set the following in the OpenHands UI through the Settings:
* `LLM Provider` to `OpenRouter`
* `LLM Model` to the model you will be using.
[Visit here to see a full list of OpenRouter models](https://openrouter.ai/models).
If the model is not in the list, toggle `Advanced Options`, and enter it in `Custom Model` (e.g. openrouter/&lt;model-name&gt; like `openrouter/anthropic/claude-3.5-sonnet`).
* `API Key` to your OpenRouter API key.
@@ -9,13 +9,14 @@ We'll try to make the install process easier, but for now you can look for your
If you find more information or a workaround for one of these issues, please open a *PR* to add details to this file.
:::tip
If you're running on Windows and having trouble, check out our [Notes for Windows and WSL users](troubleshooting/windows).
OpenHands only supports Windows via [WSL](https://learn.microsoft.com/en-us/windows/wsl/install).
Please be sure to run all commands inside your WSL terminal.
Check out [Notes for WSL on Windows Users](troubleshooting/windows) for some troubleshooting guides.
:::
## Common Issues
* [Unable to connect to Docker](#unable-to-connect-to-docker)
* [Unable to connect to SSH box](#unable-to-connect-to-ssh-box)
* [404 Resource not found](#404-resource-not-found)
* [`make build` getting stuck on package installations](#make-build-getting-stuck-on-package-installations)
* [Sessions are not restored](#sessions-are-not-restored)
@@ -45,58 +46,6 @@ OpenHands uses a Docker container to do its work safely, without potentially bre
* If you are on a Mac, check the [permissions requirements](https://docs.docker.com/desktop/mac/permission-requirements/) and in particular consider enabling the `Allow the default Docker socket to be used` under `Settings > Advanced` in Docker Desktop.
* In addition, upgrade your Docker to the latest version under `Check for Updates`
---
### Unable to connect to SSH box
[GitHub Issue](https://github.com/All-Hands-AI/OpenHands/issues/1156)
**Symptoms**
```python
self.shell = DockerSSHBox(
...
pexpect.pxssh.ExceptionPxssh: Could not establish connection to host
```
**Details**
By default, OpenHands connects to a running container using SSH. On some machines,
especially Windows, this seems to fail.
**Workarounds**
* Restart your computer (sometimes it does work)
* Be sure to have the latest versions of WSL and Docker
* Check that your distribution in WSL is up to date as well
* Try [this reinstallation guide](https://github.com/All-Hands-AI/OpenHands/issues/1156#issuecomment-2064549427)
---
### Unable to connect to LLM
[GitHub Issue](https://github.com/All-Hands-AI/OpenHands/issues/1208)
**Symptoms**
```python
File "/app/.venv/lib/python3.12/site-packages/openai/_exceptions.py", line 81, in __init__
super().__init__(message, response.request, body=body)
^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'request'
```
**Details**
[GitHub Issues](https://github.com/All-Hands-AI/OpenHands/issues?q=is%3Aissue+is%3Aopen+404)
This usually happens with *local* LLM setups, when OpenHands can't connect to the LLM server.
See our guide for [local LLMs](llms/local-llms) for more information.
**Workarounds**
* Check your `base_url` in your config.toml (if it exists) under the "llm" section
* Check that ollama (or whatever LLM you're using) is running OK
* Make sure you're using `--add-host host.docker.internal:host-gateway` when running in Docker
---
### `404 Resource not found`
@@ -138,7 +87,6 @@ the API endpoint you're trying to connect to. Most often this happens for Azure
* If you're running inside the UI, be sure to set the `model` in the settings modal
* If you're running headless (via main.py) be sure to set `LLM_MODEL` in your env/config
* Make sure you've followed any special instructions for your LLM provider
* [ollama](/modules/usage/llms/local-llms)
* [Azure](/modules/usage/llms/azure-llms)
* [Google](/modules/usage/llms/google-llms)
* Make sure your API key is correct
@@ -1,4 +1,4 @@
# Notes for Windows and WSL Users
# Notes for WSL on Windows Users
OpenHands only supports Windows via [WSL](https://learn.microsoft.com/en-us/windows/wsl/install).
Please be sure to run all commands inside your WSL terminal.
+4 -4
View File
@@ -24,7 +24,7 @@
"@docusaurus/module-type-aliases": "^3.5.1",
"@docusaurus/tsconfig": "^3.5.2",
"@docusaurus/types": "^3.5.1",
"typescript": "~5.5.4"
"typescript": "~5.6.2"
},
"engines": {
"node": ">=18.0"
@@ -14853,9 +14853,9 @@
}
},
"node_modules/typescript": {
"version": "5.5.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
+1 -1
View File
@@ -31,7 +31,7 @@
"@docusaurus/module-type-aliases": "^3.5.1",
"@docusaurus/tsconfig": "^3.5.2",
"@docusaurus/types": "^3.5.1",
"typescript": "~5.5.4"
"typescript": "~5.6.2"
},
"browserslist": {
"production": [
+106 -1
View File
@@ -1,8 +1,113 @@
import type { SidebarsConfig } from "@docusaurus/plugin-content-docs";
const sidebars: SidebarsConfig = {
docsSidebar: [{ type: "autogenerated", dirName: "usage" }],
apiSidebar: [require("./modules/python/sidebar.json")],
docsSidebar: [
{
type: 'doc',
label: 'Getting Started',
id: 'usage/getting-started',
},
{
type: 'category',
label: 'LLMs',
items: [
{
type: 'doc',
label: 'Overview',
id: 'usage/llms/llms',
},
{
type: 'category',
label: 'Providers',
items: [
{
type: 'doc',
label: 'Azure',
id: 'usage/llms/azure-llms',
},
{
type: 'doc',
label: 'Google',
id: 'usage/llms/google-llms',
},
{
type: 'doc',
label: 'Groq',
id: 'usage/llms/groq',
},
{
type: 'doc',
label: 'OpenAI',
id: 'usage/llms/openai-llms',
},
{
type: 'doc',
label: 'OpenRouter',
id: 'usage/llms/openrouter',
},
],
},
],
},
{
type: 'doc',
label: 'Troubleshooting',
id: 'usage/troubleshooting/troubleshooting',
},
{
type: 'doc',
label: 'Feedback',
id: 'usage/feedback',
},
{
type: 'category',
label: 'How-to Guides',
items: [
{
type: 'doc',
id: 'usage/how-to/cli-mode',
},
{
type: 'doc',
id: 'usage/how-to/headless-mode',
},
{
type: 'doc',
id: 'usage/how-to/custom-sandbox-guide',
},
{
type: 'doc',
id: 'usage/how-to/evaluation-harness',
},
{
type: 'doc',
id: 'usage/how-to/openshift-example',
}
]
},
{
type: 'category',
label: 'Architecture',
items: [
{
type: 'doc',
label: 'Backend',
id: 'usage/architecture/backend',
},
{
type: 'doc',
label: 'Runtime',
id: 'usage/architecture/runtime',
}
],
},
{
type: 'doc',
label: 'About',
id: 'usage/about',
}
],
};
export default sidebars;
+1 -12
View File
@@ -7,17 +7,6 @@ function CustomFooter() {
return (
<footer className="custom-footer">
<div className="footer-content">
<div className="footer-top">
<div className="footer-title">
<Translate id="footer.title">OpenHands</Translate>
</div>
<div className="footer-link">
<a href="/modules/usage/intro">
<Translate id="footer.docs">Docs</Translate>
</a>
</div>
</div>
<div className="footer-icons">
<a href="https://join.slack.com/t/opendevin/shared_invite/zt-2oikve2hu-UDxHeo8nsE69y6T7yFX_BA" target="_blank" rel="noopener noreferrer">
<FaSlack />
@@ -32,7 +21,7 @@ function CustomFooter() {
<div className="footer-bottom">
<p>
<Translate id="footer.copyright" values={{ year: new Date().getFullYear() }}>
{'Copyright © {year} OpenHands'}
{'Copyright © {year} All Hands AI, Inc'}
</Translate>
</p>
</div>
@@ -17,23 +17,19 @@ export function HomepageHeader() {
<p className="header-subtitle">{siteConfig.tagline}</p>
<div className="header-links">
<a href="https://github.com/All-Hands-AI/OpenHands">
<img src="https://img.shields.io/badge/Code-Github-purple?logo=github&logoColor=white&style=for-the-badge" alt="Code" />
</a>
<a href="https://join.slack.com/t/opendevin/shared_invite/zt-2oikve2hu-UDxHeo8nsE69y6T7yFX_BA">
<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>
<a href="https://discord.gg/ESHStjSjD4">
<img src="https://img.shields.io/badge/Discord-Join%20Us-purple?logo=discord&logoColor=white&style=for-the-badge" alt="Join our Discord community" />
</a>
<a href="https://arxiv.org/abs/2407.16741">
<img src="https://img.shields.io/badge/Paper-%20on%20Arxiv-red?logo=arxiv&style=for-the-badge" alt="Paper on Arxiv" />
</a>
<a href="https://huggingface.co/spaces/OpenDevin/evaluation">
<img src="https://img.shields.io/badge/Evaluation-Benchmark%20on%20HF%20Space-green?logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark" />
</a>
<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/opendevin/shared_invite/zt-2oikve2hu-UDxHeo8nsE69y6T7yFX_BA"><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>
<a href="https://discord.gg/ESHStjSjD4"><img src="https://img.shields.io/badge/Discord-Join%20Us-purple?logo=discord&logoColor=white&style=for-the-badge" alt="Join our Discord community" /></a>
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/CREDITS.md"><img src="https://img.shields.io/badge/Project-Credits-blue?style=for-the-badge&color=FFE165&logo=github&logoColor=white" alt="Credits" /></a>
<br/>
<a href="https://docs.all-hands.dev/modules/usage/getting-started"><img src="https://img.shields.io/badge/Documentation-000?logo=googledocs&logoColor=FFE165&style=for-the-badge" alt="Check out the documentation" /></a>
<a href="https://arxiv.org/abs/2407.16741"><img src="https://img.shields.io/badge/Paper%20on%20Arxiv-000?logoColor=FFE165&logo=arxiv&style=for-the-badge" alt="Paper on Arxiv" /></a>
<a href="https://huggingface.co/spaces/OpenHands/evaluation"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score" /></a>
</div>
<Demo />
+9 -13
View File
@@ -7,8 +7,10 @@
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #4465db;
--ifm-code-font-size: 95%;
--ifm-color-primary: #000;
--ifm-background-color: #F1EAE0;
--ifm-navbar-background-color: #F1EAE0;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
--secondary: #171717;
--secondary-dark: #0a0a0a;
@@ -17,21 +19,15 @@
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme="dark"] {
--ifm-color-primary: #4465db;
--ifm-color-primary: #FFF;
--ifm-background-color: #000;
--ifm-navbar-background-color: #000;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
--secondary: #737373;
--secondary-dark: #171717;
--secondary-light: #d4d4d4;
--secondary-light: #ccc;
}
.footer--dark {
background-image: linear-gradient(
140deg,
var(--secondary) 20%,
var(--secondary-light) 100%
);
}
.a {
article a, .a {
text-decoration: underline;
}
}
+9 -8
View File
@@ -2,13 +2,19 @@
.custom-footer {
background-color: dark;
color: white;
height: 200px;
color: #000;
height: 100px;
/* background: linear-gradient(to bottom, #1a1a1a, #1a1a1a); */
background: linear-gradient(to bottom, #1f2937, #000000);
background-color: #F1EAE0;
}
[data-theme="dark"] .custom-footer {
background-color: #000;
color: #fff;
}
.footer-content {
display: flex;
flex-direction: column;
@@ -47,7 +53,6 @@
}
.footer-community {
text-transform: uppercase;
font-weight: 300;
}
@@ -65,7 +70,3 @@
.footer-icons a:hover {
color: white;
}
.footer-bottom {
text-transform: uppercase;
}
-2
View File
@@ -2,8 +2,6 @@
.homepage-header {
height: 800px;
color: white;
background: linear-gradient(to top, #64748b, #000000);
}
.header-content {
+1 -2
View File
@@ -20,8 +20,7 @@ export default function Home(): JSX.Element {
title={`${siteConfig.title}`}
description={translate({
id: 'homepage.description',
message: 'An Open Platform for AI Software Developers as Generalist Agents',
description: 'The homepage description',
message: 'Code Less, Make More',
})}
>
<HomepageHeader />
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+3 -3
View File
@@ -9,7 +9,7 @@ To better organize the evaluation folder, we should follow the rules below:
- Each subfolder contains a specific benchmark or experiment. For example, `evaluation/swe_bench` should contain
all the preprocessing/evaluation/analysis scripts.
- Raw data and experimental records should not be stored within this repo.
- For model outputs, they should be stored at [this huggingface space](https://huggingface.co/spaces/OpenDevin/evaluation) for visualization.
- For model outputs, they should be stored at [this huggingface space](https://huggingface.co/spaces/OpenHands/evaluation) for visualization.
- Important data files of manageable size and analysis scripts (e.g., jupyter notebooks) can be directly uploaded to this repo.
## Supported Benchmarks
@@ -69,8 +69,8 @@ temperature = 0.0
### Result Visualization
Check [this huggingface space](https://huggingface.co/spaces/OpenDevin/evaluation) for visualization of existing experimental results.
Check [this huggingface space](https://huggingface.co/spaces/OpenHands/evaluation) for visualization of existing experimental results.
### Upload your results
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenDevin/evaluation) and submit a PR of your evaluation results to our hosted huggingface repo via PR following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation) and submit a PR of your evaluation results to our hosted huggingface repo via PR following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
+1
View File
@@ -256,6 +256,7 @@ def process_instance(
if __name__ == '__main__':
args = parse_arguments()
dataset = load_dataset('RajMaheshwari/Exercism-Python')
dataset = dataset.shuffle(seed=42)
aider_bench_tests = dataset['train'].to_pandas()
llm_config = None
@@ -49,4 +49,4 @@ fact8
facts.Smart(Dave, True)
facts.Kind(Dave, True)
assert
facts.Quiet(Dave, True)
facts.Quiet(Dave, True)
+1 -1
View File
@@ -52,7 +52,7 @@ def get_config(
base_container_image='xingyaoww/od-eval-logic-reasoning:v1.0',
enable_auto_lint=True,
use_host_network=False,
runtime_extra_deps='$OD_INTERPRETER_PATH -m pip install scitools-pyke',
runtime_extra_deps='$OH_INTERPRETER_PATH -m pip install scitools-pyke',
),
# do not mount workspace
workspace_base=None,
+1 -1
View File
@@ -26,7 +26,7 @@ poetry run python evaluation/miniwob/get_success_rate.py evaluation/evaluation_o
## Submit your evaluation results
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenDevin/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
## BrowsingAgent V1.0 result
+1 -1
View File
@@ -105,7 +105,7 @@ def get_config(
base_container_image='xingyaoww/od-eval-mint:v1.0',
enable_auto_lint=True,
use_host_network=False,
runtime_extra_deps=f'$OD_INTERPRETER_PATH -m pip install {" ".join(MINT_DEPENDENCIES)}',
runtime_extra_deps=f'$OH_INTERPRETER_PATH -m pip install {" ".join(MINT_DEPENDENCIES)}',
),
# do not mount workspace
workspace_base=None,
+2 -2
View File
@@ -14,9 +14,9 @@ To run the tests for OpenHands project, you can use the provided test runner scr
3. Navigate to the root directory of the project.
4. Run the test suite using the test runner script with the required arguments:
```
python evaluation/regression/run_tests.py --OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxx --model=gpt-3.5-turbo
python evaluation/regression/run_tests.py --OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxx --model=gpt-4o
```
Replace `sk-xxxxxxxxxxxxxxxxxxxxxx` with your actual OpenAI API key. The default model is `gpt-3.5-turbo`, but you can specify a different model if needed.
Replace `sk-xxxxxxxxxxxxxxxxxxxxxx` with your actual OpenAI API key. The default model is `gpt-4o`, but you can specify a different model if needed.
The test runner will discover and execute all the test cases in the `cases/` directory, and display the results of the test suite, including the status of each individual test case and the overall summary.
@@ -29,21 +29,27 @@ if __name__ == '__main__':
if command == 'reverse':
from commands.reverse import reverse_string
print(reverse_string(input_string))
elif command == 'uppercase':
from commands.uppercase import to_uppercase
print(to_uppercase(input_string))
elif command == 'lowercase':
from commands.lowercase import to_lowercase
print(to_lowercase(input_string))
elif command == 'spongebob':
from commands.spongebob import spongebob_case
print(spongebob_case(input_string))
elif command == 'length':
from commands.length import string_length
print(string_length(input_string))
elif command == 'scramble':
from commands.scramble import scramble_string
print(scramble_string(input_string))
else:
print('Invalid command!')
@@ -10,21 +10,27 @@ if __name__ == '__main__':
if command == 'reverse':
from commands.reverse import reverse_string
print(reverse_string(input_string))
elif command == 'uppercase':
from commands.uppercase import to_uppercase
print(to_uppercase(input_string))
elif command == 'lowercase':
from commands.lowercase import to_lowercase
print(to_lowercase(input_string))
elif command == 'spongebob':
from commands.spongebob import spongebob_case
print(spongebob_case(input_string))
elif command == 'length':
from commands.length import string_length
print(string_length(input_string))
elif command == 'scramble':
from commands.scramble import scramble_string
print(scramble_string(input_string))
else:
print('Invalid command!')
+38 -10
View File
@@ -24,7 +24,7 @@ This is now the default behavior.
Make sure your Docker daemon is running, and you have ample disk space (at least 200-500GB, depends on the SWE-Bench set you are running on) for the [instance-level docker image](#openhands-swe-bench-instance-level-docker-support).
When the `run_infer.sh` script is started, it will automatically pull the relavant SWE-Bench images. For example, for instance ID `django_django-11011`, it will try to pull our pre-build docker image `sweb.eval.x86_64.django_s_django-11011` from DockerHub. This image will be used create an OpenHands runtime image where the agent will operate on.
When the `run_infer.sh` script is started, it will automatically pull the relevant SWE-Bench images. For example, for instance ID `django_django-11011`, it will try to pull our pre-build docker image `sweb.eval.x86_64.django_s_django-11011` from DockerHub. This image will be used create an OpenHands runtime image where the agent will operate on.
```bash
./evaluation/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
@@ -63,11 +63,22 @@ then your command would be:
./evaluation/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 10
```
**Evaluate on `RemoteRuntime` (alpha)** (contact Xingyao over slack if you want to try this out!)
### Run Inference on `RemoteRuntime` (experimental)
This is in limited beta. Contact Xingyao over slack if you want to try this out!
```bash
SANDBOX_API_KEY="CONTACT-XINGYAO-TO-GET-A-TESTING-API-KEY" RUNTIME=remote EVAL_DOCKER_IMAGE_PREFIX="us-docker.pkg.dev/evaluation-428620/swe-bench-images" ./evaluation/swe_bench/scripts/run_infer.sh llm.eval HEAD CodeActAgent 300
# ./evaluation/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
ALLHANDS_API_KEY="YOUR-API-KEY" RUNTIME=remote EVAL_DOCKER_IMAGE_PREFIX="us-docker.pkg.dev/evaluation-428620/swe-bench-images" \
./evaluation/swe_bench/scripts/run_infer.sh llm.eval HEAD CodeActAgent 300 30 16 "princeton-nlp/SWE-bench_Lite" test
# This example runs evaluation on CodeActAgent for 300 instances on "princeton-nlp/SWE-bench_Lite"'s test set, with max 30 iteration per instances, with 16 number of workers running in parallel
```
To clean-up all existing runtime you've already started, run:
```bash
ALLHANDS_API_KEY="YOUR-API-KEY" ./evaluation/swe_bench/scripts/cleanup_remote_runtime.sh
```
Multi-processing is still WIP.
### Specify a subset of tasks to run infer
@@ -114,7 +125,7 @@ With `output.jsonl` file, you can run `eval_infer.sh` to evaluate generated patc
> If you want to evaluate existing results, you should first run this to clone existing outputs
>```bash
>git clone https://huggingface.co/spaces/OpenDevin/evaluation evaluation/evaluation_outputs
>git clone https://huggingface.co/spaces/OpenHands/evaluation evaluation/evaluation_outputs
>```
NOTE, you should have already pulled the instance-level OR env-level docker images following [this section](#openhands-swe-bench-instance-level-docker-support).
@@ -146,12 +157,29 @@ The final results will be saved to `evaluation/evaluation_outputs/outputs/swe_be
- `report.json`: a JSON file that contains keys like `"resolved_ids"` pointing to instance IDs that are resolved by the agent.
- `logs/`: a directory of test logs
## Visualize Results
### Run evaluation with `RemoteRuntime` (experimental)
First you need to clone `https://huggingface.co/spaces/OpenDevin/evaluation` and add your own running results from openhands into the `outputs` of the cloned repo.
This is in limited beta. Contact Xingyao over slack if you want to try this out!
```bash
git clone https://huggingface.co/spaces/OpenDevin/evaluation
# ./evaluation/swe_bench/scripts/eval_infer_remote.sh [output.jsonl filepath] [num_workers]
ALLHANDS_API_KEY="YOUR-API-KEY" RUNTIME=remote EVAL_DOCKER_IMAGE_PREFIX="us-docker.pkg.dev/evaluation-428620/swe-bench-images" evaluation/swe_bench/scripts/eval_infer_remote.sh evaluation/outputs/swe_bench_lite/CodeActAgent/Llama-3.1-70B-Instruct-Turbo_maxiter_30_N_v1.9-no-hint/output.jsonl 16 "princeton-nlp/SWE-bench_Lite" "test"
# This example evaluate patches generated by CodeActAgent on Llama-3.1-70B-Instruct-Turbo on "princeton-nlp/SWE-bench_Lite"'s test set, with 16 number of workers running in parallel
```
To clean-up all existing runtimes that you've already started, run:
```bash
ALLHANDS_API_KEY="YOUR-API-KEY" ./evaluation/swe_bench/scripts/cleanup_remote_runtime.sh
```
## Visualize Results
First you need to clone `https://huggingface.co/spaces/OpenHands/evaluation` and add your own running results from openhands into the `outputs` of the cloned repo.
```bash
git clone https://huggingface.co/spaces/OpenHands/evaluation
```
**(optional) setup streamlit environment with conda**:
@@ -168,11 +196,11 @@ Then, in a separate Python environment with `streamlit` library, you can run the
```bash
# Make sure you are inside the cloned `evaluation` repo
conda activate streamlit # if you follow the optional conda env setup above
streamlit run 0_📊_OpenHands_Benchmark.py --server.port 8501 --server.address 0.0.0.0
streamlit app.py --server.port 8501 --server.address 0.0.0.0
```
Then you can access the SWE-Bench trajectory visualizer at `localhost:8501`.
## Submit your evaluation results
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenDevin/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
+376
View File
@@ -0,0 +1,376 @@
import os
import tempfile
import time
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 evaluation.swe_bench.run_infer import get_instance_docker_image
from evaluation.utils.shared import (
EvalMetadata,
EvalOutput,
prepare_dataset,
reset_logger_for_multiprocessing,
run_evaluation,
)
from openhands.core.config import (
AppConfig,
SandboxConfig,
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
# 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(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.'
)
config = AppConfig(
run_as_openhands=False,
runtime=os.environ.get('RUNTIME', 'eventstream'),
sandbox=SandboxConfig(
base_container_image=base_container_image,
use_host_network=False,
# large enough timeout, since some testcases take very long to run
timeout=1800,
api_key=os.environ.get('ALLHANDS_API_KEY', None),
),
# do not mount workspace
workspace_base=None,
workspace_mount_path=None,
)
return config
def process_instance(
instance: pd.Series,
metadata: EvalMetadata | None = None,
reset_logger: bool = True,
) -> EvalOutput:
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
if reset_logger:
global output_file
log_dir = output_file.replace('.jsonl', '.logs')
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(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'],
)
runtime = create_runtime(config, sid=instance_id)
# 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.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, keep_prompt=False)
action.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
try:
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'],
)
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 $!', keep_prompt=False
)
action.timeout = 60 # 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 $?', keep_prompt=False
)
check_action.timeout = 60
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}', keep_prompt=False)
cat_action.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)
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)
_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'
]
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'],
)
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.'
predictions = pd.read_json(args.input_file, lines=True)
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['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)
run_evaluation(
instances,
metadata=None,
output_file=output_file,
num_workers=args.eval_num_workers,
process_instance_func=process_instance,
)
# 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]
for field in fields:
count = evaluated_predictions.apply(
count_report_field, args=(field,), axis=1
).sum()
logger.info(
f'# {field}: {count} / {len(evaluated_predictions)}. ({count / len(evaluated_predictions):.2%})'
)
+26 -17
View File
@@ -2,7 +2,6 @@ import asyncio
import json
import os
import tempfile
import time
from typing import Any
import pandas as pd
@@ -26,13 +25,14 @@ from openhands.core.config import (
SandboxConfig,
get_llm_config_arg,
get_parser,
load_from_env,
)
from openhands.core.logger import openhands_logger as logger
from openhands.core.main import create_runtime, run_controller
from openhands.events.action import CmdRunAction
from openhands.events.observation import CmdOutputObservation, ErrorObservation
from openhands.events.serialization.event import event_to_dict
from openhands.runtime.runtime import Runtime
from openhands.runtime.utils.shutdown_listener import sleep_if_should_continue
USE_HINT_TEXT = os.environ.get('USE_HINT_TEXT', 'false').lower() == 'true'
USE_INSTANCE_IMAGE = os.environ.get('USE_INSTANCE_IMAGE', 'false').lower() == 'true'
@@ -123,26 +123,19 @@ def get_config(
run_as_openhands=False,
max_budget_per_task=4,
max_iterations=metadata.max_iterations,
runtime=os.environ.get('RUNTIME', 'eventstream'),
sandbox=SandboxConfig(
base_container_image=base_container_image,
enable_auto_lint=True,
use_host_network=False,
# large enough timeout, since some testcases take very long to run
timeout=300,
api_key=os.environ.get('ALLHANDS_API_KEY', None),
),
# do not mount workspace
workspace_base=None,
workspace_mount_path=None,
)
selected_env_vars = {'runtime', 'sandbox_api_key'}
selected_env_vars = {
k: v for k, v in os.environ.items() if k.lower() in selected_env_vars
}
if selected_env_vars:
logger.info(
f'Loading config keys from env vars: {list(selected_env_vars.keys())}'
)
load_from_env(config, selected_env_vars)
config.set_llm_config(metadata.llm_config)
return config
@@ -165,12 +158,14 @@ def initialize_runtime(
action = CmdRunAction(
command=f"""echo 'export SWE_INSTANCE_ID={instance['instance_id']}' >> ~/.bashrc && echo 'export PIP_CACHE_DIR=~/.cache/pip' >> ~/.bashrc && echo "alias git='git --no-pager'" >> ~/.bashrc"""
)
action.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
action = CmdRunAction(command="""export USER=$(whoami); echo USER=${USER} """)
action.timeout = 600
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
@@ -182,6 +177,7 @@ def initialize_runtime(
# inject the instance info
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
action.timeout = 600
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
@@ -209,18 +205,21 @@ def initialize_runtime(
'/swe_util/',
)
action = CmdRunAction(command='cat ~/.bashrc')
action.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
action = CmdRunAction(command='source ~/.bashrc')
action.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
action = CmdRunAction(command='source /swe_util/instance_swe_entry.sh')
action.timeout = 3600
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
@@ -236,12 +235,14 @@ def initialize_runtime(
), f'Failed to source /swe_util/swe_entry.sh: {obs.content}'
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
action.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
action = CmdRunAction(command='git reset --hard')
action.timeout = 600
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
@@ -250,6 +251,7 @@ def initialize_runtime(
action = CmdRunAction(
command='for remote_name in $(git remote); do git remote remove "${remote_name}"; done'
)
action.timeout = 600
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
@@ -277,18 +279,21 @@ def complete_runtime(
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
action.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
action = CmdRunAction(command='git config --global core.pager ""')
action.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
action = CmdRunAction(command='git add -A')
action.timeout = 600
logger.info(action, extra={'msg_type': 'ACTION'})
obs = runtime.run_action(action)
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
@@ -312,10 +317,10 @@ def complete_runtime(
break
else:
logger.info('Failed to get git diff, retrying...')
time.sleep(10)
sleep_if_should_continue(10)
elif isinstance(obs, ErrorObservation):
logger.error(f'Error occurred: {obs.content}. Retrying...')
time.sleep(10)
sleep_if_should_continue(10)
else:
raise ValueError(f'Unexpected observation type: {type(obs)}')
@@ -379,10 +384,7 @@ def process_instance(
if state is None:
raise ValueError('State should not be None.')
# 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 = state.history.compatibility_for_eval_history_pairs()
histories = [event_to_dict(event) for event in state.history.get_events()]
metrics = state.metrics.get() if state.metrics else None
# Save the output
@@ -394,6 +396,7 @@ def process_instance(
metadata=metadata,
history=histories,
metrics=metrics,
llm_completions=state.extra_data.get('llm_completions', []),
error=state.last_error if state and state.last_error else None,
)
return output
@@ -464,6 +467,12 @@ if __name__ == '__main__':
output_file = os.path.join(metadata.eval_output_dir, 'output.jsonl')
instances = prepare_dataset(swe_bench_tests, output_file, args.eval_n_limit)
if len(instances) > 0 and not isinstance(
instances['PASS_TO_PASS'][instances['PASS_TO_PASS'].index[0]], str
):
for col in ['PASS_TO_PASS', 'FAIL_TO_PASS']:
instances[col] = instances[col].apply(lambda x: str(x))
run_evaluation(
instances, metadata, output_file, args.eval_num_workers, process_instance
)
@@ -0,0 +1,27 @@
#!/bin/bash
# API base URL
BASE_URL="https://api.all-hands.dev/v0"
# Get the list of runtimes
response=$(curl --silent --location --request GET "${BASE_URL}/runtime/list" \
--header "X-API-Key: ${ALLHANDS_API_KEY}")
n_runtimes=$(echo $response | jq -r '.total')
echo "Found ${n_runtimes} runtimes. Stopping them..."
runtime_ids=$(echo $response | jq -r '.runtimes | .[].runtime_id')
# Loop through each runtime and stop it
counter=1
for runtime_id in $runtime_ids; do
echo "Stopping runtime ${counter}/${n_runtimes}: ${runtime_id}"
curl --silent --location --request POST "${BASE_URL}/runtime/stop" \
--header "X-API-Key: ${ALLHANDS_API_KEY}" \
--header "Content-Type: application/json" \
--data-raw "{\"runtime_id\": \"${runtime_id}\"}"
echo
((counter++))
done
echo "All runtimes have been stopped."
@@ -1,63 +0,0 @@
import argparse
import os
import pandas as pd
parser = argparse.ArgumentParser()
parser.add_argument('od_output_file', type=str)
args = parser.parse_args()
output_filepath = args.od_output_file.replace('.jsonl', '.swebench.jsonl')
print(f'Converting {args.od_output_file} to {output_filepath}')
od_format = pd.read_json(args.od_output_file, orient='records', lines=True)
# model name is the folder name of od_output_file
model_name = os.path.basename(os.path.dirname(args.od_output_file))
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 convert_row_to_swebench_format(row):
if 'git_patch' in row:
model_patch = row['git_patch']
elif 'test_result' in row and 'git_patch' in row['test_result']:
model_patch = row['test_result']['git_patch']
else:
raise ValueError(f'Row {row} does not have a git_patch')
return {
'instance_id': row['instance_id'],
'model_patch': process_git_patch(model_patch),
'model_name_or_path': model_name,
}
swebench_format = od_format.apply(convert_row_to_swebench_format, axis=1)
swebench_format.to_json(output_filepath, lines=True, orient='records')
@@ -0,0 +1,35 @@
import argparse
import os
import pandas as pd
from evaluation.swe_bench.eval_infer import process_git_patch
parser = argparse.ArgumentParser()
parser.add_argument('oh_output_file', type=str)
args = parser.parse_args()
output_filepath = args.oh_output_file.replace('.jsonl', '.swebench.jsonl')
print(f'Converting {args.oh_output_file} to {output_filepath}')
oh_format = pd.read_json(args.oh_output_file, orient='records', lines=True)
# model name is the folder name of oh_output_file
model_name = os.path.basename(os.path.dirname(args.oh_output_file))
def convert_row_to_swebench_format(row):
if 'git_patch' in row:
model_patch = row['git_patch']
elif 'test_result' in row and 'git_patch' in row['test_result']:
model_patch = row['test_result']['git_patch']
else:
raise ValueError(f'Row {row} does not have a git_patch')
return {
'instance_id': row['instance_id'],
'model_patch': process_git_patch(model_patch),
'model_name_or_path': model_name,
}
swebench_format = oh_format.apply(convert_row_to_swebench_format, axis=1)
swebench_format.to_json(output_filepath, lines=True, orient='records')
@@ -0,0 +1,27 @@
import argparse
import pandas as pd
from datasets import load_dataset
parser = argparse.ArgumentParser()
parser.add_argument('output_filepath', type=str, help='Path to save the output file')
parser.add_argument(
'--dataset_name',
type=str,
help='Name of the dataset to download',
default='princeton-nlp/SWE-bench_Lite',
)
parser.add_argument('--split', type=str, help='Split to download', default='test')
args = parser.parse_args()
dataset = load_dataset(args.dataset_name, split=args.split)
output_filepath = args.output_filepath
print(
f'Downloading gold patches from {args.dataset_name} (split: {args.split}) to {output_filepath}'
)
patches = [
{'instance_id': row['instance_id'], 'model_patch': row['patch']} for row in dataset
]
print(f'{len(patches)} gold patches loaded')
pd.DataFrame(patches).to_json(output_filepath, lines=True, orient='records')
print(f'Patches saved to {output_filepath}')
+4 -4
View File
@@ -28,9 +28,9 @@ FILE_NAME=$(basename $PROCESS_FILEPATH)
echo "Evaluating $FILE_NAME @ $FILE_DIR"
# ================================================
# detect whether PROCESS_FILEPATH is in OD format or in SWE-bench format
# detect whether PROCESS_FILEPATH is in OH format or in SWE-bench format
echo "=============================================================="
echo "Detecting whether PROCESS_FILEPATH is in OD format or in SWE-bench format"
echo "Detecting whether PROCESS_FILEPATH is in OH format or in SWE-bench format"
echo "=============================================================="
# SWE-bench format is a JSONL where every line has three fields: model_name_or_path, instance_id, and model_patch
function is_swebench_format() {
@@ -56,9 +56,9 @@ if [ $IS_SWEBENCH_FORMAT -eq 0 ]; then
else
echo "The file IS NOT in SWE-bench format."
# ==== Convert OD format to SWE-bench format ====
# ==== Convert OH format to SWE-bench format ====
echo "Merged output file with fine-grained report will be saved to $FILE_DIR"
poetry run python3 evaluation/swe_bench/scripts/eval/convert_od_output_to_swe_json.py $PROCESS_FILEPATH
poetry run python3 evaluation/swe_bench/scripts/eval/convert_oh_output_to_swe_json.py $PROCESS_FILEPATH
# replace .jsonl with .swebench.jsonl in filename
SWEBENCH_FORMAT_JSONL=${PROCESS_FILEPATH/.jsonl/.swebench.jsonl}
echo "SWEBENCH_FORMAT_JSONL: $SWEBENCH_FORMAT_JSONL"
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
set -eo pipefail
INPUT_FILE=$1
NUM_WORKERS=$2
DATASET=$3
SPLIT=$4
if [ -z "$INPUT_FILE" ]; then
echo "INPUT_FILE not specified (should be a path to a jsonl file)"
exit 1
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 "$SPLIT" ]; then
echo "SPLIT not specified, use default test"
SPLIT="test"
fi
if [ -z "$NUM_WORKERS" ]; then
echo "NUM_WORKERS not specified, use default 1"
NUM_WORKERS=1
fi
echo "... Evaluating on $INPUT_FILE ..."
COMMAND="poetry run python evaluation/swe_bench/eval_infer.py \
--eval-num-workers $NUM_WORKERS \
--input-file $INPUT_FILE \
--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
@@ -66,6 +66,11 @@ if [ "$USE_HINT_TEXT" = false ]; then
EVAL_NOTE="$EVAL_NOTE-no-hint"
fi
if [ -n "$EXP_NAME" ]; then
EVAL_NOTE="$EVAL_NOTE-$EXP_NAME"
fi
echo "EVAL_NOTE: $EVAL_NOTE"
unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
COMMAND="poetry run python evaluation/swe_bench/run_infer.py \
@@ -19,10 +19,10 @@ def extract_modified_files(patch):
return modified_files
def process_report(od_output_file):
def process_report(oh_output_file):
succ = 0
fail = 0
for line in open(od_output_file):
for line in open(oh_output_file):
line = json.loads(line)
instance_id = line['instance_id']
gold_patch = line['swe_instance']['patch']
@@ -48,7 +48,7 @@ def process_report(od_output_file):
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--od_output_file', help='Path to the OD output file')
parser.add_argument('--oh_output_file', help='Path to the OH output file')
args = parser.parse_args()
process_report(args.od_output_file)
process_report(args.oh_output_file)
@@ -6,15 +6,15 @@ mkdir -p $EVAL_WORKSPACE
# 1. Prepare REPO
echo "==== Prepare SWE-bench repo ===="
OD_SWE_BENCH_REPO_PATH="https://github.com/All-Hands-AI/OD-SWE-bench.git"
OD_SWE_BENCH_REPO_BRANCH="eval"
git clone -b $OD_SWE_BENCH_REPO_BRANCH $OD_SWE_BENCH_REPO_PATH $EVAL_WORKSPACE/OD-SWE-bench
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/OD-SWE-bench/swebench/harness/prepare_data.sh
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
@@ -24,4 +24,4 @@ docker run \
-u $(id -u):$(id -g) \
-e HF_DATASETS_CACHE="/tmp" \
--rm -it $EVAL_IMAGE \
bash -c "cd OD-SWE-bench/swebench/harness && /swe_util/miniforge3/bin/conda run -n swe-bench-eval ./prepare_data.sh && mv eval_data /workspace/"
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/"
@@ -60,7 +60,7 @@ 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/OD-SWE-bench
SWE_BENCH_DIR=/swe_util/OH-SWE-bench
output=$(
export PYTHONPATH=$SWE_BENCH_DIR && \
cd $SWE_BENCH_DIR && \
+114 -41
View File
@@ -5,8 +5,8 @@ import os
import pathlib
import subprocess
import time
from concurrent.futures import ProcessPoolExecutor
from typing import Any, Awaitable, Callable
import traceback
from typing import Any, Awaitable, Callable, TextIO
import pandas as pd
from pydantic import BaseModel
@@ -49,15 +49,20 @@ class EvalMetadata(BaseModel):
class EvalOutput(BaseModel):
# NOTE: User-specified
instance_id: str
instruction: str
# output of the evaluation
# store anything that is needed for the score calculation
test_result: dict[str, Any]
instruction: str | None = None
# Interaction info
metadata: EvalMetadata
history: list[tuple[dict[str, Any], dict[str, Any]]]
metrics: dict[str, Any]
metadata: EvalMetadata | None = None
# list[tuple[dict[str, Any], dict[str, Any]]] - for compatibility with the old format
history: (
list[dict[str, Any]] | list[tuple[dict[str, Any], dict[str, Any]]] | None
) = None
llm_completions: list[dict[str, Any]]
metrics: dict[str, Any] | None = None
error: str | None = None
# Optionally save the input test instance
@@ -65,15 +70,19 @@ class EvalOutput(BaseModel):
def model_dump(self, *args, **kwargs):
dumped_dict = super().model_dump(*args, **kwargs)
# Remove None values
dumped_dict = {k: v for k, v in dumped_dict.items() if v is not None}
# Apply custom serialization for metadata (to avoid leaking sensitive information)
dumped_dict['metadata'] = self.metadata.model_dump()
if self.metadata is not None:
dumped_dict['metadata'] = self.metadata.model_dump()
return dumped_dict
def model_dump_json(self, *args, **kwargs):
dumped = super().model_dump_json(*args, **kwargs)
dumped_dict = json.loads(dumped)
# Apply custom serialization for metadata (to avoid leaking sensitive information)
dumped_dict['metadata'] = json.loads(self.metadata.model_dump_json())
if 'metadata' in dumped_dict:
dumped_dict['metadata'] = json.loads(self.metadata.model_dump_json())
return json.dumps(dumped_dict)
@@ -227,56 +236,120 @@ def prepare_dataset(
return pd.DataFrame(new_dataset)
def update_progress(
result: EvalOutput,
pbar: tqdm,
output_fp: TextIO,
):
"""Update the progress bar and write the result to the output file."""
pbar.update(1)
pbar.set_description(f'Instance {result.instance_id}')
pbar.set_postfix_str(f'Test Result: {result.test_result}')
logger.info(
f'Finished evaluation for instance {result.instance_id}: {str(result.test_result)[:300]}...\n'
)
output_fp.write(json.dumps(result.model_dump()) + '\n')
output_fp.flush()
def _process_instance_wrapper(
process_instance_func: Callable[[pd.Series, EvalMetadata, bool], EvalOutput],
instance: pd.Series,
metadata: EvalMetadata,
use_mp: bool,
max_retries: int = 5,
) -> EvalOutput:
"""Wrap the process_instance_func to handle retries and errors.
Retry an instance up to max_retries times if it fails (e.g., due to transient network/runtime issues).
"""
for attempt in range(max_retries + 1):
try:
result = process_instance_func(instance, metadata, use_mp)
return result
except Exception as e:
error = str(e)
stacktrace = traceback.format_exc()
if attempt == max_retries:
logger.exception(e)
msg = (
'-' * 10
+ '\n'
+ f'Error in instance [{instance.instance_id}]: {error}. Stacktrace:\n{stacktrace}'
+ '\n'
+ f'[Encountered after {max_retries} retries. Please check the logs and report the issue.]'
+ '-' * 10
)
# Raise an error after all retries & stop the evaluation
logger.exception(e)
raise RuntimeError(
f'Maximum error retries reached for instance {instance.instance_id}'
) from e
msg = (
'-' * 10
+ '\n'
+ f'Error in instance [{instance.instance_id}]: {error}. Stacktrace:\n{stacktrace}'
+ '\n'
+ '-' * 10
+ f'[The above error occurred. Retrying... (attempt {attempt + 1} of {max_retries})]'
+ '-' * 10
+ '\n'
)
logger.error(msg)
if use_mp:
print(msg) # use print to directly print to console
time.sleep(5)
def _process_instance_wrapper_mp(args):
"""Wrapper for multiprocessing, especially for imap_unordered."""
return _process_instance_wrapper(*args)
def run_evaluation(
dataset: pd.DataFrame,
metadata: EvalMetadata,
metadata: EvalMetadata | None,
output_file: str,
num_workers: int,
process_instance_func: Callable[
[pd.Series, EvalMetadata, bool], Awaitable[EvalOutput]
],
max_retries: int = 5, # number of retries for each instance
):
use_multiprocessing = num_workers > 1
logger.info(
f'Evaluation started with Agent {metadata.agent_class}:\n'
f'model {metadata.llm_config.model}, max iterations {metadata.max_iterations}.\n'
)
pbar = tqdm(total=len(dataset))
output_fp = open(output_file, 'a')
def update_progress(future):
pbar.update(1)
output: EvalOutput = future.result() if use_multiprocessing else future
pbar.set_description(f'Instance {output.instance_id}')
pbar.set_postfix_str(f'Test Result: {output.test_result}')
if metadata is not None:
logger.info(
f'Finished evaluation for instance {output.instance_id}: {str(output.test_result)[:300]}...\n'
f'Evaluation started with Agent {metadata.agent_class}:\n'
f'model {metadata.llm_config.model}, max iterations {metadata.max_iterations}.\n'
)
output_fp.write(json.dumps(output.model_dump()) + '\n')
output_fp.flush()
else:
logger.info(f'Evaluation started with {num_workers} workers.')
total_instances = len(dataset)
pbar = tqdm(total=total_instances, desc='Instances processed')
output_fp = open(output_file, 'a')
try:
if use_multiprocessing:
with ProcessPoolExecutor(num_workers) as executor:
futures = []
for _, instance in dataset.iterrows():
future = executor.submit(
process_instance_func,
instance,
metadata,
bool(num_workers > 1),
)
future.add_done_callback(update_progress)
futures.append(future)
for future in futures:
future.result()
# Use plain for loop for single process for easier debugging
with mp.Pool(num_workers) as pool:
args_iter = (
(process_instance_func, instance, metadata, True, max_retries)
for _, instance in dataset.iterrows()
)
results = pool.imap_unordered(_process_instance_wrapper_mp, args_iter)
for result in results:
update_progress(result, pbar, output_fp)
else:
assert num_workers == 1
for _, instance in dataset.iterrows():
output = process_instance_func(instance, metadata, False)
update_progress(output)
result = _process_instance_wrapper(
process_instance_func=process_instance_func,
instance=instance,
metadata=metadata,
use_mp=False,
max_retries=max_retries,
)
update_progress(result, pbar, output_fp)
except KeyboardInterrupt:
print('\nKeyboardInterrupt received. Cleaning up...\n')
+1 -1
View File
@@ -37,7 +37,7 @@ poetry run python evaluation/webarena/get_success_rate.py evaluation/evaluation_
## Submit your evaluation results
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenDevin/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
## BrowsingAgent V1.0 result
+539 -536
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -1,6 +1,6 @@
{
"name": "openhands-frontend",
"version": "0.9.1",
"version": "0.9.4",
"private": true,
"type": "module",
"engines": {
@@ -8,7 +8,7 @@
},
"dependencies": {
"@monaco-editor/react": "^4.6.0",
"@nextui-org/react": "^2.4.6",
"@nextui-org/react": "^2.4.8",
"@react-types/shared": "^3.24.1",
"@reduxjs/toolkit": "^2.2.7",
"@vitejs/plugin-react": "^4.3.1",
@@ -16,23 +16,23 @@
"@xterm/xterm": "^5.4.0",
"clsx": "^2.1.1",
"eslint-config-airbnb-typescript": "^18.0.0",
"i18next": "^23.14.0",
"i18next": "^23.15.1",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.6.1",
"jose": "^5.8.0",
"monaco-editor": "^0.51.0",
"jose": "^5.9.3",
"monaco-editor": "^0.52.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-highlight": "^0.15.0",
"react-hot-toast": "^2.4.1",
"react-i18next": "^15.0.1",
"react-i18next": "^15.0.2",
"react-icons": "^5.3.0",
"react-markdown": "^9.0.1",
"react-redux": "^9.1.2",
"react-syntax-highlighter": "^15.5.0",
"remark-gfm": "^4.0.0",
"tailwind-merge": "^2.5.2",
"vite": "^5.4.2",
"vite": "^5.4.7",
"web-vitals": "^3.5.2"
},
"scripts": {
@@ -64,8 +64,8 @@
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/node": "^22.5.2",
"@types/react": "^18.3.5",
"@types/node": "^22.6.1",
"@types/react": "^18.3.8",
"@types/react-dom": "^18.3.0",
"@types/react-highlight": "^0.12.8",
"@types/react-syntax-highlighter": "^15.5.13",
@@ -82,13 +82,13 @@
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2",
"husky": "^9.1.5",
"husky": "^9.1.6",
"jsdom": "^25.0.0",
"lint-staged": "^15.2.10",
"postcss": "^8.4.44",
"postcss": "^8.4.47",
"prettier": "^3.3.3",
"tailwindcss": "^3.4.10",
"typescript": "^5.5.4",
"tailwindcss": "^3.4.12",
"typescript": "^5.6.2",
"vite-tsconfig-paths": "^5.0.1",
"vitest": "^1.6.0"
},
Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 754 B

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

+31 -471
View File
@@ -1,472 +1,32 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1024.000000pt" height="1024.000000pt" viewBox="0 0 1024.000000 1024.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,1024.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M5195 8749 c-122 -19 -282 -101 -383 -197 -66 -61 -59 -81 52 -160
49 -34 99 -65 111 -68 16 -4 44 9 94 41 93 60 169 94 256 112 l70 14 82 -42
c46 -23 83 -44 83 -48 -1 -3 -34 -21 -74 -40 -217 -98 -499 -312 -667 -505
-138 -157 -309 -430 -309 -493 0 -38 66 -100 149 -140 42 -20 77 -38 79 -39 2
-1 -17 -32 -43 -70 -185 -277 -278 -669 -246 -1041 20 -245 61 -392 167 -612
35 -74 63 -135 62 -135 -2 -1 -30 -10 -62 -21 -38 -13 -67 -30 -79 -47 -19
-26 -19 -29 -3 -71 23 -61 101 -184 166 -262 99 -119 265 -247 425 -327 149
-75 397 -152 602 -188 l72 -13 -63 -67 c-139 -147 -205 -389 -139 -503 11 -18
40 -43 70 -58 50 -26 51 -28 33 -44 -11 -10 -40 -58 -66 -109 -77 -149 -235
-389 -267 -407 -17 -10 -269 -65 -352 -78 -38 -6 -115 -15 -169 -20 -74 -8
-107 -15 -128 -31 -21 -16 -47 -21 -110 -24 -61 -3 -121 -15 -223 -46 -77 -23
-153 -49 -168 -57 -16 -8 -52 -51 -84 -101 -31 -48 -69 -103 -85 -122 -54 -66
-31 -122 68 -159 47 -18 48 -19 18 -25 -49 -10 -352 -44 -694 -76 -314 -30
-326 -32 -347 -55 -19 -22 -31 -25 -85 -25 -91 0 -104 -12 -112 -103 -8 -94 3
-121 58 -142 23 -8 174 -56 336 -106 162 -50 445 -137 628 -195 183 -57 482
-149 665 -205 182 -55 367 -111 410 -125 43 -13 102 -24 130 -24 97 0 1501
180 1564 201 46 15 77 70 77 135 0 82 -43 130 -126 141 -24 4 -59 16 -78 29
-22 14 -129 46 -280 83 -135 34 -255 64 -268 67 -20 6 -16 10 30 31 29 13 63
34 75 45 22 21 24 21 122 5 124 -21 158 -21 217 -1 46 15 48 15 108 -13 64
-29 144 -37 231 -21 22 4 29 4 16 0 -24 -7 -23 -8 15 -19 68 -20 155 -35 169
-29 8 3 15 0 17 -6 3 -7 10 -8 17 -4 11 7 11 10 0 17 -10 6 -8 9 9 9 14 0 21
-4 16 -11 -4 -7 0 -9 14 -5 12 4 128 -13 259 -38 131 -25 362 -67 513 -95 815
-146 759 -135 707 -143 -27 -3 -51 -9 -54 -11 -2 -3 38 -12 89 -21 51 -10 125
-23 163 -31 98 -19 336 -53 420 -60 68 -5 69 -5 30 8 -22 7 -73 19 -114 27
-41 8 -70 15 -64 17 11 4 120 -12 607 -92 154 -25 281 -43 284 -40 8 7 -16 13
-153 39 -407 77 -958 186 -963 190 -8 8 15 135 48 268 46 182 103 350 221 643
144 360 219 605 288 936 69 337 104 670 99 964 -3 232 -6 241 -89 282 -50 25
-234 64 -414 88 -66 9 -134 18 -151 21 l-31 4 57 60 c233 242 426 579 505 884
14 55 30 105 35 112 23 27 71 180 78 247 4 40 3 110 -1 157 -11 105 -11 95 -2
210 5 73 3 111 -9 164 -31 131 -107 254 -204 328 -26 20 -42 40 -42 54 0 12
-27 74 -59 137 -204 399 -520 697 -963 912 -375 181 -795 278 -1268 292 -338
10 -691 -35 -972 -123 l-77 -25 -233 109 c-295 138 -320 146 -413 131z m107
-89 c20 -6 65 -24 100 -40 l63 -30 -65 6 c-68 6 -173 -10 -260 -41 -52 -18
-72 -32 -87 -59 -10 -18 -14 -14 -37 32 l-26 52 47 23 c68 34 154 60 213 66 8
0 32 -4 52 -9z m1843 -110 c448 -52 824 -167 1126 -343 307 -179 534 -393 691
-652 63 -102 101 -175 96 -181 -2 -2 -26 12 -52 31 -27 19 -64 39 -82 45 -19
7 -34 15 -34 18 -1 31 -32 148 -48 178 -32 63 -65 88 -105 80 -29 -5 -35 -3
-48 20 -8 15 -44 52 -81 83 -178 150 -544 337 -968 495 -129 48 -139 50 -235
50 -130 -1 -217 -23 -378 -96 -86 -40 -93 -59 -44 -126 41 -55 141 -152 157
-152 6 0 34 12 63 26 100 51 255 94 338 94 51 0 160 -42 324 -126 173 -88 320
-176 394 -236 l61 -49 -35 -30 c-19 -17 -38 -42 -41 -54 -3 -14 -16 -26 -32
-30 -63 -16 -56 -59 31 -192 l73 -110 -39 -44 c-53 -61 -138 -191 -180 -274
-64 -130 -120 -339 -134 -502 l-6 -72 -71 -11 c-39 -6 -87 -13 -107 -16 l-36
-5 -13 73 c-56 317 -249 568 -557 726 -254 130 -574 200 -1108 244 -339 27
-1062 15 -1363 -23 -46 -6 -85 -9 -88 -7 -6 7 63 131 124 220 365 540 1013
885 1797 958 120 11 484 5 610 -10z m-2169 -15 c20 -30 11 -81 -15 -88 -18 -4
-81 28 -81 41 0 6 70 70 77 72 2 0 10 -11 19 -25z m2662 -299 c67 -27 122 -52
122 -57 0 -12 -22 -7 -35 7 -5 6 -26 14 -45 17 -19 3 -44 9 -54 13 -14 5 -17
4 -12 -4 4 -7 2 -12 -3 -12 -6 0 -11 5 -11 11 0 6 -7 9 -15 6 -8 -4 -17 -2
-20 3 -3 5 -12 7 -20 4 -8 -4 -29 -1 -46 5 -24 8 -36 8 -45 0 -11 -9 -14 -8
-14 2 0 11 -2 11 -9 0 -6 -10 -30 -16 -68 -17 -32 -2 -58 -4 -58 -4 0 -1 -8
-3 -17 -5 -9 -2 -19 4 -22 12 -9 21 -29 4 -22 -19 2 -12 -1 -27 -9 -34 -18
-18 -25 -18 -25 1 0 9 -7 30 -16 46 -8 17 -13 34 -10 37 21 20 149 42 236 39
87 -2 105 -6 218 -51z m-478 -25 c17 -32 12 -61 -10 -61 -10 0 -23 -8 -29 -17
-9 -16 -12 -15 -40 11 -17 17 -31 33 -31 37 0 7 77 47 92 49 4 0 12 -9 18 -19z
m710 -76 c10 6 102 -34 112 -49 4 -6 8 -8 8 -4 0 4 13 2 30 -3 16 -6 28 -14
25 -19 -2 -4 8 -13 23 -20 22 -11 24 -14 9 -18 -21 -4 -47 14 -47 34 0 14 -73
14 -101 0 -8 -4 -5 -1 5 8 17 14 17 16 3 22 -9 3 -15 10 -12 14 3 5 -5 5 -17
2 -19 -5 -20 -7 -5 -10 20 -4 22 -17 5 -28 -7 -5 -8 -3 -3 6 6 10 4 12 -8 7
-9 -3 -23 1 -32 9 -8 8 -20 12 -26 8 -8 -4 -9 -3 -5 5 4 6 16 9 27 6 13 -4 19
-2 19 9 0 9 -5 15 -11 14 -6 -2 -13 3 -14 10 -2 7 -1 8 2 2 2 -5 8 -8 13 -5z
m384 -187 c-3 -4 -9 -8 -15 -8 -5 0 -9 4 -9 8 0 5 7 9 15 9 8 0 12 -4 9 -9z
m241 -144 c39 -28 83 -65 99 -82 l29 -31 -25 -6 c-40 -10 -61 -2 -79 30 -9 17
-37 51 -63 77 -25 26 -46 53 -46 58 0 6 -5 8 -12 4 -7 -4 -8 -3 -4 5 9 13 11
12 101 -55z m-61 -152 c7 -12 -101 -68 -111 -59 -11 12 58 66 84 67 12 0 24
-4 27 -8z m348 -64 l18 -48 -73 0 c-85 0 -150 -16 -246 -60 -68 -32 -95 -33
-84 -5 12 33 204 102 306 112 37 3 64 9 60 14 -10 9 -157 -14 -225 -37 -29 -9
-82 -32 -117 -50 -74 -39 -96 -41 -131 -13 l-25 21 36 -5 c25 -4 54 3 95 20
126 53 162 65 244 83 116 26 121 24 142 -32z m-24 -113 c-2 -3 -29 -9 -59 -15
-30 -6 -97 -31 -149 -56 -93 -45 -94 -45 -66 -15 32 34 111 68 182 80 59 10
99 13 92 6z m317 -219 c113 -53 219 -169 265 -292 18 -51 19 -59 6 -85 -8 -17
-10 -31 -5 -35 5 -3 13 5 18 18 8 19 9 16 9 -19 0 -22 3 -46 6 -52 4 -6 5 -11
3 -11 -2 0 -16 17 -30 39 -20 30 -23 41 -14 51 9 10 9 11 -3 8 -9 -3 -35 14
-63 39 -46 43 -156 103 -188 103 -9 0 -19 10 -23 23 -8 32 -60 144 -91 195
l-26 42 43 0 c24 0 65 -11 93 -24z m-250 -76 c41 -67 79 -166 70 -181 -4 -5
-12 -9 -18 -9 -31 0 -158 -72 -208 -118 -43 -39 -68 -74 -103 -144 -95 -192
-101 -405 -16 -586 18 -38 27 -69 22 -74 -16 -16 -88 -11 -134 10 -86 37 -172
152 -184 245 -4 26 -11 47 -17 47 -17 0 1 160 28 256 51 176 158 351 286 468
62 56 201 146 226 146 6 0 28 -27 48 -60z m-295 2 c0 -5 -34 -43 -75 -86 -41
-42 -96 -107 -122 -144 -39 -54 -49 -63 -51 -45 -10 67 166 283 230 283 10 0
18 -4 18 -8z m-3625 -38 c-42 -65 -90 -153 -129 -237 -35 -76 -41 -97 -34
-122 13 -48 0 -84 -38 -107 -19 -11 -34 -21 -34 -22 0 -1 -9 -42 -19 -91 -36
-162 -47 -318 -41 -525 3 -69 5 -55 11 75 11 230 41 363 78 341 5 -3 12 2 15
11 6 14 19 15 109 9 91 -6 142 -11 142 -16 0 -1 10 -3 22 -6 18 -3 27 4 44 37
11 23 22 39 24 37 2 -2 26 -69 53 -148 28 -80 73 -201 101 -270 62 -148 61
-145 67 -240 7 -93 -16 -250 -45 -310 -13 -26 -40 -59 -67 -79 -74 -56 -104
-68 -156 -64 -27 2 -48 -1 -48 -6 0 -5 -8 -11 -17 -13 -16 -3 -15 -7 8 -29 14
-14 32 -29 40 -32 12 -5 12 -7 -1 -16 -10 -7 -17 -6 -22 2 -6 9 -8 9 -8 -1 0
-10 -5 -10 -22 -1 -20 11 -22 11 -10 -3 10 -13 10 -18 1 -24 -8 -4 -9 -3 -5 4
6 11 2 13 -19 12 -3 0 -26 11 -50 26 -27 16 -54 24 -66 21 -18 -5 -28 10 -79
116 -68 142 -111 268 -142 411 -18 85 -22 134 -22 311 0 218 13 336 54 466 11
37 15 75 12 112 -5 67 14 107 52 107 20 0 31 13 62 73 42 81 75 136 112 185
18 23 32 32 54 32 l30 0 -17 -26z m1046 16 c27 -15 24 -24 -18 -71 -49 -54
-89 -78 -198 -119 -195 -72 -303 -179 -415 -411 -22 -46 -40 -78 -40 -72 0 9
-82 51 -115 58 -29 6 -46 19 -41 31 3 7 0 16 -6 20 -7 4 -8 3 -4 -4 7 -12 -6
-17 -17 -6 -18 18 122 230 222 336 113 121 235 201 352 232 63 17 251 21 280
6z m3039 -130 c0 -5 -8 -10 -17 -10 -15 0 -16 2 -3 10 19 12 20 12 20 0z
m-823 -221 c-35 -74 -69 -150 -77 -169 -21 -55 -30 -58 -30 -9 0 100 54 249
113 312 25 27 30 28 43 16 13 -13 7 -31 -49 -150z m952 138 c24 -12 59 -90 76
-166 l7 -34 -38 31 c-54 44 -114 62 -200 62 l-74 0 0 49 c0 48 1 49 38 59 53
14 163 14 191 -1z m-63 -219 c51 -45 74 -99 74 -175 0 -36 -4 -63 -10 -63 -5
0 -10 -9 -10 -19 0 -10 -6 -21 -14 -24 -11 -4 -13 -13 -7 -34 8 -28 -5 -73
-21 -73 -4 0 -7 -6 -5 -12 1 -7 -3 -12 -9 -11 -5 1 -16 -7 -23 -19 -10 -16
-10 -19 1 -12 10 6 10 4 -1 -9 -7 -9 -17 -14 -22 -12 -4 3 -15 -5 -24 -19 -29
-44 -108 -65 -185 -50 -70 14 -121 159 -99 280 29 159 148 283 271 284 39 0
54 -5 84 -32z m-961 -224 c0 -22 -5 -29 -20 -29 -24 0 -34 43 -13 56 21 14 33
4 33 -27z m-1195 -115 c22 -7 40 -16 40 -21 0 -4 6 -8 14 -8 8 0 33 -16 55
-34 71 -59 157 -204 180 -301 14 -60 19 -272 8 -335 -13 -71 -13 -72 -36 -125
-36 -80 -44 -95 -53 -95 -4 0 -8 -6 -8 -14 0 -8 -5 -18 -12 -22 -7 -5 -9 -2
-4 7 4 8 -1 4 -11 -8 -21 -25 -138 -85 -147 -76 -3 4 -6 1 -6 -5 0 -6 -7 -9
-15 -6 -8 4 -15 1 -15 -6 0 -6 -4 -9 -9 -6 -5 3 -26 8 -47 11 -137 20 -247 93
-274 180 -7 22 -19 53 -27 68 -8 16 -16 36 -18 45 -32 137 -36 169 -36 302 0
80 2 152 4 160 12 59 44 140 65 168 34 47 79 92 92 92 6 0 22 8 37 17 47 31
142 36 223 12z m1060 -98 c0 -38 9 -121 20 -184 35 -210 110 -369 229 -488
145 -144 299 -168 529 -83 116 43 296 135 334 172 46 43 43 18 -7 -70 -216
-375 -485 -627 -883 -827 -522 -262 -1255 -395 -1988 -360 -514 24 -883 122
-1173 312 -133 88 -278 228 -334 324 -4 6 39 -12 95 -41 275 -139 616 -208
953 -191 403 19 1003 133 1286 244 238 93 447 251 567 428 129 191 177 368
170 636 l-3 144 90 25 c50 14 96 26 103 27 8 1 12 -19 12 -68z m128 37 c14
-14 16 -94 3 -102 -30 -19 -56 28 -45 83 7 32 22 39 42 19z m1114 -185 c-6
-26 -14 -57 -18 -68 -6 -16 1 -13 36 14 45 33 45 33 -7 -17 -95 -91 -226 -131
-331 -103 l-43 12 22 37 c12 20 24 39 26 41 2 3 36 8 75 12 84 9 159 43 207
93 19 20 37 34 39 32 2 -3 -1 -26 -6 -53z m32 -158 c-4 -8 -10 -15 -16 -15 -5
0 -6 -6 -2 -12 4 -7 4 -10 -1 -6 -4 4 -16 -3 -26 -15 -16 -19 -18 -19 -12 -3
5 15 3 17 -8 11 -19 -11 -2 6 35 33 34 26 37 27 30 7z m-149 -88 c-11 -7 -35
-28 -54 -47 l-35 -35 20 34 c10 18 33 40 49 47 37 16 47 17 20 1z m-297 -84
c-60 -88 -154 -190 -165 -180 -4 4 14 29 39 55 25 26 71 82 102 125 73 100 93
100 24 0z m372 54 c0 -2 -19 -21 -42 -42 l-43 -40 40 43 c36 39 45 47 45 39z
m-215 -146 c3 -6 -4 -15 -15 -21 -20 -11 -21 -10 -10 9 12 23 16 25 25 12z
m-165 -41 c-11 -16 -26 -33 -33 -37 -12 -7 0 11 32 50 23 28 24 20 1 -13z
m-1221 -46 c9 -8 -102 -149 -183 -230 -206 -208 -417 -302 -876 -394 -340 -68
-617 -95 -885 -87 -217 6 -371 31 -539 87 -186 63 -464 202 -425 214 8 2 36
11 63 20 67 21 74 21 126 -15 120 -81 319 -161 504 -201 90 -20 129 -23 366
-22 297 0 442 15 747 79 484 101 758 245 945 496 l50 68 51 -6 c29 -3 54 -7
56 -9z m1341 -640 c104 -15 247 -40 285 -51 13 -4 -3 -12 -50 -25 -91 -25 -99
-25 -170 5 -33 14 -103 38 -155 52 -176 49 -154 53 90 19z m462 -132 c17 -65
0 -429 -33 -692 -57 -461 -173 -905 -341 -1309 -24 -58 -48 -106 -55 -108 -15
-5 -80 53 -98 88 -14 26 -12 37 35 170 28 78 49 146 48 151 -2 5 -25 -44 -52
-109 -27 -65 -93 -217 -146 -338 -54 -121 -103 -237 -111 -257 -14 -42 -17
-44 -43 -25 -17 13 -12 27 82 228 160 343 224 502 316 784 123 378 198 842
182 1120 -6 111 -28 229 -46 251 -12 13 17 27 90 43 113 26 166 27 172 3z
m-1252 -392 c63 -5 215 -10 336 -10 l222 0 7 -27 c3 -16 9 -131 12 -256 6
-245 -6 -401 -35 -449 -21 -36 -69 -58 -126 -58 -40 0 -46 3 -52 25 -3 14 -3
36 0 51 4 14 7 123 7 242 1 282 -18 394 -70 421 -10 6 -90 15 -177 21 -150 10
-240 27 -274 50 -12 8 -9 9 10 5 14 -2 77 -9 140 -15z m-275 -35 c241 -62 374
-242 375 -505 0 -115 -19 -144 -133 -199 -101 -50 -171 -69 -306 -82 -113 -11
-271 1 -340 26 -170 60 -231 160 -201 333 33 197 175 352 364 398 39 9 85 23
101 30 40 17 69 17 140 -1z m-1874 -81 l36 -6 -14 -41 c-9 -27 -12 -57 -8 -85
5 -33 3 -47 -9 -55 -8 -7 -24 -41 -36 -77 -12 -36 -36 -90 -54 -120 -18 -30
-41 -76 -51 -102 -16 -42 -21 -48 -47 -48 -45 0 -97 29 -115 63 -29 57 9 210
78 315 38 58 150 162 174 162 5 0 26 -3 46 -6z m126 -131 c10 -12 12 -13 8 -3
-4 8 1 6 10 -5 9 -11 19 -19 23 -18 4 2 15 0 25 -3 13 -4 15 -9 8 -18 -14 -17
-2 -29 15 -15 10 8 11 5 7 -12 -4 -15 -3 -20 5 -15 7 4 12 3 12 -2 0 -5 10
-12 22 -15 12 -4 20 -9 17 -12 -9 -8 -88 30 -105 51 -9 10 -13 13 -9 7 10 -22
-23 -3 -38 20 -18 28 -28 57 -20 57 3 0 12 -8 20 -17z m180 -74 c21 -8 24 -12
14 -19 -17 -10 -38 -3 -45 16 -6 17 -5 17 31 3z m724 -40 c-6 -24 -11 -78 -11
-120 l0 -76 -46 -36 c-180 -140 -693 -157 -854 -29 -53 43 -72 87 -66 149 6
53 25 106 35 101 3 -2 44 -22 91 -45 114 -57 238 -86 365 -86 160 -1 284 42
435 151 30 22 56 39 58 37 1 -1 -2 -22 -7 -46z m-711 -9 c-20 -13 -33 -13 -25
0 3 6 14 10 23 10 15 0 15 -2 2 -10z m-309 -254 c73 -120 247 -173 536 -163
222 8 391 54 495 137 28 23 38 27 46 17 14 -17 47 -143 63 -241 14 -87 38
-131 135 -242 29 -34 50 -64 47 -68 -3 -3 -1 -6 6 -6 6 0 28 -15 47 -32 33
-30 36 -37 31 -73 -7 -53 -15 -89 -33 -155 -25 -89 -24 -87 -34 -70 -6 8 -10
11 -10 5 0 -5 -12 4 -26 20 -14 17 -22 24 -19 17 4 -7 -31 14 -78 47 -161 116
-495 262 -714 312 -109 25 -337 36 -411 20 -75 -16 -140 -49 -159 -82 -10 -16
-21 -29 -25 -29 -28 0 -46 210 -29 330 18 118 77 301 98 300 4 0 20 -20 34
-44z m2441 -248 c74 -8 112 -8 159 1 33 7 64 10 67 6 16 -16 -161 -611 -192
-642 -28 -30 -107 -6 -121 37 -3 11 16 97 43 192 65 224 94 358 78 358 -6 0
-42 5 -79 10 -62 9 -93 24 -150 71 -5 3 16 0 45 -7 29 -8 97 -19 150 -26z
m-233 -47 c24 -18 23 -18 -120 -24 -86 -3 -202 -15 -289 -30 -156 -28 -310
-46 -310 -38 0 3 21 27 47 53 l47 48 91 0 c133 0 262 16 346 43 l74 23 45 -28
c25 -15 56 -36 69 -47z m-2433 51 c7 -5 8 -32 3 -82 -10 -104 4 -236 32 -300
18 -42 38 -65 96 -111 91 -72 88 -78 -3 -9 -113 87 -224 129 -336 130 l-47 0
74 110 c41 60 92 146 112 190 37 78 46 88 69 72z m2448 -162 l59 0 -6 -94
c-12 -175 -77 -427 -156 -600 l-31 -69 -28 53 c-63 125 -217 236 -362 262 -59
10 -186 0 -235 -18 -10 -4 -8 11 8 58 17 51 21 89 21 200 l1 138 45 5 c25 3
126 17 225 32 226 32 320 42 365 37 19 -2 62 -4 94 -4z m-1904 -334 c0 -88 24
-218 59 -316 l29 -83 -81 6 c-78 5 -84 7 -110 39 -60 71 -98 153 -104 227 -9
112 18 152 122 177 87 21 85 22 85 -50z m225 34 c141 -29 340 -116 488 -213
49 -33 73 -54 65 -58 -38 -21 -228 -50 -385 -60 -164 -9 -211 -16 -254 -34
-14 -5 -21 6 -37 57 -36 109 -42 141 -48 239 l-7 96 59 -7 c33 -4 86 -13 119
-20z m-969 -20 c42 -21 84 -70 103 -123 23 -61 2 -238 -31 -258 -48 -30 -558
-89 -558 -65 0 4 5 16 10 27 48 89 14 270 -62 323 -12 9 -20 17 -17 19 2 2 49
11 104 21 55 9 150 30 210 46 134 34 185 37 241 10z m-730 -164 c28 -9 63 -25
78 -37 24 -19 26 -27 26 -92 0 -40 -5 -89 -10 -109 -30 -106 -187 -190 -249
-134 -12 11 -21 25 -21 33 0 7 31 46 69 85 l69 73 -42 2 c-22 1 -65 5 -93 8
l-53 6 0 49 c0 68 -24 94 -84 95 -25 0 -46 1 -46 2 0 5 48 27 75 34 46 12 223
2 281 -15z m204 -18 c15 -24 20 -49 19 -93 l-2 -60 -7 67 c-3 36 -14 78 -23
92 -10 14 -15 26 -12 26 3 0 14 -15 25 -32z m1049 -164 c17 -28 31 -54 31 -57
0 -3 -15 -8 -32 -12 -18 -4 -68 -22 -110 -41 -43 -18 -115 -43 -160 -54 -45
-11 -92 -29 -103 -40 -12 -11 -31 -20 -43 -20 -24 0 -303 48 -308 53 -2 2 36
9 84 15 193 26 356 84 439 156 23 20 61 66 84 102 l43 65 21 -58 c12 -32 36
-81 54 -109z m-1776 111 c-12 -8 -51 -57 -87 -108 -87 -122 -95 -132 -102
-124 -4 4 11 30 32 59 22 29 55 77 73 106 18 29 45 59 60 67 35 19 51 19 24 0z
m245 3 c17 -17 15 -42 -7 -69 -16 -20 -28 -23 -79 -24 -43 0 -65 5 -79 18 -11
9 -25 17 -33 17 -7 0 -1 -9 14 -21 14 -11 26 -26 26 -33 0 -7 -14 -41 -31 -75
-34 -68 -68 -92 -131 -90 -26 0 -29 2 -14 8 14 5 16 10 7 15 -6 4 -17 3 -24
-3 -7 -5 -18 -6 -25 -2 -10 6 5 36 57 113 38 57 77 111 86 118 40 33 208 53
233 28z m2962 -43 c66 -23 125 -77 159 -147 26 -52 31 -73 31 -135 0 -104 -26
-202 -57 -214 -74 -28 -500 -69 -716 -69 -91 0 -99 2 -92 18 4 9 12 42 17 72
17 102 -20 226 -93 305 -48 52 -49 51 71 60 112 8 299 46 435 88 123 39 183
44 245 22z m265 -52 c26 -25 36 -60 25 -88 -10 -25 -30 -35 -30 -14 0 7 -13
34 -30 61 -16 26 -30 50 -30 53 0 12 50 3 65 -12z m538 -21 c58 -4 59 -5 53
-32 -3 -15 -29 -80 -58 -143 l-53 -116 -48 -1 c-27 0 -46 3 -44 8 73 124 127
223 127 231 0 6 -18 11 -40 11 -41 0 -48 9 -34 45 4 10 12 14 23 9 9 -4 42 -9
74 -12z m-3726 -149 c-9 -28 -7 -38 9 -61 60 -81 178 -81 289 -1 l45 32 117
-27 c65 -15 214 -46 330 -69 l213 -42 -61 -49 c-57 -46 -61 -52 -56 -83 5 -28
3 -33 -14 -33 -28 0 -299 62 -534 122 -110 28 -294 72 -410 98 l-210 47 60 31
c33 16 77 43 98 59 36 27 42 29 86 19 l48 -9 -10 -34z m1868 -9 l116 -18 -49
-18 c-80 -30 -87 -43 -88 -172 l-1 -111 -66 -3 -65 -3 10 35 c8 26 8 42 -2 66
-18 43 -49 61 -109 62 -45 0 -52 3 -64 26 -9 19 -22 28 -47 32 -26 4 -35 11
-40 30 -4 19 -13 26 -38 28 -42 4 -40 18 6 38 88 37 221 40 437 8z m319 -68
c22 -80 29 -129 17 -121 -6 3 -11 18 -11 33 0 32 -22 107 -45 153 l-16 34 21
-24 c11 -13 26 -46 34 -75z m-839 6 c-6 -5 -28 -14 -51 -20 -63 -18 -104 -51
-165 -132 -31 -41 -70 -83 -85 -92 -32 -20 -69 -23 -79 -8 -7 11 173 187 214
209 20 12 82 30 171 50 2 1 0 -3 -5 -7z m76 -36 c0 -5 -24 -17 -53 -26 -82
-26 -114 -46 -212 -134 -50 -45 -100 -85 -111 -89 -16 -6 -15 -3 5 13 14 11
27 20 30 20 3 0 34 36 69 80 67 83 106 109 199 135 52 15 73 15 73 1z m605
-27 c14 -16 18 -34 17 -70 -3 -74 -12 -84 -72 -83 -28 0 -53 3 -56 6 -3 3 -6
34 -6 69 -1 54 2 66 21 81 30 24 73 23 96 -3z m-2335 -21 l52 -12 -66 -12
c-57 -11 -72 -10 -124 6 -47 15 -53 19 -33 23 49 9 119 7 171 -5z m1819 -6 c0
-4 -23 -16 -52 -26 -35 -12 -72 -37 -114 -78 -34 -33 -65 -59 -68 -58 -4 1
-31 -11 -61 -26 -53 -25 -105 -28 -105 -4 0 16 163 142 216 167 29 13 78 27
110 31 59 8 74 7 74 -6z m-2055 -19 l40 -8 -40 -5 c-50 -6 -105 -1 -105 11 0
11 50 11 105 2z m-190 -28 c29 -14 26 -15 -48 -11 -43 1 -83 8 -90 15 -17 17
101 14 138 -4z m623 3 l47 -12 -55 -11 c-59 -12 -116 -5 -171 19 -34 14 -33
14 49 15 46 1 104 -4 130 -11z m-903 -18 c27 -7 27 -8 5 -8 -14 0 -36 4 -50 8
-20 6 -21 8 -5 8 11 0 34 -4 50 -8z m2689 -12 c7 -12 7 -26 0 -45 -9 -27 -12
-28 -82 -28 -62 0 -72 -2 -72 -17 0 -23 -67 -67 -113 -75 -45 -7 -87 3 -87 21
0 19 123 134 162 151 47 21 177 16 192 -7z m-2802 -5 l68 -17 -60 -13 c-55
-11 -67 -10 -138 12 l-77 23 45 4 c25 3 56 5 70 6 14 1 55 -6 92 -15z m727 -5
c36 -6 62 -13 56 -14 -5 -2 -44 2 -85 10 -41 8 -66 14 -56 15 11 1 49 -4 85
-11z m441 -7 l55 -18 -50 -7 c-31 -4 -78 -2 -120 5 l-70 13 50 12 c66 16 71
16 135 -5z m-625 -2 c13 -6 0 -7 -40 -3 -33 4 -62 8 -64 10 -9 8 85 2 104 -7z
m-242 -6 c-13 -2 -35 -2 -50 0 -16 2 -5 4 22 4 28 0 40 -2 28 -4z m4772 -13
c25 -28 8 -45 -31 -30 -20 8 -115 9 -316 4 -384 -9 -384 8 0 28 158 8 296 16
308 17 11 0 29 -8 39 -19z m-4229 1 c-3 -5 -15 -7 -26 -4 -28 7 -25 13 6 13
14 0 23 -4 20 -9z m47 -8 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13
-5z m452 -9 l40 -7 -41 -18 c-41 -17 -78 -15 -164 7 -22 6 -19 8 25 19 49 13
61 12 140 -1z m-640 -3 c14 -6 5 -8 -30 -9 -27 -1 -57 3 -65 8 -19 12 65 13
95 1z m232 3 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-622 -47
c122 -32 331 -89 455 -124 l55 -15 -34 -14 c-42 -18 -66 -14 -251 41 -80 24
-219 64 -310 89 -222 60 -237 68 -130 62 52 -3 136 -18 215 -39z m160 33 c19
-5 6 -6 -35 -3 -36 3 -67 7 -69 9 -8 7 73 2 104 -6z m383 -41 c-13 -9 -88 -3
-118 8 -11 4 -8 8 10 12 33 9 126 -9 108 -20z m194 10 c-15 -5 -36 -6 -55 0
-29 8 -27 9 23 9 44 1 50 -1 32 -9z m508 -10 l55 -13 -64 -10 c-51 -7 -78 -6
-140 10 -73 17 -75 18 -41 25 44 9 118 4 190 -12z m-925 1 c27 -7 28 -8 5 -8
-14 0 -45 3 -70 7 l-45 8 40 1 c22 0 54 -4 70 -8z m1742 -15 c-15 -14 -36 -25
-45 -25 -10 0 0 11 23 24 52 31 57 31 22 1z m-1098 -25 c21 -13 8 -12 -69 5
l-65 15 59 -5 c32 -3 66 -10 75 -15z m-474 -15 c6 -3 -16 -3 -48 -2 -32 2 -62
8 -68 14 -10 10 92 -1 116 -12z m175 15 c-12 -8 -12 -10 -1 -10 8 0 12 -2 9
-5 -3 -3 -25 -3 -49 1 -34 6 -39 9 -24 15 11 4 34 8 50 8 23 1 26 -2 15 -9z
m800 -14 l45 -13 -61 -7 c-62 -8 -184 9 -184 25 0 22 122 19 200 -5z m-722 7
c-10 -2 -28 -2 -40 0 -13 2 -5 4 17 4 22 1 32 -1 23 -4z m357 -18 l40 -14 -58
3 c-32 1 -63 8 -69 14 -17 17 35 15 87 -3z m-1473 -16 c44 -12 77 -23 75 -26
-4 -4 -158 36 -166 43 -9 8 14 4 91 -17z m1263 0 c26 0 27 -2 10 -9 -25 -11
-102 -12 -135 -3 -23 7 -21 8 15 14 22 4 49 5 60 3 11 -2 34 -4 50 -5z m1210
1 c4 -7 -3 -8 -22 -4 -38 9 -42 14 -10 14 14 0 29 -5 32 -10z m1393 3 c-10 -2
-26 -2 -35 0 -10 3 -2 5 17 5 19 0 27 -2 18 -5z m-1841 -20 c52 -9 90 -20 85
-25 -20 -20 -113 -21 -198 -2 l-85 19 48 11 c26 6 50 12 52 13 3 0 47 -7 98
-16z m-1027 -3 l25 -8 -25 0 c-14 -1 -43 3 -65 7 l-40 9 40 0 c22 0 51 -4 65
-8z m745 -21 l40 -13 -42 -9 c-52 -12 -226 22 -182 35 32 10 134 2 184 -13z
m-1085 -152 c578 -168 1031 -304 1038 -312 18 -18 -78 6 -332 81 -160 47 -356
104 -435 125 -225 63 -901 279 -826 265 11 -2 261 -74 555 -159z m769 144 c25
-16 -6 -22 -76 -15 -47 5 -61 10 -48 15 27 10 107 11 124 0z m-259 -11 c19 -6
12 -8 -30 -8 -30 0 -64 3 -75 8 -26 11 70 11 105 0z m1148 -28 c97 -34 108
-42 56 -42 -30 0 -36 3 -24 11 11 8 -1 9 -44 5 -35 -3 -91 1 -135 10 -104 21
-114 27 -61 34 88 13 128 10 208 -18z m2355 -9 c-2 -10 -11 -27 -18 -37 -14
-18 -17 -18 -97 -2 -139 27 -154 35 -73 34 39 0 81 4 95 10 14 6 41 11 62 11
30 1 35 -2 31 -16z m-2978 -22 c44 -11 113 -25 154 -32 l74 -11 -32 -14 c-19
-8 -45 -14 -60 -14 -24 0 -290 69 -351 91 -47 17 132 0 215 -20z m245 22 c73
-5 74 -5 46 -20 -23 -12 -39 -13 -99 -3 -133 22 -105 35 53 23z m-815 -31 c64
-21 61 -27 -22 -37 -42 -4 -71 0 -140 22 l-88 28 50 6 c69 9 130 4 200 -19z
m225 19 l25 -7 -30 -6 c-16 -4 -57 0 -90 7 l-60 13 65 0 c36 0 76 -3 90 -7z
m765 -28 c31 -5 35 -8 20 -14 -30 -12 -86 -9 -125 6 l-35 13 50 1 c28 0 68 -2
90 -6z m508 -24 c26 -6 47 -14 47 -17 0 -15 -139 -11 -210 7 l-75 18 95 1 c52
1 116 -3 143 -9z m107 -19 c-36 -11 -52 -11 -45 0 3 6 21 10 38 9 31 -1 31 -1
7 -9z m-359 -14 l34 -14 -28 -7 c-29 -8 -172 1 -217 13 -24 6 -23 7 10 13 65
12 167 9 201 -5z m-986 -10 c28 -7 66 -20 85 -28 l35 -15 -83 -6 c-75 -6 -89
-4 -160 22 -68 26 -74 29 -47 33 61 10 121 7 170 -6z m1544 -14 l75 -17 -78
-14 c-74 -12 -83 -11 -160 11 l-81 23 65 6 c36 3 74 6 85 7 11 1 53 -7 94 -16z
m-819 -2 c0 -5 -6 -10 -12 -11 -7 0 -4 -4 7 -9 40 -17 -59 -10 -125 10 l-65
19 98 0 c58 1 97 -3 97 -9z m-181 -38 c20 -7 11 -10 -52 -19 -65 -9 -86 -8
-144 7 -65 17 -66 18 -33 23 49 7 200 0 229 -11z m743 -1 c11 -12 10 -13 -3
-8 -8 3 -38 1 -65 -5 -56 -10 -211 10 -177 24 32 13 231 5 245 -11z m-265 -30
c15 -9 13 -10 -12 -11 -17 0 -45 -4 -62 -9 -24 -7 -49 -5 -95 9 l-63 18 40 5
c57 7 172 0 192 -12z m-730 -15 l37 -13 -46 -6 c-47 -6 -143 14 -163 35 -13
14 123 1 172 -16z m488 -16 c14 -5 -1 -11 -55 -20 -60 -10 -87 -10 -135 0 -63
12 -115 34 -60 24 17 -2 57 0 90 5 59 9 121 6 160 -9z m1154 -44 c-2 -2 -13 8
-23 22 l-19 27 24 -22 c12 -12 21 -24 18 -27z m-1420 -6 c12 -7 8 -10 -19 -11
-53 -3 -80 1 -114 17 -29 13 -27 14 43 9 40 -3 81 -10 90 -15z m1351 17 c0 -2
-9 -12 -20 -22 -24 -21 -27 -14 -4 9 15 15 24 20 24 13z m35 -17 c3 -6 -1 -7
-9 -4 -18 7 -21 14 -7 14 6 0 13 -4 16 -10z m2322 -26 c-3 -3 -12 -4 -19 -1
-8 3 -5 6 6 6 11 1 17 -2 13 -5z m-2383 -57 c7 -6 6 -7 -4 -4 -8 2 -16 14 -17
28 -1 19 -1 20 4 4 3 -11 10 -24 17 -28z"/>
<path d="M5283 8633 c9 -2 25 -2 35 0 9 3 1 5 -18 5 -19 0 -27 -2 -17 -5z"/>
<path d="M5218 8623 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
<path d="M5113 8592 c-23 -10 -48 -23 -55 -30 -11 -11 97 33 111 44 10 9 -17
2 -56 -14z"/>
<path d="M7275 8230 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
-7 -4 -4 -10z"/>
<path d="M9280 6916 c0 -2 7 -9 15 -16 9 -7 15 -8 15 -2 0 5 -7 12 -15 16 -8
3 -15 4 -15 2z"/>
<path d="M8555 7085 c-33 -30 -55 -54 -49 -55 6 0 17 6 23 13 6 8 28 22 49 31
29 13 38 23 38 42 0 13 0 24 0 24 -1 0 -28 -25 -61 -55z"/>
<path d="M8865 7010 c-16 -7 -17 -9 -3 -9 9 -1 20 4 23 9 7 11 7 11 -20 0z"/>
<path d="M8760 6979 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M4910 6295 c0 -8 4 -15 8 -15 8 0 32 -43 32 -57 0 -3 -8 1 -17 8 -16
13 -17 12 -4 -3 7 -10 17 -15 22 -13 12 8 36 -32 59 -100 22 -64 25 -77 10
-55 -8 12 -10 11 -10 -7 0 -15 6 -23 18 -24 10 0 12 -3 5 -6 -9 -3 -13 -31
-12 -91 0 -58 3 -80 9 -67 7 15 9 16 9 4 1 -9 -6 -22 -14 -29 -17 -14 -20 -40
-5 -40 6 0 6 -9 -1 -26 -5 -15 -9 -45 -7 -66 2 -39 2 -39 18 -17 39 51 55 120
55 239 0 93 -5 128 -23 184 -25 75 -67 143 -108 175 -32 25 -44 26 -44 6z"/>
<path d="M4622 5910 c0 -19 2 -27 5 -17 2 9 2 25 0 35 -3 9 -5 1 -5 -18z"/>
<path d="M4632 5840 c0 -14 2 -19 5 -12 2 6 2 18 0 25 -3 6 -5 1 -5 -13z"/>
<path d="M4760 5454 c0 -5 7 -18 15 -28 8 -11 15 -16 15 -10 0 5 -7 18 -15 28
-8 11 -15 16 -15 10z"/>
<path d="M7960 4356 c24 -26 60 -52 60 -42 0 2 -19 19 -42 37 -40 30 -41 31
-18 5z"/>
<path d="M8027 4286 c-3 -8 1 -13 11 -12 9 0 16 -5 14 -12 -1 -8 2 -11 8 -7 8
5 6 13 -6 26 -20 23 -20 23 -27 5z"/>
<path d="M8143 3935 c0 -27 2 -38 4 -22 2 15 2 37 0 50 -2 12 -4 0 -4 -28z"/>
<path d="M8131 3834 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M4667 2598 c-22 -14 46 -12 71 1 8 4 -3 7 -23 7 -20 -1 -42 -4 -48
-8z"/>
<path d="M6554 2467 c-12 -13 4 -87 20 -87 5 0 1 -7 -10 -15 -10 -8 -14 -15
-7 -15 36 -1 56 67 33 111 -12 22 -20 23 -36 6z"/>
<path d="M6520 2441 c0 -12 5 -21 10 -21 6 0 10 6 10 14 0 8 -4 18 -10 21 -5
3 -10 -3 -10 -14z"/>
<path d="M6098 2353 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M1455 5297 c-20 -17 -28 -32 -27 -55 0 -17 41 -128 91 -247 90 -217
90 -217 70 -234 -21 -17 -21 -22 -14 -209 7 -173 10 -195 28 -219 20 -25 23
-26 108 -20 62 4 90 2 97 -6 5 -7 71 -156 146 -332 89 -207 133 -321 125 -324
-15 -5 -45 -35 -51 -51 -2 -7 -83 -20 -238 -36 -441 -45 -636 -92 -873 -210
-204 -103 -362 -274 -412 -448 -69 -241 88 -466 431 -615 119 -51 269 -94 489
-138 145 -29 185 -41 206 -60 21 -20 491 -223 643 -279 48 -17 222 -18 600 -3
290 11 307 15 327 65 6 18 5 34 -3 52 -14 29 -107 72 -433 202 -88 35 -165 68
-172 74 -7 6 -17 41 -23 77 -30 195 76 616 194 763 l23 30 79 -17 c148 -31
889 -188 1033 -218 160 -35 178 -33 206 21 20 39 19 42 -95 315 -98 234 -363
899 -605 1515 -201 514 -202 516 -233 536 -28 19 -28 19 -1052 63 -256 11
-504 23 -551 26 -81 6 -88 5 -114 -18z m792 -83 c-3 -3 -12 -4 -19 -1 -8 3 -5
6 6 6 11 1 17 -2 13 -5z m578 -25 c73 -5 19 -6 -160 -3 -148 3 -301 9 -340 14
-86 10 341 1 500 -11z m-947 -135 c23 -4 32 -10 32 -24 0 -24 -2 -24 -105 -8
-76 11 -94 20 -95 44 0 9 38 7 168 -12z m132 -67 c0 -32 0 -32 -45 -29 -42 4
-45 6 -45 33 0 28 2 29 45 29 44 0 45 -1 45 -33z m90 4 c0 -17 -4 -33 -10 -36
-6 -4 -10 8 -10 29 0 20 5 36 10 36 6 0 10 -13 10 -29z m190 4 c0 -11 -5 -12
-23 -6 -14 6 -30 6 -38 0 -19 -12 -32 -11 -24 1 3 6 -5 10 -19 10 -15 0 -26
-7 -29 -17 -4 -14 -5 -12 -6 5 -1 21 3 22 69 22 55 0 70 -3 70 -15z m-421 -1
c21 -4 31 -12 31 -25 0 -17 -3 -17 -45 -2 -68 23 -59 41 14 27z m718 -20 c18
-5 21 -13 21 -48 l-1 -42 -56 8 c-130 19 -121 14 -121 60 l0 41 68 -7 c37 -4
77 -9 89 -12z m-217 -25 c0 -17 -4 -28 -10 -24 -5 3 -10 17 -10 31 0 13 5 24
10 24 6 0 10 -14 10 -31z m308 -16 c2 -8 -5 -13 -17 -13 -12 0 -21 6 -21 16 0
18 31 15 38 -3z m-816 -9 c53 -6 56 -8 61 -38 2 -17 3 -32 2 -34 -2 -2 -46 5
-99 14 -96 17 -96 17 -96 47 0 29 1 29 38 24 20 -4 62 -9 94 -13z m1101 5 c3
-2 8 -21 11 -43 l7 -39 -63 7 c-140 16 -138 15 -138 54 l0 34 90 -4 c49 -2 91
-6 93 -9z m-1253 -96 c0 -5 -5 -15 -10 -23 -8 -12 -10 -11 -10 8 0 12 5 22 10
22 6 0 10 -3 10 -7z m1039 -14 c83 -10 102 -15 106 -30 4 -11 12 -19 19 -19 8
0 19 -7 26 -15 16 -19 9 -19 -145 0 -66 8 -123 15 -127 15 -5 0 -8 14 -8 30 0
35 -6 34 129 19z m-611 -40 c116 -12 157 -29 52 -21 l-60 4 6 -78 c3 -44 7
-92 9 -109 4 -28 4 -29 -10 -11 -31 40 -76 86 -85 86 -15 0 -23 49 -11 64 9
10 4 19 -24 40 -40 31 -45 48 -12 42 12 -3 73 -10 135 -17z m850 -30 c4 -53
-13 -42 -21 14 -4 27 -3 37 6 34 7 -2 13 -23 15 -48z m-1020 10 c-3 -8 -7 -3
-11 10 -4 17 -3 21 5 13 5 -5 8 -16 6 -23z m952 21 c0 -5 -2 -10 -4 -10 -3 0
-8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m477 -210 c30 -69 79 -183 108
-255 29 -71 110 -269 179 -439 69 -170 124 -311 122 -313 -2 -2 -9 11 -16 29
-7 18 -47 107 -87 198 -117 260 -414 977 -413 997 1 14 50 -85 107 -217z
m-1462 196 c18 -13 18 -14 -8 -9 -15 3 -27 9 -27 14 0 13 13 11 35 -5z m24
-24 c54 -7 54 -7 58 -44 4 -38 4 -38 -34 -38 -49 1 -122 15 -133 26 -5 5 -12
21 -15 37 -7 26 -6 27 31 26 22 -1 63 -4 93 -7z m567 -12 l61 0 7 -47 c3 -25
4 -48 1 -51 -2 -2 -16 -2 -30 2 -21 5 -25 12 -25 42 0 19 -4 33 -9 30 -12 -8
-124 14 -136 27 -7 6 4 8 30 3 22 -3 68 -6 101 -6z m-336 -21 c0 -11 -5 -17
-10 -14 -6 4 -8 10 -5 15 3 4 -1 11 -7 13 -8 3 -6 6 5 6 11 1 17 -6 17 -20z
m53 14 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5 17 0 24 -2 18 -5z m497 -18 c10
-6 50 -78 50 -90 0 -7 -85 -6 -104 1 -12 5 -16 20 -16 59 l0 54 30 -9 c16 -5
34 -11 40 -15z m-1026 -165 l65 -155 -61 -8 c-34 -4 -64 -4 -68 0 -11 12 -22
340 -11 328 5 -6 39 -80 75 -165z m713 123 c-3 -10 -5 -2 -5 17 0 19 2 27 5
18 2 -10 2 -26 0 -35z m-17 13 c0 -9 -8 -12 -25 -8 -37 7 -41 22 -6 22 20 0
31 -5 31 -14z m-535 -46 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10
3 0 8 -4 11 -10z m82 -22 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
m51 4 c2 -7 -2 -10 -12 -6 -9 3 -16 11 -16 16 0 13 23 5 28 -10z m-19 -52 c71
-18 91 -30 91 -57 0 -16 1 -16 -97 4 -73 15 -83 20 -83 38 0 17 8 36 14 35 1
0 34 -9 75 -20z m98 -111 c57 -10 61 -13 65 -40 3 -16 3 -29 0 -29 -25 0 -190
35 -199 43 -7 5 -13 18 -13 29 0 22 3 21 147 -3z m661 -33 c3 -33 1 -36 -22
-36 -21 0 -26 6 -32 34 -8 44 0 57 29 47 16 -6 23 -18 25 -45z m248 -6 c1 0 4
-14 6 -31 l5 -31 -65 6 c-36 4 -73 11 -83 17 -17 9 -26 48 -14 60 3 4 126 -13
151 -21z m-770 10 c21 0 24 -5 24 -35 0 -33 -1 -35 -27 -29 -36 8 -40 13 -49
48 -6 25 -5 28 10 23 10 -4 29 -7 42 -7z m124 -36 c0 -19 -4 -34 -10 -34 -5 0
-10 18 -10 41 0 24 4 38 10 34 6 -3 10 -22 10 -41z m176 6 c20 0 24 -5 24 -29
0 -17 5 -33 10 -36 15 -9 12 -35 -4 -35 -8 0 -16 4 -18 9 -1 5 -26 11 -54 15
-72 8 -117 27 -50 20 27 -2 60 -7 73 -10 19 -5 23 -2 23 16 0 19 -4 22 -26 17
-14 -2 -31 1 -37 7 -7 6 -23 17 -37 24 -23 11 -20 12 24 7 27 -3 59 -5 72 -5z
m-599 -6 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m59 -61 c-2
-3 -15 5 -28 17 -16 16 -18 21 -6 17 10 -3 19 1 24 11 6 13 9 11 12 -11 2 -16
1 -31 -2 -34z m150 25 c54 -10 64 -15 69 -36 3 -13 4 -26 1 -29 -2 -2 -40 1
-85 8 -79 12 -81 13 -81 41 0 32 5 33 96 16z m489 2 c3 -5 -1 -10 -10 -10 -9
0 -13 5 -10 10 3 6 8 10 10 10 2 0 7 -4 10 -10z m-183 -75 c4 -16 1 -25 -8
-25 -14 0 -23 19 -16 38 7 20 19 14 24 -13z m88 -5 c0 -5 -4 -10 -9 -10 -6 0
-13 5 -16 10 -3 6 1 10 9 10 9 0 16 -4 16 -10z m140 -41 c0 -16 -4 -29 -10
-29 -5 0 -10 16 -10 36 0 21 4 33 10 29 6 -3 10 -19 10 -36z m-614 23 c6 -4
14 -16 17 -27 7 -18 6 -18 -10 2 -12 14 -32 23 -58 26 l-40 4 40 1 c22 1 45
-2 51 -6z m222 -27 c6 -2 12 -16 12 -30 0 -28 -12 -31 -70 -16 -19 5 -52 12
-72 16 -34 5 -38 9 -38 34 l0 29 78 -15 c42 -7 83 -16 90 -18z m-238 5 c0 -5
-4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m877 -12
c53 -8 62 -13 68 -35 3 -14 3 -28 0 -31 -5 -5 -213 32 -220 40 -2 2 -2 14 2
27 6 24 -2 24 150 -1z m-567 -34 c0 -16 -26 -19 -35 -4 -3 6 -4 14 0 20 8 13
35 1 35 -16z m173 9 c13 -4 17 -16 17 -49 0 -50 -12 -55 -47 -22 -29 27 -34
95 -5 83 9 -4 25 -10 35 -12z m-405 -71 c2 -32 0 -42 -12 -42 -9 0 -18 12 -22
28 -3 15 -7 32 -9 39 -5 15 6 24 25 21 10 -2 16 -17 18 -46z m512 8 c0 -19 -5
-30 -14 -30 -8 0 -16 13 -18 30 -4 24 -1 30 14 30 13 0 18 -8 18 -30z m-325
-13 c57 -11 60 -14 63 -43 l3 -31 -93 18 c-51 10 -94 19 -95 19 -2 0 -3 14 -3
30 0 34 -12 34 125 7z m485 10 c50 -11 55 -15 58 -40 3 -27 4 -28 18 -10 12
16 15 16 24 3 19 -30 10 -33 -77 -27 -130 10 -148 17 -148 55 -1 30 1 32 35
31 19 0 60 -6 90 -12z m-248 -88 c5 -33 6 -33 -59 -18 -46 11 -49 14 -45 39 4
26 4 27 52 17 43 -8 49 -13 52 -38z m88 -19 c0 -11 -2 -20 -4 -20 -2 0 -6 9
-9 20 -3 11 -1 20 4 20 5 0 9 -9 9 -20z m198 -7 c5 -34 -34 -31 -41 3 -4 21
-1 25 17 22 13 -2 22 -12 24 -25z m-144 -8 c3 -8 1 -15 -4 -15 -6 0 -10 7 -10
15 0 8 2 15 4 15 2 0 6 -7 10 -15z m-279 -24 c75 -15 80 -18 83 -43 4 -33 10
-32 -101 -13 -119 21 -137 29 -137 59 0 28 -1 28 155 -3z m623 1 c8 -11 12
-12 12 -3 0 8 11 11 32 9 24 -2 34 -9 37 -23 5 -29 40 -50 37 -22 0 6 3 13 9
14 5 2 10 -5 10 -15 0 -13 11 -18 52 -22 45 -5 87 -20 54 -20 -7 0 -9 -4 -6
-10 4 -6 -21 -10 -68 -10 -107 0 -137 8 -151 40 -6 15 -16 25 -23 23 -6 -2
-29 1 -51 6 -34 10 -39 14 -35 35 5 22 9 24 42 19 20 -3 42 -12 49 -21z m-168
-16 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z
m-632 -37 c1 -8 -4 -23 -12 -34 -15 -19 -15 -18 -16 18 0 27 4 37 13 35 6 -3
13 -11 15 -19z m212 -73 c56 -10 65 -15 68 -35 4 -23 2 -23 -35 -17 -21 4 -57
10 -80 13 -24 3 -43 9 -43 13 0 5 -3 15 -6 24 -7 19 6 20 96 2z m778 -13 c2
-16 4 -37 5 -47 1 -10 -4 -21 -10 -23 -9 -3 -13 5 -13 24 0 15 -3 38 -6 51 -4
15 -2 22 8 22 8 0 15 -12 16 -27z m69 21 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6
11 1 17 -2 13 -5z m-1080 -46 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1
-19z m93 -8 c0 -5 -7 -10 -15 -10 -8 0 -15 5 -15 10 0 6 7 10 15 10 8 0 15 -4
15 -10z m400 -51 c0 -28 -4 -39 -12 -37 -18 6 -19 78 -2 78 10 0 14 -13 14
-41z m-221 25 c18 -4 31 -13 31 -21 0 -12 -8 -14 -37 -8 -44 8 -53 13 -53 26
0 11 15 11 59 3z m-295 -10 c20 -8 21 -48 2 -63 -12 -10 -17 -8 -25 8 -13 24
-14 61 -2 61 5 0 16 -3 25 -6z m416 -19 c0 -23 -3 -25 -27 -19 -38 9 -43 13
-43 30 0 9 11 14 35 14 31 0 35 -3 35 -25z m317 -25 c3 -44 -2 -50 -37 -39
-24 7 -24 7 -2 8 19 1 22 6 22 43 0 51 13 42 17 -12z m48 10 c3 -5 2 -10 -4
-10 -5 0 -13 5 -16 10 -3 6 -2 10 4 10 5 0 13 -4 16 -10z m-665 -20 c7 0 -49
-38 -85 -57 -29 -15 -30 -15 -14 3 9 11 19 31 23 46 6 25 8 26 38 17 18 -5 35
-9 38 -9z m817 -106 c-14 -14 -27 11 -27 50 0 62 14 66 24 7 5 -28 6 -54 3
-57z m298 31 c119 -23 115 -20 115 -70 l0 -43 -72 14 c-122 23 -118 21 -118
57 0 18 -5 38 -12 45 -15 15 -9 15 87 -3z m-155 -19 c0 -2 -7 -7 -16 -10 -8
-3 -12 -2 -9 4 6 10 25 14 25 6z m312 -68 c-9 -9 -12 -7 -12 12 0 19 3 21 12
12 9 -9 9 -15 0 -24z m-1505 -78 c15 -12 41 -20 62 -20 35 0 37 -2 59 -58 12
-32 22 -61 22 -64 0 -4 -20 -36 -45 -71 -81 -117 -123 -227 -179 -478 -45
-202 -52 -358 -21 -482 6 -23 4 -24 -127 -46 -73 -13 -154 -30 -179 -38 -44
-14 -55 -13 -220 21 -381 78 -596 167 -739 307 -82 80 -115 153 -115 250 1
110 48 204 159 315 123 123 270 201 506 269 144 41 264 61 555 90 127 12 232
23 233 24 2 0 15 -8 29 -19z m311 -216 c2 -22 -25 -85 -104 -242 -58 -117
-110 -212 -115 -212 -16 0 -10 94 11 176 24 97 77 203 131 267 47 54 72 58 77
11z m26 -181 c-31 -74 -85 -226 -104 -296 -23 -87 -26 -55 -4 50 18 88 44 157
86 231 35 61 45 68 22 15z m-268 -940 c65 -31 148 -67 184 -80 52 -19 57 -22
25 -17 -46 7 -279 96 -312 119 -20 14 -31 35 -19 35 1 0 57 -25 122 -57z"/>
<path d="M7090 1674 c-52 -7 -131 -25 -175 -39 -92 -29 -208 -103 -242 -154
-26 -39 -30 -93 -8 -111 11 -9 13 -16 5 -24 -38 -38 23 -52 265 -61 250 -10
695 25 783 61 41 17 52 42 26 63 -14 12 -19 29 -19 61 0 93 -49 126 -278 185
-152 39 -203 41 -357 19z m270 -74 c11 -7 6 -10 -21 -10 -20 0 -72 -3 -115 -6
-43 -4 -76 -3 -72 1 20 21 181 32 208 15z m-427 -166 c56 -36 48 -48 -25 -40
-34 3 -66 10 -70 14 -5 5 -4 21 2 36 12 32 31 30 93 -10z"/>
</g>
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1365 1365" width="1365" height="1365">
<title>safari-pinned-tab-svg</title>
<defs>
<clipPath clipPathUnits="userSpaceOnUse" id="cp1">
<path d="m655.2 313.1v822.23h-622.69v-822.23z"/>
</clipPath>
<clipPath clipPathUnits="userSpaceOnUse" id="cp2">
<path d="m1308.84 304v828.5h-617.24v-828.5z"/>
</clipPath>
</defs>
<style>
.s0 { fill: none }
.s1 { fill: #000000 }
</style>
<g id="surface1">
<path class="s0" d="m1258.6 499.2c-40.8-26.1-68 13.8-64.7 68.1l-0.3 0.4c0.1-56.6-7.3-119.2-31.7-169.8-8.7-17.9-26.2-47.4-61-33.5-15.2 6.1-29 24.4-21.9 71.7 0 0 8 49.7 6.5 112.2v0.8c-9.9-172.2-47.3-224.7-100.7-221.3-17.1 3.1-40.5 10.8-32.6 63.8 0 0 8.5 55.2 11.3 99.2l0.2 2.2h-0.2c-25.2-94.9-59-96.2-83.5-92.5-22.3 3.3-46.6 27.3-34.3 74.7 38.6 148.4 31 327.2 28.2 352.9-7.9-17.6-10.3-31.4-21.3-50.7-43.9-77.1-64.8-82.8-90.4-84-25.5-1.1-53 15.2-51.2 46.3 1.9 31.1 17.1 36.3 38.7 79.6 16.9 33.8 21.7 78 55.7 158.4 28.1 66.5 101.6 139.5 235.6 130.8 108.5-3.7 270.6-43.2 242.4-302.5-7-45-1.7-82.7 1.9-121.4 5.8-60 14.1-159.4-26.7-185.5z"/>
<path class="s0" d="m580.9 695.3c-25.7 1.7-46.4 7.7-89 85.7-10.6 19.4-12.7 33.3-20.3 50.9-3.3-25.5-14-204.2 21.9-353.4 11.4-47.5-13.3-71-35.6-73.9-24.6-3.3-58.5-1.3-81.9 94.6h-0.3l0.4-2.8c1.9-44 9.5-99.4 9.5-99.4 6.9-53.1-16.6-60.3-33.7-63.2-53.4-2.3-89.7 50.4-96.7 221.1h-0.2c-2.4-61.8 4.6-111 4.6-111 6.3-47.5-7.9-65.5-23.2-71.3-35-13.3-52 16.6-60.3 34.7-23.6 51-29.9 113.7-28.7 170.3l-0.4-0.4c2.4-54.2-25.6-93.7-65.9-66.9-40.3 26.9-30.1 126.2-23.4 186 4.5 38.6 10.4 76.2 4.1 121.4-23.5 259.7 139.3 296.1 247.8 297.8 134.1 6.1 206.3-68.3 233.3-135.4 32.5-80.9 36.6-125.3 52.8-159.3 20.8-43.8 36-49.2 37.3-80.3 1.3-31.1-26.5-46.9-52-45.3z"/>
<g id="Clip-Path" clip-path="url(#cp1)">
<g>
<path fill-rule="evenodd" class="s1" d="m634.4 695.7c11.9 12 17.8 27.9 17.1 45.7-1 24.6-9.5 37.8-19.4 53.2-5.8 9-12.3 19.2-19.8 34.9-6.6 13.8-11.2 30.4-17 51.5-7.6 27.3-17 61.2-35.3 106.7-14.1 35.1-71.4 146.1-231.3 147.6q-9.8 0.1-20-0.3c-93.6-1.5-164.2-28.5-209.3-80.6-46.9-54-65.8-134.2-56.4-238.4l0.1-0.9c5.2-37.6 1.5-69.5-2.6-103.3-0.5-4.4-1-8.7-1.5-13.1-9.4-82.5-15.4-173.1 31.8-204.6 27.9-18.5 49.3-11.1 59.6-4.9 1 0.6 1.9 1.2 2.9 1.9 4.5-32.3 12.6-63.9 25.6-92.2 11.2-24.2 37.1-62.2 83.8-44.5 7.6 3 17.3 8.8 24.8 20.2 6.7-14.7 14.5-26.6 23.5-35.8 16.6-17.2 37.4-25.4 61.6-24.3l2.1 0.2c39.2 6.5 55.9 35 49.4 84.9 0 0 0 0.3 0 0.6 20-17 40.4-16.9 56.1-14.8 17.2 2.2 32.8 12.1 42.8 27.2 8.6 13 17.1 35.8 8.7 70.7-22.3 92.9-26.1 198.5-25.2 268.8 36.3-61.5 59.9-74.1 93.2-76.2 20.8-1.3 41.3 6 54.8 19.8zm-316.9-329.4c-35.1 36.2-49.7 148.5-43.4 333.7 19.5-3 39.5-5.2 59.6-6.5 4.7-91.2 13.3-153.7 23.7-197q0-0.5 0-0.9c2-44.4 9.3-98.9 9.7-101.2 4.7-36.3-5.7-39.2-17-41.1-13.2-0.3-23.5 3.8-32.5 13zm-124.6 49.5c-50 108.3-16.2 277.2-8.5 303.8 16.1-4.8 33.8-9.2 52.4-13-2.1-57.7-2.3-108.1-0.6-151.9-2.3-62.3 4.4-111.4 4.7-113.5 1.8-13 4.2-44.5-11.1-50.3-10.9-4.1-22.8-5.7-36.9 24.8zm407.9 357.3c8.9-13.8 12.6-19.5 13.2-33.3 0.2-6.7-1.6-12-5.9-16.3-5.9-6.1-16-9.4-26.1-8.8-17.3 1.2-33.6 2.2-73.8 75.9-5.6 10.4-8.5 18.9-11.8 28.6-2.1 6.3-4.4 13.2-7.7 20.8-0.1 0.3-0.2 0.6-0.4 0.8-1.4 3.3-3 6.8-4.8 10.4-17.6 34.2-46.2 53.4-76.5 51.6-10.4-0.7-18.2-9.9-17.6-20.6 0.6-10.7 9.6-18.7 19.8-18.2 18 1.1 33.1-15.3 41.2-31.1 0.7-1.4 1.3-2.8 2-4.2-4-41.1-11.8-210.7 22.9-354.8 3.9-16.5 2.8-30.1-3.3-39.3-5.6-8.4-13.4-10.3-16.5-10.7-11.2-1.5-19.3-0.9-27.8 6.4-20.5 17.8-46.8 77.8-56.4 261.8 5.8 0 11.6 0 17.3 0.2 10.3 0.3 18.5 9.2 18.2 19.9-0.3 10.7-8.8 19.1-19.2 18.9-95.8-2.8-204.4 22.8-250.2 47.9-2.8 1.5-5.7 2.3-8.6 2.3-6.8 0.1-13.4-3.7-16.8-10.3-4.8-9.5-1.4-21.2 7.8-26.3 8.1-4.4 17.9-8.9 28.9-13.1-6.7-22.4-18.6-82-20.1-150.6-0.3-1.5-0.5-3-0.4-4.6 1.2-29.4-7.6-48.4-16.4-53.6-5.2-3.1-12.1-1.8-20.6 3.9-31.6 21-19.4 127.4-14.9 167.4 0.5 4.3 1 8.6 1.5 12.9 4.1 34.7 8.4 70.6 2.6 113-8.3 92.7 7.5 162.9 47 208.5 38.4 44.2 98 66.3 182.4 67.6 151.5 7.1 203.3-92.6 215.7-123.3 17.4-43.4 26.5-76.2 33.8-102.5 6.4-22.9 11.4-41 19.5-58 8.5-17.9 16.1-29.7 22.2-39.2z"/>
</g>
</g>
<g id="Clip-Path" clip-path="url(#cp2)">
<g>
<path fill-rule="evenodd" class="s1" d="m1301.9 802.9l0.1 0.9c11.3 104-6.3 184.6-52.2 239.5-44.1 52.8-114.2 81.3-208.3 84.5q-10.2 0.7-19.9 0.8c-159.5 1.6-218.8-108.4-233.5-143.2-19.1-45.1-29.1-78.9-37.2-106-6.2-21-11.1-37.5-18-51.2-7.7-15.5-14.4-25.6-20.4-34.5-10.1-15.1-18.8-28.2-20.3-52.8-1.1-17.7 4.5-33.6 16.2-45.9 13.3-14 33.8-21.8 54.5-20.9 33.3 1.5 57.1 13.7 94.5 74.5-0.3-70.4-6-175.9-30-268.4-9-34.8-0.9-57.7 7.5-70.8 9.7-15.3 25.1-25.5 42.2-28.1 15.7-2.3 36.2-2.9 56.4 13.8 0-0.2 0-0.4 0-0.4-7.4-49.9 8.8-78.8 47.9-86l2.1-0.3c24.1-1.6 45 6.3 62 23.2 9.1 9 17.1 20.7 24.1 35.3 7.4-11.6 16.9-17.6 24.5-20.6 46.4-18.7 72.9 18.9 84.5 42.9 13.5 28 22.1 59.5 27.3 91.6 0.9-0.6 1.8-1.3 2.8-1.9 10.2-6.3 31.5-14.3 59.7 3.8 47.8 30.6 43.4 121.3 35.5 203.9-0.4 4.4-0.8 8.7-1.3 13.1-3.4 33.9-6.6 65.9-0.8 103.3zm-197.6-256.5c2.5 43.7 3.2 94.2 2.1 151.9 18.7 3.5 36.4 7.5 52.7 12 7.2-26.7 37.9-196.3-14-303.7-14.6-30.1-26.5-28.4-37.4-24.1-15.1 6.1-12.2 37.5-10.2 50.7 0.4 1.9 8 50.9 6.8 113.2zm-117.5-199.2c-11.4 2.2-21.6 5.2-16.3 41.6 0.4 2.1 8.8 56.4 11.5 100.8q0 0.5 0 0.9c11.2 43.2 21 105.4 27.2 196.6 20.2 0.9 40.2 2.7 59.7 5.3 3-185.3-13.5-297.2-49.3-332.8-9.1-9.1-19.5-13-32.7-12.4zm278.5 348.5c0.5-4.3 0.9-8.6 1.3-13 3.9-40.1 14.1-146.6-17.9-167-8.6-5.5-15.5-6.7-20.6-3.5-8.7 5.4-17.2 24.5-15.4 53.9 0.1 1.5 0 3.1-0.3 4.6-0.4 68.5-11.2 128.4-17.5 150.9 11.1 4.1 20.9 8.3 29.1 12.6 9.3 4.9 13 16.6 8.3 26.2-3.3 6.7-9.8 10.6-16.6 10.6-2.9 0-5.9-0.6-8.6-2.1-46.2-24.3-155.4-47.7-251-43.2-10.5 0.3-19.2-7.7-19.6-18.5-0.5-10.7 7.5-19.8 17.9-20.2 5.6-0.3 11.4-0.5 17.2-0.6-12.8-183.8-40.2-243.3-61-260.7-8.6-7.1-16.8-7.6-27.9-5.9-3.2 0.5-10.9 2.5-16.4 11.1-5.9 9.3-6.8 22.9-2.5 39.3 37.3 143.5 32.4 313.2 29.2 354.3 0.7 1.4 1.3 2.7 2.1 4.2 8.4 15.6 23.7 31.7 41.7 30.3 10.3-0.7 19.3 7.2 20.1 17.9 0.8 10.6-6.9 20-17.2 20.8-30.3 2.5-59.3-16.3-77.4-50.1-2-3.6-3.6-7-5.1-10.3-0.1-0.2-0.2-0.5-0.3-0.7-3.5-7.5-5.9-14.5-8.2-20.8-3.5-9.6-6.4-18-12.3-28.3-41.6-72.9-57.9-73.7-75.1-74.5-10.2-0.5-20.2 3.1-26.1 9.3-4.1 4.3-5.9 9.7-5.5 16.4 0.8 13.8 4.6 19.4 13.7 33.1 6.3 9.4 14.1 21 23 38.7 8.3 16.9 13.7 34.8 20.5 57.7 7.7 26.2 17.4 58.7 35.6 101.8 12.9 30.5 66.7 129.1 217.3 119.2 84.9-2.9 144.2-26.2 181.7-71.1 38.7-46.3 53.2-116.8 43.3-209.4-6.6-42.3-3-78.2 0.5-113z"/>
</g>
</g>
<path class="s1" d="m739.8 434.2c-3 0-6.1-0.6-9-2-10.5-5-15.2-18-10.3-28.9 15.7-35.6 38.8-68.4 66.6-94.9 8.5-8.1 21.9-7.6 29.7 1.3 7.9 8.9 7.4 22.7-1.2 30.8-23.7 22.7-43.4 50.6-56.8 81-3.6 7.9-11.1 12.6-19 12.7z"/>
<path class="s1" d="m668.8 421.6c-10.9 0.1-20.3-8.5-21.2-20-4-51.4-4.2-103.5-0.4-154.8 0.9-12 11.1-21 22.6-20.1 11.6 0.9 20.3 11.3 19.4 23.3-3.6 49.1-3.4 98.9 0.4 148 1 12-7.7 22.5-19.3 23.5-0.5 0-1 0-1.5 0z"/>
<path class="s1" d="m596.2 435.1c-9.4 0.1-18.2-6.5-20.6-16.4-8.9-36.3-25.9-70.8-48.9-99.7-7.4-9.3-6.1-23 2.8-30.7 9-7.6 22.3-6.3 29.7 3 26.9 33.8 46.7 74.2 57.2 116.7 2.9 11.6-4 23.5-15.2 26.5-1.8 0.4-3.4 0.6-5.1 0.7z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

+19 -7
View File
@@ -18,6 +18,7 @@ enum IndicatorColor {
function AgentStatusBar() {
const { t } = useTranslation();
const { curAgentState } = useSelector((state: RootState) => state.agent);
const { curStatusMessage } = useSelector((state: RootState) => state.status);
const AgentStatusMap: {
[k: string]: { message: string; indicator: IndicatorColor };
@@ -90,14 +91,25 @@ function AgentStatusBar() {
}
}, [curAgentState]);
const [statusMessage, setStatusMessage] = React.useState<string>("");
React.useEffect(() => {
const trimmedCustomMessage = curStatusMessage.message.trim();
if (trimmedCustomMessage) {
setStatusMessage(t(trimmedCustomMessage));
} else {
setStatusMessage(AgentStatusMap[curAgentState].message);
}
}, [curAgentState, curStatusMessage.message]);
return (
<div className="flex items-center">
<div
className={`w-3 h-3 mr-2 rounded-full animate-pulse ${AgentStatusMap[curAgentState].indicator}`}
/>
<span className="text-sm text-stone-400">
{AgentStatusMap[curAgentState].message}
</span>
<div className="flex flex-col items-center">
<div className="flex items-center">
<div
className={`w-3 h-3 mr-2 rounded-full animate-pulse ${AgentStatusMap[curAgentState].indicator}`}
/>
<span className="text-sm text-stone-400">{statusMessage}</span>
</div>
</div>
);
}
+13 -4
View File
@@ -5,16 +5,25 @@ import { renderWithProviders } from "test-utils";
import Chat from "./Chat";
const MESSAGES: Message[] = [
{ sender: "assistant", content: "Hello!", imageUrls: [] },
{ sender: "user", content: "Hi!", imageUrls: [] },
{ sender: "assistant", content: "How can I help you today?", imageUrls: [] },
{
sender: "assistant",
content: "Hello!",
imageUrls: [],
timestamp: new Date().toISOString(),
},
{
sender: "user",
content: "Hi!",
imageUrls: [],
timestamp: new Date().toISOString(),
},
];
describe("Chat", () => {
it("should render chat messages", () => {
renderWithProviders(<Chat messages={MESSAGES} />);
const messages = screen.getAllByTestId("message");
const messages = screen.getAllByTestId("article");
expect(messages).toHaveLength(MESSAGES.length);
});
});
@@ -9,17 +9,62 @@ import ActionType from "#/types/ActionType";
import { addAssistantMessage } from "#/state/chatSlice";
import AgentState from "#/types/AgentState";
/// <reference types="vitest" />
interface CustomMatchers<R = unknown> {
toMatchMessageEvent(expected: string): R;
}
declare module "vitest" {
interface Assertion<T> extends CustomMatchers<T> {}
interface AsymmetricMatchersContaining extends CustomMatchers {}
}
// This is for the scrollview ref in Chat.tsx
// TODO: Move this into test setup
HTMLElement.prototype.scrollTo = vi.fn().mockImplementation(() => {});
const TEST_TIMESTAMP = new Date().toISOString();
describe("ChatInterface", () => {
const sessionSendSpy = vi.spyOn(Session, "send");
vi.spyOn(Session, "isConnected").mockReturnValue(true);
// TODO: replace below with e.g. fake timers
// https://vitest.dev/guide/mocking#timers
// https://vitest.dev/api/vi.html#vi-usefaketimers
// Custom matcher for testing message events
expect.extend({
toMatchMessageEvent(received, expected) {
const receivedObj = JSON.parse(received);
const expectedObj = JSON.parse(expected);
// Compare everything except the timestamp
const { timestamp: receivedTimestamp, ...receivedRest } =
receivedObj.args;
const { timestamp: expectedTimestamp, ...expectedRest } =
expectedObj.args;
const pass =
this.equals(receivedRest, expectedRest) &&
typeof receivedTimestamp === "string";
return {
pass,
message: () =>
pass
? `expected ${received} not to match the structure of ${expected} (ignoring exact timestamp)`
: `expected ${received} to match the structure of ${expected} (ignoring exact timestamp)`,
};
},
});
const userMessageEvent = {
action: ActionType.MESSAGE,
args: { content: "my message", images_urls: [] },
args: {
content: "my message",
images_urls: [],
timestamp: TEST_TIMESTAMP,
},
};
afterEach(() => {
@@ -28,19 +73,26 @@ describe("ChatInterface", () => {
it("should render empty message list and input", () => {
renderWithProviders(<ChatInterface />);
expect(screen.queryAllByTestId("message")).toHaveLength(0);
expect(screen.queryAllByTestId("article")).toHaveLength(0);
});
it("should render user and assistant messages", () => {
const { store } = renderWithProviders(<ChatInterface />, {
preloadedState: {
chat: {
messages: [{ sender: "user", content: "Hello", imageUrls: [] }],
messages: [
{
sender: "user",
content: "Hello",
imageUrls: [],
timestamp: TEST_TIMESTAMP,
},
],
},
},
});
expect(screen.getAllByTestId("message")).toHaveLength(1);
expect(screen.getAllByTestId("article")).toHaveLength(1);
expect(screen.getByText("Hello")).toBeInTheDocument();
act(() => {
@@ -48,7 +100,7 @@ describe("ChatInterface", () => {
store.dispatch(addAssistantMessage("Hello to you!"));
});
expect(screen.getAllByTestId("message")).toHaveLength(2);
expect(screen.getAllByTestId("article")).toHaveLength(2);
expect(screen.getByText("Hello to you!")).toBeInTheDocument();
});
@@ -67,7 +119,7 @@ describe("ChatInterface", () => {
await user.keyboard("{Enter}");
expect(sessionSendSpy).toHaveBeenCalledWith(
JSON.stringify(userMessageEvent),
expect.toMatchMessageEvent(JSON.stringify(userMessageEvent)),
);
});
@@ -86,7 +138,7 @@ describe("ChatInterface", () => {
await user.keyboard("{Enter}");
expect(sessionSendSpy).toHaveBeenCalledWith(
JSON.stringify(userMessageEvent),
expect.toMatchMessageEvent(JSON.stringify(userMessageEvent)),
);
});

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