mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
* This has been a headache for a long time, and we had #1071 and #1100 with the hope to fix the inconsistent behaviour across linters and environments. However, we recently found out that double-quote-string-fixer plugin in pre-commit-hook has inconsistent behaviour on python 3.11 and 3.12. See discussion here. This is sad because while this plugin enforces single quote behaviour with 3.11, it doesn't always enforce so with 3.12. Specifically, with fstr syntax, this plugin allows both single quotes and double quotes with python 3.12. The problem is, some developers have black linter installed/integrated with their IDE, which is probably the most popular linter in python world (ranked by GitHub stars). This linter insists on always using double quotes. Now we have black and double-quote-string-fixer fight each other (iff the developer uses python 3.12) for some quotes (fstr syntax). After a lot of research, I couldn't find a way to enforce single quote behaviour without introducing a new dependency, flake8, together with a plugin for it to enforce quotes' behavior. I believe it's better off introducing the more popular black if we have to introduce a new linter. Since black and autopep8 sometimes fight each other, and they mostly overlap, I further remove autopep8. The unfortunate consequence of this PR is that I had to revert all single quotes back to double quotes. This might cause some inconvenience to existing PRs as they have to resolve conflicts, but I believe the headache will be gone soon. That being said, I am open to abandon this PR if anyone has a better idea to solve the headache. * Remove black * Prevent black from changing quotes * Use flake8 to enforce single quotes * Fix quotes in config.py * Add back autopep8 * Add make lint to run linters
196 lines
8.2 KiB
Makefile
196 lines
8.2 KiB
Makefile
# Makefile for OpenDevin project
|
|
|
|
# Variables
|
|
DOCKER_IMAGE = ghcr.io/opendevin/sandbox
|
|
BACKEND_PORT = 3000
|
|
BACKEND_HOST = "127.0.0.1:$(BACKEND_PORT)"
|
|
FRONTEND_PORT = 3001
|
|
DEFAULT_WORKSPACE_DIR = "./workspace"
|
|
DEFAULT_MODEL = "gpt-3.5-turbo-1106"
|
|
CONFIG_FILE = config.toml
|
|
PRECOMMIT_CONFIG_PATH = "./dev_config/python/.pre-commit-config.yaml"
|
|
|
|
# ANSI color codes
|
|
GREEN=\033[0;32m
|
|
YELLOW=\033[0;33m
|
|
RED=\033[0;31m
|
|
BLUE=\033[0;34m
|
|
RESET=\033[0m
|
|
|
|
# Build
|
|
build:
|
|
@echo "$(GREEN)Building project...$(RESET)"
|
|
@$(MAKE) -s check-dependencies
|
|
@$(MAKE) -s pull-docker-image
|
|
@$(MAKE) -s install-python-dependencies
|
|
@$(MAKE) -s install-frontend-dependencies
|
|
@$(MAKE) -s install-precommit-hooks
|
|
@$(MAKE) -s build-frontend
|
|
@echo "$(GREEN)Build completed successfully.$(RESET)"
|
|
|
|
check-dependencies:
|
|
@echo "$(YELLOW)Checking dependencies...$(RESET)"
|
|
@$(MAKE) -s check-python
|
|
@$(MAKE) -s check-npm
|
|
@$(MAKE) -s check-docker
|
|
@$(MAKE) -s check-poetry
|
|
@echo "$(GREEN)Dependencies checked successfully.$(RESET)"
|
|
|
|
check-python:
|
|
@echo "$(YELLOW)Checking Python installation...$(RESET)"
|
|
@if command -v python3 > /dev/null; then \
|
|
echo "$(BLUE)$(shell python3 --version) is already installed.$(RESET)"; \
|
|
else \
|
|
echo "$(RED)Python 3 is not installed. Please install Python 3 to continue.$(RESET)"; \
|
|
exit 1; \
|
|
fi
|
|
|
|
check-npm:
|
|
@echo "$(YELLOW)Checking npm installation...$(RESET)"
|
|
@if command -v npm > /dev/null; then \
|
|
echo "$(BLUE)npm $(shell npm --version) is already installed.$(RESET)"; \
|
|
else \
|
|
echo "$(RED)npm is not installed. Please install Node.js to continue.$(RESET)"; \
|
|
exit 1; \
|
|
fi
|
|
|
|
check-docker:
|
|
@echo "$(YELLOW)Checking Docker installation...$(RESET)"
|
|
@if command -v docker > /dev/null; then \
|
|
echo "$(BLUE)$(shell docker --version) is already installed.$(RESET)"; \
|
|
else \
|
|
echo "$(RED)Docker is not installed. Please install Docker to continue.$(RESET)"; \
|
|
exit 1; \
|
|
fi
|
|
|
|
check-poetry:
|
|
@echo "$(YELLOW)Checking Poetry installation...$(RESET)"
|
|
@if command -v poetry > /dev/null; then \
|
|
echo "$(BLUE)$(shell poetry --version) is already installed.$(RESET)"; \
|
|
else \
|
|
echo "$(RED)Poetry is not installed. You can install poetry by running the following command, then adding Poetry to your PATH:"; \
|
|
echo "$(RED) curl -sSL https://install.python-poetry.org | python3 -$(RESET)"; \
|
|
echo "$(RED)More detail here: https://python-poetry.org/docs/#installing-with-the-official-installer$(RESET)"; \
|
|
exit 1; \
|
|
fi
|
|
|
|
pull-docker-image:
|
|
@echo "$(YELLOW)Pulling Docker image...$(RESET)"
|
|
@docker pull $(DOCKER_IMAGE)
|
|
@echo "$(GREEN)Docker image pulled successfully.$(RESET)"
|
|
|
|
install-python-dependencies:
|
|
@echo "$(GREEN)Installing Python dependencies...$(RESET)"
|
|
@if [ "$(shell uname)" = "Darwin" ]; then \
|
|
echo "$(BLUE)Installing `chroma-hnswlib`...$(RESET)"; \
|
|
export HNSWLIB_NO_NATIVE=1; \
|
|
poetry run pip install chroma-hnswlib; \
|
|
fi
|
|
@poetry install --without evaluation
|
|
@echo "$(GREEN)Python dependencies installed successfully.$(RESET)"
|
|
|
|
install-frontend-dependencies:
|
|
@echo "$(YELLOW)Setting up frontend environment...$(RESET)"
|
|
@echo "$(YELLOW)Detect Node.js version...$(RESET)"
|
|
@cd frontend && node ./scripts/detect-node-version.js
|
|
@cd frontend && \
|
|
echo "$(BLUE)Installing frontend dependencies with npm...$(RESET)" && \
|
|
npm install && \
|
|
echo "$(BLUE)Running make-i18n with npm...$(RESET)" && \
|
|
npm run make-i18n
|
|
@echo "$(GREEN)Frontend dependencies installed successfully.$(RESET)"
|
|
|
|
install-precommit-hooks:
|
|
@echo "$(YELLOW)Installing pre-commit hooks...$(RESET)"
|
|
@git config --unset-all core.hooksPath || true
|
|
@poetry run pre-commit install --config $(PRECOMMIT_CONFIG_PATH)
|
|
@echo "$(GREEN)Pre-commit hooks installed successfully.$(RESET)"
|
|
|
|
lint:
|
|
@echo "$(YELLOW)Running linters...$(RESET)"
|
|
@poetry run pre-commit run --files opendevin/**/* agenthub/**/* --show-diff-on-failure --config $(PRECOMMIT_CONFIG_PATH)
|
|
|
|
build-frontend:
|
|
@echo "$(YELLOW)Building frontend...$(RESET)"
|
|
@cd frontend && npm run build
|
|
|
|
# Start backend
|
|
start-backend:
|
|
@echo "$(YELLOW)Starting backend...$(RESET)"
|
|
@poetry run uvicorn opendevin.server.listen:app --port $(BACKEND_PORT)
|
|
|
|
# Start frontend
|
|
start-frontend:
|
|
@echo "$(YELLOW)Starting frontend...$(RESET)"
|
|
@cd frontend && BACKEND_HOST=$(BACKEND_HOST) FRONTEND_PORT=$(FRONTEND_PORT) npm run start
|
|
|
|
# Run the app
|
|
run:
|
|
@echo "$(YELLOW)Running the app...$(RESET)"
|
|
@if [ "$(OS)" = "Windows_NT" ]; then \
|
|
echo "$(RED)`make run` is not supported on Windows. Please run `make start-frontend` and `make start-backend` separately.$(RESET)"; \
|
|
exit 1; \
|
|
fi
|
|
@mkdir -p logs
|
|
@echo "$(YELLOW)Starting backend server...$(RESET)"
|
|
@poetry run uvicorn opendevin.server.listen:app --port $(BACKEND_PORT) &
|
|
@echo "$(YELLOW)Waiting for the backend to start...$(RESET)"
|
|
@until nc -z localhost $(BACKEND_PORT); do sleep 0.1; done
|
|
@echo "$(GREEN)Backend started successfully.$(RESET)"
|
|
@cd frontend && echo "$(BLUE)Starting frontend with npm...$(RESET)" && npm run start -- --port $(FRONTEND_PORT)
|
|
@echo "$(GREEN)Application started successfully.$(RESET)"
|
|
|
|
# Setup config.toml
|
|
setup-config:
|
|
@echo "$(YELLOW)Setting up config.toml...$(RESET)"
|
|
@$(MAKE) setup-config-prompts
|
|
@mv $(CONFIG_FILE).tmp $(CONFIG_FILE)
|
|
@echo "$(GREEN)Config.toml setup completed.$(RESET)"
|
|
|
|
setup-config-prompts:
|
|
@read -p "Enter your LLM Model name (see https://docs.litellm.ai/docs/providers for full list) [default: $(DEFAULT_MODEL)]: " llm_model; \
|
|
llm_model=$${llm_model:-$(DEFAULT_MODEL)}; \
|
|
echo "LLM_MODEL=\"$$llm_model\"" > $(CONFIG_FILE).tmp
|
|
|
|
@read -p "Enter your LLM API key: " llm_api_key; \
|
|
echo "LLM_API_KEY=\"$$llm_api_key\"" >> $(CONFIG_FILE).tmp
|
|
|
|
@read -p "Enter your LLM Base URL [mostly used for local LLMs, leave blank if not needed - example: http://localhost:5001/v1/]: " llm_base_url; \
|
|
if [[ ! -z "$$llm_base_url" ]]; then echo "LLM_BASE_URL=\"$$llm_base_url\"" >> $(CONFIG_FILE).tmp; fi
|
|
|
|
@echo "Enter your LLM Embedding Model\nChoices are openai, azureopenai, llama2 or leave blank to default to 'BAAI/bge-small-en-v1.5' via huggingface"; \
|
|
read -p "> " llm_embedding_model; \
|
|
echo "LLM_EMBEDDING_MODEL=\"$$llm_embedding_model\"" >> $(CONFIG_FILE).tmp; \
|
|
if [ "$$llm_embedding_model" = "llama2" ]; then \
|
|
read -p "Enter the local model URL (will overwrite LLM_BASE_URL): " llm_base_url; \
|
|
echo "LLM_BASE_URL=\"$$llm_base_url\"" >> $(CONFIG_FILE).tmp; \
|
|
elif [ "$$llm_embedding_model" = "azureopenai" ]; then \
|
|
read -p "Enter the Azure endpoint URL (will overwrite LLM_BASE_URL): " llm_base_url; \
|
|
echo "LLM_BASE_URL=\"$$llm_base_url\"" >> $(CONFIG_FILE).tmp; \
|
|
read -p "Enter the Azure LLM Deployment Name: " llm_deployment_name; \
|
|
echo "LLM_DEPLOYMENT_NAME=\"$$llm_deployment_name\"" >> $(CONFIG_FILE).tmp; \
|
|
read -p "Enter the Azure API Version: " llm_api_version; \
|
|
echo "LLM_API_VERSION=\"$$llm_api_version\"" >> $(CONFIG_FILE).tmp; \
|
|
fi
|
|
|
|
@read -p "Enter your workspace directory [default: $(DEFAULT_WORKSPACE_DIR)]: " workspace_dir; \
|
|
workspace_dir=$${workspace_dir:-$(DEFAULT_WORKSPACE_DIR)}; \
|
|
echo "WORKSPACE_BASE=\"$$workspace_dir\"" >> $(CONFIG_FILE).tmp
|
|
|
|
# Help
|
|
help:
|
|
@echo "$(BLUE)Usage: make [target]$(RESET)"
|
|
@echo "Targets:"
|
|
@echo " $(GREEN)build$(RESET) - Build project, including environment setup and dependencies."
|
|
@echo " $(GREEN)lint$(RESET) - Run linters on the project."
|
|
@echo " $(GREEN)setup-config$(RESET) - Setup the configuration for OpenDevin by providing LLM API key,"
|
|
@echo " LLM Model name, and workspace directory."
|
|
@echo " $(GREEN)start-backend$(RESET) - Start the backend server for the OpenDevin project."
|
|
@echo " $(GREEN)start-frontend$(RESET) - Start the frontend server for the OpenDevin project."
|
|
@echo " $(GREEN)run$(RESET) - Run the OpenDevin application, starting both backend and frontend servers."
|
|
@echo " Backend Log file will be stored in the 'logs' directory."
|
|
@echo " $(GREEN)help$(RESET) - Display this help message, providing information on available targets."
|
|
|
|
# Phony targets
|
|
.PHONY: build check-dependencies check-python check-npm check-docker check-poetry pull-docker-image install-python-dependencies install-frontend-dependencies install-precommit-hooks lint start-backend start-frontend run setup-config setup-config-prompts help
|