Backup-bdg commited on
Commit
51ff9e5
·
verified ·
1 Parent(s): 9334ab9

Upload 964 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +13 -0
  2. CITATION.cff +55 -0
  3. CODE_OF_CONDUCT.md +147 -0
  4. COMMUNITY.md +43 -0
  5. CONTRIBUTING.md +123 -0
  6. CREDITS.md +312 -0
  7. Development.md +181 -0
  8. ISSUE_TRIAGE.md +27 -0
  9. LICENSE.txt +25 -0
  10. MANIFEST.in +5 -0
  11. Makefile.make +335 -0
  12. README.md +146 -9
  13. README_CN.md +146 -0
  14. build.sh +4 -0
  15. config.template.toml +417 -0
  16. containers/README.md +12 -0
  17. containers/app/Dockerfile +98 -0
  18. containers/app/config.sh +4 -0
  19. containers/app/entrypoint.sh +61 -0
  20. containers/build.sh +182 -0
  21. containers/dev/Dockerfile +124 -0
  22. containers/dev/README.md +57 -0
  23. containers/dev/compose.yml +38 -0
  24. containers/dev/dev.sh +39 -0
  25. containers/e2b-sandbox/Dockerfile +19 -0
  26. containers/e2b-sandbox/README.md +15 -0
  27. containers/e2b-sandbox/e2b.toml +14 -0
  28. containers/runtime/README.md +12 -0
  29. containers/runtime/config.sh +7 -0
  30. dev_config/python/mypy.ini +9 -0
  31. dev_config/python/ruff.toml +39 -0
  32. docker-compose.yml +23 -0
  33. docs/DOC_STYLE_GUIDE.md +67 -0
  34. docs/docs.json +204 -0
  35. docs/favicon.svg +19 -0
  36. docs/index.mdx +16 -0
  37. docs/logo-square.png +3 -0
  38. docs/logo/dark.svg +29 -0
  39. docs/logo/light.svg +29 -0
  40. docs/openapi.json +2091 -0
  41. docs/static/img/backend_architecture.png +3 -0
  42. docs/static/img/backend_architecture.puml +201 -0
  43. docs/static/img/backend_architecture.svg +0 -0
  44. docs/static/img/connect-repo.png +0 -0
  45. docs/static/img/docs/api-key-generation.png +0 -0
  46. docs/static/img/logo-square.png +3 -0
  47. docs/static/img/logo.png +0 -0
  48. docs/static/img/oh-features.png +3 -0
  49. docs/static/img/results.png +3 -0
  50. docs/static/img/screenshot.png +3 -0
.gitattributes CHANGED
@@ -33,3 +33,16 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ docs/logo-square.png filter=lfs diff=lfs merge=lfs -text
37
+ docs/static/img/backend_architecture.png filter=lfs diff=lfs merge=lfs -text
38
+ docs/static/img/logo-square.png filter=lfs diff=lfs merge=lfs -text
39
+ docs/static/img/oh-features.png filter=lfs diff=lfs merge=lfs -text
40
+ docs/static/img/results.png filter=lfs diff=lfs merge=lfs -text
41
+ docs/static/img/screenshot.png filter=lfs diff=lfs merge=lfs -text
42
+ docs/static/img/system_architecture_overview.png filter=lfs diff=lfs merge=lfs -text
43
+ docs/static/img/teaser.mp4 filter=lfs diff=lfs merge=lfs -text
44
+ docs/usage/llms/screenshots/1_select_power_user.png filter=lfs diff=lfs merge=lfs -text
45
+ docs/usage/llms/screenshots/2_select_model.png filter=lfs diff=lfs merge=lfs -text
46
+ docs/usage/llms/screenshots/4_set_context_window.png filter=lfs diff=lfs merge=lfs -text
47
+ docs/usage/llms/screenshots/5_copy_url.png filter=lfs diff=lfs merge=lfs -text
48
+ evaluation/static/example_task_1.png filter=lfs diff=lfs merge=lfs -text
CITATION.cff ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it using the following metadata."
3
+ title: "OpenHands: An Open Platform for AI Software Developers as Generalist Agents"
4
+ authors:
5
+ - family-names: Wang
6
+ given-names: Xingyao
7
+ - family-names: Li
8
+ given-names: Boxuan
9
+ - family-names: Song
10
+ given-names: Yufan
11
+ - family-names: Xu
12
+ given-names: Frank F.
13
+ - family-names: Tang
14
+ given-names: Xiangru
15
+ - family-names: Zhuge
16
+ given-names: Mingchen
17
+ - family-names: Pan
18
+ given-names: Jiayi
19
+ - family-names: Song
20
+ given-names: Yueqi
21
+ - family-names: Li
22
+ given-names: Bowen
23
+ - family-names: Singh
24
+ given-names: Jaskirat
25
+ - family-names: Tran
26
+ given-names: Hoang H.
27
+ - family-names: Li
28
+ given-names: Fuqiang
29
+ - family-names: Ma
30
+ given-names: Ren
31
+ - family-names: Zheng
32
+ given-names: Mingzhang
33
+ - family-names: Qian
34
+ given-names: Bill
35
+ - family-names: Shao
36
+ given-names: Yanjun
37
+ - family-names: Muennighoff
38
+ given-names: Niklas
39
+ - family-names: Zhang
40
+ given-names: Yizhe
41
+ - family-names: Hui
42
+ given-names: Binyuan
43
+ - family-names: Lin
44
+ given-names: Junyang
45
+ - family-names: Brennan
46
+ given-names: Robert
47
+ - family-names: Peng
48
+ given-names: Hao
49
+ - family-names: Ji
50
+ given-names: Heng
51
+ - family-names: Neubig
52
+ given-names: Graham
53
+ year: 2024
54
+ doi: "10.48550/arXiv.2407.16741"
55
+ url: "https://arxiv.org/abs/2407.16741"
CODE_OF_CONDUCT.md ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Contributor Covenant Code of Conduct
3
+
4
+ ## Our Pledge
5
+
6
+ We as members, contributors, and leaders pledge to make participation in our
7
+ community a harassment-free experience for everyone, regardless of age, body
8
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
9
+ identity and expression, level of experience, education, socio-economic status,
10
+ nationality, personal appearance, race, caste, color, religion, or sexual
11
+ identity and orientation.
12
+
13
+ We pledge to act and interact in ways that contribute to an open, welcoming,
14
+ diverse, inclusive, and healthy community.
15
+
16
+ ## Our Standards
17
+
18
+ Examples of behavior that contributes to a positive environment for our
19
+ community include:
20
+
21
+ * Demonstrating empathy and kindness toward other people.
22
+ * Being respectful of differing opinions, viewpoints, and experiences.
23
+ * Giving and gracefully accepting constructive feedback.
24
+ * Accepting responsibility and apologizing to those affected by our mistakes,
25
+ and learning from the experience.
26
+ * Focusing on what is best not just for us as individuals, but for the overall
27
+ community.
28
+
29
+ Examples of unacceptable behavior include:
30
+
31
+ * The use of sexualized language or imagery, and sexual attention or advances of
32
+ any kind.
33
+ * Trolling, insulting or derogatory comments, and personal or political attacks.
34
+ * Public or private harassment.
35
+ * Publishing others' private information, such as a physical or email address,
36
+ without their explicit permission.
37
+ * Other conduct which could reasonably be considered inappropriate in a
38
+ professional setting.
39
+
40
+ ## Enforcement Responsibilities
41
+
42
+ Community leaders are responsible for clarifying and enforcing our standards of
43
+ acceptable behavior and will take appropriate and fair corrective action in
44
+ response to any behavior that they deem inappropriate, threatening, offensive,
45
+ or harmful.
46
+
47
+ Community leaders have the right and responsibility to remove, edit, or reject
48
+ comments, commits, code, wiki edits, issues, and other contributions that are
49
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
50
+ decisions when appropriate.
51
+
52
+ ## Scope
53
+
54
+ This Code of Conduct applies within all community spaces, and also applies when
55
+ an individual is officially representing the community in public spaces.
56
+ Examples of representing our community include using an official email address,
57
+ posting via an official social media account, or acting as an appointed
58
+ representative at an online or offline event.
59
+
60
+ ## Enforcement
61
+
62
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
63
+ reported to the community leaders responsible for enforcement at
64
65
+ All complaints will be reviewed and investigated promptly and fairly.
66
+
67
+ All community leaders are obligated to respect the privacy and security of the
68
+ reporter of any incident.
69
+
70
+ ## Enforcement Guidelines
71
+
72
+ Community leaders will follow these Community Impact Guidelines in determining
73
+ the consequences for any action they deem in violation of this Code of Conduct:
74
+
75
+ ### 1. Correction
76
+
77
+ **Community Impact**: Use of inappropriate language or other behavior deemed
78
+ unprofessional or unwelcome in the community.
79
+
80
+ **Consequence**: A private, written warning from community leaders, providing
81
+ clarity around the nature of the violation and an explanation of why the
82
+ behavior was inappropriate. A public apology may be requested.
83
+
84
+ ### 2. Warning
85
+
86
+ **Community Impact**: A violation through a single incident or series of
87
+ actions.
88
+
89
+ **Consequence**: A warning with consequences for continued behavior. No
90
+ interaction with the people involved, including unsolicited interaction with
91
+ those enforcing the Code of Conduct, for a specified period of time. This
92
+ includes avoiding interactions in community spaces as well as external channels
93
+ like social media. Violating these terms may lead to a temporary or permanent
94
+ ban.
95
+
96
+ ### 3. Temporary Ban
97
+
98
+ **Community Impact**: A serious violation of community standards, including
99
+ sustained inappropriate behavior.
100
+
101
+ **Consequence**: A temporary ban from any sort of interaction or public
102
+ communication with the community for a specified period of time. No public or
103
+ private interaction with the people involved, including unsolicited interaction
104
+ with those enforcing the Code of Conduct, is allowed during this period.
105
+ Violating these terms may lead to a permanent ban.
106
+
107
+ ### 4. Permanent Ban
108
+
109
+ **Community Impact**: Demonstrating a pattern of violation of community
110
+ standards, including sustained inappropriate behavior, harassment of an
111
+ individual, or aggression toward or disparagement of classes of individuals.
112
+
113
+ **Consequence**: A permanent ban from any sort of public interaction within the
114
+ community.
115
+
116
+ ### Slack and Discord Etiquettes
117
+
118
+ These Slack and Discord etiquette guidelines are designed to foster an inclusive, respectful, and productive environment for all community members. By following these best practices, we ensure effective communication and collaboration while minimizing disruptions. Let’s work together to build a supportive and welcoming community!
119
+
120
+ - Communicate respectfully and professionally, avoiding sarcasm or harsh language, and remember that tone can be difficult to interpret in text.
121
+ - Use threads for specific discussions to keep channels organized and easier to follow.
122
+ - Tag others only when their input is critical or urgent, and use @here, @channel or @everyone sparingly to minimize disruptions.
123
+ - Be patient, as open-source contributors and maintainers often have other commitments and may need time to respond.
124
+ - Post questions or discussions in the most relevant channel (e.g., for [slack - #general](https://openhands-ai.slack.com/archives/C06P5NCGSFP) for general topics, [slack - #questions](https://openhands-ai.slack.com/archives/C06U8UTKSAD) for queries/questions, [discord - #general](https://discord.com/channels/1222935860639563850/1222935861386018885)).
125
+ - When asking for help or raising issues, include necessary details like links, screenshots, or clear explanations to provide context.
126
+ - Keep discussions in public channels whenever possible to allow others to benefit from the conversation, unless the matter is sensitive or private.
127
+ - Always adhere to [our standards](https://github.com/All-Hands-AI/OpenHands/blob/main/CODE_OF_CONDUCT.md#our-standards) to ensure a welcoming and collaborative environment.
128
+ - If you choose to mute a channel, consider setting up alerts for topics that still interest you to stay engaged. For Slack, Go to Settings → Notifications → My Keywords to add specific keywords that will notify you when mentioned. For example, if you're here for discussions about LLMs, mute the channel if it’s too busy, but set notifications to alert you only when “LLMs” appears in messages. Also for Discord, go to the channel notifications and choose the option that best describes your need.
129
+
130
+ ## Attribution
131
+
132
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
133
+ version 2.1, available at
134
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
135
+
136
+ Community Impact Guidelines were inspired by
137
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
138
+
139
+ For answers to common questions about this code of conduct, see the FAQ at
140
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
141
+ [https://www.contributor-covenant.org/translations][translations].
142
+
143
+ [homepage]: https://www.contributor-covenant.org
144
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
145
+ [Mozilla CoC]: https://github.com/mozilla/diversity
146
+ [FAQ]: https://www.contributor-covenant.org/faq
147
+ [translations]: https://www.contributor-covenant.org/translations
COMMUNITY.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🙌 The OpenHands Community
2
+
3
+ The OpenHands community is built around the belief that (1) AI and AI agents are going to fundamentally change the way
4
+ we build software, and (2) if this is true, we should do everything we can to make sure that the benefits provided by
5
+ such powerful technology are accessible to everyone.
6
+
7
+ If this resonates with you, we'd love to have you join us in our quest!
8
+
9
+ ## 🤝 How to Join
10
+
11
+ Check out our [How to Join the Community section.](https://github.com/All-Hands-AI/OpenHands?tab=readme-ov-file#-how-to-join-the-community)
12
+
13
+ ## 💪 Becoming a Contributor
14
+
15
+ We welcome contributions from everyone! Whether you're a developer, a researcher, or simply enthusiastic about advancing
16
+ the field of software engineering with AI, there are many ways to get involved:
17
+
18
+ - **Code Contributions:** Help us develop new core functionality, improve our agents, improve the frontend and other
19
+ interfaces, or anything else that would help make OpenHands better.
20
+ - **Research and Evaluation:** Contribute to our understanding of LLMs in software engineering, participate in
21
+ evaluating the models, or suggest improvements.
22
+ - **Feedback and Testing:** Use the OpenHands toolset, report bugs, suggest features, or provide feedback on usability.
23
+
24
+ For details, please check [CONTRIBUTING.md](./CONTRIBUTING.md).
25
+
26
+ ## Code of Conduct
27
+
28
+ We have a [Code of Conduct](./CODE_OF_CONDUCT.md) that we expect all contributors to adhere to.
29
+ Long story short, we are aiming for an open, welcoming, diverse, inclusive, and healthy community.
30
+ All contributors are expected to contribute to building this sort of community.
31
+
32
+ ## 🛠️ Becoming a Maintainer
33
+
34
+ For contributors who have made significant and sustained contributions to the project, there is a possibility of joining
35
+ the maintainer team. The process for this is as follows:
36
+
37
+ 1. Any contributor who has made sustained and high-quality contributions to the codebase can be nominated by any
38
+ maintainer. If you feel that you may qualify you can reach out to any of the maintainers that have reviewed your PRs and ask if you can be nominated.
39
+ 2. Once a maintainer nominates a new maintainer, there will be a discussion period among the maintainers for at least 3 days.
40
+ 3. If no concerns are raised the nomination will be accepted by acclamation, and if concerns are raised there will be a discussion and possible vote.
41
+
42
+ Note that just making many PRs does not immediately imply that you will become a maintainer. We will be looking
43
+ at sustained high-quality contributions over a period of time, as well as good teamwork and adherence to our [Code of Conduct](./CODE_OF_CONDUCT.md).
CONTRIBUTING.md ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing
2
+
3
+ Thanks for your interest in contributing to OpenHands! We welcome and appreciate contributions.
4
+
5
+ ## Understanding OpenHands's CodeBase
6
+
7
+ To understand the codebase, please refer to the README in each module:
8
+ - [frontend](./frontend/README.md)
9
+ - [evaluation](./evaluation/README.md)
10
+ - [openhands](./openhands/README.md)
11
+ - [agenthub](./openhands/agenthub/README.md)
12
+ - [server](./openhands/server/README.md)
13
+
14
+ ## Setting up Your Development Environment
15
+
16
+ We have a separate doc [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md) that tells you how to set up a development workflow.
17
+
18
+ ## How Can I Contribute?
19
+
20
+ There are many ways that you can contribute:
21
+
22
+ 1. **Download and use** OpenHands, and send [issues](https://github.com/All-Hands-AI/OpenHands/issues) when you encounter something that isn't working or a feature that you'd like to see.
23
+ 2. **Send feedback** after each session by [clicking the thumbs-up thumbs-down buttons](https://docs.all-hands.dev/usage/feedback), so we can see where things are working and failing, and also build an open dataset for training code agents.
24
+ 3. **Improve the Codebase** by sending [PRs](#sending-pull-requests-to-openhands) (see details below). In particular, we have some [good first issues](https://github.com/All-Hands-AI/OpenHands/labels/good%20first%20issue) that may be ones to start on.
25
+
26
+ ## What Can I Build?
27
+ Here are a few ways you can help improve the codebase.
28
+
29
+ #### UI/UX
30
+ We're always looking to improve the look and feel of the application. If you've got a small fix
31
+ for something that's bugging you, feel free to open up a PR that changes the [`./frontend`](./frontend) directory.
32
+
33
+ If you're looking to make a bigger change, add a new UI element, or significantly alter the style
34
+ of the application, please open an issue first, or better, join the #frontend channel in our Slack
35
+ to gather consensus from our design team first.
36
+
37
+ #### Improving the agent
38
+ Our main agent is the CodeAct agent. You can [see its prompts here](https://github.com/All-Hands-AI/OpenHands/tree/main/openhands/agenthub/codeact_agent).
39
+
40
+ Changes to these prompts, and to the underlying behavior in Python, can have a huge impact on user experience.
41
+ You can try modifying the prompts to see how they change the behavior of the agent as you use the app
42
+ locally, but we will need to do an end-to-end evaluation of any changes here to ensure that the agent
43
+ is getting better over time.
44
+
45
+ We use the [SWE-bench](https://www.swebench.com/) benchmark to test our agent. You can join the #evaluation
46
+ channel in Slack to learn more.
47
+
48
+ #### Adding a new agent
49
+ You may want to experiment with building new types of agents. You can add an agent to [`openhands/agenthub`](./openhands/agenthub)
50
+ to help expand the capabilities of OpenHands.
51
+
52
+ #### Adding a new runtime
53
+ The agent needs a place to run code and commands. When you run OpenHands on your laptop, it uses a Docker container
54
+ to do this by default. But there are other ways of creating a sandbox for the agent.
55
+
56
+ If you work for a company that provides a cloud-based runtime, you could help us add support for that runtime
57
+ by implementing the [interface specified here](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/base.py).
58
+
59
+ #### Testing
60
+ When you write code, it is also good to write tests. Please navigate to the [`./tests`](./tests) folder to see existing test suites.
61
+ At the moment, we have two kinds of tests: [`unit`](./tests/unit) and [`integration`](./evaluation/integration_tests). Please refer to the README for each test suite. These tests also run on GitHub's continuous integration to ensure quality of the project.
62
+
63
+ ## Sending Pull Requests to OpenHands
64
+
65
+ You'll need to fork our repository to send us a Pull Request. You can learn more
66
+ about how to fork a GitHub repo and open a PR with your changes in [this article](https://medium.com/swlh/forks-and-pull-requests-how-to-contribute-to-github-repos-8843fac34ce8).
67
+
68
+ ### Pull Request title
69
+ As described [here](https://github.com/commitizen/conventional-commit-types/blob/master/index.json), a valid PR title should begin with one of the following prefixes:
70
+
71
+ - `feat`: A new feature
72
+ - `fix`: A bug fix
73
+ - `docs`: Documentation only changes
74
+ - `style`: Changes that do not affect the meaning of the code (white space, formatting, missing semicolons, etc.)
75
+ - `refactor`: A code change that neither fixes a bug nor adds a feature
76
+ - `perf`: A code change that improves performance
77
+ - `test`: Adding missing tests or correcting existing tests
78
+ - `build`: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
79
+ - `ci`: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
80
+ - `chore`: Other changes that don't modify src or test files
81
+ - `revert`: Reverts a previous commit
82
+
83
+ For example, a PR title could be:
84
+ - `refactor: modify package path`
85
+ - `feat(frontend): xxxx`, where `(frontend)` means that this PR mainly focuses on the frontend component.
86
+
87
+ You may also check out previous PRs in the [PR list](https://github.com/All-Hands-AI/OpenHands/pulls).
88
+
89
+ ### Pull Request description
90
+ - If your PR is small (such as a typo fix), you can go brief.
91
+ - If it contains a lot of changes, it's better to write more details.
92
+
93
+ If your changes are user-facing (e.g. a new feature in the UI, a change in behavior, or a bugfix)
94
+ please include a short message that we can add to our changelog.
95
+
96
+ ## How to Make Effective Contributions
97
+
98
+ ### Opening Issues
99
+
100
+ If you notice any bugs or have any feature requests please open them via the [issues page](https://github.com/All-Hands-AI/OpenHands/issues). We will triage based on how critical the bug is or how potentially useful the improvement is, discuss, and implement the ones that the community has interest/effort for.
101
+
102
+ Further, if you see an issue you like, please leave a "thumbs-up" or a comment, which will help us prioritize.
103
+
104
+ ### Making Pull Requests
105
+
106
+ We're generally happy to consider all pull requests with the evaluation process varying based on the type of change:
107
+
108
+ #### For Small Improvements
109
+
110
+ Small improvements with few downsides are typically reviewed and approved quickly.
111
+ One thing to check when making changes is to ensure that all continuous integration tests pass, which you can check before getting a review.
112
+
113
+ #### For Core Agent Changes
114
+
115
+ We need to be more careful with changes to the core agent, as it is imperative to maintain high quality. These PRs are evaluated based on three key metrics:
116
+
117
+ 1. **Accuracy**
118
+ 2. **Efficiency**
119
+ 3. **Code Complexity**
120
+
121
+ If it improves accuracy, efficiency, or both with only a minimal change to code quality, that's great we're happy to merge it in!
122
+ If there are bigger tradeoffs (e.g. helping efficiency a lot and hurting accuracy a little) we might want to put it behind a feature flag.
123
+ Either way, please feel free to discuss on github issues or slack, and we will give guidance and preliminary feedback.
CREDITS.md ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Credits
2
+
3
+ ## Contributors
4
+
5
+ We would like to thank all the [contributors](https://github.com/All-Hands-AI/OpenHands/graphs/contributors) who have helped make OpenHands possible. We greatly appreciate your dedication and hard work.
6
+
7
+ ## Open Source Projects
8
+
9
+ OpenHands includes and adapts the following open source projects. We are grateful for their contributions to the open source community:
10
+
11
+ #### [SWE Agent](https://github.com/princeton-nlp/swe-agent)
12
+ - License: MIT License
13
+ - Description: Adapted for use in OpenHands's agent hub
14
+
15
+ #### [Aider](https://github.com/paul-gauthier/aider)
16
+ - License: Apache License 2.0
17
+ - Description: AI pair programming tool. OpenHands has adapted and integrated its linter module for code-related tasks in [`agentskills utilities`](https://github.com/All-Hands-AI/OpenHands/tree/main/openhands/runtime/plugins/agent_skills/utils/aider)
18
+
19
+ #### [BrowserGym](https://github.com/ServiceNow/BrowserGym)
20
+ - License: Apache License 2.0
21
+ - Description: Adapted in implementing the browsing agent
22
+
23
+
24
+ ### Reference Implementations for Evaluation Benchmarks
25
+ OpenHands integrates code of the reference implementations for the following agent evaluation benchmarks:
26
+
27
+ #### [HumanEval](https://github.com/openai/human-eval)
28
+ - License: MIT License
29
+
30
+ #### [DSP](https://github.com/microsoft/DataScienceProblems)
31
+ - License: MIT License
32
+
33
+ #### [HumanEvalPack](https://github.com/bigcode-project/bigcode-evaluation-harness)
34
+ - License: Apache License 2.0
35
+
36
+ #### [AgentBench](https://github.com/THUDM/AgentBench)
37
+ - License: Apache License 2.0
38
+
39
+ #### [SWE-Bench](https://github.com/princeton-nlp/SWE-bench)
40
+ - License: MIT License
41
+
42
+ #### [BIRD](https://bird-bench.github.io/)
43
+ - License: MIT License
44
+ - Dataset: CC-BY-SA 4.0
45
+
46
+ #### [Gorilla APIBench](https://github.com/ShishirPatil/gorilla)
47
+ - License: Apache License 2.0
48
+
49
+ #### [GPQA](https://github.com/idavidrein/gpqa)
50
+ - License: MIT License
51
+
52
+ #### [ProntoQA](https://github.com/asaparov/prontoqa)
53
+ - License: Apache License 2.0
54
+
55
+
56
+ ## Open Source licenses
57
+
58
+ ### MIT License
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
61
+
62
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
63
+
64
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
65
+
66
+ ### BSD 3-Clause License
67
+
68
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
69
+
70
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
71
+
72
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
73
+
74
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
75
+
76
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
77
+
78
+ ### Apache License 2.0
79
+
80
+
81
+ Apache License
82
+ Version 2.0, January 2004
83
+ http://www.apache.org/licenses/
84
+
85
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
86
+
87
+ 1. Definitions.
88
+
89
+ "License" shall mean the terms and conditions for use, reproduction,
90
+ and distribution as defined by Sections 1 through 9 of this document.
91
+
92
+ "Licensor" shall mean the copyright owner or entity authorized by
93
+ the copyright owner that is granting the License.
94
+
95
+ "Legal Entity" shall mean the union of the acting entity and all
96
+ other entities that control, are controlled by, or are under common
97
+ control with that entity. For the purposes of this definition,
98
+ "control" means (i) the power, direct or indirect, to cause the
99
+ direction or management of such entity, whether by contract or
100
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
101
+ outstanding shares, or (iii) beneficial ownership of such entity.
102
+
103
+ "You" (or "Your") shall mean an individual or Legal Entity
104
+ exercising permissions granted by this License.
105
+
106
+ "Source" form shall mean the preferred form for making modifications,
107
+ including but not limited to software source code, documentation
108
+ source, and configuration files.
109
+
110
+ "Object" form shall mean any form resulting from mechanical
111
+ transformation or translation of a Source form, including but
112
+ not limited to compiled object code, generated documentation,
113
+ and conversions to other media types.
114
+
115
+ "Work" shall mean the work of authorship, whether in Source or
116
+ Object form, made available under the License, as indicated by a
117
+ copyright notice that is included in or attached to the work
118
+ (an example is provided in the Appendix below).
119
+
120
+ "Derivative Works" shall mean any work, whether in Source or Object
121
+ form, that is based on (or derived from) the Work and for which the
122
+ editorial revisions, annotations, elaborations, or other modifications
123
+ represent, as a whole, an original work of authorship. For the purposes
124
+ of this License, Derivative Works shall not include works that remain
125
+ separable from, or merely link (or bind by name) to the interfaces of,
126
+ the Work and Derivative Works thereof.
127
+
128
+ "Contribution" shall mean any work of authorship, including
129
+ the original version of the Work and any modifications or additions
130
+ to that Work or Derivative Works thereof, that is intentionally
131
+ submitted to Licensor for inclusion in the Work by the copyright owner
132
+ or by an individual or Legal Entity authorized to submit on behalf of
133
+ the copyright owner. For the purposes of this definition, "submitted"
134
+ means any form of electronic, verbal, or written communication sent
135
+ to the Licensor or its representatives, including but not limited to
136
+ communication on electronic mailing lists, source code control systems,
137
+ and issue tracking systems that are managed by, or on behalf of, the
138
+ Licensor for the purpose of discussing and improving the Work, but
139
+ excluding communication that is conspicuously marked or otherwise
140
+ designated in writing by the copyright owner as "Not a Contribution."
141
+
142
+ "Contributor" shall mean Licensor and any individual or Legal Entity
143
+ on behalf of whom a Contribution has been received by Licensor and
144
+ subsequently incorporated within the Work.
145
+
146
+ 2. Grant of Copyright License. Subject to the terms and conditions of
147
+ this License, each Contributor hereby grants to You a perpetual,
148
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
149
+ copyright license to reproduce, prepare Derivative Works of,
150
+ publicly display, publicly perform, sublicense, and distribute the
151
+ Work and such Derivative Works in Source or Object form.
152
+
153
+ 3. Grant of Patent License. Subject to the terms and conditions of
154
+ this License, each Contributor hereby grants to You a perpetual,
155
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
156
+ (except as stated in this section) patent license to make, have made,
157
+ use, offer to sell, sell, import, and otherwise transfer the Work,
158
+ where such license applies only to those patent claims licensable
159
+ by such Contributor that are necessarily infringed by their
160
+ Contribution(s) alone or by combination of their Contribution(s)
161
+ with the Work to which such Contribution(s) was submitted. If You
162
+ institute patent litigation against any entity (including a
163
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
164
+ or a Contribution incorporated within the Work constitutes direct
165
+ or contributory patent infringement, then any patent licenses
166
+ granted to You under this License for that Work shall terminate
167
+ as of the date such litigation is filed.
168
+
169
+ 4. Redistribution. You may reproduce and distribute copies of the
170
+ Work or Derivative Works thereof in any medium, with or without
171
+ modifications, and in Source or Object form, provided that You
172
+ meet the following conditions:
173
+
174
+ (a) You must give any other recipients of the Work or
175
+ Derivative Works a copy of this License; and
176
+
177
+ (b) You must cause any modified files to carry prominent notices
178
+ stating that You changed the files; and
179
+
180
+ (c) You must retain, in the Source form of any Derivative Works
181
+ that You distribute, all copyright, patent, trademark, and
182
+ attribution notices from the Source form of the Work,
183
+ excluding those notices that do not pertain to any part of
184
+ the Derivative Works; and
185
+
186
+ (d) If the Work includes a "NOTICE" text file as part of its
187
+ distribution, then any Derivative Works that You distribute must
188
+ include a readable copy of the attribution notices contained
189
+ within such NOTICE file, excluding those notices that do not
190
+ pertain to any part of the Derivative Works, in at least one
191
+ of the following places: within a NOTICE text file distributed
192
+ as part of the Derivative Works; within the Source form or
193
+ documentation, if provided along with the Derivative Works; or,
194
+ within a display generated by the Derivative Works, if and
195
+ wherever such third-party notices normally appear. The contents
196
+ of the NOTICE file are for informational purposes only and
197
+ do not modify the License. You may add Your own attribution
198
+ notices within Derivative Works that You distribute, alongside
199
+ or as an addendum to the NOTICE text from the Work, provided
200
+ that such additional attribution notices cannot be construed
201
+ as modifying the License.
202
+
203
+ You may add Your own copyright statement to Your modifications and
204
+ may provide additional or different license terms and conditions
205
+ for use, reproduction, or distribution of Your modifications, or
206
+ for any such Derivative Works as a whole, provided Your use,
207
+ reproduction, and distribution of the Work otherwise complies with
208
+ the conditions stated in this License.
209
+
210
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
211
+ any Contribution intentionally submitted for inclusion in the Work
212
+ by You to the Licensor shall be under the terms and conditions of
213
+ this License, without any additional terms or conditions.
214
+ Notwithstanding the above, nothing herein shall supersede or modify
215
+ the terms of any separate license agreement you may have executed
216
+ with Licensor regarding such Contributions.
217
+
218
+ 6. Trademarks. This License does not grant permission to use the trade
219
+ names, trademarks, service marks, or product names of the Licensor,
220
+ except as required for reasonable and customary use in describing the
221
+ origin of the Work and reproducing the content of the NOTICE file.
222
+
223
+ 7. Disclaimer of Warranty. Unless required by applicable law or
224
+ agreed to in writing, Licensor provides the Work (and each
225
+ Contributor provides its Contributions) on an "AS IS" BASIS,
226
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
227
+ implied, including, without limitation, any warranties or conditions
228
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
229
+ PARTICULAR PURPOSE. You are solely responsible for determining the
230
+ appropriateness of using or redistributing the Work and assume any
231
+ risks associated with Your exercise of permissions under this License.
232
+
233
+ 8. Limitation of Liability. In no event and under no legal theory,
234
+ whether in tort (including negligence), contract, or otherwise,
235
+ unless required by applicable law (such as deliberate and grossly
236
+ negligent acts) or agreed to in writing, shall any Contributor be
237
+ liable to You for damages, including any direct, indirect, special,
238
+ incidental, or consequential damages of any character arising as a
239
+ result of this License or out of the use or inability to use the
240
+ Work (including but not limited to damages for loss of goodwill,
241
+ work stoppage, computer failure or malfunction, or any and all
242
+ other commercial damages or losses), even if such Contributor
243
+ has been advised of the possibility of such damages.
244
+
245
+ 9. Accepting Warranty or Additional Liability. While redistributing
246
+ the Work or Derivative Works thereof, You may choose to offer,
247
+ and charge a fee for, acceptance of support, warranty, indemnity,
248
+ or other liability obligations and/or rights consistent with this
249
+ License. However, in accepting such obligations, You may act only
250
+ on Your own behalf and on Your sole responsibility, not on behalf
251
+ of any other Contributor, and only if You agree to indemnify,
252
+ defend, and hold each Contributor harmless for any liability
253
+ incurred by, or claims asserted against, such Contributor by reason
254
+ of your accepting any such warranty or additional liability.
255
+
256
+ END OF TERMS AND CONDITIONS
257
+
258
+ APPENDIX: How to apply the Apache License to your work.
259
+
260
+ To apply the Apache License to your work, attach the following
261
+ boilerplate notice, with the fields enclosed by brackets "[]"
262
+ replaced with your own identifying information. (Don't include
263
+ the brackets!) The text should be enclosed in the appropriate
264
+ comment syntax for the file format. We also recommend that a
265
+ file or class name and description of purpose be included on the
266
+ same "printed page" as the copyright notice for easier
267
+ identification within third-party archives.
268
+
269
+ Copyright [yyyy] [name of copyright owner]
270
+
271
+
272
+
273
+ ### Non-Open Source Reference Implementations:
274
+
275
+ #### [MultiPL-E](https://github.com/nuprl/MultiPL-E)
276
+ - License: BSD 3-Clause License with Machine Learning Restriction
277
+
278
+ BSD 3-Clause License with Machine Learning Restriction
279
+
280
+ Copyright (c) 2022, Northeastern University, Oberlin College, Roblox Inc,
281
+ Stevens Institute of Technology, University of Massachusetts Amherst, and
282
+ Wellesley College.
283
+
284
+ All rights reserved.
285
+
286
+ Redistribution and use in source and binary forms, with or without
287
+ modification, are permitted provided that the following conditions are met:
288
+
289
+ 1. Redistributions of source code must retain the above copyright notice, this
290
+ list of conditions and the following disclaimer.
291
+
292
+ 2. Redistributions in binary form must reproduce the above copyright notice,
293
+ this list of conditions and the following disclaimer in the documentation
294
+ and/or other materials provided with the distribution.
295
+
296
+ 3. Neither the name of the copyright holder nor the names of its
297
+ contributors may be used to endorse or promote products derived from
298
+ this software without specific prior written permission.
299
+
300
+ 4. The contents of this repository may not be used as training data for any
301
+ machine learning model, including but not limited to neural networks.
302
+
303
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
304
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
305
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
306
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
307
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
308
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
309
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
310
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
311
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
312
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Development.md ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Development Guide
2
+
3
+ This guide is for people working on OpenHands and editing the source code.
4
+ If you wish to contribute your changes, check out the
5
+ [CONTRIBUTING.md](https://github.com/All-Hands-AI/OpenHands/blob/main/CONTRIBUTING.md)
6
+ on how to clone and setup the project initially before moving on. Otherwise,
7
+ you can clone the OpenHands project directly.
8
+
9
+ ## Start the Server for Development
10
+
11
+ ### 1. Requirements
12
+
13
+ - Linux, Mac OS, or [WSL on Windows](https://learn.microsoft.com/en-us/windows/wsl/install) [Ubuntu >= 22.04]
14
+ - [Docker](https://docs.docker.com/engine/install/) (For those on MacOS, make sure to allow the default Docker socket to be used from advanced settings!)
15
+ - [Python](https://www.python.org/downloads/) = 3.12
16
+ - [NodeJS](https://nodejs.org/en/download/package-manager) >= 22.x
17
+ - [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) >= 1.8
18
+ - OS-specific dependencies:
19
+ - Ubuntu: build-essential => `sudo apt-get install build-essential python3.12-dev`
20
+ - WSL: netcat => `sudo apt-get install netcat`
21
+
22
+ Make sure you have all these dependencies installed before moving on to `make build`.
23
+
24
+ #### Dev container
25
+
26
+ There is a [dev container](https://containers.dev/) available which provides a
27
+ pre-configured environment with all the necessary dependencies installed if you
28
+ are using a [supported editor or tool](https://containers.dev/supporting). For
29
+ example, if you are using Visual Studio Code (VS Code) with the
30
+ [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
31
+ extension installed, you can open the project in a dev container by using the
32
+ _Dev Container: Reopen in Container_ command from the Command Palette
33
+ (Ctrl+Shift+P).
34
+
35
+ #### Develop without sudo access
36
+
37
+ If you want to develop without system admin/sudo access to upgrade/install `Python` and/or `NodeJs`, you can use
38
+ `conda` or `mamba` to manage the packages for you:
39
+
40
+ ```bash
41
+ # Download and install Mamba (a faster version of conda)
42
+ curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
43
+ bash Miniforge3-$(uname)-$(uname -m).sh
44
+
45
+ # Install Python 3.12, nodejs, and poetry
46
+ mamba install python=3.12
47
+ mamba install conda-forge::nodejs
48
+ mamba install conda-forge::poetry
49
+ ```
50
+
51
+ ### 2. Build and Setup The Environment
52
+
53
+ Begin by building the project which includes setting up the environment and installing dependencies. This step ensures
54
+ that OpenHands is ready to run on your system:
55
+
56
+ ```bash
57
+ make build
58
+ ```
59
+
60
+ ### 3. Configuring the Language Model
61
+
62
+ OpenHands supports a diverse array of Language Models (LMs) through the powerful [litellm](https://docs.litellm.ai) library.
63
+
64
+ To configure the LM of your choice, run:
65
+
66
+ ```bash
67
+ make setup-config
68
+ ```
69
+
70
+ This command will prompt you to enter the LLM API key, model name, and other variables ensuring that OpenHands is
71
+ tailored to your specific needs. Note that the model name will apply only when you run headless. If you use the UI,
72
+ please set the model in the UI.
73
+
74
+ Note: If you have previously run OpenHands using the docker command, you may have already set some environmental
75
+ variables in your terminal. The final configurations are set from highest to lowest priority:
76
+ Environment variables > config.toml variables > default variables
77
+
78
+ **Note on Alternative Models:**
79
+ See [our documentation](https://docs.all-hands.dev/usage/llms) for recommended models.
80
+
81
+ ### 4. Running the application
82
+
83
+ #### Option A: Run the Full Application
84
+
85
+ Once the setup is complete, this command starts both the backend and frontend servers, allowing you to interact with OpenHands:
86
+
87
+ ```bash
88
+ make run
89
+ ```
90
+
91
+ #### Option B: Individual Server Startup
92
+
93
+ - **Start the Backend Server:** If you prefer, you can start the backend server independently to focus on
94
+ backend-related tasks or configurations.
95
+
96
+ ```bash
97
+ make start-backend
98
+ ```
99
+
100
+ - **Start the Frontend Server:** Similarly, you can start the frontend server on its own to work on frontend-related
101
+ components or interface enhancements.
102
+ ```bash
103
+ make start-frontend
104
+ ```
105
+
106
+ ### 6. LLM Debugging
107
+
108
+ If you encounter any issues with the Language Model (LM) or you're simply curious, export DEBUG=1 in the environment and restart the backend.
109
+ OpenHands will log the prompts and responses in the logs/llm/CURRENT_DATE directory, allowing you to identify the causes.
110
+
111
+ ### 7. Help
112
+
113
+ Need help or info on available targets and commands? Use the help command for all the guidance you need with OpenHands.
114
+
115
+ ```bash
116
+ make help
117
+ ```
118
+
119
+ ### 8. Testing
120
+
121
+ To run tests, refer to the following:
122
+
123
+ #### Unit tests
124
+
125
+ ```bash
126
+ poetry run pytest ./tests/unit/test_*.py
127
+ ```
128
+
129
+ ### 9. Add or update dependency
130
+
131
+ 1. Add your dependency in `pyproject.toml` or use `poetry add xxx`.
132
+ 2. Update the poetry.lock file via `poetry lock --no-update`.
133
+
134
+ ### 9. Use existing Docker image
135
+
136
+ To reduce build time (e.g., if no changes were made to the client-runtime component), you can use an existing Docker
137
+ container image by setting the SANDBOX_RUNTIME_CONTAINER_IMAGE environment variable to the desired Docker image.
138
+
139
+ Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.41-nikolaik`
140
+
141
+ ## Develop inside Docker container
142
+
143
+ TL;DR
144
+
145
+ ```bash
146
+ make docker-dev
147
+ ```
148
+
149
+ See more details [here](./containers/dev/README.md).
150
+
151
+ If you are just interested in running `OpenHands` without installing all the required tools on your host.
152
+
153
+ ```bash
154
+ make docker-run
155
+ ```
156
+
157
+ If you do not have `make` on your host, run:
158
+
159
+ ```bash
160
+ cd ./containers/dev
161
+ ./dev.sh
162
+ ```
163
+
164
+ You do need [Docker](https://docs.docker.com/engine/install/) installed on your host though.
165
+
166
+ ## Key Documentation Resources
167
+
168
+ Here's a guide to the important documentation files in the repository:
169
+
170
+ - [/README.md](./README.md): Main project overview, features, and basic setup instructions
171
+ - [/Development.md](./Development.md) (this file): Comprehensive guide for developers working on OpenHands
172
+ - [/CONTRIBUTING.md](./CONTRIBUTING.md): Guidelines for contributing to the project, including code style and PR process
173
+ - [/docs/DOC_STYLE_GUIDE.md](./docs/DOC_STYLE_GUIDE.md): Standards for writing and maintaining project documentation
174
+ - [/openhands/README.md](./openhands/README.md): Details about the backend Python implementation
175
+ - [/frontend/README.md](./frontend/README.md): Frontend React application setup and development guide
176
+ - [/containers/README.md](./containers/README.md): Information about Docker containers and deployment
177
+ - [/tests/unit/README.md](./tests/unit/README.md): Guide to writing and running unit tests
178
+ - [/evaluation/README.md](./evaluation/README.md): Documentation for the evaluation framework and benchmarks
179
+ - [/microagents/README.md](./microagents/README.md): Information about the microagents architecture and implementation
180
+ - [/openhands/server/README.md](./openhands/server/README.md): Server implementation details and API documentation
181
+ - [/openhands/runtime/README.md](./openhands/runtime/README.md): Documentation for the runtime environment and execution model
ISSUE_TRIAGE.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Issue Triage
2
+ These are the procedures and guidelines on how issues are triaged in this repo by the maintainers.
3
+
4
+ ## General
5
+ * All issues must be tagged with **enhancement**, **bug** or **troubleshooting/help**.
6
+ * Issues may be tagged with what it relates to (**agent quality**, **resolver**, **CLI**, etc.).
7
+
8
+ ## Severity
9
+ * **High**: High visibility issues or affecting many users.
10
+ * **Critical**: Affecting all users or potential security issues.
11
+
12
+ ## Difficulty
13
+ * Issues with low implementation difficulty may be tagged with **good first issue**.
14
+
15
+ ## Not Enough Information
16
+ * User is asked to provide more information (logs, how to reproduce, etc.) when the issue is not clear.
17
+ * If an issue is unclear and the author does not provide more information or respond to a request,
18
+ the issue may be closed as **not planned** (Usually after a week).
19
+
20
+ ## Multiple Requests/Fixes in One Issue
21
+ * These issues will be narrowed down to one request/fix so the issue is more easily tracked and fixed.
22
+ * Issues may be broken down into multiple issues if required.
23
+
24
+ ## Stale and Auto Closures
25
+ * In order to keep a maintainable backlog, issues that have no activity within 30 days are automatically marked as **Stale**.
26
+ * If issues marked as **Stale** continue to have no activity for 7 more days, they will automatically be closed as not planned.
27
+ * Issues may be reopened by maintainers if deemed important.
LICENSE.txt ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+ =====================
3
+
4
+ Copyright © 2023
5
+
6
+ Permission is hereby granted, free of charge, to any person
7
+ obtaining a copy of this software and associated documentation
8
+ files (the “Software”), to deal in the Software without
9
+ restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the
12
+ Software is furnished to do so, subject to the following
13
+ conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
MANIFEST.in ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Exclude all Python bytecode files
2
+ global-exclude *.pyc
3
+
4
+ # Exclude Python cache directories
5
+ global-exclude __pycache__
Makefile.make ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SHELL=/usr/bin/env bash
2
+ # Makefile for OpenHands project
3
+
4
+ # Variables
5
+ BACKEND_HOST ?= "127.0.0.1"
6
+ BACKEND_PORT = 3000
7
+ BACKEND_HOST_PORT = "$(BACKEND_HOST):$(BACKEND_PORT)"
8
+ FRONTEND_HOST ?= "127.0.0.1"
9
+ FRONTEND_PORT = 3001
10
+ DEFAULT_WORKSPACE_DIR = "./workspace"
11
+ DEFAULT_MODEL = "gpt-4o"
12
+ CONFIG_FILE = config.toml
13
+ PRE_COMMIT_CONFIG_PATH = "./dev_config/python/.pre-commit-config.yaml"
14
+ PYTHON_VERSION = 3.12
15
+
16
+ # ANSI color codes
17
+ GREEN=$(shell tput -Txterm setaf 2)
18
+ YELLOW=$(shell tput -Txterm setaf 3)
19
+ RED=$(shell tput -Txterm setaf 1)
20
+ BLUE=$(shell tput -Txterm setaf 6)
21
+ RESET=$(shell tput -Txterm sgr0)
22
+
23
+ # Build
24
+ build:
25
+ @echo "$(GREEN)Building project...$(RESET)"
26
+ @$(MAKE) -s check-dependencies
27
+ @$(MAKE) -s install-python-dependencies
28
+ @$(MAKE) -s install-frontend-dependencies
29
+ @$(MAKE) -s install-pre-commit-hooks
30
+ @$(MAKE) -s build-frontend
31
+ @echo "$(GREEN)Build completed successfully.$(RESET)"
32
+
33
+ check-dependencies:
34
+ @echo "$(YELLOW)Checking dependencies...$(RESET)"
35
+ @$(MAKE) -s check-system
36
+ @$(MAKE) -s check-python
37
+ @$(MAKE) -s check-npm
38
+ @$(MAKE) -s check-nodejs
39
+ ifeq ($(INSTALL_DOCKER),)
40
+ @$(MAKE) -s check-docker
41
+ endif
42
+ @$(MAKE) -s check-poetry
43
+ @$(MAKE) -s check-tmux
44
+ @echo "$(GREEN)Dependencies checked successfully.$(RESET)"
45
+
46
+ check-system:
47
+ @echo "$(YELLOW)Checking system...$(RESET)"
48
+ @if [ "$(shell uname)" = "Darwin" ]; then \
49
+ echo "$(BLUE)macOS detected.$(RESET)"; \
50
+ elif [ "$(shell uname)" = "Linux" ]; then \
51
+ if [ -f "/etc/manjaro-release" ]; then \
52
+ echo "$(BLUE)Manjaro Linux detected.$(RESET)"; \
53
+ else \
54
+ echo "$(BLUE)Linux detected.$(RESET)"; \
55
+ fi; \
56
+ elif [ "$$(uname -r | grep -i microsoft)" ]; then \
57
+ echo "$(BLUE)Windows Subsystem for Linux detected.$(RESET)"; \
58
+ else \
59
+ echo "$(RED)Unsupported system detected. Please use macOS, Linux, or Windows Subsystem for Linux (WSL).$(RESET)"; \
60
+ exit 1; \
61
+ fi
62
+
63
+ check-python:
64
+ @echo "$(YELLOW)Checking Python installation...$(RESET)"
65
+ @if command -v python$(PYTHON_VERSION) > /dev/null; then \
66
+ echo "$(BLUE)$(shell python$(PYTHON_VERSION) --version) is already installed.$(RESET)"; \
67
+ else \
68
+ echo "$(RED)Python $(PYTHON_VERSION) is not installed. Please install Python $(PYTHON_VERSION) to continue.$(RESET)"; \
69
+ exit 1; \
70
+ fi
71
+
72
+ check-npm:
73
+ @echo "$(YELLOW)Checking npm installation...$(RESET)"
74
+ @if command -v npm > /dev/null; then \
75
+ echo "$(BLUE)npm $(shell npm --version) is already installed.$(RESET)"; \
76
+ else \
77
+ echo "$(RED)npm is not installed. Please install Node.js to continue.$(RESET)"; \
78
+ exit 1; \
79
+ fi
80
+
81
+ check-nodejs:
82
+ @echo "$(YELLOW)Checking Node.js installation...$(RESET)"
83
+ @if command -v node > /dev/null; then \
84
+ NODE_VERSION=$(shell node --version | sed -E 's/v//g'); \
85
+ IFS='.' read -r -a NODE_VERSION_ARRAY <<< "$$NODE_VERSION"; \
86
+ if [ "$${NODE_VERSION_ARRAY[0]}" -ge 22 ]; then \
87
+ echo "$(BLUE)Node.js $$NODE_VERSION is already installed.$(RESET)"; \
88
+ else \
89
+ echo "$(RED)Node.js 22.x or later is required. Please install Node.js 22.x or later to continue.$(RESET)"; \
90
+ exit 1; \
91
+ fi; \
92
+ else \
93
+ echo "$(RED)Node.js is not installed. Please install Node.js to continue.$(RESET)"; \
94
+ exit 1; \
95
+ fi
96
+
97
+ check-docker:
98
+ @echo "$(YELLOW)Checking Docker installation...$(RESET)"
99
+ @if command -v docker > /dev/null; then \
100
+ echo "$(BLUE)$(shell docker --version) is already installed.$(RESET)"; \
101
+ else \
102
+ echo "$(RED)Docker is not installed. Please install Docker to continue.$(RESET)"; \
103
+ exit 1; \
104
+ fi
105
+
106
+ check-tmux:
107
+ @echo "$(YELLOW)Checking tmux installation...$(RESET)"
108
+ @if command -v tmux > /dev/null; then \
109
+ echo "$(BLUE)$(shell tmux -V) is already installed.$(RESET)"; \
110
+ else \
111
+ echo "$(YELLOW)╔════════════════════════════════════════════════════════════════════════════╗$(RESET)"; \
112
+ echo "$(YELLOW)║ OPTIONAL: tmux is not installed. ║$(RESET)"; \
113
+ echo "$(YELLOW)║ Some advanced terminal features may not work without tmux. ║$(RESET)"; \
114
+ echo "$(YELLOW)║ You can install it if needed, but it's not required for development. ║$(RESET)"; \
115
+ echo "$(YELLOW)╚════════════════════════════════════════════════════════════════════════════╝$(RESET)"; \
116
+ fi
117
+
118
+ check-poetry:
119
+ @echo "$(YELLOW)Checking Poetry installation...$(RESET)"
120
+ @if command -v poetry > /dev/null; then \
121
+ POETRY_VERSION=$(shell poetry --version 2>&1 | sed -E 's/Poetry \(version ([0-9]+\.[0-9]+\.[0-9]+)\)/\1/'); \
122
+ IFS='.' read -r -a POETRY_VERSION_ARRAY <<< "$$POETRY_VERSION"; \
123
+ if [ $${POETRY_VERSION_ARRAY[0]} -gt 1 ] || ([ $${POETRY_VERSION_ARRAY[0]} -eq 1 ] && [ $${POETRY_VERSION_ARRAY[1]} -ge 8 ]); then \
124
+ echo "$(BLUE)$(shell poetry --version) is already installed.$(RESET)"; \
125
+ else \
126
+ echo "$(RED)Poetry 1.8 or later is required. You can install poetry by running the following command, then adding Poetry to your PATH:"; \
127
+ echo "$(RED) curl -sSL https://install.python-poetry.org | python$(PYTHON_VERSION) -$(RESET)"; \
128
+ echo "$(RED)More detail here: https://python-poetry.org/docs/#installing-with-the-official-installer$(RESET)"; \
129
+ exit 1; \
130
+ fi; \
131
+ else \
132
+ echo "$(RED)Poetry is not installed. You can install poetry by running the following command, then adding Poetry to your PATH:"; \
133
+ echo "$(RED) curl -sSL https://install.python-poetry.org | python$(PYTHON_VERSION) -$(RESET)"; \
134
+ echo "$(RED)More detail here: https://python-poetry.org/docs/#installing-with-the-official-installer$(RESET)"; \
135
+ exit 1; \
136
+ fi
137
+
138
+ install-python-dependencies:
139
+ @echo "$(GREEN)Installing Python dependencies...$(RESET)"
140
+ @if [ -z "${TZ}" ]; then \
141
+ echo "Defaulting TZ (timezone) to UTC"; \
142
+ export TZ="UTC"; \
143
+ fi
144
+ poetry env use python$(PYTHON_VERSION)
145
+ @if [ "$(shell uname)" = "Darwin" ]; then \
146
+ echo "$(BLUE)Installing chroma-hnswlib...$(RESET)"; \
147
+ export HNSWLIB_NO_NATIVE=1; \
148
+ poetry run pip install chroma-hnswlib; \
149
+ fi
150
+ @if [ -n "${POETRY_GROUP}" ]; then \
151
+ echo "Installing only POETRY_GROUP=${POETRY_GROUP}"; \
152
+ poetry install --only $${POETRY_GROUP}; \
153
+ else \
154
+ poetry install --with dev,test,runtime; \
155
+ fi
156
+ @if [ "${INSTALL_PLAYWRIGHT}" != "false" ] && [ "${INSTALL_PLAYWRIGHT}" != "0" ]; then \
157
+ if [ -f "/etc/manjaro-release" ]; then \
158
+ echo "$(BLUE)Detected Manjaro Linux. Installing Playwright dependencies...$(RESET)"; \
159
+ poetry run pip install playwright; \
160
+ poetry run playwright install chromium; \
161
+ else \
162
+ if [ ! -f cache/playwright_chromium_is_installed.txt ]; then \
163
+ echo "Running playwright install --with-deps chromium..."; \
164
+ poetry run playwright install --with-deps chromium; \
165
+ mkdir -p cache; \
166
+ touch cache/playwright_chromium_is_installed.txt; \
167
+ else \
168
+ echo "Setup already done. Skipping playwright installation."; \
169
+ fi \
170
+ fi \
171
+ else \
172
+ echo "Skipping Playwright installation (INSTALL_PLAYWRIGHT=${INSTALL_PLAYWRIGHT})."; \
173
+ fi
174
+ @echo "$(GREEN)Python dependencies installed successfully.$(RESET)"
175
+
176
+ install-frontend-dependencies:
177
+ @echo "$(YELLOW)Setting up frontend environment...$(RESET)"
178
+ @echo "$(YELLOW)Detect Node.js version...$(RESET)"
179
+ @cd frontend && node ./scripts/detect-node-version.js
180
+ echo "$(BLUE)Installing frontend dependencies with npm...$(RESET)"
181
+ @cd frontend && npm install
182
+ @echo "$(GREEN)Frontend dependencies installed successfully.$(RESET)"
183
+
184
+ install-pre-commit-hooks:
185
+ @echo "$(YELLOW)Installing pre-commit hooks...$(RESET)"
186
+ @git config --unset-all core.hooksPath || true
187
+ @poetry run pre-commit install --config $(PRE_COMMIT_CONFIG_PATH)
188
+ @echo "$(GREEN)Pre-commit hooks installed successfully.$(RESET)"
189
+
190
+ lint-backend:
191
+ @echo "$(YELLOW)Running linters...$(RESET)"
192
+ @poetry run pre-commit run --files openhands/**/* evaluation/**/* tests/**/* --show-diff-on-failure --config $(PRE_COMMIT_CONFIG_PATH)
193
+
194
+ lint-frontend:
195
+ @echo "$(YELLOW)Running linters for frontend...$(RESET)"
196
+ @cd frontend && npm run lint
197
+
198
+ lint:
199
+ @$(MAKE) -s lint-frontend
200
+ @$(MAKE) -s lint-backend
201
+
202
+ test-frontend:
203
+ @echo "$(YELLOW)Running tests for frontend...$(RESET)"
204
+ @cd frontend && npm run test
205
+
206
+ test:
207
+ @$(MAKE) -s test-frontend
208
+
209
+ build-frontend:
210
+ @echo "$(YELLOW)Building frontend...$(RESET)"
211
+ @cd frontend && npm run prepare && npm run build
212
+
213
+ # Start backend
214
+ start-backend:
215
+ @echo "$(YELLOW)Starting backend...$(RESET)"
216
+ @poetry run uvicorn openhands.server.listen:app --host $(BACKEND_HOST) --port $(BACKEND_PORT) --reload --reload-exclude "./workspace"
217
+
218
+ # Start frontend
219
+ start-frontend:
220
+ @echo "$(YELLOW)Starting frontend...$(RESET)"
221
+ @cd frontend && \
222
+ if grep -qi microsoft /proc/version 2>/dev/null; then \
223
+ echo "Detected WSL environment. Using 'dev_wsl'"; \
224
+ SCRIPT=dev_wsl; \
225
+ else \
226
+ SCRIPT=dev; \
227
+ fi; \
228
+ VITE_BACKEND_HOST=$(BACKEND_HOST_PORT) VITE_FRONTEND_PORT=$(FRONTEND_PORT) npm run $$SCRIPT -- --port $(FRONTEND_PORT) --host $(BACKEND_HOST)
229
+
230
+ # Common setup for running the app (non-callable)
231
+ _run_setup:
232
+ @if [ "$(OS)" = "Windows_NT" ]; then \
233
+ echo "$(RED) Windows is not supported, use WSL instead!$(RESET)"; \
234
+ exit 1; \
235
+ fi
236
+ @mkdir -p logs
237
+ @echo "$(YELLOW)Starting backend server...$(RESET)"
238
+ @poetry run uvicorn openhands.server.listen:app --host $(BACKEND_HOST) --port $(BACKEND_PORT) &
239
+ @echo "$(YELLOW)Waiting for the backend to start...$(RESET)"
240
+ @until nc -z localhost $(BACKEND_PORT); do sleep 0.1; done
241
+ @echo "$(GREEN)Backend started successfully.$(RESET)"
242
+
243
+ # Run the app (standard mode)
244
+ run:
245
+ @echo "$(YELLOW)Running the app...$(RESET)"
246
+ @$(MAKE) -s _run_setup
247
+ @$(MAKE) -s start-frontend
248
+ @echo "$(GREEN)Application started successfully.$(RESET)"
249
+
250
+ # Run the app (in docker)
251
+ docker-run: WORKSPACE_BASE ?= $(PWD)/workspace
252
+ docker-run:
253
+ @if [ -f /.dockerenv ]; then \
254
+ echo "Running inside a Docker container. Exiting..."; \
255
+ exit 0; \
256
+ else \
257
+ echo "$(YELLOW)Running the app in Docker $(OPTIONS)...$(RESET)"; \
258
+ export WORKSPACE_BASE=${WORKSPACE_BASE}; \
259
+ export SANDBOX_USER_ID=$(shell id -u); \
260
+ export DATE=$(shell date +%Y%m%d%H%M%S); \
261
+ docker compose up $(OPTIONS); \
262
+ fi
263
+
264
+
265
+ # Setup config.toml
266
+ setup-config:
267
+ @echo "$(YELLOW)Setting up config.toml...$(RESET)"
268
+ @$(MAKE) setup-config-prompts
269
+ @mv $(CONFIG_FILE).tmp $(CONFIG_FILE)
270
+ @echo "$(GREEN)Config.toml setup completed.$(RESET)"
271
+
272
+ setup-config-prompts:
273
+ @echo "[core]" > $(CONFIG_FILE).tmp
274
+
275
+ @read -p "Enter your workspace directory (as absolute path) [default: $(DEFAULT_WORKSPACE_DIR)]: " workspace_dir; \
276
+ workspace_dir=$${workspace_dir:-$(DEFAULT_WORKSPACE_DIR)}; \
277
+ echo "workspace_base=\"$$workspace_dir\"" >> $(CONFIG_FILE).tmp
278
+
279
+ @echo "" >> $(CONFIG_FILE).tmp
280
+
281
+ @echo "[llm]" >> $(CONFIG_FILE).tmp
282
+ @read -p "Enter your LLM model name, used for running without UI. Set the model in the UI after you start the app. (see https://docs.litellm.ai/docs/providers for full list) [default: $(DEFAULT_MODEL)]: " llm_model; \
283
+ llm_model=$${llm_model:-$(DEFAULT_MODEL)}; \
284
+ echo "model=\"$$llm_model\"" >> $(CONFIG_FILE).tmp
285
+
286
+ @read -p "Enter your LLM api key: " llm_api_key; \
287
+ echo "api_key=\"$$llm_api_key\"" >> $(CONFIG_FILE).tmp
288
+
289
+ @read -p "Enter your LLM base URL [mostly used for local LLMs, leave blank if not needed - example: http://localhost:5001/v1/]: " llm_base_url; \
290
+ if [[ ! -z "$$llm_base_url" ]]; then echo "base_url=\"$$llm_base_url\"" >> $(CONFIG_FILE).tmp; fi
291
+
292
+ setup-config-basic:
293
+ @printf '%s\n' \
294
+ '[core]' \
295
+ 'workspace_base="./workspace"' \
296
+ > config.toml
297
+ @echo "$(GREEN)config.toml created.$(RESET)"
298
+
299
+ openhands-cloud-run:
300
+ @$(MAKE) run BACKEND_HOST="0.0.0.0" BACKEND_PORT="12000" FRONTEND_HOST="0.0.0.0" FRONTEND_PORT="12001"
301
+
302
+ # Develop in container
303
+ docker-dev:
304
+ @if [ -f /.dockerenv ]; then \
305
+ echo "Running inside a Docker container. Exiting..."; \
306
+ exit 0; \
307
+ else \
308
+ echo "$(YELLOW)Build and run in Docker $(OPTIONS)...$(RESET)"; \
309
+ ./containers/dev/dev.sh $(OPTIONS); \
310
+ fi
311
+
312
+ # Clean up all caches
313
+ clean:
314
+ @echo "$(YELLOW)Cleaning up caches...$(RESET)"
315
+ @rm -rf openhands/.cache
316
+ @echo "$(GREEN)Caches cleaned up successfully.$(RESET)"
317
+
318
+ # Help
319
+ help:
320
+ @echo "$(BLUE)Usage: make [target]$(RESET)"
321
+ @echo "Targets:"
322
+ @echo " $(GREEN)build$(RESET) - Build project, including environment setup and dependencies."
323
+ @echo " $(GREEN)lint$(RESET) - Run linters on the project."
324
+ @echo " $(GREEN)setup-config$(RESET) - Setup the configuration for OpenHands by providing LLM API key,"
325
+ @echo " LLM Model name, and workspace directory."
326
+ @echo " $(GREEN)start-backend$(RESET) - Start the backend server for the OpenHands project."
327
+ @echo " $(GREEN)start-frontend$(RESET) - Start the frontend server for the OpenHands project."
328
+ @echo " $(GREEN)run$(RESET) - Run the OpenHands application, starting both backend and frontend servers."
329
+ @echo " Backend Log file will be stored in the 'logs' directory."
330
+ @echo " $(GREEN)docker-dev$(RESET) - Build and run the OpenHands application in Docker."
331
+ @echo " $(GREEN)docker-run$(RESET) - Run the OpenHands application, starting both backend and frontend servers in Docker."
332
+ @echo " $(GREEN)help$(RESET) - Display this help message, providing information on available targets."
333
+
334
+ # Phony targets
335
+ .PHONY: build check-dependencies check-system check-python check-npm check-nodejs check-docker check-poetry install-python-dependencies install-frontend-dependencies install-pre-commit-hooks lint-backend lint-frontend lint test-frontend test build-frontend start-backend start-frontend _run_setup run run-wsl setup-config setup-config-prompts setup-config-basic openhands-cloud-run docker-dev docker-run clean help
README.md CHANGED
@@ -1,9 +1,146 @@
1
- ---
2
- title: OpenHands App
3
- emoji: 🐳
4
- colorFrom: purple
5
- colorTo: gray
6
- sdk: docker
7
- app_port: 3000
8
- ---
9
- This Space runs the OpenHands application using a Docker container.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <a name="readme-top"></a>
2
+
3
+ <div align="center">
4
+ <img src="./docs/static/img/logo.png" alt="Logo" width="200">
5
+ <h1 align="center">OpenHands: Code Less, Make More</h1>
6
+ </div>
7
+
8
+
9
+ <div align="center">
10
+ <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>
11
+ <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>
12
+ <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>
13
+ <br/>
14
+ <a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-34zm4j0gj-Qz5kRHoca8DFCbqXPS~f_A"><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>
15
+ <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>
16
+ <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>
17
+ <br/>
18
+ <a href="https://docs.all-hands.dev/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>
19
+ <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>
20
+ <a href="https://docs.google.com/spreadsheets/d/1wOUdFCMyY6Nt0AIqF705KN4JKOWgeI4wUGUP60krXXs/edit?gid=0#gid=0"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score"></a>
21
+ <hr>
22
+ </div>
23
+
24
+ Welcome to OpenHands (formerly OpenDevin), a platform for software development agents powered by AI.
25
+
26
+ OpenHands agents can do anything a human developer can: modify code, run commands, browse the web,
27
+ call APIs, and yes—even copy code snippets from StackOverflow.
28
+
29
+ Learn more at [docs.all-hands.dev](https://docs.all-hands.dev), or [sign up for OpenHands Cloud](https://app.all-hands.dev) to get started.
30
+
31
+ > [!IMPORTANT]
32
+ > Using OpenHands for work? We'd love to chat! Fill out
33
+ > [this short form](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
34
+ > to join our Design Partner program, where you'll get early access to commercial features and the opportunity to provide input on our product roadmap.
35
+
36
+ ![App screenshot](./docs/static/img/screenshot.png)
37
+
38
+ ## ☁️ OpenHands Cloud
39
+ The easiest way to get started with OpenHands is on [OpenHands Cloud](https://app.all-hands.dev),
40
+ which comes with $50 in free credits for new users.
41
+
42
+ ## 💻 Running OpenHands Locally
43
+
44
+ OpenHands can also run on your local system using Docker.
45
+ See the [Running OpenHands](https://docs.all-hands.dev/usage/installation) guide for
46
+ system requirements and more information.
47
+
48
+ > [!WARNING]
49
+ > On a public network? See our [Hardened Docker Installation Guide](https://docs.all-hands.dev/usage/runtimes/docker#hardened-docker-installation)
50
+ > to secure your deployment by restricting network binding and implementing additional security measures.
51
+
52
+
53
+ ```bash
54
+ docker pull docker.all-hands.dev/all-hands-ai/runtime:0.41-nikolaik
55
+
56
+ docker run -it --rm --pull=always \
57
+ -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.41-nikolaik \
58
+ -e LOG_ALL_EVENTS=true \
59
+ -v /var/run/docker.sock:/var/run/docker.sock \
60
+ -v ~/.openhands-state:/.openhands-state \
61
+ -p 3000:3000 \
62
+ --add-host host.docker.internal:host-gateway \
63
+ --name openhands-app \
64
+ docker.all-hands.dev/all-hands-ai/openhands:0.41
65
+ ```
66
+
67
+ You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)!
68
+
69
+ When you open the application, you'll be asked to choose an LLM provider and add an API key.
70
+ [Anthropic's Claude Sonnet 4](https://www.anthropic.com/api) (`anthropic/claude-sonnet-4-20250514`)
71
+ works best, but you have [many options](https://docs.all-hands.dev/usage/llms).
72
+
73
+ ## 💡 Other ways to run OpenHands
74
+
75
+ > [!CAUTION]
76
+ > OpenHands is meant to be run by a single user on their local workstation.
77
+ > It is not appropriate for multi-tenant deployments where multiple users share the same instance. There is no built-in authentication, isolation, or scalability.
78
+ >
79
+ > If you're interested in running OpenHands in a multi-tenant environment, please
80
+ > [get in touch with us](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
81
+ > for advanced deployment options.
82
+
83
+ You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem),
84
+ run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/usage/how-to/headless-mode),
85
+ interact with it via a [friendly CLI](https://docs.all-hands.dev/usage/how-to/cli-mode),
86
+ or run it on tagged issues with [a github action](https://docs.all-hands.dev/usage/how-to/github-action).
87
+
88
+ Visit [Running OpenHands](https://docs.all-hands.dev/usage/installation) for more information and setup instructions.
89
+
90
+ If you want to modify the OpenHands source code, check out [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
91
+
92
+ Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/usage/troubleshooting) can help.
93
+
94
+ ## 📖 Documentation
95
+ <a href="https://deepwiki.com/All-Hands-AI/OpenHands"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki" title="Autogenerated Documentation by DeepWiki"></a>
96
+
97
+ To learn more about the project, and for tips on using OpenHands,
98
+ check out our [documentation](https://docs.all-hands.dev/usage/getting-started).
99
+
100
+ There you'll find resources on how to use different LLM providers,
101
+ troubleshooting resources, and advanced configuration options.
102
+
103
+ ## 🤝 How to Join the Community
104
+
105
+ OpenHands is a community-driven project, and we welcome contributions from everyone. We do most of our communication
106
+ through Slack, so this is the best place to start, but we also are happy to have you contact us on Discord or Github:
107
+
108
+ - [Join our Slack workspace](https://join.slack.com/t/openhands-ai/shared_invite/zt-34zm4j0gj-Qz5kRHoca8DFCbqXPS~f_A) - Here we talk about research, architecture, and future development.
109
+ - [Join our Discord server](https://discord.gg/ESHStjSjD4) - This is a community-run server for general discussion, questions, and feedback.
110
+ - [Read or post Github Issues](https://github.com/All-Hands-AI/OpenHands/issues) - Check out the issues we're working on, or add your own ideas.
111
+
112
+ See more about the community in [COMMUNITY.md](./COMMUNITY.md) or find details on contributing in [CONTRIBUTING.md](./CONTRIBUTING.md).
113
+
114
+ ## 📈 Progress
115
+
116
+ See the monthly OpenHands roadmap [here](https://github.com/orgs/All-Hands-AI/projects/1) (updated at the maintainer's meeting at the end of each month).
117
+
118
+ <p align="center">
119
+ <a href="https://star-history.com/#All-Hands-AI/OpenHands&Date">
120
+ <img src="https://api.star-history.com/svg?repos=All-Hands-AI/OpenHands&type=Date" width="500" alt="Star History Chart">
121
+ </a>
122
+ </p>
123
+
124
+ ## 📜 License
125
+
126
+ Distributed under the MIT License. See [`LICENSE`](./LICENSE) for more information.
127
+
128
+ ## 🙏 Acknowledgements
129
+
130
+ 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.
131
+
132
+ For a list of open source projects and licenses used in OpenHands, please see our [CREDITS.md](./CREDITS.md) file.
133
+
134
+ ## 📚 Cite
135
+
136
+ ```
137
+ @misc{openhands,
138
+ title={{OpenHands: An Open Platform for AI Software Developers as Generalist Agents}},
139
+ author={Xingyao Wang and Boxuan Li and Yufan Song and Frank F. Xu and Xiangru Tang and Mingchen Zhuge and Jiayi Pan and Yueqi Song and Bowen Li and Jaskirat Singh and Hoang H. Tran and Fuqiang Li and Ren Ma and Mingzhang Zheng and Bill Qian and Yanjun Shao and Niklas Muennighoff and Yizhe Zhang and Binyuan Hui and Junyang Lin and Robert Brennan and Hao Peng and Heng Ji and Graham Neubig},
140
+ year={2024},
141
+ eprint={2407.16741},
142
+ archivePrefix={arXiv},
143
+ primaryClass={cs.SE},
144
+ url={https://arxiv.org/abs/2407.16741},
145
+ }
146
+ ```
README_CN.md ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <a name="readme-top"></a>
3
+
4
+ <div align="center">
5
+ <img src="./docs/static/img/logo.png" alt="Logo" width="200">
6
+ <h1 align="center">OpenHands: 少写代码,多做事</h1>
7
+ </div>
8
+
9
+
10
+ <div align="center">
11
+ <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>
12
+ <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>
13
+ <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>
14
+ <br/>
15
+ <a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-34zm4j0gj-Qz5kRHoca8DFCbqXPS~f_A"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="加入我们的Slack社区"></a>
16
+ <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="加入我们的Discord社区"></a>
17
+ <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="致谢"></a>
18
+ <br/>
19
+ <a href="https://docs.all-hands.dev/usage/getting-started"><img src="https://img.shields.io/badge/Documentation-000?logo=googledocs&logoColor=FFE165&style=for-the-badge" alt="查看文档"></a>
20
+ <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="Arxiv论文"></a>
21
+ <a href="https://docs.google.com/spreadsheets/d/1wOUdFCMyY6Nt0AIqF705KN4JKOWgeI4wUGUP60krXXs/edit?gid=0#gid=0"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="评估基准分数"></a>
22
+ <hr>
23
+ </div>
24
+
25
+ 欢迎使用OpenHands(前身为OpenDevin),这是一个由AI驱动的软件开发代理平台。
26
+
27
+ OpenHands代理可以完成人类开发者能做的任何事情:修改代码、运行命令、浏览网页、调用API,甚至从StackOverflow复制代码片段。
28
+
29
+ 在[docs.all-hands.dev](https://docs.all-hands.dev)了解更多信息,或[注册OpenHands Cloud](https://app.all-hands.dev)开始使用。
30
+
31
+ > [!IMPORTANT]
32
+ > 在工作中使用OpenHands?我们很想与您交流!填写
33
+ > [这份简短表格](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
34
+ > 加入我们的设计合作伙伴计划,您将获得商业功能的早期访问权限,并有机会对我们的产品路线图提供意见。
35
+
36
+ ![应用截图](./docs/static/img/screenshot.png)
37
+
38
+ ## ☁️ OpenHands Cloud
39
+ 开始使用OpenHands的最简单方式是在[OpenHands Cloud](https://app.all-hands.dev)上,
40
+ 新用户可获得$50的免费额度。
41
+
42
+ ## 💻 在本地运行OpenHands
43
+
44
+ OpenHands也可以使用Docker在本地系统上运行。
45
+ 查看[运行OpenHands](https://docs.all-hands.dev/usage/installation)指南了解
46
+ 系统要求和更多信息。
47
+
48
+ > [!WARNING]
49
+ > 在公共网络上?请参阅我们的[强化Docker安装指南](https://docs.all-hands.dev/usage/runtimes/docker#hardened-docker-installation)
50
+ > 通过限制网络绑定和实施其他安全措施来保护您的部署。
51
+
52
+
53
+ ```bash
54
+ docker pull docker.all-hands.dev/all-hands-ai/runtime:0.41-nikolaik
55
+
56
+ docker run -it --rm --pull=always \
57
+ -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.41-nikolaik \
58
+ -e LOG_ALL_EVENTS=true \
59
+ -v /var/run/docker.sock:/var/run/docker.sock \
60
+ -v ~/.openhands-state:/.openhands-state \
61
+ -p 3000:3000 \
62
+ --add-host host.docker.internal:host-gateway \
63
+ --name openhands-app \
64
+ docker.all-hands.dev/all-hands-ai/openhands:0.41
65
+ ```
66
+
67
+ 您将在[http://localhost:3000](http://localhost:3000)找到运行中的OpenHands!
68
+
69
+ 打开应用程序时,您将被要求选择一个LLM提供商并添加API密钥。
70
+ [Anthropic的Claude Sonnet 4](https://www.anthropic.com/api)(`anthropic/claude-sonnet-4-20250514`)
71
+ 效果最佳,但您还有[许多选择](https://docs.all-hands.dev/usage/llms)。
72
+
73
+ ## 💡 运行OpenHands的其他方式
74
+
75
+ > [!CAUTION]
76
+ > OpenHands旨在由单个用户在其本地工作站上运行。
77
+ > 它不适合多租户部署,即多个用户共享同一实例。没有内置的身份验证、隔离或可扩展性。
78
+ >
79
+ > 如果您有兴趣在多租户环境中运行OpenHands,请
80
+ > [与我们联系](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform)
81
+ > 了解高级部署选项。
82
+
83
+ 您还可以[将OpenHands连接到本地文件系统](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem),
84
+ 以可编程的[无头模���](https://docs.all-hands.dev/usage/how-to/headless-mode)运行OpenHands,
85
+ 通过[友好的CLI](https://docs.all-hands.dev/usage/how-to/cli-mode)与其交互,
86
+ 或使用[GitHub Action](https://docs.all-hands.dev/usage/how-to/github-action)在标记的问题上运行它。
87
+
88
+ 访问[运行OpenHands](https://docs.all-hands.dev/usage/installation)获取更多信息和设置说明。
89
+
90
+ 如果您想修改OpenHands源代码,请查看[Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)。
91
+
92
+ 遇到问题?[故障排除指南](https://docs.all-hands.dev/usage/troubleshooting)可以提供帮助。
93
+
94
+ ## 📖 文档
95
+ <a href="https://deepwiki.com/All-Hands-AI/OpenHands"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki" title="DeepWiki自动生成文档"></a>
96
+
97
+ 要了解有关项目的更多信息,以及使用OpenHands的技巧,
98
+ 请查看我们的[文档](https://docs.all-hands.dev/usage/getting-started)。
99
+
100
+ 在那里,您将找到有关如何使用不同LLM提供商、
101
+ 故障排除资源和高级配置选项的资源。
102
+
103
+ ## 🤝 如何加入社区
104
+
105
+ OpenHands是一个社区驱动的项目,我们欢迎每个人的贡献。我们大部分沟通
106
+ 通过Slack进行,因此这是开始的最佳场所,但我们也很乐意您通过Discord或Github与我们联系:
107
+
108
+ - [加入我们的Slack工作空间](https://join.slack.com/t/openhands-ai/shared_invite/zt-34zm4j0gj-Qz5kRHoca8DFCbqXPS~f_A) - 这里我们讨论研究、架构和未来发展。
109
+ - [加入我们的Discord服务器](https://discord.gg/ESHStjSjD4) - 这是一个社区运营的服务器,用于一般讨论、问题和反馈。
110
+ - [阅读或发布Github问题](https://github.com/All-Hands-AI/OpenHands/issues) - 查看我们正在处理的问题,或添加您自己的想法。
111
+
112
+ 在[COMMUNITY.md](./COMMUNITY.md)中了解更多关于社区的信息,或在[CONTRIBUTING.md](./CONTRIBUTING.md)中找到有关贡献的详细信息。
113
+
114
+ ## 📈 进展
115
+
116
+ 在[这里](https://github.com/orgs/All-Hands-AI/projects/1)查看OpenHands月度路线图(每月月底在维护者会议上更新)。
117
+
118
+ <p align="center">
119
+ <a href="https://star-history.com/#All-Hands-AI/OpenHands&Date">
120
+ <img src="https://api.star-history.com/svg?repos=All-Hands-AI/OpenHands&type=Date" width="500" alt="Star History Chart">
121
+ </a>
122
+ </p>
123
+
124
+ ## 📜 许可证
125
+
126
+ 根据MIT许可证分发。有关更多信息,请参阅[`LICENSE`](./LICENSE)。
127
+
128
+ ## 🙏 致谢
129
+
130
+ OpenHands由大量贡献者构建,每一份贡献都备受感谢!我们还借鉴了其他开源项目,对他们的工作深表感谢。
131
+
132
+ 有关OpenHands中使用的开源项目和许可证列表,请参阅我们的[CREDITS.md](./CREDITS.md)文件。
133
+
134
+ ## 📚 引用
135
+
136
+ ```
137
+ @misc{openhands,
138
+ title={{OpenHands: An Open Platform for AI Software Developers as Generalist Agents}},
139
+ author={Xingyao Wang and Boxuan Li and Yufan Song and Frank F. Xu and Xiangru Tang and Mingchen Zhuge and Jiayi Pan and Yueqi Song and Bowen Li and Jaskirat Singh and Hoang H. Tran and Fuqiang Li and Ren Ma and Mingzhang Zheng and Bill Qian and Yanjun Shao and Niklas Muennighoff and Yizhe Zhang and Binyuan Hui and Junyang Lin and Robert Brennan and Hao Peng and Heng Ji and Graham Neubig},
140
+ year={2024},
141
+ eprint={2407.16741},
142
+ archivePrefix={arXiv},
143
+ primaryClass={cs.SE},
144
+ url={https://arxiv.org/abs/2407.16741},
145
+ }
146
+ ```
build.sh ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ poetry build -v
config.template.toml ADDED
@@ -0,0 +1,417 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ###################### OpenHands Configuration Example ######################
2
+ #
3
+ # All settings have default values, so you only need to uncomment and
4
+ # modify what you want to change
5
+ # The fields within each section are sorted in alphabetical order.
6
+ #
7
+ ##############################################################################
8
+
9
+ #################################### Core ####################################
10
+ # General core configurations
11
+ ##############################################################################
12
+ [core]
13
+ # API key for E2B
14
+ #e2b_api_key = ""
15
+
16
+ # API key for Modal
17
+ #modal_api_token_id = ""
18
+ #modal_api_token_secret = ""
19
+
20
+ # API key for Daytona
21
+ #daytona_api_key = ""
22
+
23
+ # Daytona Target
24
+ #daytona_target = ""
25
+
26
+ # Base path for the workspace
27
+ #workspace_base = "./workspace"
28
+
29
+ # Cache directory path
30
+ #cache_dir = "/tmp/cache"
31
+
32
+ # Reasoning effort for o1 models (low, medium, high, or not set)
33
+ #reasoning_effort = "medium"
34
+
35
+ # Debugging enabled
36
+ #debug = false
37
+
38
+ # Disable color in terminal output
39
+ #disable_color = false
40
+
41
+ # Path to store trajectories, can be a folder or a file
42
+ # If it's a folder, the session id will be used as the file name
43
+ #save_trajectory_path="./trajectories"
44
+
45
+ # Whether to save screenshots in the trajectory
46
+ # The screenshots are encoded and can make trajectory json files very large
47
+ #save_screenshots_in_trajectory = false
48
+
49
+ # Path to replay a trajectory, must be a file path
50
+ # If provided, trajectory will be loaded and replayed before the
51
+ # agent responds to any user instruction
52
+ #replay_trajectory_path = ""
53
+
54
+ # File store path
55
+ #file_store_path = "/tmp/file_store"
56
+
57
+ # File store type
58
+ #file_store = "memory"
59
+
60
+ # Maximum file size for uploads, in megabytes
61
+ #file_uploads_max_file_size_mb = 0
62
+
63
+ # Maximum budget per task, 0.0 means no limit
64
+ #max_budget_per_task = 0.0
65
+
66
+ # Maximum number of iterations
67
+ #max_iterations = 250
68
+
69
+ # Path to mount the workspace in the sandbox
70
+ #workspace_mount_path_in_sandbox = "/workspace"
71
+
72
+ # Path to mount the workspace
73
+ #workspace_mount_path = ""
74
+
75
+ # Path to rewrite the workspace mount path to
76
+ #workspace_mount_rewrite = ""
77
+
78
+ # Run as openhands
79
+ #run_as_openhands = true
80
+
81
+ # Runtime environment
82
+ #runtime = "docker"
83
+
84
+ # Name of the default agent
85
+ #default_agent = "CodeActAgent"
86
+
87
+ # JWT secret for authentication
88
+ #jwt_secret = ""
89
+
90
+ # Restrict file types for file uploads
91
+ #file_uploads_restrict_file_types = false
92
+
93
+ # List of allowed file extensions for uploads
94
+ #file_uploads_allowed_extensions = [".*"]
95
+
96
+ # Whether to enable the default LLM summarizing condenser when no condenser is specified in config
97
+ # When true, a LLMSummarizingCondenserConfig will be used as the default condenser
98
+ # When false, a NoOpCondenserConfig (no summarization) will be used
99
+ #enable_default_condenser = true
100
+
101
+ # Maximum number of concurrent conversations per user
102
+ #max_concurrent_conversations = 3
103
+
104
+ # Maximum age of conversations in seconds before they are automatically closed
105
+ #conversation_max_age_seconds = 864000 # 10 days
106
+
107
+ #################################### LLM #####################################
108
+ # Configuration for LLM models (group name starts with 'llm')
109
+ # use 'llm' for the default LLM config
110
+ ##############################################################################
111
+ [llm]
112
+ # AWS access key ID
113
+ #aws_access_key_id = ""
114
+
115
+ # AWS region name
116
+ #aws_region_name = ""
117
+
118
+ # AWS secret access key
119
+ #aws_secret_access_key = ""
120
+
121
+ # API key to use (For Headless / CLI only - In Web this is overridden by Session Init)
122
+ api_key = ""
123
+
124
+ # API base URL (For Headless / CLI only - In Web this is overridden by Session Init)
125
+ #base_url = ""
126
+
127
+ # API version
128
+ #api_version = ""
129
+
130
+ # Cost per input token
131
+ #input_cost_per_token = 0.0
132
+
133
+ # Cost per output token
134
+ #output_cost_per_token = 0.0
135
+
136
+ # Custom LLM provider
137
+ #custom_llm_provider = ""
138
+
139
+ # Maximum number of characters in an observation's content
140
+ #max_message_chars = 10000
141
+
142
+ # Maximum number of input tokens
143
+ #max_input_tokens = 0
144
+
145
+ # Maximum number of output tokens
146
+ #max_output_tokens = 0
147
+
148
+ # Model to use. (For Headless / CLI only - In Web this is overridden by Session Init)
149
+ model = "gpt-4o"
150
+
151
+ # Number of retries to attempt when an operation fails with the LLM.
152
+ # Increase this value to allow more attempts before giving up
153
+ #num_retries = 8
154
+
155
+ # Maximum wait time (in seconds) between retry attempts
156
+ # This caps the exponential backoff to prevent excessively long
157
+ #retry_max_wait = 120
158
+
159
+ # Minimum wait time (in seconds) between retry attempts
160
+ # This sets the initial delay before the first retry
161
+ #retry_min_wait = 15
162
+
163
+ # Multiplier for exponential backoff calculation
164
+ # The wait time increases by this factor after each failed attempt
165
+ # A value of 2.0 means each retry waits twice as long as the previous one
166
+ #retry_multiplier = 2.0
167
+
168
+ # Drop any unmapped (unsupported) params without causing an exception
169
+ #drop_params = false
170
+
171
+ # Modify params for litellm to do transformations like adding a default message, when a message is empty.
172
+ # Note: this setting is global, unlike drop_params, it cannot be overridden in each call to litellm.
173
+ #modify_params = true
174
+
175
+ # Using the prompt caching feature if provided by the LLM and supported
176
+ #caching_prompt = true
177
+
178
+ # Base URL for the OLLAMA API
179
+ #ollama_base_url = ""
180
+
181
+ # Temperature for the API
182
+ #temperature = 0.0
183
+
184
+ # Timeout for the API
185
+ #timeout = 0
186
+
187
+ # Top p for the API
188
+ #top_p = 1.0
189
+
190
+ # If model is vision capable, this option allows to disable image processing (useful for cost reduction).
191
+ #disable_vision = true
192
+
193
+ # Custom tokenizer to use for token counting
194
+ # https://docs.litellm.ai/docs/completion/token_usage
195
+ #custom_tokenizer = ""
196
+
197
+ # Whether to use native tool calling if supported by the model. Can be true, false, or None by default, which chooses the model's default behavior based on the evaluation.
198
+ # ATTENTION: Based on evaluation, enabling native function calling may lead to worse results
199
+ # in some scenarios. Use with caution and consider testing with your specific use case.
200
+ # https://github.com/All-Hands-AI/OpenHands/pull/4711
201
+ #native_tool_calling = None
202
+
203
+
204
+
205
+ [llm.gpt4o-mini]
206
+ api_key = ""
207
+ model = "gpt-4o"
208
+
209
+
210
+ #################################### Agent ###################################
211
+ # Configuration for agents (group name starts with 'agent')
212
+ # Use 'agent' for the default agent config
213
+ # otherwise, group name must be `agent.<agent_name>` (case-sensitive), e.g.
214
+ # agent.CodeActAgent
215
+ ##############################################################################
216
+ [agent]
217
+
218
+ # Whether the browsing tool is enabled
219
+ enable_browsing = true
220
+
221
+ # Whether the LLM draft editor is enabled
222
+ enable_llm_editor = false
223
+
224
+ # Whether the standard editor tool (str_replace_editor) is enabled
225
+ # Only has an effect if enable_llm_editor is False
226
+ enable_editor = true
227
+
228
+ # Whether the IPython tool is enabled
229
+ enable_jupyter = true
230
+
231
+ # Whether the command tool is enabled
232
+ enable_cmd = true
233
+
234
+ # Whether the think tool is enabled
235
+ enable_think = true
236
+
237
+ # Whether the finish tool is enabled
238
+ enable_finish = true
239
+
240
+ # LLM config group to use
241
+ #llm_config = 'your-llm-config-group'
242
+
243
+ # Whether to use prompt extension (e.g., microagent, repo/runtime info) at all
244
+ #enable_prompt_extensions = true
245
+
246
+ # List of microagents to disable
247
+ #disabled_microagents = []
248
+
249
+ # Whether history should be truncated to continue the session when hitting LLM context
250
+ # length limit
251
+ enable_history_truncation = true
252
+
253
+ [agent.RepoExplorerAgent]
254
+ # Example: use a cheaper model for RepoExplorerAgent to reduce cost, especially
255
+ # useful when an agent doesn't demand high quality but uses a lot of tokens
256
+ llm_config = 'gpt3'
257
+
258
+ [agent.CustomAgent]
259
+ # Example: use a custom agent from a different package
260
+ # This will be automatically be registered as a new agent named "CustomAgent"
261
+ classpath = "my_package.my_module.MyCustomAgent"
262
+
263
+ #################################### Sandbox ###################################
264
+ # Configuration for the sandbox
265
+ ##############################################################################
266
+ [sandbox]
267
+ # Sandbox timeout in seconds
268
+ #timeout = 120
269
+
270
+ # Sandbox user ID
271
+ #user_id = 1000
272
+
273
+ # Container image to use for the sandbox
274
+ #base_container_image = "nikolaik/python-nodejs:python3.12-nodejs22"
275
+
276
+ # Use host network
277
+ #use_host_network = false
278
+
279
+ # Runtime extra build args
280
+ #runtime_extra_build_args = ["--network=host", "--add-host=host.docker.internal:host-gateway"]
281
+
282
+ # Enable auto linting after editing
283
+ #enable_auto_lint = false
284
+
285
+ # Whether to initialize plugins
286
+ #initialize_plugins = true
287
+
288
+ # Extra dependencies to install in the runtime image
289
+ #runtime_extra_deps = ""
290
+
291
+ # Environment variables to set at the launch of the runtime
292
+ #runtime_startup_env_vars = {}
293
+
294
+ # BrowserGym environment to use for evaluation
295
+ #browsergym_eval_env = ""
296
+
297
+ # Platform to use for building the runtime image (e.g., "linux/amd64")
298
+ #platform = ""
299
+
300
+ # Force rebuild of runtime image even if it exists
301
+ #force_rebuild_runtime = false
302
+
303
+ # Runtime container image to use (if not provided, will be built from base_container_image)
304
+ #runtime_container_image = ""
305
+
306
+ # Keep runtime alive after session ends
307
+ #keep_runtime_alive = false
308
+
309
+ # Pause closed runtimes instead of stopping them
310
+ #pause_closed_runtimes = false
311
+
312
+ # Delay in seconds before closing idle runtimes
313
+ #close_delay = 300
314
+
315
+ # Remove all containers when stopping the runtime
316
+ #rm_all_containers = false
317
+
318
+ # Enable GPU support in the runtime
319
+ #enable_gpu = false
320
+
321
+ # Additional Docker runtime kwargs
322
+ #docker_runtime_kwargs = {}
323
+
324
+ # Specific port to use for VSCode. If not set, a random port will be chosen.
325
+ # Useful when deploying OpenHands in a remote machine where you need to expose a specific port.
326
+ #vscode_port = 41234
327
+
328
+ # Volume mounts in the format 'host_path:container_path[:mode]'
329
+ # e.g. '/my/host/dir:/workspace:rw'
330
+ # Multiple mounts can be specified using commas
331
+ # e.g. '/path1:/workspace/path1,/path2:/workspace/path2:ro'
332
+
333
+ # Configure volumes under the [sandbox] section:
334
+ # [sandbox]
335
+ # volumes = "/my/host/dir:/workspace:rw,/path2:/workspace/path2:ro"
336
+
337
+ #################################### Security ###################################
338
+ # Configuration for security features
339
+ ##############################################################################
340
+ [security]
341
+
342
+ # Enable confirmation mode (For Headless / CLI only - In Web this is overridden by Session Init)
343
+ #confirmation_mode = false
344
+
345
+ # The security analyzer to use (For Headless / CLI only - In Web this is overridden by Session Init)
346
+ #security_analyzer = ""
347
+
348
+ # Whether to enable security analyzer
349
+ #enable_security_analyzer = false
350
+
351
+ #################################### Condenser #################################
352
+ # Condensers control how conversation history is managed and compressed when
353
+ # the context grows too large. Each agent uses one condenser configuration.
354
+ ##############################################################################
355
+ [condenser]
356
+ # The type of condenser to use. Available options:
357
+ # - "noop": No condensing, keeps full history (default)
358
+ # - "observation_masking": Keeps full event structure but masks older observations
359
+ # - "recent": Keeps only recent events and discards older ones
360
+ # - "llm": Uses an LLM to summarize conversation history
361
+ # - "amortized": Intelligently forgets older events while preserving important context
362
+ # - "llm_attention": Uses an LLM to prioritize most relevant context
363
+ type = "noop"
364
+
365
+ # Examples for each condenser type (uncomment and modify as needed):
366
+
367
+ # 1. NoOp Condenser - No additional settings needed
368
+ #type = "noop"
369
+
370
+ # 2. Observation Masking Condenser
371
+ #type = "observation_masking"
372
+ # Number of most-recent events where observations will not be masked
373
+ #attention_window = 100
374
+
375
+ # 3. Recent Events Condenser
376
+ #type = "recent"
377
+ # Number of initial events to always keep (typically includes task description)
378
+ #keep_first = 1
379
+ # Maximum number of events to keep in history
380
+ #max_events = 100
381
+
382
+ # 4. LLM Summarizing Condenser
383
+ #type = "llm"
384
+ # Reference to an LLM config to use for summarization
385
+ #llm_config = "condenser"
386
+ # Number of initial events to always keep (typically includes task description)
387
+ #keep_first = 1
388
+ # Maximum size of history before triggering summarization
389
+ #max_size = 100
390
+
391
+ # 5. Amortized Forgetting Condenser
392
+ #type = "amortized"
393
+ # Number of initial events to always keep (typically includes task description)
394
+ #keep_first = 1
395
+ # Maximum size of history before triggering forgetting
396
+ #max_size = 100
397
+
398
+ # 6. LLM Attention Condenser
399
+ #type = "llm_attention"
400
+ # Reference to an LLM config to use for attention scoring
401
+ #llm_config = "condenser"
402
+ # Number of initial events to always keep (typically includes task description)
403
+ #keep_first = 1
404
+ # Maximum size of history before triggering attention mechanism
405
+ #max_size = 100
406
+
407
+ # Example of a custom LLM configuration for condensers that require an LLM
408
+ # If not provided, it falls back to the default LLM
409
+ #[llm.condenser]
410
+ #model = "gpt-4o"
411
+ #temperature = 0.1
412
+ #max_input_tokens = 1024
413
+
414
+ #################################### Eval ####################################
415
+ # Configuration for the evaluation, please refer to the specific evaluation
416
+ # plugin for the available options
417
+ ##############################################################################
containers/README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Docker Containers
2
+
3
+ Each folder here contains a Dockerfile, and a config.sh describing how to build
4
+ the images and where to push them. These images are built and pushed in GitHub Actions
5
+ by the `ghcr.yml` workflow.
6
+
7
+ ## Building Manually
8
+
9
+ ```bash
10
+ docker build -f containers/app/Dockerfile -t openhands .
11
+ docker build -f containers/sandbox/Dockerfile -t sandbox .
12
+ ```
containers/app/Dockerfile ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ARG OPENHANDS_BUILD_VERSION=dev
2
+ FROM node:21.7.2-bookworm-slim AS frontend-builder
3
+
4
+ WORKDIR /app
5
+
6
+ COPY ./frontend/package.json frontend/package-lock.json ./
7
+ RUN npm install -g [email protected]
8
+ RUN npm ci
9
+
10
+ COPY ./frontend ./
11
+ RUN npm run build
12
+
13
+ FROM python:3.12.3-slim AS backend-builder
14
+
15
+ WORKDIR /app
16
+ ENV PYTHONPATH='/app'
17
+
18
+ ENV POETRY_NO_INTERACTION=1 \
19
+ POETRY_VIRTUALENVS_IN_PROJECT=1 \
20
+ POETRY_VIRTUALENVS_CREATE=1 \
21
+ POETRY_CACHE_DIR=/tmp/poetry_cache
22
+
23
+ RUN apt-get update -y \
24
+ && apt-get install -y curl make git build-essential \
25
+ && python3 -m pip install poetry==1.8.2 --break-system-packages
26
+
27
+ COPY ./pyproject.toml ./poetry.lock ./
28
+ RUN touch README.md
29
+ RUN export POETRY_CACHE_DIR && poetry install --no-root && rm -rf $POETRY_CACHE_DIR
30
+
31
+ FROM python:3.12.3-slim AS openhands-app
32
+
33
+ WORKDIR /app
34
+
35
+ ARG OPENHANDS_BUILD_VERSION #re-declare for this section
36
+
37
+ ENV RUN_AS_OPENHANDS=true
38
+ # A random number--we need this to be different from the user's UID on the host machine
39
+ ENV OPENHANDS_USER_ID=42420
40
+ ENV SANDBOX_LOCAL_RUNTIME_URL=http://host.docker.internal
41
+ ENV USE_HOST_NETWORK=false
42
+ ENV WORKSPACE_BASE=/opt/workspace_base
43
+ ENV OPENHANDS_BUILD_VERSION=$OPENHANDS_BUILD_VERSION
44
+ ENV SANDBOX_USER_ID=0
45
+ ENV FILE_STORE=local
46
+ ENV FILE_STORE_PATH=/.openhands-state
47
+ RUN mkdir -p $FILE_STORE_PATH
48
+ RUN mkdir -p $WORKSPACE_BASE
49
+
50
+ RUN apt-get update -y \
51
+ && apt-get install -y curl ssh sudo \
52
+ && rm -rf /var/lib/apt/lists/*
53
+
54
+ # Default is 1000, but OSX is often 501
55
+ RUN sed -i 's/^UID_MIN.*/UID_MIN 499/' /etc/login.defs
56
+ # Default is 60000, but we've seen up to 200000
57
+ RUN sed -i 's/^UID_MAX.*/UID_MAX 1000000/' /etc/login.defs
58
+
59
+ RUN groupadd app
60
+ RUN useradd -l -m -u $OPENHANDS_USER_ID -s /bin/bash openhands && \
61
+ usermod -aG app openhands && \
62
+ usermod -aG sudo openhands && \
63
+ echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
64
+ RUN chown -R openhands:app /app && chmod -R 770 /app
65
+ RUN sudo chown -R openhands:app $WORKSPACE_BASE && sudo chmod -R 770 $WORKSPACE_BASE
66
+ USER openhands
67
+
68
+ ENV VIRTUAL_ENV=/app/.venv \
69
+ PATH="/app/.venv/bin:$PATH" \
70
+ PYTHONPATH='/app'
71
+
72
+ COPY --chown=openhands:app --chmod=770 --from=backend-builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
73
+
74
+ COPY --chown=openhands:app --chmod=770 ./microagents ./microagents
75
+ COPY --chown=openhands:app --chmod=770 ./openhands ./openhands
76
+ COPY --chown=openhands:app --chmod=777 ./openhands/runtime/plugins ./openhands/runtime/plugins
77
+ COPY --chown=openhands:app --chmod=770 ./openhands/agenthub ./openhands/agenthub
78
+ COPY --chown=openhands:app ./pyproject.toml ./pyproject.toml
79
+ COPY --chown=openhands:app ./poetry.lock ./poetry.lock
80
+ COPY --chown=openhands:app ./README.md ./README.md
81
+ COPY --chown=openhands:app ./MANIFEST.in ./MANIFEST.in
82
+ COPY --chown=openhands:app ./LICENSE ./LICENSE
83
+
84
+ # This is run as "openhands" user, and will create __pycache__ with openhands:openhands ownership
85
+ RUN python openhands/core/download.py # No-op to download assets
86
+ # Add this line to set group ownership of all files/directories not already in "app" group
87
+ # openhands:openhands -> openhands:app
88
+ RUN find /app \! -group app -exec chgrp app {} +
89
+
90
+ COPY --chown=openhands:app --chmod=770 --from=frontend-builder /app/build ./frontend/build
91
+ COPY --chown=openhands:app --chmod=770 ./containers/app/entrypoint.sh /app/entrypoint.sh
92
+
93
+ USER root
94
+
95
+ WORKDIR /app
96
+
97
+ ENTRYPOINT ["/app/entrypoint.sh"]
98
+ CMD ["uvicorn", "openhands.server.listen:app", "--host", "0.0.0.0", "--port", "3000"]
containers/app/config.sh ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ DOCKER_REGISTRY=ghcr.io
2
+ DOCKER_ORG=all-hands-ai
3
+ DOCKER_IMAGE=openhands
4
+ DOCKER_BASE_DIR="."
containers/app/entrypoint.sh ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -eo pipefail
3
+
4
+ echo "Starting OpenHands..."
5
+ if [[ $NO_SETUP == "true" ]]; then
6
+ echo "Skipping setup, running as $(whoami)"
7
+ "$@"
8
+ exit 0
9
+ fi
10
+
11
+ if [ "$(id -u)" -ne 0 ]; then
12
+ echo "The OpenHands entrypoint.sh must run as root"
13
+ exit 1
14
+ fi
15
+
16
+ if [ -z "$SANDBOX_USER_ID" ]; then
17
+ echo "SANDBOX_USER_ID is not set"
18
+ exit 1
19
+ fi
20
+
21
+ if [ -z "$WORKSPACE_MOUNT_PATH" ]; then
22
+ # This is set to /opt/workspace in the Dockerfile. But if the user isn't mounting, we want to unset it so that OpenHands doesn't mount at all
23
+ unset WORKSPACE_BASE
24
+ fi
25
+
26
+ if [[ "$SANDBOX_USER_ID" -eq 0 ]]; then
27
+ echo "Running OpenHands as root"
28
+ export RUN_AS_OPENHANDS=false
29
+ "$@"
30
+ else
31
+ echo "Setting up enduser with id $SANDBOX_USER_ID"
32
+ if id "enduser" &>/dev/null; then
33
+ echo "User enduser already exists. Skipping creation."
34
+ else
35
+ if ! useradd -l -m -u $SANDBOX_USER_ID -s /bin/bash enduser; then
36
+ echo "Failed to create user enduser with id $SANDBOX_USER_ID. Moving openhands user."
37
+ incremented_id=$(($SANDBOX_USER_ID + 1))
38
+ usermod -u $incremented_id openhands
39
+ if ! useradd -l -m -u $SANDBOX_USER_ID -s /bin/bash enduser; then
40
+ echo "Failed to create user enduser with id $SANDBOX_USER_ID for a second time. Exiting."
41
+ exit 1
42
+ fi
43
+ fi
44
+ fi
45
+ usermod -aG app enduser
46
+ # get the user group of /var/run/docker.sock and set openhands to that group
47
+ DOCKER_SOCKET_GID=$(stat -c '%g' /var/run/docker.sock)
48
+ echo "Docker socket group id: $DOCKER_SOCKET_GID"
49
+ if getent group $DOCKER_SOCKET_GID; then
50
+ echo "Group with id $DOCKER_SOCKET_GID already exists"
51
+ else
52
+ echo "Creating group with id $DOCKER_SOCKET_GID"
53
+ groupadd -g $DOCKER_SOCKET_GID docker
54
+ fi
55
+
56
+ mkdir -p /home/enduser/.cache/huggingface/hub/
57
+
58
+ usermod -aG $DOCKER_SOCKET_GID enduser
59
+ echo "Running as enduser"
60
+ su enduser /bin/bash -c "${*@Q}" # This magically runs any arguments passed to the script as a command
61
+ fi
containers/build.sh ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -eo pipefail
3
+
4
+ # Initialize variables with default values
5
+ image_name=""
6
+ org_name=""
7
+ push=0
8
+ load=0
9
+ tag_suffix=""
10
+ dry_run=0
11
+
12
+ # Function to display usage information
13
+ usage() {
14
+ echo "Usage: $0 -i <image_name> [-o <org_name>] [--push] [--load] [-t <tag_suffix>] [--dry]"
15
+ echo " -i: Image name (required)"
16
+ echo " -o: Organization name"
17
+ echo " --push: Push the image"
18
+ echo " --load: Load the image"
19
+ echo " -t: Tag suffix"
20
+ echo " --dry: Don't build, only create build-args.json"
21
+ exit 1
22
+ }
23
+
24
+ # Parse command-line options
25
+ while [[ $# -gt 0 ]]; do
26
+ case $1 in
27
+ -i) image_name="$2"; shift 2 ;;
28
+ -o) org_name="$2"; shift 2 ;;
29
+ --push) push=1; shift ;;
30
+ --load) load=1; shift ;;
31
+ -t) tag_suffix="$2"; shift 2 ;;
32
+ --dry) dry_run=1; shift ;;
33
+ *) usage ;;
34
+ esac
35
+ done
36
+ # Check if required arguments are provided
37
+ if [[ -z "$image_name" ]]; then
38
+ echo "Error: Image name is required."
39
+ usage
40
+ fi
41
+
42
+ echo "Building: $image_name"
43
+ tags=()
44
+
45
+ OPENHANDS_BUILD_VERSION="dev"
46
+
47
+ cache_tag_base="buildcache"
48
+ cache_tag="$cache_tag_base"
49
+
50
+ if [[ -n $RELEVANT_SHA ]]; then
51
+ git_hash=$(git rev-parse --short "$RELEVANT_SHA")
52
+ tags+=("$git_hash")
53
+ tags+=("$RELEVANT_SHA")
54
+ fi
55
+
56
+ if [[ -n $GITHUB_REF_NAME ]]; then
57
+ # check if ref name is a version number
58
+ if [[ $GITHUB_REF_NAME =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
59
+ major_version=$(echo "$GITHUB_REF_NAME" | cut -d. -f1)
60
+ minor_version=$(echo "$GITHUB_REF_NAME" | cut -d. -f1,2)
61
+ tags+=("$major_version" "$minor_version")
62
+ tags+=("latest")
63
+ fi
64
+ sanitized_ref_name=$(echo "$GITHUB_REF_NAME" | sed 's/[^a-zA-Z0-9.-]\+/-/g')
65
+ OPENHANDS_BUILD_VERSION=$sanitized_ref_name
66
+ sanitized_ref_name=$(echo "$sanitized_ref_name" | tr '[:upper:]' '[:lower:]') # lower case is required in tagging
67
+ tags+=("$sanitized_ref_name")
68
+ cache_tag+="-${sanitized_ref_name}"
69
+ fi
70
+
71
+ if [[ -n $tag_suffix ]]; then
72
+ cache_tag+="-${tag_suffix}"
73
+ for i in "${!tags[@]}"; do
74
+ tags[$i]="${tags[$i]}-$tag_suffix"
75
+ done
76
+ fi
77
+
78
+ echo "Tags: ${tags[@]}"
79
+
80
+ if [[ "$image_name" == "openhands" ]]; then
81
+ dir="./containers/app"
82
+ elif [[ "$image_name" == "runtime" ]]; then
83
+ dir="./containers/runtime"
84
+ else
85
+ dir="./containers/$image_name"
86
+ fi
87
+
88
+ if [[ (! -f "$dir/Dockerfile") && "$image_name" != "runtime" ]]; then
89
+ # Allow runtime to be built without a Dockerfile
90
+ echo "No Dockerfile found"
91
+ exit 1
92
+ fi
93
+ if [[ ! -f "$dir/config.sh" ]]; then
94
+ echo "No config.sh found for Dockerfile"
95
+ exit 1
96
+ fi
97
+
98
+ source "$dir/config.sh"
99
+
100
+ if [[ -n "$org_name" ]]; then
101
+ DOCKER_ORG="$org_name"
102
+ fi
103
+
104
+ # If $DOCKER_IMAGE_SOURCE_TAG is set, add it to the tags
105
+ if [[ -n "$DOCKER_IMAGE_SOURCE_TAG" ]]; then
106
+ tags+=("$DOCKER_IMAGE_SOURCE_TAG")
107
+ fi
108
+ # If $DOCKER_IMAGE_TAG is set, add it to the tags
109
+ if [[ -n "$DOCKER_IMAGE_TAG" ]]; then
110
+ tags+=("$DOCKER_IMAGE_TAG")
111
+ fi
112
+
113
+ DOCKER_REPOSITORY="$DOCKER_REGISTRY/$DOCKER_ORG/$DOCKER_IMAGE"
114
+ DOCKER_REPOSITORY=${DOCKER_REPOSITORY,,} # lowercase
115
+ echo "Repo: $DOCKER_REPOSITORY"
116
+ echo "Base dir: $DOCKER_BASE_DIR"
117
+
118
+ args=""
119
+ full_tags=()
120
+ for tag in "${tags[@]}"; do
121
+ args+=" -t $DOCKER_REPOSITORY:$tag"
122
+ full_tags+=("$DOCKER_REPOSITORY:$tag")
123
+ done
124
+
125
+
126
+ if [[ $push -eq 1 ]]; then
127
+ args+=" --push"
128
+ args+=" --cache-to=type=registry,ref=$DOCKER_REPOSITORY:$cache_tag,mode=max"
129
+ fi
130
+
131
+ if [[ $load -eq 1 ]]; then
132
+ args+=" --load"
133
+ fi
134
+
135
+ echo "Args: $args"
136
+
137
+ # Modify the platform selection based on --load flag
138
+ if [[ $load -eq 1 ]]; then
139
+ # When loading, build only for the current platform
140
+ platform=$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')
141
+ else
142
+ # For push or without load, build for multiple platforms
143
+ platform="linux/amd64,linux/arm64"
144
+ fi
145
+ if [[ $dry_run -eq 1 ]]; then
146
+ echo "Dry Run is enabled. Writing build config to docker-build-dry.json"
147
+ jq -n \
148
+ --argjson tags "$(printf '%s\n' "${full_tags[@]}" | jq -R . | jq -s .)" \
149
+ --arg platform "$platform" \
150
+ --arg openhands_build_version "$OPENHANDS_BUILD_VERSION" \
151
+ --arg dockerfile "$dir/Dockerfile" \
152
+ '{
153
+ tags: $tags,
154
+ platform: $platform,
155
+ build_args: [
156
+ "OPENHANDS_BUILD_VERSION=" + $openhands_build_version
157
+ ],
158
+ dockerfile: $dockerfile
159
+ }' > docker-build-dry.json
160
+
161
+ exit 0
162
+ fi
163
+
164
+
165
+
166
+ echo "Building for platform(s): $platform"
167
+
168
+ docker buildx build \
169
+ $args \
170
+ --build-arg OPENHANDS_BUILD_VERSION="$OPENHANDS_BUILD_VERSION" \
171
+ --cache-from=type=registry,ref=$DOCKER_REPOSITORY:$cache_tag \
172
+ --cache-from=type=registry,ref=$DOCKER_REPOSITORY:$cache_tag_base-main \
173
+ --platform $platform \
174
+ --provenance=false \
175
+ -f "$dir/Dockerfile" \
176
+ "$DOCKER_BASE_DIR"
177
+
178
+ # If load was requested, print the loaded images
179
+ if [[ $load -eq 1 ]]; then
180
+ echo "Local images built:"
181
+ docker images "$DOCKER_REPOSITORY" --format "{{.Repository}}:{{.Tag}}"
182
+ fi
containers/dev/Dockerfile ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+
3
+ ###
4
+ FROM ubuntu:22.04 AS dind
5
+
6
+ # https://docs.docker.com/engine/install/ubuntu/
7
+ RUN apt-get update && apt-get install -y \
8
+ ca-certificates \
9
+ curl \
10
+ && install -m 0755 -d /etc/apt/keyrings \
11
+ && curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc \
12
+ && chmod a+r /etc/apt/keyrings/docker.asc \
13
+ && echo \
14
+ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
15
+ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
16
+
17
+ RUN apt-get update && apt-get install -y \
18
+ docker-ce \
19
+ docker-ce-cli \
20
+ containerd.io \
21
+ docker-buildx-plugin \
22
+ docker-compose-plugin \
23
+ && rm -rf /var/lib/apt/lists/* \
24
+ && apt-get clean \
25
+ && apt-get autoremove -y
26
+
27
+ ###
28
+ FROM dind AS openhands
29
+
30
+ ENV DEBIAN_FRONTEND=noninteractive
31
+
32
+ #
33
+ RUN apt-get update && apt-get install -y \
34
+ bash \
35
+ build-essential \
36
+ curl \
37
+ git \
38
+ git-lfs \
39
+ software-properties-common \
40
+ make \
41
+ netcat \
42
+ sudo \
43
+ wget \
44
+ && rm -rf /var/lib/apt/lists/* \
45
+ && apt-get clean \
46
+ && apt-get autoremove -y
47
+
48
+ # https://github.com/cli/cli/blob/trunk/docs/install_linux.md
49
+ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
50
+ && chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
51
+ && 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 \
52
+ && apt-get update && apt-get -y install \
53
+ gh \
54
+ && rm -rf /var/lib/apt/lists/* \
55
+ && apt-get clean \
56
+ && apt-get autoremove -y
57
+
58
+ # Python 3.12
59
+ RUN add-apt-repository ppa:deadsnakes/ppa \
60
+ && apt-get update \
61
+ && apt-get install -y python3.12 python3.12-venv python3.12-dev python3-pip \
62
+ && ln -s /usr/bin/python3.12 /usr/bin/python
63
+
64
+ # NodeJS >= 22.x
65
+ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
66
+ && apt-get install -y nodejs
67
+
68
+ # Poetry >= 1.8
69
+ RUN curl -fsSL https://install.python-poetry.org | python3.12 - \
70
+ && ln -s ~/.local/bin/poetry /usr/local/bin/poetry
71
+
72
+ #
73
+ RUN <<EOF
74
+ #!/bin/bash
75
+ printf "#!/bin/bash
76
+ set +x
77
+ uname -a
78
+ docker --version
79
+ gh --version | head -n 1
80
+ git --version
81
+ #
82
+ python --version
83
+ echo node `node --version`
84
+ echo npm `npm --version`
85
+ poetry --version
86
+ netcat -h 2>&1 | head -n 1
87
+ " > /version.sh
88
+ chmod a+x /version.sh
89
+ EOF
90
+
91
+ ###
92
+ FROM openhands AS dev
93
+
94
+ RUN apt-get update && apt-get install -y \
95
+ dnsutils \
96
+ file \
97
+ iproute2 \
98
+ jq \
99
+ lsof \
100
+ ripgrep \
101
+ silversearcher-ag \
102
+ vim \
103
+ && rm -rf /var/lib/apt/lists/* \
104
+ && apt-get clean \
105
+ && apt-get autoremove -y
106
+
107
+ WORKDIR /app
108
+
109
+ # cache build dependencies
110
+ RUN \
111
+ --mount=type=bind,source=./,target=/app/,rw \
112
+ <<EOF
113
+ #!/bin/bash
114
+ make -s clean
115
+ make -s check-dependencies
116
+ make -s install-python-dependencies
117
+
118
+ # NOTE
119
+ # node_modules are .dockerignore-d therefore not mountable
120
+ # make -s install-frontend-dependencies
121
+ EOF
122
+
123
+ #
124
+ CMD ["bash"]
containers/dev/README.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Develop in Docker
2
+
3
+ > [!WARNING]
4
+ > This is not officially supported and may not work.
5
+
6
+ Install [Docker](https://docs.docker.com/engine/install/) on your host machine and run:
7
+
8
+ ```bash
9
+ make docker-dev
10
+ # same as:
11
+ cd ./containers/dev
12
+ ./dev.sh
13
+ ```
14
+
15
+ 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.
16
+
17
+ ## Build and run
18
+
19
+ If everything goes well, you should be inside a container after Docker finishes building the `openhands:dev` image similar to the following:
20
+
21
+ ```bash
22
+ Build and run in Docker ...
23
+ root@93fc0005fcd2:/app#
24
+ ```
25
+
26
+ You may now proceed with the normal [build and run](../../Development.md) workflow as if you were on the host.
27
+
28
+ ## Make changes
29
+
30
+ 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.
31
+
32
+ The following are also mapped as readonly from your host:
33
+
34
+ ```yaml
35
+ # host credentials
36
+ - $HOME/.git-credentials:/root/.git-credentials:ro
37
+ - $HOME/.gitconfig:/root/.gitconfig:ro
38
+ - $HOME/.npmrc:/root/.npmrc:ro
39
+ ```
40
+
41
+ ## VSCode
42
+
43
+ Alternatively, if you use VSCode, you could also [attach to the running container](https://code.visualstudio.com/docs/devcontainers/attach-container).
44
+
45
+ See details for [developing in docker](https://code.visualstudio.com/docs/devcontainers/containers) or simply ask `OpenHands` ;-)
46
+
47
+ ## Rebuild dev image
48
+
49
+ You could optionally pass additional options to the build script.
50
+
51
+ ```bash
52
+ make docker-dev OPTIONS="--build"
53
+ # or
54
+ ./containers/dev/dev.sh --build
55
+ ```
56
+
57
+ See [docker compose run](https://docs.docker.com/reference/cli/docker/compose/run/) for more options.
containers/dev/compose.yml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ services:
3
+ dev:
4
+ privileged: true
5
+ build:
6
+ context: ${OPENHANDS_WORKSPACE:-../../}
7
+ dockerfile: ./containers/dev/Dockerfile
8
+ image: openhands:dev
9
+ container_name: openhands-dev
10
+ environment:
11
+ - BACKEND_HOST=${BACKEND_HOST:-"0.0.0.0"}
12
+ - SANDBOX_API_HOSTNAME=host.docker.internal
13
+ #
14
+ - SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.41-nikolaik}
15
+ - SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
16
+ - WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
17
+ ports:
18
+ - "3000:3000"
19
+ extra_hosts:
20
+ - "host.docker.internal:host-gateway"
21
+ volumes:
22
+ - /var/run/docker.sock:/var/run/docker.sock
23
+ - ${WORKSPACE_BASE:-$PWD/workspace}:/opt/workspace_base
24
+ # source code
25
+ - ${OPENHANDS_WORKSPACE:-../../}:/app
26
+ # host credentials
27
+ - $HOME/.git-credentials:/root/.git-credentials:ro
28
+ - $HOME/.gitconfig:/root/.gitconfig:ro
29
+ - $HOME/.npmrc:/root/.npmrc:ro
30
+ # cache
31
+ - cache-data:/root/.cache
32
+ pull_policy: never
33
+ stdin_open: true
34
+ tty: true
35
+
36
+ ##
37
+ volumes:
38
+ cache-data:
containers/dev/dev.sh ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -o pipefail
3
+
4
+ function get_docker() {
5
+ echo "Docker is required to build and run OpenHands."
6
+ echo "https://docs.docker.com/get-started/get-docker/"
7
+ exit 1
8
+ }
9
+
10
+ function check_tools() {
11
+ command -v docker &>/dev/null || get_docker
12
+ }
13
+
14
+ function exit_if_indocker() {
15
+ if [ -f /.dockerenv ]; then
16
+ echo "Running inside a Docker container. Exiting..."
17
+ exit 1
18
+ fi
19
+ }
20
+
21
+ #
22
+ exit_if_indocker
23
+
24
+ check_tools
25
+
26
+ ##
27
+ OPENHANDS_WORKSPACE=$(git rev-parse --show-toplevel)
28
+
29
+ cd "$OPENHANDS_WORKSPACE/containers/dev/" || exit 1
30
+
31
+ ##
32
+ export BACKEND_HOST="0.0.0.0"
33
+ #
34
+ export SANDBOX_USER_ID=$(id -u)
35
+ export WORKSPACE_BASE=${WORKSPACE_BASE:-$OPENHANDS_WORKSPACE/workspace}
36
+
37
+ docker compose run --rm --service-ports "$@" dev
38
+
39
+ ##
containers/e2b-sandbox/Dockerfile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM ubuntu:22.04
2
+
3
+ # install basic packages
4
+ RUN apt-get update && apt-get install -y \
5
+ curl \
6
+ wget \
7
+ git \
8
+ vim \
9
+ nano \
10
+ unzip \
11
+ zip \
12
+ python3 \
13
+ python3-pip \
14
+ python3-venv \
15
+ python3-dev \
16
+ build-essential \
17
+ openssh-server \
18
+ sudo \
19
+ && rm -rf /var/lib/apt/lists/*
containers/e2b-sandbox/README.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # How to build custom E2B sandbox for OpenHands
2
+
3
+ [E2B](https://e2b.dev) is an [open-source](https://github.com/e2b-dev/e2b) secure cloud environment (sandbox) made for running AI-generated code and agents. E2B offers [Python](https://pypi.org/project/e2b/) and [JS/TS](https://www.npmjs.com/package/e2b) SDK to spawn and control these sandboxes.
4
+
5
+
6
+ 1. Install the CLI with NPM.
7
+ ```sh
8
+ npm install -g @e2b/cli@latest
9
+ ```
10
+ Full CLI API is [here](https://e2b.dev/docs/cli/installation).
11
+
12
+ 1. Build the sandbox
13
+ ```sh
14
+ e2b template build --dockerfile ./Dockerfile --name "openhands"
15
+ ```
containers/e2b-sandbox/e2b.toml ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is a config for E2B sandbox template.
2
+ # You can use 'template_id' (785n69crgahmz0lkdw9h) or 'template_name (openhands) from this config to spawn a sandbox:
3
+
4
+ # Python SDK
5
+ # from e2b import Sandbox
6
+ # sandbox = Sandbox(template='openhands')
7
+
8
+ # JS SDK
9
+ # import { Sandbox } from 'e2b'
10
+ # const sandbox = await Sandbox.create({ template: 'openhands' })
11
+
12
+ dockerfile = "Dockerfile"
13
+ template_name = "openhands"
14
+ template_id = "785n69crgahmz0lkdw9h"
containers/runtime/README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dynamically constructed Dockerfile
2
+
3
+ This folder builds a runtime image (sandbox), which will use a dynamically generated `Dockerfile`
4
+ 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`.
5
+
6
+ The following command will generate a `Dockerfile` file for `nikolaik/python-nodejs:python3.12-nodejs22` (the default base image), an updated `config.sh` and the runtime source distribution files/folders into `containers/runtime`:
7
+
8
+ ```bash
9
+ poetry run python3 openhands/runtime/utils/runtime_build.py \
10
+ --base_image nikolaik/python-nodejs:python3.12-nodejs22 \
11
+ --build_folder containers/runtime
12
+ ```
containers/runtime/config.sh ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ DOCKER_REGISTRY=ghcr.io
2
+ DOCKER_ORG=all-hands-ai
3
+ DOCKER_BASE_DIR="./containers/runtime"
4
+ DOCKER_IMAGE=runtime
5
+ # These variables will be appended by the runtime_build.py script
6
+ # DOCKER_IMAGE_TAG=
7
+ # DOCKER_IMAGE_SOURCE_TAG=
dev_config/python/mypy.ini ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ [mypy]
2
+ warn_unused_configs = True
3
+ ignore_missing_imports = True
4
+ check_untyped_defs = True
5
+ explicit_package_bases = True
6
+ warn_unreachable = True
7
+ warn_redundant_casts = True
8
+ no_implicit_optional = True
9
+ strict_optional = True
dev_config/python/ruff.toml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [lint]
2
+ select = [
3
+ "E",
4
+ "W",
5
+ "F",
6
+ "I",
7
+ "Q",
8
+ "B",
9
+ "ASYNC",
10
+ "UP006", # Use `list` instead of `List` for annotations
11
+ "UP007", # Use `X | Y` instead of `Union[X, Y]`
12
+ "UP008", # Use `X | None` instead of `Optional[X]`
13
+ ]
14
+
15
+ ignore = [
16
+ "E501",
17
+ "B003",
18
+ "B007",
19
+ "B009",
20
+ "B010",
21
+ "B904",
22
+ "B018",
23
+ # Temporarily ignore ASYNC rules until they can be properly fixed in a separate PR
24
+ "ASYNC110",
25
+ "ASYNC220",
26
+ "ASYNC221",
27
+ "ASYNC230",
28
+ "ASYNC251",
29
+ ]
30
+
31
+ [lint.flake8-quotes]
32
+ docstring-quotes = "double"
33
+ inline-quotes = "single"
34
+
35
+ [format]
36
+ quote-style = "single"
37
+
38
+ [lint.flake8-bugbear]
39
+ extend-immutable-calls = ["Depends", "fastapi.Depends", "fastapi.params.Depends"]
docker-compose.yml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ services:
3
+ openhands:
4
+ build:
5
+ context: ./
6
+ dockerfile: ./containers/app/Dockerfile
7
+ image: openhands:latest
8
+ container_name: openhands-app-${DATE:-}
9
+ environment:
10
+ - SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.all-hands.dev/all-hands-ai/runtime:0.41-nikolaik}
11
+ #- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234} # enable this only if you want a specific non-root sandbox user but you will have to manually adjust permissions of openhands-state for this user
12
+ - WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
13
+ ports:
14
+ - "3000:3000"
15
+ extra_hosts:
16
+ - "host.docker.internal:host-gateway"
17
+ volumes:
18
+ - /var/run/docker.sock:/var/run/docker.sock
19
+ - ~/.openhands-state:/.openhands-state
20
+ - ${WORKSPACE_BASE:-$PWD/workspace}:/opt/workspace_base
21
+ pull_policy: build
22
+ stdin_open: true
23
+ tty: true
docs/DOC_STYLE_GUIDE.md ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Documentation Style Guide
2
+
3
+ ## General Writing Principles
4
+
5
+ - **Clarity & Conciseness**: Always prioritize clarity and brevity. Avoid unnecessary jargon or overly complex explanations.
6
+ Keep sentences short and to the point.
7
+ - **Gradual Complexity**: Start with the simplest, most basic setup, and then gradually introduce more advanced
8
+ concepts and configurations.
9
+
10
+ ## Formatting Guidelines
11
+
12
+ ### Headers
13
+
14
+ Use **Title Case** for the first and second level headers.
15
+
16
+ Example:
17
+ - **Basic Usage**
18
+ - **Advanced Configuration Options**
19
+
20
+ ### Lists
21
+
22
+ When listing items or options, use bullet points to enhance readability.
23
+
24
+ Example:
25
+ - Option A
26
+ - Option B
27
+ - Option C
28
+
29
+ ### Procedures
30
+
31
+ For instructions or processes that need to be followed in a specific order, use numbered steps.
32
+
33
+ Example:
34
+ 1. Step one: Do this.
35
+ - First this sub step.
36
+ - Then this sub step.
37
+ 2. Step two: Complete this action.
38
+ 3. Step three: Verify the result.
39
+
40
+ ### Code Blocks
41
+
42
+ * Use code blocks for multi-line inputs, outputs, commands and code samples.
43
+
44
+ Example:
45
+ ```bash
46
+ docker run -it \
47
+ -e THIS=this \
48
+ -e THAT=that
49
+ ...
50
+ ```
51
+
52
+ ### Use of Note and Warning
53
+
54
+ When adding a note or warning, use the built-in note and warning syntax.
55
+
56
+ Example:
57
+ <Note>
58
+ This section is for advanced users only.
59
+ </Note>
60
+
61
+ ### Referring to UI Elements
62
+
63
+ When referencing UI elements, use ``.
64
+
65
+ Example:
66
+ 1. Toggle the `Advanced` option
67
+ 2. Enter your model in the `Custom Model` textbox.
docs/docs.json ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://mintlify.com/docs.json",
3
+ "theme": "mint",
4
+ "name": "All Hands Docs",
5
+ "colors": {
6
+ "primary": "#99873c",
7
+ "light": "#ffe165",
8
+ "dark": "#ffe165"
9
+ },
10
+ "background": {
11
+ "color": {
12
+ "light": "#f7f3ee",
13
+ "dark": "#0B0D0E"
14
+ }
15
+ },
16
+ "appearance": {
17
+ "default": "light"
18
+ },
19
+ "favicon": "/logo-square.png",
20
+ "navigation": {
21
+ "tabs": [
22
+ {
23
+ "tab": "Docs",
24
+ "pages": [
25
+ "index",
26
+ "usage/installation",
27
+ "usage/getting-started",
28
+ "usage/key-features",
29
+ {
30
+ "group": "OpenHands Cloud",
31
+ "pages": [
32
+ "usage/cloud/openhands-cloud",
33
+ {
34
+ "group": "Integrations",
35
+ "pages": [
36
+ "usage/cloud/github-installation",
37
+ "usage/cloud/gitlab-installation"
38
+ ]
39
+ },
40
+ "usage/cloud/cloud-ui",
41
+ "usage/cloud/cloud-api"
42
+ ]
43
+ },
44
+ {
45
+ "group": "Running OpenHands Locally",
46
+ "pages": [
47
+ "usage/local-setup",
48
+ "usage/how-to/gui-mode",
49
+ "usage/how-to/cli-mode",
50
+ "usage/how-to/headless-mode",
51
+ "usage/how-to/github-action"
52
+ ]
53
+ },
54
+ {
55
+ "group": "Customization",
56
+ "pages": [
57
+ "usage/prompting/prompting-best-practices",
58
+ "usage/prompting/repository",
59
+ {
60
+ "group": "Microagents",
61
+ "pages": [
62
+ "usage/prompting/microagents-overview",
63
+ "usage/prompting/microagents-repo",
64
+ "usage/prompting/microagents-keyword",
65
+ "usage/prompting/microagents-org",
66
+ "usage/prompting/microagents-public"
67
+ ]
68
+ }
69
+ ]
70
+ },
71
+ {
72
+ "group": "Advanced Configuration",
73
+ "pages": [
74
+ {
75
+ "group": "LLM Configuration",
76
+ "pages": [
77
+ "usage/llms/llms",
78
+ {
79
+ "group": "Providers",
80
+ "pages": [
81
+ "usage/llms/azure-llms",
82
+ "usage/llms/google-llms",
83
+ "usage/llms/groq",
84
+ "usage/llms/local-llms",
85
+ "usage/llms/litellm-proxy",
86
+ "usage/llms/openai-llms",
87
+ "usage/llms/openrouter"
88
+ ]
89
+ }
90
+ ]
91
+ },
92
+ {
93
+ "group": "Runtime Configuration",
94
+ "pages": [
95
+ "usage/runtimes/overview",
96
+ {
97
+ "group": "Providers",
98
+ "pages": [
99
+ "usage/runtimes/docker",
100
+ "usage/runtimes/remote",
101
+ "usage/runtimes/local",
102
+ {
103
+ "group": "Third-Party Providers",
104
+ "pages": [
105
+ "usage/runtimes/modal",
106
+ "usage/runtimes/daytona",
107
+ "usage/runtimes/runloop",
108
+ "usage/runtimes/e2b"
109
+ ]
110
+ }
111
+ ]
112
+ }
113
+ ]
114
+ },
115
+ "usage/configuration-options",
116
+ "usage/how-to/custom-sandbox-guide",
117
+ "usage/search-engine-setup",
118
+ "usage/mcp"
119
+ ]
120
+ },
121
+ {
122
+ "group": "Troubleshooting & Feedback",
123
+ "pages": [
124
+ "usage/troubleshooting/troubleshooting",
125
+ "usage/feedback"
126
+ ]
127
+ },
128
+ {
129
+ "group": "OpenHands Developers",
130
+ "pages": [
131
+ "usage/how-to/development-overview",
132
+ {
133
+ "group": "Architecture",
134
+ "pages": [
135
+ "usage/architecture/backend",
136
+ "usage/architecture/runtime"
137
+ ]
138
+ },
139
+ "usage/how-to/debugging",
140
+ "usage/how-to/evaluation-harness",
141
+ "usage/how-to/websocket-connection"
142
+ ]
143
+ }
144
+ ]
145
+ },
146
+ {
147
+ "tab": "API Reference",
148
+ "openapi": "/openapi.json"
149
+ }
150
+ ],
151
+ "global": {
152
+ "anchors": [
153
+ {
154
+ "anchor": "Company",
155
+ "href": "https://www.all-hands.dev/",
156
+ "icon": "house"
157
+ },
158
+ {
159
+ "anchor": "Blog",
160
+ "href": "https://www.all-hands.dev/blog",
161
+ "icon": "newspaper"
162
+ },
163
+ {
164
+ "anchor": "OpenHands Cloud",
165
+ "href": "https://app.all-hands.dev",
166
+ "icon": "cloud"
167
+ }
168
+ ]
169
+ }
170
+ },
171
+ "logo": {
172
+ "light": "/logo/light.svg",
173
+ "dark": "/logo/dark.svg"
174
+ },
175
+ "navbar": {
176
+ "links": [
177
+ ],
178
+ "primary": {
179
+ "type": "github",
180
+ "href": "https://github.com/All-Hands-AI/OpenHands"
181
+ }
182
+ },
183
+ "footer": {
184
+ "socials": {
185
+ "slack": "https://join.slack.com/t/openhands-ai/shared_invite/zt-34zm4j0gj-Qz5kRHoca8DFCbqXPS~f_A",
186
+ "github": "https://github.com/All-Hands-AI/OpenHands",
187
+ "discord": "https://discord.gg/ESHStjSjD4"
188
+ }
189
+ },
190
+ "contextual": {
191
+ "options": [
192
+ "copy",
193
+ "view",
194
+ "chatgpt",
195
+ "claude"
196
+ ]
197
+ },
198
+ "redirects": [
199
+ {
200
+ "source": "/modules/:slug*",
201
+ "destination": "/:slug*"
202
+ }
203
+ ]
204
+ }
docs/favicon.svg ADDED
docs/index.mdx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Introduction
3
+ description: OpenHands - Code Less, Make More
4
+ icon: book-open
5
+ mode: wide
6
+ ---
7
+ Use AI to tackle the toil in your backlog. Our agents have all the same tools as a human developer: they can modify code, run commands, browse the web, call APIs, and yes-even copy code snippets from StackOverflow.
8
+
9
+ <iframe
10
+ className="w-full aspect-video"
11
+ src="https://www.youtube.com/embed/oB4JR98KRAA"
12
+ title="YouTube video player"
13
+ frameborder="0"
14
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
15
+ allowfullscreen
16
+ ></iframe>
docs/logo-square.png ADDED

Git LFS Details

  • SHA256: de58ad6132a9afb7d4924612c5e013695658af993a81a7611a6564f6a8063d59
  • Pointer size: 132 Bytes
  • Size of remote file: 1.19 MB
docs/logo/dark.svg ADDED
docs/logo/light.svg ADDED
docs/openapi.json ADDED
@@ -0,0 +1,2091 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "openapi": "3.0.3",
3
+ "info": {
4
+ "title": "OpenHands API",
5
+ "description": "OpenHands: Code Less, Make More",
6
+ "version": "1.0.0"
7
+ },
8
+ "servers": [
9
+ {
10
+ "url": "https://app.all-hands.dev",
11
+ "description": "Production server"
12
+ },
13
+ {
14
+ "url": "http://localhost:3000",
15
+ "description": "Local development server"
16
+ }
17
+ ],
18
+ "paths": {
19
+ "/health": {
20
+ "get": {
21
+ "summary": "Health check",
22
+ "description": "Check if the API is running",
23
+ "operationId": "health",
24
+ "responses": {
25
+ "200": {
26
+ "description": "API is running",
27
+ "content": {
28
+ "text/plain": {
29
+ "schema": {
30
+ "type": "string",
31
+ "example": "OK"
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ },
39
+ "/api/conversations/{conversation_id}/config": {
40
+ "get": {
41
+ "summary": "Get runtime configuration",
42
+ "description": "Retrieve the runtime configuration (session ID and runtime ID)",
43
+ "operationId": "getRemoteRuntimeConfig",
44
+ "parameters": [
45
+ {
46
+ "name": "conversation_id",
47
+ "in": "path",
48
+ "required": true,
49
+ "schema": {
50
+ "type": "string"
51
+ },
52
+ "description": "Conversation ID"
53
+ }
54
+ ],
55
+ "responses": {
56
+ "200": {
57
+ "description": "Runtime configuration",
58
+ "content": {
59
+ "application/json": {
60
+ "schema": {
61
+ "type": "object",
62
+ "properties": {
63
+ "runtime_id": {
64
+ "type": "string",
65
+ "nullable": true
66
+ },
67
+ "session_id": {
68
+ "type": "string",
69
+ "nullable": true
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ },
79
+ "/api/conversations/{conversation_id}/vscode-url": {
80
+ "get": {
81
+ "summary": "Get VSCode URL",
82
+ "description": "Get the VSCode URL for the conversation",
83
+ "operationId": "getVscodeUrl",
84
+ "parameters": [
85
+ {
86
+ "name": "conversation_id",
87
+ "in": "path",
88
+ "required": true,
89
+ "schema": {
90
+ "type": "string"
91
+ },
92
+ "description": "Conversation ID"
93
+ }
94
+ ],
95
+ "responses": {
96
+ "200": {
97
+ "description": "VSCode URL",
98
+ "content": {
99
+ "application/json": {
100
+ "schema": {
101
+ "type": "object",
102
+ "properties": {
103
+ "vscode_url": {
104
+ "type": "string",
105
+ "nullable": true
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ },
112
+ "500": {
113
+ "description": "Error getting VSCode URL",
114
+ "content": {
115
+ "application/json": {
116
+ "schema": {
117
+ "type": "object",
118
+ "properties": {
119
+ "vscode_url": {
120
+ "type": "string",
121
+ "nullable": true
122
+ },
123
+ "error": {
124
+ "type": "string"
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ },
134
+ "/api/conversations/{conversation_id}/web-hosts": {
135
+ "get": {
136
+ "summary": "Get runtime hosts",
137
+ "description": "Get the hosts used by the runtime",
138
+ "operationId": "getHosts",
139
+ "parameters": [
140
+ {
141
+ "name": "conversation_id",
142
+ "in": "path",
143
+ "required": true,
144
+ "schema": {
145
+ "type": "string"
146
+ },
147
+ "description": "Conversation ID"
148
+ }
149
+ ],
150
+ "responses": {
151
+ "200": {
152
+ "description": "Runtime hosts",
153
+ "content": {
154
+ "application/json": {
155
+ "schema": {
156
+ "type": "object",
157
+ "properties": {
158
+ "hosts": {
159
+ "type": "array",
160
+ "items": {
161
+ "type": "string"
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ },
169
+ "500": {
170
+ "description": "Error getting runtime hosts",
171
+ "content": {
172
+ "application/json": {
173
+ "schema": {
174
+ "type": "object",
175
+ "properties": {
176
+ "hosts": {
177
+ "type": "array",
178
+ "items": {
179
+ "type": "string"
180
+ },
181
+ "nullable": true
182
+ },
183
+ "error": {
184
+ "type": "string"
185
+ }
186
+ }
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ },
194
+ "/api/conversations/{conversation_id}/submit-feedback": {
195
+ "post": {
196
+ "summary": "Submit feedback",
197
+ "description": "Submit user feedback for a conversation",
198
+ "operationId": "submitFeedback",
199
+ "parameters": [
200
+ {
201
+ "name": "conversation_id",
202
+ "in": "path",
203
+ "required": true,
204
+ "schema": {
205
+ "type": "string"
206
+ },
207
+ "description": "Conversation ID"
208
+ }
209
+ ],
210
+ "requestBody": {
211
+ "required": true,
212
+ "content": {
213
+ "application/json": {
214
+ "schema": {
215
+ "type": "object",
216
+ "properties": {
217
+ "email": {
218
+ "type": "string",
219
+ "format": "email"
220
+ },
221
+ "version": {
222
+ "type": "string"
223
+ },
224
+ "permissions": {
225
+ "type": "string",
226
+ "default": "private"
227
+ },
228
+ "polarity": {
229
+ "type": "string"
230
+ },
231
+ "feedback": {
232
+ "type": "string"
233
+ }
234
+ }
235
+ }
236
+ }
237
+ }
238
+ },
239
+ "responses": {
240
+ "200": {
241
+ "description": "Feedback submitted successfully",
242
+ "content": {
243
+ "application/json": {
244
+ "schema": {
245
+ "type": "object"
246
+ }
247
+ }
248
+ }
249
+ },
250
+ "500": {
251
+ "description": "Error submitting feedback",
252
+ "content": {
253
+ "application/json": {
254
+ "schema": {
255
+ "type": "object",
256
+ "properties": {
257
+ "error": {
258
+ "type": "string"
259
+ }
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
265
+ }
266
+ }
267
+ },
268
+ "/api/conversations/{conversation_id}/list-files": {
269
+ "get": {
270
+ "summary": "List files",
271
+ "description": "List files in the specified path",
272
+ "operationId": "listFiles",
273
+ "parameters": [
274
+ {
275
+ "name": "conversation_id",
276
+ "in": "path",
277
+ "required": true,
278
+ "schema": {
279
+ "type": "string"
280
+ },
281
+ "description": "Conversation ID"
282
+ },
283
+ {
284
+ "name": "path",
285
+ "in": "query",
286
+ "required": false,
287
+ "schema": {
288
+ "type": "string"
289
+ },
290
+ "description": "Path to list files from"
291
+ }
292
+ ],
293
+ "responses": {
294
+ "200": {
295
+ "description": "List of files",
296
+ "content": {
297
+ "application/json": {
298
+ "schema": {
299
+ "type": "array",
300
+ "items": {
301
+ "type": "string"
302
+ }
303
+ }
304
+ }
305
+ }
306
+ },
307
+ "404": {
308
+ "description": "Runtime not initialized",
309
+ "content": {
310
+ "application/json": {
311
+ "schema": {
312
+ "type": "object",
313
+ "properties": {
314
+ "error": {
315
+ "type": "string"
316
+ }
317
+ }
318
+ }
319
+ }
320
+ }
321
+ },
322
+ "500": {
323
+ "description": "Error listing files",
324
+ "content": {
325
+ "application/json": {
326
+ "schema": {
327
+ "type": "object",
328
+ "properties": {
329
+ "error": {
330
+ "type": "string"
331
+ }
332
+ }
333
+ }
334
+ }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ },
340
+ "/api/conversations/{conversation_id}/select-file": {
341
+ "get": {
342
+ "summary": "Get file content",
343
+ "description": "Retrieve the content of a specified file",
344
+ "operationId": "selectFile",
345
+ "parameters": [
346
+ {
347
+ "name": "conversation_id",
348
+ "in": "path",
349
+ "required": true,
350
+ "schema": {
351
+ "type": "string"
352
+ },
353
+ "description": "Conversation ID"
354
+ },
355
+ {
356
+ "name": "file",
357
+ "in": "query",
358
+ "required": true,
359
+ "schema": {
360
+ "type": "string"
361
+ },
362
+ "description": "Path of the file to be retrieved"
363
+ }
364
+ ],
365
+ "responses": {
366
+ "200": {
367
+ "description": "File content",
368
+ "content": {
369
+ "application/json": {
370
+ "schema": {
371
+ "type": "object",
372
+ "properties": {
373
+ "code": {
374
+ "type": "string"
375
+ }
376
+ }
377
+ }
378
+ }
379
+ }
380
+ },
381
+ "415": {
382
+ "description": "Unable to open binary file",
383
+ "content": {
384
+ "application/json": {
385
+ "schema": {
386
+ "type": "object",
387
+ "properties": {
388
+ "error": {
389
+ "type": "string"
390
+ }
391
+ }
392
+ }
393
+ }
394
+ }
395
+ },
396
+ "500": {
397
+ "description": "Error opening file",
398
+ "content": {
399
+ "application/json": {
400
+ "schema": {
401
+ "type": "object",
402
+ "properties": {
403
+ "error": {
404
+ "type": "string"
405
+ }
406
+ }
407
+ }
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
413
+ },
414
+ "/api/conversations/{conversation_id}/zip-directory": {
415
+ "get": {
416
+ "summary": "Download workspace as zip",
417
+ "description": "Download the current workspace as a zip file",
418
+ "operationId": "zipCurrentWorkspace",
419
+ "parameters": [
420
+ {
421
+ "name": "conversation_id",
422
+ "in": "path",
423
+ "required": true,
424
+ "schema": {
425
+ "type": "string"
426
+ },
427
+ "description": "Conversation ID"
428
+ }
429
+ ],
430
+ "responses": {
431
+ "200": {
432
+ "description": "Workspace zip file",
433
+ "content": {
434
+ "application/zip": {
435
+ "schema": {
436
+ "type": "string",
437
+ "format": "binary"
438
+ }
439
+ }
440
+ }
441
+ },
442
+ "500": {
443
+ "description": "Error zipping workspace",
444
+ "content": {
445
+ "application/json": {
446
+ "schema": {
447
+ "type": "object",
448
+ "properties": {
449
+ "error": {
450
+ "type": "string"
451
+ }
452
+ }
453
+ }
454
+ }
455
+ }
456
+ }
457
+ }
458
+ }
459
+ },
460
+ "/api/conversations/{conversation_id}/git/changes": {
461
+ "get": {
462
+ "summary": "Get git changes",
463
+ "description": "Get git changes in the workspace",
464
+ "operationId": "gitChanges",
465
+ "parameters": [
466
+ {
467
+ "name": "conversation_id",
468
+ "in": "path",
469
+ "required": true,
470
+ "schema": {
471
+ "type": "string"
472
+ },
473
+ "description": "Conversation ID"
474
+ }
475
+ ],
476
+ "responses": {
477
+ "200": {
478
+ "description": "Git changes",
479
+ "content": {
480
+ "application/json": {
481
+ "schema": {
482
+ "type": "object"
483
+ }
484
+ }
485
+ }
486
+ },
487
+ "500": {
488
+ "description": "Error getting git changes",
489
+ "content": {
490
+ "application/json": {
491
+ "schema": {
492
+ "type": "object",
493
+ "properties": {
494
+ "error": {
495
+ "type": "string"
496
+ }
497
+ }
498
+ }
499
+ }
500
+ }
501
+ }
502
+ }
503
+ }
504
+ },
505
+ "/api/conversations/{conversation_id}/git/diff": {
506
+ "get": {
507
+ "summary": "Get git diff",
508
+ "description": "Get git diff for a specific file",
509
+ "operationId": "gitDiff",
510
+ "parameters": [
511
+ {
512
+ "name": "conversation_id",
513
+ "in": "path",
514
+ "required": true,
515
+ "schema": {
516
+ "type": "string"
517
+ },
518
+ "description": "Conversation ID"
519
+ },
520
+ {
521
+ "name": "path",
522
+ "in": "query",
523
+ "required": true,
524
+ "schema": {
525
+ "type": "string"
526
+ },
527
+ "description": "Path of the file to get diff for"
528
+ }
529
+ ],
530
+ "responses": {
531
+ "200": {
532
+ "description": "Git diff",
533
+ "content": {
534
+ "application/json": {
535
+ "schema": {
536
+ "type": "string"
537
+ }
538
+ }
539
+ }
540
+ },
541
+ "500": {
542
+ "description": "Error getting git diff",
543
+ "content": {
544
+ "application/json": {
545
+ "schema": {
546
+ "type": "object",
547
+ "properties": {
548
+ "error": {
549
+ "type": "string"
550
+ }
551
+ }
552
+ }
553
+ }
554
+ }
555
+ }
556
+ }
557
+ }
558
+ },
559
+ "/api/conversations/{conversation_id}/trajectory": {
560
+ "get": {
561
+ "summary": "Get trajectory",
562
+ "description": "Get the conversation trajectory",
563
+ "operationId": "getTrajectory",
564
+ "parameters": [
565
+ {
566
+ "name": "conversation_id",
567
+ "in": "path",
568
+ "required": true,
569
+ "schema": {
570
+ "type": "string"
571
+ },
572
+ "description": "Conversation ID"
573
+ }
574
+ ],
575
+ "responses": {
576
+ "200": {
577
+ "description": "Conversation trajectory",
578
+ "content": {
579
+ "application/json": {
580
+ "schema": {
581
+ "type": "object",
582
+ "properties": {
583
+ "trajectory": {
584
+ "type": "array",
585
+ "items": {
586
+ "type": "object"
587
+ }
588
+ }
589
+ }
590
+ }
591
+ }
592
+ }
593
+ },
594
+ "500": {
595
+ "description": "Error getting trajectory",
596
+ "content": {
597
+ "application/json": {
598
+ "schema": {
599
+ "type": "object",
600
+ "properties": {
601
+ "trajectory": {
602
+ "type": "array",
603
+ "items": {
604
+ "type": "object"
605
+ },
606
+ "nullable": true
607
+ },
608
+ "error": {
609
+ "type": "string"
610
+ }
611
+ }
612
+ }
613
+ }
614
+ }
615
+ }
616
+ }
617
+ }
618
+ },
619
+ "/api/conversations/{conversation_id}/security/{path}": {
620
+ "get": {
621
+ "summary": "Security analyzer API (GET)",
622
+ "description": "Catch-all route for security analyzer API GET requests",
623
+ "operationId": "securityApiGet",
624
+ "parameters": [
625
+ {
626
+ "name": "conversation_id",
627
+ "in": "path",
628
+ "required": true,
629
+ "schema": {
630
+ "type": "string"
631
+ },
632
+ "description": "Conversation ID"
633
+ },
634
+ {
635
+ "name": "path",
636
+ "in": "path",
637
+ "required": true,
638
+ "schema": {
639
+ "type": "string"
640
+ },
641
+ "description": "Security analyzer API path"
642
+ }
643
+ ],
644
+ "responses": {
645
+ "200": {
646
+ "description": "Security analyzer response",
647
+ "content": {
648
+ "application/json": {
649
+ "schema": {
650
+ "type": "object"
651
+ }
652
+ }
653
+ }
654
+ },
655
+ "404": {
656
+ "description": "Security analyzer not initialized",
657
+ "content": {
658
+ "application/json": {
659
+ "schema": {
660
+ "type": "object",
661
+ "properties": {
662
+ "detail": {
663
+ "type": "string"
664
+ }
665
+ }
666
+ }
667
+ }
668
+ }
669
+ }
670
+ }
671
+ },
672
+ "post": {
673
+ "summary": "Security analyzer API (POST)",
674
+ "description": "Catch-all route for security analyzer API POST requests",
675
+ "operationId": "securityApiPost",
676
+ "parameters": [
677
+ {
678
+ "name": "conversation_id",
679
+ "in": "path",
680
+ "required": true,
681
+ "schema": {
682
+ "type": "string"
683
+ },
684
+ "description": "Conversation ID"
685
+ },
686
+ {
687
+ "name": "path",
688
+ "in": "path",
689
+ "required": true,
690
+ "schema": {
691
+ "type": "string"
692
+ },
693
+ "description": "Security analyzer API path"
694
+ }
695
+ ],
696
+ "requestBody": {
697
+ "required": false,
698
+ "content": {
699
+ "application/json": {
700
+ "schema": {
701
+ "type": "object"
702
+ }
703
+ }
704
+ }
705
+ },
706
+ "responses": {
707
+ "200": {
708
+ "description": "Security analyzer response",
709
+ "content": {
710
+ "application/json": {
711
+ "schema": {
712
+ "type": "object"
713
+ }
714
+ }
715
+ }
716
+ },
717
+ "404": {
718
+ "description": "Security analyzer not initialized",
719
+ "content": {
720
+ "application/json": {
721
+ "schema": {
722
+ "type": "object",
723
+ "properties": {
724
+ "detail": {
725
+ "type": "string"
726
+ }
727
+ }
728
+ }
729
+ }
730
+ }
731
+ }
732
+ }
733
+ },
734
+ "put": {
735
+ "summary": "Security analyzer API (PUT)",
736
+ "description": "Catch-all route for security analyzer API PUT requests",
737
+ "operationId": "securityApiPut",
738
+ "parameters": [
739
+ {
740
+ "name": "conversation_id",
741
+ "in": "path",
742
+ "required": true,
743
+ "schema": {
744
+ "type": "string"
745
+ },
746
+ "description": "Conversation ID"
747
+ },
748
+ {
749
+ "name": "path",
750
+ "in": "path",
751
+ "required": true,
752
+ "schema": {
753
+ "type": "string"
754
+ },
755
+ "description": "Security analyzer API path"
756
+ }
757
+ ],
758
+ "requestBody": {
759
+ "required": false,
760
+ "content": {
761
+ "application/json": {
762
+ "schema": {
763
+ "type": "object"
764
+ }
765
+ }
766
+ }
767
+ },
768
+ "responses": {
769
+ "200": {
770
+ "description": "Security analyzer response",
771
+ "content": {
772
+ "application/json": {
773
+ "schema": {
774
+ "type": "object"
775
+ }
776
+ }
777
+ }
778
+ },
779
+ "404": {
780
+ "description": "Security analyzer not initialized",
781
+ "content": {
782
+ "application/json": {
783
+ "schema": {
784
+ "type": "object",
785
+ "properties": {
786
+ "detail": {
787
+ "type": "string"
788
+ }
789
+ }
790
+ }
791
+ }
792
+ }
793
+ }
794
+ }
795
+ },
796
+ "delete": {
797
+ "summary": "Security analyzer API (DELETE)",
798
+ "description": "Catch-all route for security analyzer API DELETE requests",
799
+ "operationId": "securityApiDelete",
800
+ "parameters": [
801
+ {
802
+ "name": "conversation_id",
803
+ "in": "path",
804
+ "required": true,
805
+ "schema": {
806
+ "type": "string"
807
+ },
808
+ "description": "Conversation ID"
809
+ },
810
+ {
811
+ "name": "path",
812
+ "in": "path",
813
+ "required": true,
814
+ "schema": {
815
+ "type": "string"
816
+ },
817
+ "description": "Security analyzer API path"
818
+ }
819
+ ],
820
+ "responses": {
821
+ "200": {
822
+ "description": "Security analyzer response",
823
+ "content": {
824
+ "application/json": {
825
+ "schema": {
826
+ "type": "object"
827
+ }
828
+ }
829
+ }
830
+ },
831
+ "404": {
832
+ "description": "Security analyzer not initialized",
833
+ "content": {
834
+ "application/json": {
835
+ "schema": {
836
+ "type": "object",
837
+ "properties": {
838
+ "detail": {
839
+ "type": "string"
840
+ }
841
+ }
842
+ }
843
+ }
844
+ }
845
+ }
846
+ }
847
+ }
848
+ },
849
+ "/api/conversations": {
850
+ "post": {
851
+ "summary": "Create new conversation",
852
+ "description": "Initialize a new conversation",
853
+ "operationId": "newConversation",
854
+ "requestBody": {
855
+ "required": true,
856
+ "content": {
857
+ "application/json": {
858
+ "schema": {
859
+ "type": "object",
860
+ "properties": {
861
+ "repository": {
862
+ "type": "string",
863
+ "nullable": true,
864
+ "description": "Full name of the repository (e.g., owner/repo)"
865
+ },
866
+ "git_provider": {
867
+ "type": "string",
868
+ "nullable": true,
869
+ "description": "The Git provider (e.g., github or gitlab). If omitted, all configured providers are checked for the repository."
870
+ },
871
+ "selected_branch": {
872
+ "type": "string",
873
+ "nullable": true
874
+ },
875
+ "initial_user_msg": {
876
+ "type": "string",
877
+ "nullable": true
878
+ },
879
+ "conversation_instructions": {
880
+ "type": "string",
881
+ "nullable": true,
882
+ "description": "Optional instructions the agent must follow throughout the conversation while addressing the user's initial task"
883
+ },
884
+ "image_urls": {
885
+ "type": "array",
886
+ "items": {
887
+ "type": "string"
888
+ },
889
+ "nullable": true
890
+ },
891
+ "replay_json": {
892
+ "type": "string",
893
+ "nullable": true
894
+ }
895
+ }
896
+ }
897
+ }
898
+ }
899
+ },
900
+ "responses": {
901
+ "200": {
902
+ "description": "Conversation created successfully",
903
+ "content": {
904
+ "application/json": {
905
+ "schema": {
906
+ "type": "object",
907
+ "properties": {
908
+ "status": {
909
+ "type": "string",
910
+ "example": "ok"
911
+ },
912
+ "conversation_id": {
913
+ "type": "string"
914
+ }
915
+ }
916
+ }
917
+ }
918
+ }
919
+ },
920
+ "400": {
921
+ "description": "Error creating conversation",
922
+ "content": {
923
+ "application/json": {
924
+ "schema": {
925
+ "type": "object",
926
+ "properties": {
927
+ "status": {
928
+ "type": "string",
929
+ "example": "error"
930
+ },
931
+ "message": {
932
+ "type": "string"
933
+ },
934
+ "msg_id": {
935
+ "type": "string"
936
+ }
937
+ }
938
+ }
939
+ }
940
+ }
941
+ }
942
+ }
943
+ },
944
+ "get": {
945
+ "summary": "Search conversations",
946
+ "description": "Search for conversations",
947
+ "operationId": "searchConversations",
948
+ "parameters": [
949
+ {
950
+ "name": "page_id",
951
+ "in": "query",
952
+ "required": false,
953
+ "schema": {
954
+ "type": "string"
955
+ },
956
+ "description": "Page ID for pagination"
957
+ },
958
+ {
959
+ "name": "limit",
960
+ "in": "query",
961
+ "required": false,
962
+ "schema": {
963
+ "type": "integer",
964
+ "default": 20
965
+ },
966
+ "description": "Number of conversations to return"
967
+ }
968
+ ],
969
+ "responses": {
970
+ "200": {
971
+ "description": "Conversations",
972
+ "content": {
973
+ "application/json": {
974
+ "schema": {
975
+ "type": "object",
976
+ "properties": {
977
+ "results": {
978
+ "type": "array",
979
+ "items": {
980
+ "type": "object",
981
+ "properties": {
982
+ "conversation_id": {
983
+ "type": "string"
984
+ },
985
+ "title": {
986
+ "type": "string"
987
+ },
988
+ "last_updated_at": {
989
+ "type": "string",
990
+ "format": "date-time"
991
+ },
992
+ "created_at": {
993
+ "type": "string",
994
+ "format": "date-time"
995
+ },
996
+ "selected_repository": {
997
+ "type": "string",
998
+ "nullable": true
999
+ },
1000
+ "status": {
1001
+ "type": "string",
1002
+ "enum": ["RUNNING", "STOPPED"]
1003
+ },
1004
+ "trigger": {
1005
+ "type": "string",
1006
+ "enum": ["GUI", "API"]
1007
+ }
1008
+ }
1009
+ }
1010
+ },
1011
+ "next_page_id": {
1012
+ "type": "string",
1013
+ "nullable": true
1014
+ }
1015
+ }
1016
+ }
1017
+ }
1018
+ }
1019
+ }
1020
+ }
1021
+ }
1022
+ },
1023
+ "/api/conversations/{conversation_id}": {
1024
+ "get": {
1025
+ "summary": "Get conversation",
1026
+ "description": "Get conversation details",
1027
+ "operationId": "getConversation",
1028
+ "parameters": [
1029
+ {
1030
+ "name": "conversation_id",
1031
+ "in": "path",
1032
+ "required": true,
1033
+ "schema": {
1034
+ "type": "string"
1035
+ },
1036
+ "description": "Conversation ID"
1037
+ }
1038
+ ],
1039
+ "responses": {
1040
+ "200": {
1041
+ "description": "Conversation details",
1042
+ "content": {
1043
+ "application/json": {
1044
+ "schema": {
1045
+ "type": "object",
1046
+ "properties": {
1047
+ "conversation_id": {
1048
+ "type": "string"
1049
+ },
1050
+ "title": {
1051
+ "type": "string"
1052
+ },
1053
+ "last_updated_at": {
1054
+ "type": "string",
1055
+ "format": "date-time"
1056
+ },
1057
+ "created_at": {
1058
+ "type": "string",
1059
+ "format": "date-time"
1060
+ },
1061
+ "selected_repository": {
1062
+ "type": "string",
1063
+ "nullable": true
1064
+ },
1065
+ "status": {
1066
+ "type": "string",
1067
+ "enum": ["RUNNING", "STOPPED"]
1068
+ },
1069
+ "trigger": {
1070
+ "type": "string",
1071
+ "enum": ["GUI", "API"]
1072
+ }
1073
+ }
1074
+ }
1075
+ }
1076
+ }
1077
+ },
1078
+ "404": {
1079
+ "description": "Conversation not found",
1080
+ "content": {
1081
+ "application/json": {
1082
+ "schema": {
1083
+ "type": "object",
1084
+ "nullable": true
1085
+ }
1086
+ }
1087
+ }
1088
+ }
1089
+ }
1090
+ },
1091
+ "patch": {
1092
+ "summary": "Update conversation",
1093
+ "description": "Update conversation details",
1094
+ "operationId": "updateConversation",
1095
+ "parameters": [
1096
+ {
1097
+ "name": "conversation_id",
1098
+ "in": "path",
1099
+ "required": true,
1100
+ "schema": {
1101
+ "type": "string"
1102
+ },
1103
+ "description": "Conversation ID"
1104
+ }
1105
+ ],
1106
+ "requestBody": {
1107
+ "required": true,
1108
+ "content": {
1109
+ "application/json": {
1110
+ "schema": {
1111
+ "type": "object",
1112
+ "properties": {
1113
+ "title": {
1114
+ "type": "string"
1115
+ }
1116
+ }
1117
+ }
1118
+ }
1119
+ }
1120
+ },
1121
+ "responses": {
1122
+ "200": {
1123
+ "description": "Conversation updated successfully",
1124
+ "content": {
1125
+ "application/json": {
1126
+ "schema": {
1127
+ "type": "boolean"
1128
+ }
1129
+ }
1130
+ }
1131
+ }
1132
+ }
1133
+ },
1134
+ "delete": {
1135
+ "summary": "Delete conversation",
1136
+ "description": "Delete a conversation",
1137
+ "operationId": "deleteConversation",
1138
+ "parameters": [
1139
+ {
1140
+ "name": "conversation_id",
1141
+ "in": "path",
1142
+ "required": true,
1143
+ "schema": {
1144
+ "type": "string"
1145
+ },
1146
+ "description": "Conversation ID"
1147
+ }
1148
+ ],
1149
+ "responses": {
1150
+ "200": {
1151
+ "description": "Conversation deleted successfully",
1152
+ "content": {
1153
+ "application/json": {
1154
+ "schema": {
1155
+ "type": "boolean"
1156
+ }
1157
+ }
1158
+ }
1159
+ }
1160
+ }
1161
+ }
1162
+ },
1163
+ "/api/user/repositories": {
1164
+ "get": {
1165
+ "summary": "Get user repositories",
1166
+ "description": "Get repositories for the authenticated user",
1167
+ "operationId": "getUserRepositories",
1168
+ "parameters": [
1169
+ {
1170
+ "name": "sort",
1171
+ "in": "query",
1172
+ "required": false,
1173
+ "schema": {
1174
+ "type": "string",
1175
+ "default": "pushed"
1176
+ },
1177
+ "description": "Sort order for repositories"
1178
+ }
1179
+ ],
1180
+ "responses": {
1181
+ "200": {
1182
+ "description": "User repositories",
1183
+ "content": {
1184
+ "application/json": {
1185
+ "schema": {
1186
+ "type": "array",
1187
+ "items": {
1188
+ "type": "object",
1189
+ "properties": {
1190
+ "full_name": {
1191
+ "type": "string"
1192
+ },
1193
+ "description": {
1194
+ "type": "string",
1195
+ "nullable": true
1196
+ },
1197
+ "html_url": {
1198
+ "type": "string"
1199
+ },
1200
+ "private": {
1201
+ "type": "boolean"
1202
+ },
1203
+ "fork": {
1204
+ "type": "boolean"
1205
+ },
1206
+ "updated_at": {
1207
+ "type": "string",
1208
+ "format": "date-time"
1209
+ }
1210
+ }
1211
+ }
1212
+ }
1213
+ }
1214
+ }
1215
+ },
1216
+ "401": {
1217
+ "description": "Authentication error",
1218
+ "content": {
1219
+ "application/json": {
1220
+ "schema": {
1221
+ "type": "string"
1222
+ }
1223
+ }
1224
+ }
1225
+ },
1226
+ "500": {
1227
+ "description": "Unknown error",
1228
+ "content": {
1229
+ "application/json": {
1230
+ "schema": {
1231
+ "type": "string"
1232
+ }
1233
+ }
1234
+ }
1235
+ }
1236
+ }
1237
+ }
1238
+ },
1239
+ "/api/user/info": {
1240
+ "get": {
1241
+ "summary": "Get user info",
1242
+ "description": "Get information about the authenticated user",
1243
+ "operationId": "getUser",
1244
+ "responses": {
1245
+ "200": {
1246
+ "description": "User information",
1247
+ "content": {
1248
+ "application/json": {
1249
+ "schema": {
1250
+ "type": "object",
1251
+ "properties": {
1252
+ "login": {
1253
+ "type": "string"
1254
+ },
1255
+ "name": {
1256
+ "type": "string",
1257
+ "nullable": true
1258
+ },
1259
+ "email": {
1260
+ "type": "string",
1261
+ "nullable": true
1262
+ },
1263
+ "avatar_url": {
1264
+ "type": "string",
1265
+ "nullable": true
1266
+ }
1267
+ }
1268
+ }
1269
+ }
1270
+ }
1271
+ },
1272
+ "401": {
1273
+ "description": "Authentication error",
1274
+ "content": {
1275
+ "application/json": {
1276
+ "schema": {
1277
+ "type": "string"
1278
+ }
1279
+ }
1280
+ }
1281
+ },
1282
+ "500": {
1283
+ "description": "Unknown error",
1284
+ "content": {
1285
+ "application/json": {
1286
+ "schema": {
1287
+ "type": "string"
1288
+ }
1289
+ }
1290
+ }
1291
+ }
1292
+ }
1293
+ }
1294
+ },
1295
+ "/api/user/search/repositories": {
1296
+ "get": {
1297
+ "summary": "Search repositories",
1298
+ "description": "Search for repositories",
1299
+ "operationId": "searchRepositories",
1300
+ "parameters": [
1301
+ {
1302
+ "name": "query",
1303
+ "in": "query",
1304
+ "required": true,
1305
+ "schema": {
1306
+ "type": "string"
1307
+ },
1308
+ "description": "Search query"
1309
+ },
1310
+ {
1311
+ "name": "per_page",
1312
+ "in": "query",
1313
+ "required": false,
1314
+ "schema": {
1315
+ "type": "integer",
1316
+ "default": 5
1317
+ },
1318
+ "description": "Number of repositories to return per page"
1319
+ },
1320
+ {
1321
+ "name": "sort",
1322
+ "in": "query",
1323
+ "required": false,
1324
+ "schema": {
1325
+ "type": "string",
1326
+ "default": "stars"
1327
+ },
1328
+ "description": "Sort order for repositories"
1329
+ },
1330
+ {
1331
+ "name": "order",
1332
+ "in": "query",
1333
+ "required": false,
1334
+ "schema": {
1335
+ "type": "string",
1336
+ "default": "desc"
1337
+ },
1338
+ "description": "Sort direction"
1339
+ }
1340
+ ],
1341
+ "responses": {
1342
+ "200": {
1343
+ "description": "Search results",
1344
+ "content": {
1345
+ "application/json": {
1346
+ "schema": {
1347
+ "type": "array",
1348
+ "items": {
1349
+ "type": "object",
1350
+ "properties": {
1351
+ "full_name": {
1352
+ "type": "string"
1353
+ },
1354
+ "description": {
1355
+ "type": "string",
1356
+ "nullable": true
1357
+ },
1358
+ "html_url": {
1359
+ "type": "string"
1360
+ },
1361
+ "private": {
1362
+ "type": "boolean"
1363
+ },
1364
+ "fork": {
1365
+ "type": "boolean"
1366
+ },
1367
+ "updated_at": {
1368
+ "type": "string",
1369
+ "format": "date-time"
1370
+ }
1371
+ }
1372
+ }
1373
+ }
1374
+ }
1375
+ }
1376
+ },
1377
+ "401": {
1378
+ "description": "Authentication error",
1379
+ "content": {
1380
+ "application/json": {
1381
+ "schema": {
1382
+ "type": "string"
1383
+ }
1384
+ }
1385
+ }
1386
+ },
1387
+ "500": {
1388
+ "description": "Unknown error",
1389
+ "content": {
1390
+ "application/json": {
1391
+ "schema": {
1392
+ "type": "string"
1393
+ }
1394
+ }
1395
+ }
1396
+ }
1397
+ }
1398
+ }
1399
+ },
1400
+ "/api/user/suggested-tasks": {
1401
+ "get": {
1402
+ "summary": "Get suggested tasks",
1403
+ "description": "Get suggested tasks for the authenticated user across their most recently pushed repositories",
1404
+ "operationId": "getSuggestedTasks",
1405
+ "responses": {
1406
+ "200": {
1407
+ "description": "Suggested tasks",
1408
+ "content": {
1409
+ "application/json": {
1410
+ "schema": {
1411
+ "type": "array",
1412
+ "items": {
1413
+ "type": "object",
1414
+ "properties": {
1415
+ "title": {
1416
+ "type": "string"
1417
+ },
1418
+ "url": {
1419
+ "type": "string"
1420
+ },
1421
+ "repository": {
1422
+ "type": "string"
1423
+ },
1424
+ "type": {
1425
+ "type": "string"
1426
+ },
1427
+ "created_at": {
1428
+ "type": "string",
1429
+ "format": "date-time"
1430
+ }
1431
+ }
1432
+ }
1433
+ }
1434
+ }
1435
+ }
1436
+ },
1437
+ "401": {
1438
+ "description": "Authentication error",
1439
+ "content": {
1440
+ "application/json": {
1441
+ "schema": {
1442
+ "type": "string"
1443
+ }
1444
+ }
1445
+ }
1446
+ },
1447
+ "500": {
1448
+ "description": "Unknown error",
1449
+ "content": {
1450
+ "application/json": {
1451
+ "schema": {
1452
+ "type": "string"
1453
+ }
1454
+ }
1455
+ }
1456
+ }
1457
+ }
1458
+ }
1459
+ },
1460
+ "/api/settings": {
1461
+ "get": {
1462
+ "summary": "Get settings",
1463
+ "description": "Get user settings",
1464
+ "operationId": "loadSettings",
1465
+ "responses": {
1466
+ "200": {
1467
+ "description": "User settings",
1468
+ "content": {
1469
+ "application/json": {
1470
+ "schema": {
1471
+ "type": "object",
1472
+ "properties": {
1473
+ "language": {
1474
+ "type": "string"
1475
+ },
1476
+ "agent": {
1477
+ "type": "string"
1478
+ },
1479
+ "security_analyzer": {
1480
+ "type": "string"
1481
+ },
1482
+ "confirmation_mode": {
1483
+ "type": "boolean"
1484
+ },
1485
+ "llm_model": {
1486
+ "type": "string"
1487
+ },
1488
+ "llm_api_key_set": {
1489
+ "type": "boolean"
1490
+ },
1491
+ "llm_base_url": {
1492
+ "type": "string",
1493
+ "nullable": true
1494
+ },
1495
+ "remote_runtime_resource_factor": {
1496
+ "type": "number"
1497
+ },
1498
+ "enable_default_condenser": {
1499
+ "type": "boolean"
1500
+ },
1501
+ "enable_sound_notifications": {
1502
+ "type": "boolean"
1503
+ },
1504
+ "user_consents_to_analytics": {
1505
+ "type": "boolean"
1506
+ },
1507
+ "provider_tokens_set": {
1508
+ "type": "object",
1509
+ "additionalProperties": {
1510
+ "type": "boolean"
1511
+ }
1512
+ }
1513
+ }
1514
+ }
1515
+ }
1516
+ }
1517
+ },
1518
+ "401": {
1519
+ "description": "Invalid token",
1520
+ "content": {
1521
+ "application/json": {
1522
+ "schema": {
1523
+ "type": "object",
1524
+ "properties": {
1525
+ "error": {
1526
+ "type": "string"
1527
+ }
1528
+ }
1529
+ }
1530
+ }
1531
+ }
1532
+ },
1533
+ "404": {
1534
+ "description": "Settings not found",
1535
+ "content": {
1536
+ "application/json": {
1537
+ "schema": {
1538
+ "type": "object",
1539
+ "properties": {
1540
+ "error": {
1541
+ "type": "string"
1542
+ }
1543
+ }
1544
+ }
1545
+ }
1546
+ }
1547
+ }
1548
+ }
1549
+ },
1550
+ "post": {
1551
+ "summary": "Store settings",
1552
+ "description": "Store user settings",
1553
+ "operationId": "storeSettings",
1554
+ "requestBody": {
1555
+ "required": true,
1556
+ "content": {
1557
+ "application/json": {
1558
+ "schema": {
1559
+ "type": "object",
1560
+ "properties": {
1561
+ "language": {
1562
+ "type": "string"
1563
+ },
1564
+ "agent": {
1565
+ "type": "string"
1566
+ },
1567
+ "security_analyzer": {
1568
+ "type": "string"
1569
+ },
1570
+ "confirmation_mode": {
1571
+ "type": "boolean"
1572
+ },
1573
+ "llm_model": {
1574
+ "type": "string"
1575
+ },
1576
+ "llm_api_key": {
1577
+ "type": "string"
1578
+ },
1579
+ "llm_base_url": {
1580
+ "type": "string",
1581
+ "nullable": true
1582
+ },
1583
+ "remote_runtime_resource_factor": {
1584
+ "type": "number"
1585
+ },
1586
+ "enable_default_condenser": {
1587
+ "type": "boolean"
1588
+ },
1589
+ "enable_sound_notifications": {
1590
+ "type": "boolean"
1591
+ },
1592
+ "user_consents_to_analytics": {
1593
+ "type": "boolean"
1594
+ },
1595
+ "provider_tokens": {
1596
+ "type": "object",
1597
+ "additionalProperties": {
1598
+ "type": "string"
1599
+ }
1600
+ }
1601
+ }
1602
+ }
1603
+ }
1604
+ }
1605
+ },
1606
+ "responses": {
1607
+ "200": {
1608
+ "description": "Settings stored successfully",
1609
+ "content": {
1610
+ "application/json": {
1611
+ "schema": {
1612
+ "type": "object",
1613
+ "properties": {
1614
+ "message": {
1615
+ "type": "string"
1616
+ }
1617
+ }
1618
+ }
1619
+ }
1620
+ }
1621
+ },
1622
+ "401": {
1623
+ "description": "Invalid token",
1624
+ "content": {
1625
+ "application/json": {
1626
+ "schema": {
1627
+ "type": "object",
1628
+ "properties": {
1629
+ "error": {
1630
+ "type": "string"
1631
+ }
1632
+ }
1633
+ }
1634
+ }
1635
+ }
1636
+ },
1637
+ "500": {
1638
+ "description": "Error storing settings",
1639
+ "content": {
1640
+ "application/json": {
1641
+ "schema": {
1642
+ "type": "object",
1643
+ "properties": {
1644
+ "error": {
1645
+ "type": "string"
1646
+ }
1647
+ }
1648
+ }
1649
+ }
1650
+ }
1651
+ }
1652
+ }
1653
+ }
1654
+ },
1655
+ "/api/reset-settings": {
1656
+ "post": {
1657
+ "summary": "Reset settings (Deprecated)",
1658
+ "description": "This endpoint is deprecated and will return a 410 Gone error. Reset functionality has been removed.",
1659
+ "operationId": "resetSettings",
1660
+ "deprecated": true,
1661
+ "responses": {
1662
+ "410": {
1663
+ "description": "Feature removed",
1664
+ "content": {
1665
+ "application/json": {
1666
+ "schema": {
1667
+ "type": "object",
1668
+ "properties": {
1669
+ "error": {
1670
+ "type": "string",
1671
+ "example": "Reset settings functionality has been removed."
1672
+ }
1673
+ }
1674
+ }
1675
+ }
1676
+ }
1677
+ }
1678
+ }
1679
+ }
1680
+ },
1681
+ "/api/unset-settings-tokens": {
1682
+ "post": {
1683
+ "summary": "Unset settings tokens",
1684
+ "description": "Unset provider tokens in settings",
1685
+ "operationId": "unsetSettingsTokens",
1686
+ "responses": {
1687
+ "200": {
1688
+ "description": "Tokens unset successfully",
1689
+ "content": {
1690
+ "application/json": {
1691
+ "schema": {
1692
+ "type": "object",
1693
+ "properties": {
1694
+ "message": {
1695
+ "type": "string"
1696
+ }
1697
+ }
1698
+ }
1699
+ }
1700
+ }
1701
+ },
1702
+ "500": {
1703
+ "description": "Error unsetting tokens",
1704
+ "content": {
1705
+ "application/json": {
1706
+ "schema": {
1707
+ "type": "object",
1708
+ "properties": {
1709
+ "error": {
1710
+ "type": "string"
1711
+ }
1712
+ }
1713
+ }
1714
+ }
1715
+ }
1716
+ }
1717
+ }
1718
+ }
1719
+ },
1720
+ "/api/options/models": {
1721
+ "get": {
1722
+ "summary": "Get models",
1723
+ "description": "Get all models supported by LiteLLM",
1724
+ "operationId": "getLitellmModels",
1725
+ "responses": {
1726
+ "200": {
1727
+ "description": "List of models",
1728
+ "content": {
1729
+ "application/json": {
1730
+ "schema": {
1731
+ "type": "array",
1732
+ "items": {
1733
+ "type": "string"
1734
+ }
1735
+ }
1736
+ }
1737
+ }
1738
+ }
1739
+ }
1740
+ }
1741
+ },
1742
+ "/api/options/agents": {
1743
+ "get": {
1744
+ "summary": "Get agents",
1745
+ "description": "Get all agents supported by OpenHands",
1746
+ "operationId": "getAgents",
1747
+ "responses": {
1748
+ "200": {
1749
+ "description": "List of agents",
1750
+ "content": {
1751
+ "application/json": {
1752
+ "schema": {
1753
+ "type": "array",
1754
+ "items": {
1755
+ "type": "string"
1756
+ }
1757
+ }
1758
+ }
1759
+ }
1760
+ }
1761
+ }
1762
+ }
1763
+ },
1764
+ "/api/options/security-analyzers": {
1765
+ "get": {
1766
+ "summary": "Get security analyzers",
1767
+ "description": "Get all supported security analyzers",
1768
+ "operationId": "getSecurityAnalyzers",
1769
+ "responses": {
1770
+ "200": {
1771
+ "description": "List of security analyzers",
1772
+ "content": {
1773
+ "application/json": {
1774
+ "schema": {
1775
+ "type": "array",
1776
+ "items": {
1777
+ "type": "string"
1778
+ }
1779
+ }
1780
+ }
1781
+ }
1782
+ }
1783
+ }
1784
+ }
1785
+ },
1786
+ "/api/options/config": {
1787
+ "get": {
1788
+ "summary": "Get config",
1789
+ "description": "Get current server configuration",
1790
+ "operationId": "getConfig",
1791
+ "responses": {
1792
+ "200": {
1793
+ "description": "Server configuration",
1794
+ "content": {
1795
+ "application/json": {
1796
+ "schema": {
1797
+ "type": "object"
1798
+ }
1799
+ }
1800
+ }
1801
+ }
1802
+ }
1803
+ }
1804
+ }
1805
+ },
1806
+ "components": {
1807
+ "schemas": {
1808
+ "Repository": {
1809
+ "type": "object",
1810
+ "properties": {
1811
+ "full_name": {
1812
+ "type": "string"
1813
+ },
1814
+ "description": {
1815
+ "type": "string",
1816
+ "nullable": true
1817
+ },
1818
+ "html_url": {
1819
+ "type": "string"
1820
+ },
1821
+ "private": {
1822
+ "type": "boolean"
1823
+ },
1824
+ "fork": {
1825
+ "type": "boolean"
1826
+ },
1827
+ "updated_at": {
1828
+ "type": "string",
1829
+ "format": "date-time"
1830
+ }
1831
+ }
1832
+ },
1833
+ "User": {
1834
+ "type": "object",
1835
+ "properties": {
1836
+ "login": {
1837
+ "type": "string"
1838
+ },
1839
+ "name": {
1840
+ "type": "string",
1841
+ "nullable": true
1842
+ },
1843
+ "email": {
1844
+ "type": "string",
1845
+ "nullable": true
1846
+ },
1847
+ "avatar_url": {
1848
+ "type": "string",
1849
+ "nullable": true
1850
+ }
1851
+ }
1852
+ },
1853
+ "SuggestedTask": {
1854
+ "type": "object",
1855
+ "properties": {
1856
+ "title": {
1857
+ "type": "string"
1858
+ },
1859
+ "url": {
1860
+ "type": "string"
1861
+ },
1862
+ "repository": {
1863
+ "type": "string"
1864
+ },
1865
+ "type": {
1866
+ "type": "string"
1867
+ },
1868
+ "created_at": {
1869
+ "type": "string",
1870
+ "format": "date-time"
1871
+ }
1872
+ }
1873
+ },
1874
+ "ConversationInfo": {
1875
+ "type": "object",
1876
+ "properties": {
1877
+ "conversation_id": {
1878
+ "type": "string"
1879
+ },
1880
+ "title": {
1881
+ "type": "string"
1882
+ },
1883
+ "last_updated_at": {
1884
+ "type": "string",
1885
+ "format": "date-time"
1886
+ },
1887
+ "created_at": {
1888
+ "type": "string",
1889
+ "format": "date-time"
1890
+ },
1891
+ "selected_repository": {
1892
+ "type": "string",
1893
+ "nullable": true
1894
+ },
1895
+ "status": {
1896
+ "type": "string",
1897
+ "enum": ["RUNNING", "STOPPED"]
1898
+ },
1899
+ "trigger": {
1900
+ "type": "string",
1901
+ "enum": ["GUI", "API"]
1902
+ }
1903
+ }
1904
+ },
1905
+ "ConversationInfoResultSet": {
1906
+ "type": "object",
1907
+ "properties": {
1908
+ "results": {
1909
+ "type": "array",
1910
+ "items": {
1911
+ "$ref": "#/components/schemas/ConversationInfo"
1912
+ }
1913
+ },
1914
+ "next_page_id": {
1915
+ "type": "string",
1916
+ "nullable": true
1917
+ }
1918
+ }
1919
+ },
1920
+ "FeedbackDataModel": {
1921
+ "type": "object",
1922
+ "properties": {
1923
+ "email": {
1924
+ "type": "string",
1925
+ "format": "email"
1926
+ },
1927
+ "version": {
1928
+ "type": "string"
1929
+ },
1930
+ "permissions": {
1931
+ "type": "string",
1932
+ "default": "private"
1933
+ },
1934
+ "polarity": {
1935
+ "type": "string"
1936
+ },
1937
+ "feedback": {
1938
+ "type": "string"
1939
+ },
1940
+ "trajectory": {
1941
+ "type": "array",
1942
+ "items": {
1943
+ "type": "object"
1944
+ }
1945
+ }
1946
+ }
1947
+ },
1948
+ "Settings": {
1949
+ "type": "object",
1950
+ "properties": {
1951
+ "language": {
1952
+ "type": "string"
1953
+ },
1954
+ "agent": {
1955
+ "type": "string"
1956
+ },
1957
+ "security_analyzer": {
1958
+ "type": "string"
1959
+ },
1960
+ "confirmation_mode": {
1961
+ "type": "boolean"
1962
+ },
1963
+ "llm_model": {
1964
+ "type": "string"
1965
+ },
1966
+ "llm_api_key": {
1967
+ "type": "string"
1968
+ },
1969
+ "llm_base_url": {
1970
+ "type": "string",
1971
+ "nullable": true
1972
+ },
1973
+ "remote_runtime_resource_factor": {
1974
+ "type": "number"
1975
+ },
1976
+ "enable_default_condenser": {
1977
+ "type": "boolean"
1978
+ },
1979
+ "enable_sound_notifications": {
1980
+ "type": "boolean"
1981
+ },
1982
+ "user_consents_to_analytics": {
1983
+ "type": "boolean"
1984
+ }
1985
+ }
1986
+ },
1987
+ "GETSettingsModel": {
1988
+ "type": "object",
1989
+ "properties": {
1990
+ "language": {
1991
+ "type": "string"
1992
+ },
1993
+ "agent": {
1994
+ "type": "string"
1995
+ },
1996
+ "security_analyzer": {
1997
+ "type": "string"
1998
+ },
1999
+ "confirmation_mode": {
2000
+ "type": "boolean"
2001
+ },
2002
+ "llm_model": {
2003
+ "type": "string"
2004
+ },
2005
+ "llm_api_key_set": {
2006
+ "type": "boolean"
2007
+ },
2008
+ "llm_base_url": {
2009
+ "type": "string",
2010
+ "nullable": true
2011
+ },
2012
+ "remote_runtime_resource_factor": {
2013
+ "type": "number"
2014
+ },
2015
+ "enable_default_condenser": {
2016
+ "type": "boolean"
2017
+ },
2018
+ "enable_sound_notifications": {
2019
+ "type": "boolean"
2020
+ },
2021
+ "user_consents_to_analytics": {
2022
+ "type": "boolean"
2023
+ },
2024
+ "provider_tokens_set": {
2025
+ "type": "object",
2026
+ "additionalProperties": {
2027
+ "type": "boolean"
2028
+ }
2029
+ }
2030
+ }
2031
+ },
2032
+ "POSTSettingsModel": {
2033
+ "type": "object",
2034
+ "properties": {
2035
+ "language": {
2036
+ "type": "string"
2037
+ },
2038
+ "agent": {
2039
+ "type": "string"
2040
+ },
2041
+ "security_analyzer": {
2042
+ "type": "string"
2043
+ },
2044
+ "confirmation_mode": {
2045
+ "type": "boolean"
2046
+ },
2047
+ "llm_model": {
2048
+ "type": "string"
2049
+ },
2050
+ "llm_api_key": {
2051
+ "type": "string"
2052
+ },
2053
+ "llm_base_url": {
2054
+ "type": "string",
2055
+ "nullable": true
2056
+ },
2057
+ "remote_runtime_resource_factor": {
2058
+ "type": "number"
2059
+ },
2060
+ "enable_default_condenser": {
2061
+ "type": "boolean"
2062
+ },
2063
+ "enable_sound_notifications": {
2064
+ "type": "boolean"
2065
+ },
2066
+ "user_consents_to_analytics": {
2067
+ "type": "boolean"
2068
+ },
2069
+ "provider_tokens": {
2070
+ "type": "object",
2071
+ "additionalProperties": {
2072
+ "type": "string"
2073
+ }
2074
+ }
2075
+ }
2076
+ }
2077
+ },
2078
+ "securitySchemes": {
2079
+ "bearerAuth": {
2080
+ "type": "http",
2081
+ "scheme": "bearer",
2082
+ "bearerFormat": "JWT"
2083
+ }
2084
+ }
2085
+ },
2086
+ "security": [
2087
+ {
2088
+ "bearerAuth": []
2089
+ }
2090
+ ]
2091
+ }
docs/static/img/backend_architecture.png ADDED

Git LFS Details

  • SHA256: ec7d7be3dc2240b7beefd169d9aadeb261a885ba036d48ee1c869f2f72c93cfe
  • Pointer size: 131 Bytes
  • Size of remote file: 273 kB
docs/static/img/backend_architecture.puml ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @startuml openhands
2
+ !pragma useIntermediatePackages false
3
+
4
+ class openhands.action.agent.AgentEchoAction {
5
+ content: str
6
+ runnable: bool
7
+ action: str
8
+ }
9
+ class openhands.action.agent.AgentFinishAction {
10
+ runnable: bool
11
+ action: str
12
+ }
13
+ class openhands.observation.AgentMessageObservation {
14
+ role: str
15
+ observation: str
16
+ }
17
+ class openhands.action.agent.AgentSummarizeAction {
18
+ summary: str
19
+ action: str
20
+ }
21
+ class openhands.action.agent.AgentThinkAction {
22
+ thought: str
23
+ runnable: bool
24
+ action: str
25
+ }
26
+ class openhands.action.base.ExecutableAction {
27
+ }
28
+ class openhands.action.base.NotExecutableAction {
29
+ }
30
+ class openhands.observation.Observation {
31
+ content: str
32
+ }
33
+ class openhands.action.base.Action {
34
+ }
35
+ class openhands.action.base.NullAction {
36
+ action: str
37
+ }
38
+ class openhands.action.bash.CmdRunAction {
39
+ command: str
40
+ action: str
41
+ }
42
+ class openhands.action.browse.BrowseURLAction {
43
+ url: str
44
+ action: str
45
+ }
46
+ class openhands.observation.BrowserOutputObservation {
47
+ url: str
48
+ status_code: int
49
+ error: bool
50
+ observation: str
51
+ }
52
+ class openhands.action.fileop.FileReadAction {
53
+ path: str
54
+ action: str
55
+ }
56
+ class openhands.observation.FileReadObservation {
57
+ path: str
58
+ observation: str
59
+ }
60
+ class openhands.action.fileop.FileWriteAction {
61
+ path: str
62
+ contents: str
63
+ action: str
64
+ }
65
+ class openhands.observation.FileWriteObservation {
66
+ path: str
67
+ observation: str
68
+ }
69
+ class openhands.action.tasks.AddTaskAction {
70
+ parent: str
71
+ goal: str
72
+ subtasks: list
73
+ action: str
74
+ }
75
+ class openhands.action.tasks.ModifyTaskAction {
76
+ id: str
77
+ state: str
78
+ action: str
79
+ }
80
+ abstract class openhands.agent.Agent {
81
+ _registry: Dict[str, Type[Agent]] {static}
82
+ llm: LLM
83
+ _complete: None
84
+ }
85
+ class openhands.llm.llm.LLM {
86
+ model: None
87
+ api_key: None
88
+ base_url: None
89
+ _debug_dir: None
90
+ _debug_idx: None
91
+ _debug_id: None
92
+ _completion: None
93
+ }
94
+ class openhands.controller.agent_controller.AgentController {
95
+ agent: Agent
96
+ max_iterations: int
97
+ workdir: str
98
+ command_manager: CommandManager
99
+ state: State
100
+ plan: Plan
101
+ callbacks: List[Callable]
102
+ }
103
+ class openhands.observation.AgentErrorObservation {
104
+ observation: str
105
+ }
106
+ class openhands.controller.command_manager.CommandManager {
107
+ directory: None
108
+ shell: None
109
+ }
110
+ class openhands.observation.NullObservation {
111
+ observation: str
112
+ }
113
+ class openhands.plan.Plan {
114
+ main_goal: str {static}
115
+ task: Task {static}
116
+ main_goal: str
117
+ task: None
118
+ }
119
+ class openhands.state.State {
120
+ plan: Plan
121
+ iteration: int
122
+ history: List[Tuple[Action, Observation]]
123
+ updated_info: List[Tuple[Action, Observation]]
124
+ }
125
+ class openhands.observation.CmdOutputObservation {
126
+ command: str
127
+ exit_code: int
128
+ observation: str
129
+ }
130
+ class openhands.sandbox.sandbox.DockerInteractive {
131
+ instance_id: None
132
+ instance_id: None
133
+ workspace_dir: None
134
+ workspace_dir: None
135
+ workspace_dir: None
136
+ timeout: int
137
+ base_container_image: None
138
+ container_name: None
139
+ }
140
+ class openhands.observation.UserMessageObservation {
141
+ role: str
142
+ observation: str
143
+ }
144
+ class openhands.plan.Task {
145
+ id: str {static}
146
+ goal: str {static}
147
+ parent: Task | None {static}
148
+ subtasks: List[Task] {static}
149
+ id: None
150
+ id: None
151
+ parent: None
152
+ goal: str
153
+ subtasks: None
154
+ }
155
+
156
+ class openhands.server.session.Session {
157
+ websocket: None
158
+ controller: Optional[AgentController]
159
+ agent: Optional[Agent]
160
+ agent_task: None
161
+ }
162
+
163
+ openhands.action.base.ExecutableAction <|-- openhands.action.agent.AgentEchoAction
164
+ openhands.action.base.NotExecutableAction <|-- openhands.action.agent.AgentFinishAction
165
+ openhands.observation.Observation <|-- openhands.observation.AgentMessageObservation
166
+ openhands.action.base.NotExecutableAction <|-- openhands.action.agent.AgentSummarizeAction
167
+ openhands.action.base.NotExecutableAction <|-- openhands.action.agent.AgentThinkAction
168
+ openhands.action.base.Action <|-- openhands.action.base.ExecutableAction
169
+ openhands.action.base.Action <|-- openhands.action.base.NotExecutableAction
170
+ openhands.action.base.NotExecutableAction <|-- openhands.action.base.NullAction
171
+ openhands.action.base.ExecutableAction <|-- openhands.action.bash.CmdRunAction
172
+ openhands.action.base.ExecutableAction <|-- openhands.action.browse.BrowseURLAction
173
+ openhands.observation.Observation <|-- openhands.observation.BrowserOutputObservation
174
+ openhands.action.base.ExecutableAction <|-- openhands.action.fileop.FileReadAction
175
+ openhands.observation.Observation <|-- openhands.observation.FileReadObservation
176
+ openhands.action.base.ExecutableAction <|-- openhands.action.fileop.FileWriteAction
177
+ openhands.observation.Observation <|-- openhands.observation.FileWriteObservation
178
+ openhands.action.base.NotExecutableAction <|-- openhands.action.tasks.AddTaskAction
179
+ openhands.action.base.NotExecutableAction <|-- openhands.action.tasks.ModifyTaskAction
180
+ openhands.agent.Agent *-- openhands.agent.Agent
181
+ openhands.agent.Agent *-- openhands.llm.llm.LLM
182
+ openhands.controller.agent_controller.AgentController *-- openhands.agent.Agent
183
+ openhands.observation.Observation <|-- openhands.observation.AgentErrorObservation
184
+ openhands.observation.Observation <|-- openhands.observation.NullObservation
185
+ openhands.plan.Plan *-- openhands.plan.Task
186
+ openhands.state.State *-- openhands.plan.Plan
187
+ openhands.state.State *-- openhands.observation.CmdOutputObservation
188
+ openhands.state.State *-- openhands.action.base.Action
189
+ openhands.state.State *-- openhands.observation.Observation
190
+ openhands.observation.Observation <|-- openhands.observation.CmdOutputObservation
191
+ openhands.observation.Observation <|-- openhands.observation.UserMessageObservation
192
+ openhands.plan.Task *-- openhands.plan.Task
193
+ openhands.server.session.Session *-- openhands.controller.agent_controller.AgentController
194
+ openhands.server.session.Session *-- openhands.agent.Agent
195
+ openhands.controller.agent_controller.AgentController -> openhands.state.State
196
+ openhands.controller.agent_controller.AgentController -> openhands.plan.Plan
197
+ openhands.controller.agent_controller.AgentController -> openhands.controller.command_manager.CommandManager
198
+ openhands.controller.command_manager.CommandManager -> openhands.sandbox.sandbox.DockerInteractive
199
+
200
+ footer Based on f3fda42; Generated by //py2puml//
201
+ @enduml
docs/static/img/backend_architecture.svg ADDED
docs/static/img/connect-repo.png ADDED
docs/static/img/docs/api-key-generation.png ADDED
docs/static/img/logo-square.png ADDED

Git LFS Details

  • SHA256: de58ad6132a9afb7d4924612c5e013695658af993a81a7611a6564f6a8063d59
  • Pointer size: 132 Bytes
  • Size of remote file: 1.19 MB
docs/static/img/logo.png ADDED
docs/static/img/oh-features.png ADDED

Git LFS Details

  • SHA256: 0e5022b7839f81b08e06b7b4f2f6e624259aa68ed6bfd95b47026cb940bacacb
  • Pointer size: 131 Bytes
  • Size of remote file: 148 kB
docs/static/img/results.png ADDED

Git LFS Details

  • SHA256: 920040c9ef19e8bed163da4b2ba337f8108e8636f55ce0a1b6388d5cd9ab32c2
  • Pointer size: 131 Bytes
  • Size of remote file: 323 kB
docs/static/img/screenshot.png ADDED

Git LFS Details

  • SHA256: 4bb621a61826a12dc8eea4fb2b8d270e8b6a12dcb77ac84665982452a48cb6c4
  • Pointer size: 131 Bytes
  • Size of remote file: 679 kB