fix(install): cap requires-python at <3.14 and pin UV_PYTHON to the venv (#38535)

uv selects the project Python from requires-python and from the UV_PYTHON
env var, both of which override an already-created venv on the next
'uv sync'. With no upper bound on requires-python, an inherited
UV_PYTHON=3.14 (or a fresh distro whose newest interpreter uv auto-picks)
silently recreated the installer's 3.11 venv at 3.14, where Rust-backed
transitives (pydantic-core) have no cp314 wheel and fall back to a maturin
source build that fails. This bit a Windows/WSL user with UV_PYTHON set in
their shell and a fresh WSL-arch box where uv auto-picked 3.14.

Two layers:
- pyproject: requires-python '>=3.11' -> '>=3.11,<3.14' (+ uv lock regen).
  uv now refuses a 3.14 interpreter with a clear error instead of attempting
  the maturin build. Backstop independent of the installer.
- install.sh / install.ps1: pin UV_PYTHON to the venv interpreter after
  creating it (in both the venv step and the deps step, since bootstrap runs
  those stages as separate processes). An inherited UV_PYTHON can no longer
  hijack the sync/pip tiers, so the install just works regardless of shell env.

Verified E2E: hostile UV_PYTHON=3.14 + uv venv --python 3.11 + uv sync now
installs into 3.11 with pydantic-core's 3.11 wheel; without the re-pin the
capped requires-python produces a legible incompatibility error rather than a
cryptic build failure.
This commit is contained in:
Teknium
2026-06-03 16:45:47 -07:00
committed by GitHub
parent e8c3ac2f5c
commit 475ecea3d7
4 changed files with 60 additions and 584 deletions
+8 -1
View File
@@ -10,7 +10,14 @@ name = "hermes-agent"
version = "0.15.1"
description = "The self-improving AI agent — creates skills from experience, improves them during use, and runs anywhere"
readme = "README.md"
requires-python = ">=3.11"
# Upper bound is load-bearing, not cosmetic. uv resolves the project's
# Python from `requires-python`, and an inherited `UV_PYTHON` env var (or a
# fresh distro whose newest interpreter uv auto-picks) will otherwise select
# 3.14, where Rust-backed transitives (e.g. pydantic-core) have no cp314
# wheel yet and fall back to a maturin source build that fails. Capping at
# <3.14 makes uv refuse 3.14 with a clear error instead of attempting that
# build. Raise the ceiling once our Rust transitives ship cp314 wheels.
requires-python = ">=3.11,<3.14"
authors = [{ name = "Nous Research" }]
license = "MIT"
license-files = ["LICENSE"]