fix(deps): move gunicorn to [proxy-prod] extra, add Windows guard (#537)

* fix(deps): add missing runtime deps to [code] and [proxy] extras

- Add gunicorn>=21.0.0 to the [proxy] extra

The proxy docs (docs/content/docs/proxy.mdx and wiki/proxy.md) show
gunicorn as the recommended production deployment server:

  pip install gunicorn
  gunicorn headroom.proxy.server:app --worker-class uvicorn.workers.UvicornWorker

Users installing headroom-ai[proxy] for production get uvicorn (already
declared) but had to discover and install gunicorn manually. Adding it
to [proxy] removes that friction.

Investigation notes:
- [code] only needs tree-sitter-language-pack (already declared).
  code_compressor.py has zero numpy imports. The kompress fallback
  inside code_compressor.py is guarded by ImportError and requires [ml].
- numpy is correctly declared in [relevance] (numpy>=1.24.0) and pulled
  transitively by sentence-transformers in [memory]. It is NOT needed
  under [code].
- tree-sitter is a transitive dep of tree-sitter-language-pack (requires
  tree-sitter>=0.25.2) so it does not need an explicit entry.

* docs(changelog): add entry for gunicorn proxy dep fix

style(tests): ruff format test_provider_proxy_routes.py (blank lines after docstrings)

* fix(deps): move gunicorn to [proxy-prod] extra, add Windows guard

- Remove gunicorn from [proxy] so dev, CI, and Windows users are not
  forced to install a Unix-only package that does nothing on Windows
- Add new [proxy-prod] extra that includes [proxy] + gunicorn with a
  sys_platform != 'win32' environment marker
- Production users: pip install 'headroom-ai[proxy,proxy-prod]'
- Update CHANGELOG to reflect the new extra name

* fix(devcontainer): bump uv floor to >=0.11.0 for lockfile compatibility

uv 0.6.17 (previously pinned) cannot parse lockfiles generated by
uv >= 0.11.x. The validate CI job (triggered by pyproject.toml
changes) was failing with 'Failed to parse uv.lock'. Loosening the
pin to >=0.11.0 picks up the matching format parser while keeping the
Docker layer cacheable with a range rather than an exact pin.

* fix(devcontainer): skip gitpython wheel filename check in uv sync

gitpython 3.1.47 on PyPI has wheel gitpython-3.1.46-py3-none-any.whl
(wrong filename). uv >=0.11.19 strict filename validation rejects this
lockfile entry. UV_SKIP_WHEEL_FILENAME_CHECK=1 bypasses the check until
the upstream lockfile is regenerated with a corrected entry.

* fix(deps): correct gitpython version in uv.lock to match actual wheel

gitpython 3.1.47 on PyPI was uploaded with sdist/wheel files named
gitpython-3.1.46.*. The version field in uv.lock said 3.1.47 but all
download URLs reference 3.1.46 files, causing uv >=0.11.19 to refuse
to parse the lockfile with a version-mismatch error.

Change the version field to 3.1.46 so the entry is internally
consistent. Also revert the now-unnecessary UV_SKIP_WHEEL_FILENAME_CHECK
workaround from post-create.sh.

---------

Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
This commit is contained in:
Patrick A 2026-06-08 02:49:14 -04:00 committed by GitHub
parent cbba035386
commit fa558c5647
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 10 additions and 1 deletions

View file

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Bug Fixes
* **deps:** move `gunicorn` to `[proxy-prod]` extra with `sys_platform != 'win32'` guard; removed from `[proxy]` to avoid forcing a Unix-only package on dev, CI, and Windows users ([#537](https://github.com/chopratejas/headroom/pull/537))
* **startup:** suppress proxy startup log noise — litellm banner, trafilatura parse errors, HuggingFace Hub unauthenticated warnings, tiktoken fallback warning, and httpx INFO lines from sentence_transformers HEAD checks. Affected files: `headroom/providers/litellm.py`, `headroom/transforms/html_extractor.py`, `headroom/memory/adapters/embedders.py`, `headroom/providers/anthropic.py`, `headroom/providers/registry.py`, `headroom/image/onnx_router.py`, `headroom/transforms/kompress_compressor.py`.

View file

@ -71,6 +71,14 @@ proxy = [
"watchdog>=4.0.0", # File watcher for live code graph reindexing (--code-graph)
"sqlite-vec>=0.1.6", # Vector index for memory (--memory). Lightweight, no torch.
]
# Production ASGI/WSGI server — Unix-only (gunicorn does not support Windows).
# Kept separate from [proxy] so that dev, CI, and Windows users are not forced
# to install a non-functional package. Production deployments should use:
# pip install headroom-ai[proxy,proxy-prod]
proxy-prod = [
"headroom-ai[proxy]",
"gunicorn>=21.0.0; sys_platform != 'win32'",
]
# AST-based code compression (tree-sitter)
code = [
"tree-sitter-language-pack>=0.10.0",

2
uv.lock generated
View file

@ -1200,7 +1200,7 @@ wheels = [
[[package]]
name = "gitpython"
version = "3.1.47"
version = "3.1.46"
source = { registry = "https://pypi.org/simple/" }
dependencies = [
{ name = "gitdb" },