[build-system] build-backend = "poetry.core.masonry.api" # PEP 621 project metadata (for UV compatibility) # This section coexists with [tool.poetry] during the migration period requires = [ "poetry-core" ] [project] name = "openhands-ai" description = "OpenHands: Code Less, Make More" readme = "README.md" license = "MIT" authors = [ { name = "OpenHands", email = "contact@all-hands.dev" } ] requires-python = ">=3.12,<3.14" classifiers = [ "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] # Version is managed dynamically by poetry-dynamic-versioning dynamic = [ "version" ] # Main dependencies (mirrors [tool.poetry.dependencies] for UV compatibility) dependencies = [ "aiohttp>=3.13.3", "anthropic[vertex]", "anyio==4.9", "asyncpg>=0.30", "authlib>=1.6.7", "bashlex>=0.18", "boto3", "browsergym-core==0.13.3", "deprecated", "deprecation>=2.1", "dirhash", "docker", "fastapi", "fastmcp>=2.12.4,<2.12.5", "google-api-python-client>=2.164", "google-auth-httplib2", "google-auth-oauthlib", "google-cloud-aiplatform", "google-genai", "html2text", "httpx-aiohttp>=0.1.8", "ipywidgets>=8.1.5", "jinja2>=3.1.6", "joblib", "json-repair", "jupyter-kernel-gateway", "jwcrypto>=1.5.6", "kubernetes>=33.1", "libtmux>=0.46.2", "litellm!=1.64.4,!=1.67.*,>=1.74.3", "lmnr>=0.7.20", "memory-profiler>=0.61", "numpy", "openai==2.8", "openhands-aci==0.3.3", "openhands-agent-server==1.11.5", "openhands-sdk==1.11.5", "openhands-tools==1.11.5", "opentelemetry-api>=1.33.1", "opentelemetry-exporter-otlp-proto-grpc>=1.33.1", "pathspec>=0.12.1", "pexpect", "pg8000>=1.31.5", "pillow>=12.1.1", "playwright>=1.55", "poetry>=2.1.2", "prompt-toolkit>=3.0.50", "protobuf>=5.29.6,<6", "psutil", "pybase62>=1", "pygithub>=2.5", "pyjwt>=2.9", "pylatexenc", "pypdf>=6.7.2", "python-docx", "python-dotenv", "python-frontmatter>=1.1", "python-json-logger>=3.2.1", "python-multipart>=0.0.22", "python-pptx", "python-socketio==5.14", "pythonnet", "pyyaml>=6.0.2", "qtconsole>=5.6.1", "rapidfuzz>=3.9", "redis>=5.2,<7", "requests>=2.32.5", "setuptools>=78.1.1", "shellingham>=1.5.4", "sqlalchemy[asyncio]>=2.0.40", "sse-starlette>=3.0.2", "starlette>=0.49.1", "tenacity>=8.5,<10", "termcolor", "toml", "tornado>=6.5", "types-toml", "urllib3>=2.6.3", "uvicorn", "whatthepatch>=1.0.6", "zope-interface==7.2", ] optional-dependencies.third_party_runtimes = [ "daytona==0.24.2", "e2b-code-interpreter>=2", "modal>=0.66.26,<1.2", "runloop-api-client==0.50", ] urls.Homepage = "https://github.com/OpenHands/OpenHands" urls.Repository = "https://github.com/OpenHands/OpenHands" [dependency-groups] dev = [ "build", "mypy==1.17", "pre-commit==4.2", "pytest>=8.4", "pytest-asyncio>=1.3", "ruff==0.12.5", "types-setuptools", ] test = [ "gevent>=24.2.1,<26", "pandas", "pytest", "pytest-asyncio", "pytest-cov", "pytest-forked", "pytest-playwright>=0.7", "pytest-timeout>=2.4", "pytest-xdist", "reportlab", ] runtime = [ "flake8", "jupyterlab", "notebook", ] [tool.poetry] name = "openhands-ai" version = "1.4.0" description = "OpenHands: Code Less, Make More" authors = [ "OpenHands" ] license = "MIT" readme = "README.md" repository = "https://github.com/OpenHands/OpenHands" packages = [ { include = "openhands/**/*" }, { include = "third_party/**/*" }, { include = "pyproject.toml", to = "openhands" }, { include = "poetry.lock", to = "openhands" }, ] include = [ "skills/**/*", ] [tool.poetry.dependencies] python = "^3.12,<3.14" authlib = ">=1.6.7" # Pinned to fix CVE-2026-28802 litellm = ">=1.74.3, !=1.64.4, !=1.67.*" # avoid 1.64.4 (known bug) & 1.67.* (known bug #10272) openai = "2.8.0" # Pin due to litellm incompatibility with >=1.100.0 (BerriAI/litellm#13711) aiohttp = ">=3.13.3" # Pin to avoid CVE-2025-69223 (vulnerable versions < 3.13.3) google-genai = "*" # To use litellm with Gemini Pro API google-api-python-client = "^2.164.0" # For Google Sheets API google-auth-httplib2 = "*" # For Google Sheets authentication google-auth-oauthlib = "*" # For Google Sheets OAuth termcolor = "*" docker = "*" fastapi = "*" toml = "*" types-toml = "*" uvicorn = "*" numpy = "*" json-repair = "*" browsergym-core = "0.13.3" # integrate browsergym-core as the browsing interface playwright = "^1.55.0" html2text = "*" deprecated = "*" pexpect = "*" jinja2 = "^3.1.6" python-multipart = ">=0.0.22" tenacity = ">=8.5,<10.0" zope-interface = "7.2" pathspec = "^0.12.1" pyjwt = "^2.9.0" dirhash = "*" tornado = ">=6.5" python-dotenv = "*" rapidfuzz = "^3.9.0" whatthepatch = "^1.0.6" protobuf = ">=5.29.6,<6.0.0" # Updated to fix CVE-2026-0994 opentelemetry-api = "^1.33.1" opentelemetry-exporter-otlp-proto-grpc = "^1.33.1" libtmux = ">=0.46.2" pygithub = "^2.5.0" joblib = "*" openhands-aci = "0.3.3" python-socketio = "5.14.0" sse-starlette = "^3.0.2" psutil = "*" python-json-logger = "^3.2.1" prompt-toolkit = "^3.0.50" poetry = "^2.1.2" anyio = "4.9.0" pythonnet = "*" fastmcp = "^2.12.4" # Note: 2.12.0+ has breaking auth API changes python-frontmatter = "^1.1.0" shellingham = "^1.5.4" # TODO: Should these go into the runtime group? ipywidgets = "^8.1.5" qtconsole = "^5.6.1" python-pptx = "*" pylatexenc = "*" python-docx = "*" bashlex = "^0.18" # Explicitly pinned packages for latest versions pypdf = "^6.7.2" pillow = "^12.1.1" starlette = "^0.49.1" urllib3 = "^2.6.3" requests = "^2.32.5" setuptools = ">=78.1.1" # TODO: These are integrations that should probably be optional redis = ">=5.2,<7.0" google-cloud-aiplatform = "*" anthropic = { extras = [ "vertex" ], version = "*" } boto3 = "*" kubernetes = "^33.1.0" pyyaml = "^6.0.2" memory-profiler = "^0.61.0" jupyter_kernel_gateway = "*" # Third-party runtime dependencies (optional) modal = { version = ">=0.66.26,<1.2.0", optional = true } runloop-api-client = { version = "0.50.0", optional = true } daytona = { version = "0.24.2", optional = true } httpx-aiohttp = "^0.1.8" e2b-code-interpreter = { version = "^2.0.0", optional = true } pybase62 = "^1.0.0" # V1 dependencies openhands-sdk = "1.11.5" openhands-agent-server = "1.11.5" openhands-tools = "1.11.5" jwcrypto = ">=1.5.6" sqlalchemy = { extras = [ "asyncio" ], version = "^2.0.40" } pg8000 = "^1.31.5" asyncpg = "^0.30.0" deprecation = "^2.1.0" lmnr = "^0.7.20" [tool.poetry.extras] third_party_runtimes = [ "e2b-code-interpreter", "modal", "runloop-api-client", "daytona" ] [tool.poetry.group.dev] optional = true [tool.poetry.group.dev.dependencies] ruff = "0.12.5" mypy = "1.17.0" pre-commit = "4.2.0" build = "*" types-setuptools = "*" pytest = "^8.4.0" pytest-asyncio = "^1.3.0" [tool.poetry.group.test] optional = true [tool.poetry.group.test.dependencies] pytest = "*" pytest-cov = "*" pytest-asyncio = "*" pytest-forked = "*" pytest-xdist = "*" pytest-playwright = "^0.7.0" pytest-timeout = "^2.4.0" pandas = "*" reportlab = "*" gevent = ">=24.2.1,<26.0.0" [tool.poetry.group.runtime] optional = true [tool.poetry.group.runtime.dependencies] jupyterlab = "*" notebook = "*" flake8 = "*" [tool.poetry-dynamic-versioning] enable = true style = "semver" [tool.autopep8] # autopep8 fights with mypy on line length issue ignore = [ "E501" ] [tool.black] # prevent black (if installed) from changing single quotes to double quotes skip-string-normalization = true [tool.ruff] lint.select = [ "D" ] # ignore warnings for missing docstrings lint.ignore = [ "D1" ] lint.pydocstyle.convention = "google" [tool.coverage.run] concurrency = [ "gevent" ] relative_files = true omit = [ "enterprise/tests/*", "**/test_*" ]