mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-09 14:57:59 -05:00
345 lines
17 KiB
Markdown
345 lines
17 KiB
Markdown
This repository contains the code for OpenHands, an automated AI software engineer. It has a Python backend
|
|
(in the `openhands` directory) and React frontend (in the `frontend` directory).
|
|
|
|
## General Setup:
|
|
To set up the entire repo, including frontend and backend, run `make build`.
|
|
You don't need to do this unless the user asks you to, or if you're trying to run the entire application.
|
|
|
|
## Running OpenHands with OpenHands:
|
|
To run the full application to debug issues:
|
|
```bash
|
|
export INSTALL_DOCKER=0
|
|
export RUNTIME=local
|
|
make build && make run FRONTEND_PORT=12000 FRONTEND_HOST=0.0.0.0 BACKEND_HOST=0.0.0.0 &> /tmp/openhands-log.txt &
|
|
```
|
|
|
|
IMPORTANT: Before making any changes to the codebase, ALWAYS run `make install-pre-commit-hooks` to ensure pre-commit hooks are properly installed.
|
|
|
|
Before pushing any changes, you MUST ensure that any lint errors or simple test errors have been fixed.
|
|
|
|
* If you've made changes to the backend, you should run `pre-commit run --config ./dev_config/python/.pre-commit-config.yaml` (this will run on staged files).
|
|
* If you've made changes to the frontend, you should run `cd frontend && npm run lint:fix && npm run build ; cd ..`
|
|
* If you've made changes to the VSCode extension, you should run `cd openhands/integrations/vscode && npm run lint:fix && npm run compile ; cd ../../..`
|
|
|
|
The pre-commit hooks MUST pass successfully before pushing any changes to the repository. This is a mandatory requirement to maintain code quality and consistency.
|
|
|
|
If either command fails, it may have automatically fixed some issues. You should fix any issues that weren't automatically fixed,
|
|
then re-run the command to ensure it passes. Common issues include:
|
|
- Mypy type errors
|
|
- Ruff formatting issues
|
|
- Trailing whitespace
|
|
- Missing newlines at end of files
|
|
|
|
## Git Best Practices
|
|
|
|
- Prefer specific `git add <filename>` instead of `git add .` to avoid accidentally staging unintended files
|
|
- Be especially careful with `git reset --hard` after staging files, as it will remove accidentally staged files
|
|
- When remote has new changes, use `git fetch upstream && git rebase upstream/<branch>` on the same branch
|
|
|
|
## Repository Structure
|
|
Backend:
|
|
- Located in the `openhands` directory
|
|
- Testing:
|
|
- All tests are in `tests/unit/test_*.py`
|
|
- To test new code, run `poetry run pytest tests/unit/test_xxx.py` where `xxx` is the appropriate file for the current functionality
|
|
- Write all tests with pytest
|
|
|
|
Frontend:
|
|
- Located in the `frontend` directory
|
|
- Prerequisites: A recent version of NodeJS / NPM
|
|
- Setup: Run `npm install` in the frontend directory
|
|
- Testing:
|
|
- Run tests: `npm run test`
|
|
- To run specific tests: `npm run test -- -t "TestName"`
|
|
- Our test framework is vitest
|
|
- Building:
|
|
- Build for production: `npm run build`
|
|
- Environment Variables:
|
|
- Set in `frontend/.env` or as environment variables
|
|
- Available variables: VITE_BACKEND_HOST, VITE_USE_TLS, VITE_INSECURE_SKIP_VERIFY, VITE_FRONTEND_PORT
|
|
- Internationalization:
|
|
- Generate i18n declaration file: `npm run make-i18n`
|
|
- Data Fetching & Cache Management:
|
|
- We use TanStack Query (fka React Query) for data fetching and cache management
|
|
- Data Access Layer: API client methods are located in `frontend/src/api` and should never be called directly from UI components - they must always be wrapped with TanStack Query
|
|
- Custom hooks are located in `frontend/src/hooks/query/` and `frontend/src/hooks/mutation/`
|
|
- Query hooks should follow the pattern use[Resource] (e.g., `useConversationSkills`)
|
|
- Mutation hooks should follow the pattern use[Action] (e.g., `useDeleteConversation`)
|
|
- Architecture rule: UI components → TanStack Query hooks → Data Access Layer (`frontend/src/api`) → API endpoints
|
|
|
|
VSCode Extension:
|
|
- Located in the `openhands/integrations/vscode` directory
|
|
- Setup: Run `npm install` in the extension directory
|
|
- Linting:
|
|
- Run linting with fixes: `npm run lint:fix`
|
|
- Check only: `npm run lint`
|
|
- Type checking: `npm run typecheck`
|
|
- Building:
|
|
- Compile TypeScript: `npm run compile`
|
|
- Package extension: `npm run package-vsix`
|
|
- Testing:
|
|
- Run tests: `npm run test`
|
|
- Development Best Practices:
|
|
- Use `vscode.window.createOutputChannel()` for debug logging instead of `showErrorMessage()` popups
|
|
- Pre-commit process runs both frontend and backend checks when committing extension changes
|
|
|
|
## Enterprise Directory
|
|
|
|
The `enterprise/` directory contains additional functionality that extends the open-source OpenHands codebase. This includes:
|
|
- Authentication and user management (Keycloak integration)
|
|
- Database migrations (Alembic)
|
|
- Integration services (GitHub, GitLab, Jira, Linear, Slack)
|
|
- Billing and subscription management (Stripe)
|
|
- Telemetry and analytics (PostHog, custom metrics framework)
|
|
|
|
### Enterprise Development Setup
|
|
|
|
**Prerequisites:**
|
|
- Python 3.12
|
|
- Poetry (for dependency management)
|
|
- Node.js 22.x (for frontend)
|
|
- Docker (optional)
|
|
|
|
**Setup Steps:**
|
|
1. First, build the main OpenHands project: `make build`
|
|
2. Then install enterprise dependencies: `cd enterprise && poetry install --with dev,test` (This can take a very long time. Be patient.)
|
|
3. Set up enterprise pre-commit hooks: `poetry run pre-commit install --config ./dev_config/python/.pre-commit-config.yaml`
|
|
|
|
**Running Enterprise Tests:**
|
|
```bash
|
|
# Enterprise unit tests (full suite)
|
|
PYTHONPATH=".:$PYTHONPATH" poetry run --project=enterprise pytest --forked -n auto -s -p no:ddtrace -p no:ddtrace.pytest_bdd -p no:ddtrace.pytest_benchmark ./enterprise/tests/unit --cov=enterprise --cov-branch
|
|
|
|
# Test specific modules (faster for development)
|
|
cd enterprise
|
|
PYTHONPATH=".:$PYTHONPATH" poetry run pytest tests/unit/telemetry/ --confcutdir=tests/unit/telemetry
|
|
|
|
# Enterprise linting (IMPORTANT: use --show-diff-on-failure to match GitHub CI)
|
|
poetry run pre-commit run --all-files --show-diff-on-failure --config ./dev_config/python/.pre-commit-config.yaml
|
|
```
|
|
|
|
**Running Enterprise Server:**
|
|
```bash
|
|
cd enterprise
|
|
make start-backend # Development mode with hot reload
|
|
# or
|
|
make run # Full application (backend + frontend)
|
|
```
|
|
|
|
**Key Configuration Files:**
|
|
- `enterprise/pyproject.toml` - Enterprise-specific dependencies
|
|
- `enterprise/Makefile` - Enterprise build and run commands
|
|
- `enterprise/dev_config/python/` - Linting and type checking configuration
|
|
- `enterprise/migrations/` - Database migration files
|
|
|
|
**Database Migrations:**
|
|
Enterprise uses Alembic for database migrations. When making schema changes:
|
|
1. Create migration files in `enterprise/migrations/versions/`
|
|
2. Test migrations thoroughly
|
|
3. The CI will check for migration conflicts on PRs
|
|
|
|
**Integration Development:**
|
|
The enterprise codebase includes integrations for:
|
|
- **GitHub** - PR management, webhooks, app installations
|
|
- **GitLab** - Similar to GitHub but for GitLab instances
|
|
- **Jira** - Issue tracking and project management
|
|
- **Linear** - Modern issue tracking
|
|
- **Slack** - Team communication and notifications
|
|
|
|
Each integration follows a consistent pattern with service classes, storage models, and API endpoints.
|
|
|
|
**Important Notes:**
|
|
- Enterprise code is licensed under Polyform Free Trial License (30-day limit)
|
|
- The enterprise server extends the OSS server through dynamic imports
|
|
- Database changes require careful migration planning in `enterprise/migrations/`
|
|
- Always test changes in both OSS and enterprise contexts
|
|
- Use the enterprise-specific Makefile commands for development
|
|
|
|
**Enterprise Testing Best Practices:**
|
|
|
|
**Database Testing:**
|
|
- Use SQLite in-memory databases (`sqlite:///:memory:`) for unit tests instead of real PostgreSQL
|
|
- Create module-specific `conftest.py` files with database fixtures
|
|
- Mock external database connections in unit tests to avoid dependency on running services
|
|
- Use real database connections only for integration tests
|
|
|
|
**Import Patterns:**
|
|
- Use relative imports without `enterprise.` prefix in enterprise code
|
|
- Example: `from storage.database import session_maker` not `from enterprise.storage.database import session_maker`
|
|
- This ensures code works in both OSS and enterprise contexts
|
|
|
|
**Test Structure:**
|
|
- Place tests in `enterprise/tests/unit/` following the same structure as the source code
|
|
- Use `--confcutdir=tests/unit/[module]` when testing specific modules
|
|
- Create comprehensive fixtures for complex objects (databases, external services)
|
|
- Write platform-agnostic tests (avoid hardcoded OS-specific assertions)
|
|
|
|
**Mocking Strategy:**
|
|
- Use `AsyncMock` for async operations and `MagicMock` for complex objects
|
|
- Mock all external dependencies (databases, APIs, file systems) in unit tests
|
|
- Use `patch` with correct import paths (e.g., `telemetry.registry.logger` not `enterprise.telemetry.registry.logger`)
|
|
- Test both success and failure scenarios with proper error handling
|
|
|
|
**Coverage Goals:**
|
|
- Aim for 90%+ test coverage on new enterprise modules
|
|
- Focus on critical business logic and error handling paths
|
|
- Use `--cov-report=term-missing` to identify uncovered lines
|
|
|
|
**Troubleshooting:**
|
|
- If tests fail, ensure all dependencies are installed: `poetry install --with dev,test`
|
|
- For database issues, check migration status and run migrations if needed
|
|
- For frontend issues, ensure the main OpenHands frontend is built: `make build`
|
|
- Check logs in the `logs/` directory for runtime issues
|
|
- If tests fail with import errors, verify `PYTHONPATH=".:$PYTHONPATH"` is set
|
|
- **If GitHub CI fails but local linting passes**: Always use `--show-diff-on-failure` flag to match CI behavior exactly
|
|
|
|
## Template for Github Pull Request
|
|
|
|
If you are starting a pull request (PR), please follow the template in `.github/pull_request_template.md`.
|
|
|
|
## Implementation Details
|
|
|
|
These details may or may not be useful for your current task.
|
|
|
|
### Microagents
|
|
|
|
Microagents are specialized prompts that enhance OpenHands with domain-specific knowledge and task-specific workflows. They are Markdown files that can include frontmatter for configuration.
|
|
|
|
#### Types:
|
|
- **Public Microagents**: Located in `microagents/`, available to all users
|
|
- **Repository Microagents**: Located in `.openhands/microagents/`, specific to this repository
|
|
|
|
#### Loading Behavior:
|
|
- **Without frontmatter**: Always loaded into LLM context
|
|
- **With triggers in frontmatter**: Only loaded when user's message matches the specified trigger keywords
|
|
|
|
#### Structure:
|
|
```yaml
|
|
---
|
|
triggers:
|
|
- keyword1
|
|
- keyword2
|
|
---
|
|
# Microagent Content
|
|
Your specialized knowledge and instructions here...
|
|
```
|
|
|
|
### Frontend
|
|
|
|
#### Action Handling:
|
|
- Actions are defined in `frontend/src/types/action-type.ts`
|
|
- The `HANDLED_ACTIONS` array in `frontend/src/state/chat-slice.ts` determines which actions are displayed as collapsible UI elements
|
|
- To add a new action type to the UI:
|
|
1. Add the action type to the `HANDLED_ACTIONS` array
|
|
2. Implement the action handling in `addAssistantAction` function in chat-slice.ts
|
|
3. Add a translation key in the format `ACTION_MESSAGE$ACTION_NAME` to the i18n files
|
|
- Actions with `thought` property are displayed in the UI based on their action type:
|
|
- Regular actions (like "run", "edit") display the thought as a separate message
|
|
- Special actions (like "think") are displayed as collapsible elements only
|
|
|
|
#### Adding User Settings:
|
|
- To add a new user setting to OpenHands, follow these steps:
|
|
1. Add the setting to the frontend:
|
|
- Add the setting to the `Settings` type in `frontend/src/types/settings.ts`
|
|
- Add the setting to the `ApiSettings` type in the same file
|
|
- Add the setting with an appropriate default value to `DEFAULT_SETTINGS` in `frontend/src/services/settings.ts`
|
|
- Update the `useSettings` hook in `frontend/src/hooks/query/use-settings.ts` to map the API response
|
|
- Update the `useSaveSettings` hook in `frontend/src/hooks/mutation/use-save-settings.ts` to include the setting in API requests
|
|
- Add UI components (like toggle switches) in the appropriate settings screen (e.g., `frontend/src/routes/app-settings.tsx`)
|
|
- Add i18n translations for the setting name and any tooltips in `frontend/src/i18n/translation.json`
|
|
- Add the translation key to `frontend/src/i18n/declaration.ts`
|
|
2. Add the setting to the backend:
|
|
- Add the setting to the `Settings` model in `openhands/storage/data_models/settings.py`
|
|
- Update any relevant backend code to apply the setting (e.g., in session creation)
|
|
|
|
#### Settings UI Patterns:
|
|
|
|
There are two main patterns for saving settings in the OpenHands frontend:
|
|
|
|
**Pattern 1: Entity-based Resources (Immediate Save)**
|
|
- Used for: API Keys, Secrets, MCP Servers
|
|
- Behavior: Changes are saved immediately when user performs actions (add/edit/delete)
|
|
- Implementation:
|
|
- No "Save Changes" button
|
|
- No local state management or `isDirty` tracking
|
|
- Uses dedicated mutation hooks for each operation (e.g., `use-add-mcp-server.ts`, `use-delete-mcp-server.ts`)
|
|
- Each mutation triggers immediate API call with query invalidation for UI updates
|
|
- Example: MCP settings, API Keys & Secrets tabs
|
|
- Benefits: Simpler UX, no risk of losing changes, consistent with modern web app patterns
|
|
|
|
**Pattern 2: Form-based Settings (Manual Save)**
|
|
- Used for: Application settings, LLM configuration
|
|
- Behavior: Changes are accumulated locally and saved when user clicks "Save Changes"
|
|
- Implementation:
|
|
- Has "Save Changes" button that becomes enabled when changes are detected
|
|
- Uses local state management with `isDirty` tracking
|
|
- Uses `useSaveSettings` hook to save all changes at once
|
|
- Example: LLM tab, Application tab
|
|
- Benefits: Allows bulk changes, explicit save action, can validate all fields before saving
|
|
|
|
**When to use each pattern:**
|
|
- Use Pattern 1 (Immediate Save) for entity management where each item is independent
|
|
- Use Pattern 2 (Manual Save) for configuration forms where settings are interdependent or need validation
|
|
|
|
### Adding New LLM Models
|
|
|
|
To add a new LLM model to OpenHands, you need to update multiple files across both frontend and backend:
|
|
|
|
#### Model Configuration Procedure:
|
|
|
|
1. **Frontend Model Arrays** (`frontend/src/utils/verified-models.ts`):
|
|
- Add the model to `VERIFIED_MODELS` array (main list of all verified models)
|
|
- Add to provider-specific arrays based on the model's provider:
|
|
- `VERIFIED_OPENAI_MODELS` for OpenAI models
|
|
- `VERIFIED_ANTHROPIC_MODELS` for Anthropic models
|
|
- `VERIFIED_MISTRAL_MODELS` for Mistral models
|
|
- `VERIFIED_OPENHANDS_MODELS` for models available through OpenHands provider
|
|
|
|
2. **Backend CLI Integration** (`openhands/cli/utils.py`):
|
|
- Add the model to the appropriate `VERIFIED_*_MODELS` arrays
|
|
- This ensures the model appears in CLI model selection
|
|
|
|
3. **Backend Model List** (`openhands/utils/llm.py`):
|
|
- **CRITICAL**: Add the model to the `openhands_models` list (lines 57-66) if using OpenHands provider
|
|
- This is required for the model to appear in the frontend model selector
|
|
- Format: `'openhands/model-name'` (e.g., `'openhands/o3'`)
|
|
|
|
4. **Backend LLM Configuration** (`openhands/llm/llm.py`):
|
|
- Add to feature-specific arrays based on model capabilities:
|
|
- `FUNCTION_CALLING_SUPPORTED_MODELS` if the model supports function calling
|
|
- `REASONING_EFFORT_SUPPORTED_MODELS` if the model supports reasoning effort parameters
|
|
- `CACHE_PROMPT_SUPPORTED_MODELS` if the model supports prompt caching
|
|
- `MODELS_WITHOUT_STOP_WORDS` if the model doesn't support stop words
|
|
|
|
5. **Validation**:
|
|
- Run backend linting: `pre-commit run --config ./dev_config/python/.pre-commit-config.yaml`
|
|
- Run frontend linting: `cd frontend && npm run lint:fix`
|
|
- Run frontend build: `cd frontend && npm run build`
|
|
|
|
#### Model Verification Arrays:
|
|
|
|
- **VERIFIED_MODELS**: Main array of all verified models shown in the UI
|
|
- **VERIFIED_OPENAI_MODELS**: OpenAI models (LiteLLM doesn't return provider prefix)
|
|
- **VERIFIED_ANTHROPIC_MODELS**: Anthropic models (LiteLLM doesn't return provider prefix)
|
|
- **VERIFIED_MISTRAL_MODELS**: Mistral models (LiteLLM doesn't return provider prefix)
|
|
- **VERIFIED_OPENHANDS_MODELS**: Models available through OpenHands managed provider
|
|
|
|
#### Model Feature Support Arrays:
|
|
|
|
- **FUNCTION_CALLING_SUPPORTED_MODELS**: Models that support structured function calling
|
|
- **REASONING_EFFORT_SUPPORTED_MODELS**: Models that support reasoning effort parameters (like o1, o3)
|
|
- **CACHE_PROMPT_SUPPORTED_MODELS**: Models that support prompt caching for efficiency
|
|
- **MODELS_WITHOUT_STOP_WORDS**: Models that don't support stop word parameters
|
|
|
|
#### Frontend Model Integration:
|
|
|
|
- Models are automatically available in the model selector UI once added to verified arrays
|
|
- The `extractModelAndProvider` utility automatically detects provider from model arrays
|
|
- Provider-specific models are grouped and prioritized in the UI selection
|
|
|
|
#### CLI Model Integration:
|
|
|
|
- Models appear in CLI provider selection based on the verified arrays
|
|
- The `organize_models_and_providers` function groups models by provider
|
|
- Default model selection prioritizes verified models for each provider
|