diff --git a/Dockerfile b/Dockerfile index 8a73b44dd..fc2c3d176 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,10 @@ COPY Cargo.toml Cargo.lock rust-toolchain.toml ./ COPY crates/ crates/ COPY headroom/ headroom/ -ARG HEADROOM_EXTRAS=proxy,code +# The standalone Dockerfile must support every backend advertised by +# `headroom proxy --backend`, including Bedrock temporary/SSO credentials. +# Those credentials require botocore (GH #1551), supplied by [bedrock]. +ARG HEADROOM_EXTRAS=proxy,code,bedrock RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ diff --git a/README.md b/README.md index 39a5852a3..0b923e940 100644 --- a/README.md +++ b/README.md @@ -415,7 +415,7 @@ Everything in this repo stays open source (Apache 2.0). The managed offering is uv tool install --python 3.13 "headroom-ai[all]" # CLI, isolated app env pip install "headroom-ai[all]" # Python, everything — includes the `headroom` CLI npm install headroom-ai # TypeScript SDK (library only — no `headroom` CLI) -docker pull ghcr.io/chopratejas/headroom:latest +docker pull ghcr.io/headroomlabs-ai/headroom:latest ``` Granular extras: `[proxy]`, `[mcp]`, `[ml]` (Kompress-v2-base), `[code]`, `[memory]`, `[vector]` (optional HNSW backend — needs a C++ toolchain, not in `[all]`), `[relevance]`, `[image]`, `[agno]`, `[langchain]`, `[evals]`, `[pytorch-mps]` (Apple-GPU memory-embedder offload — set `HEADROOM_EMBEDDER_RUNTIME=pytorch_mps`). Requires **Python 3.10+**. diff --git a/TESTING-copilot-subscription.md b/TESTING-copilot-subscription.md index 69204ca24..2255ccb28 100644 --- a/TESTING-copilot-subscription.md +++ b/TESTING-copilot-subscription.md @@ -107,7 +107,7 @@ There is **no native Windows wheel yet**, so pick one: **A. Mechanism test (easiest — Docker Desktop or WSL2):** ```powershell -$env:HEADROOM_DOCKER_IMAGE = "ghcr.io/chopratejas/headroom:" # ask the maintainer for the tag +$env:HEADROOM_DOCKER_IMAGE = "ghcr.io/headroomlabs-ai/headroom:" # ask the maintainer for the tag # run the Docker-native installer (scripts/install.ps1), then: $env:GITHUB_COPILOT_TOKEN = "" headroom wrap copilot --subscription -- --model gpt-4o -p "Reply with: HEADROOM_OK" diff --git a/docker-bake.hcl b/docker-bake.hcl index 07397c965..f7ca8aacd 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -10,7 +10,7 @@ target "runtime-default" { inherits = ["_common", "docker-metadata-action"] target = "runtime" args = { - HEADROOM_EXTRAS = "proxy" + HEADROOM_EXTRAS = "proxy,bedrock" RUNTIME_USER = "nonroot" } } @@ -19,7 +19,7 @@ target "runtime" { inherits = ["_common", "docker-metadata-action"] target = "runtime" args = { - HEADROOM_EXTRAS = "proxy" + HEADROOM_EXTRAS = "proxy,bedrock" RUNTIME_USER = "root" } } @@ -28,7 +28,7 @@ target "runtime-nonroot" { inherits = ["_common", "docker-metadata-action"] target = "runtime" args = { - HEADROOM_EXTRAS = "proxy" + HEADROOM_EXTRAS = "proxy,bedrock" RUNTIME_USER = "nonroot" } } @@ -37,7 +37,7 @@ target "runtime-code" { inherits = ["_common", "docker-metadata-action"] target = "runtime" args = { - HEADROOM_EXTRAS = "proxy,code" + HEADROOM_EXTRAS = "proxy,code,bedrock" RUNTIME_USER = "root" } } @@ -46,7 +46,7 @@ target "runtime-code-nonroot" { inherits = ["_common", "docker-metadata-action"] target = "runtime" args = { - HEADROOM_EXTRAS = "proxy,code" + HEADROOM_EXTRAS = "proxy,code,bedrock" RUNTIME_USER = "nonroot" } } @@ -55,7 +55,7 @@ target "runtime-slim" { inherits = ["_common", "docker-metadata-action"] target = "runtime-slim" args = { - HEADROOM_EXTRAS = "proxy" + HEADROOM_EXTRAS = "proxy,bedrock" RUNTIME_USER = "root" } } @@ -64,7 +64,7 @@ target "runtime-slim-nonroot" { inherits = ["_common", "docker-metadata-action"] target = "runtime-slim" args = { - HEADROOM_EXTRAS = "proxy" + HEADROOM_EXTRAS = "proxy,bedrock" RUNTIME_USER = "nonroot" } } @@ -73,7 +73,7 @@ target "runtime-code-slim" { inherits = ["_common", "docker-metadata-action"] target = "runtime-slim" args = { - HEADROOM_EXTRAS = "proxy,code" + HEADROOM_EXTRAS = "proxy,code,bedrock" RUNTIME_USER = "root" } } @@ -82,7 +82,7 @@ target "runtime-code-slim-nonroot" { inherits = ["_common", "docker-metadata-action"] target = "runtime-slim" args = { - HEADROOM_EXTRAS = "proxy,code" + HEADROOM_EXTRAS = "proxy,code,bedrock" RUNTIME_USER = "nonroot" } } diff --git a/docker-compose.yml b/docker-compose.yml index 47b707b2d..204aecb81 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ # 3. point your LLM client at http://localhost:8787 (proxy) # # Just want the proxy without the memory features? You can run the proxy image -# on its own (`docker run -p 8787:8787 ghcr.io/chopratejas/headroom`); the two +# on its own (`docker run -p 8787:8787 ghcr.io/headroomlabs-ai/headroom`); the two # database services below are only required for the memory/relevance features. # # Ports exposed on the host: diff --git a/llms.txt b/llms.txt index 84cc27da9..fe2412fdb 100644 --- a/llms.txt +++ b/llms.txt @@ -19,7 +19,7 @@ The canonical, always-current documentation index lives at the docs site below. - Python: `pip install headroom-ai` (add `[all]` for every optional extra) - TypeScript / Node: `npm install headroom-ai` (or `pnpm add headroom-ai`, `bun add headroom-ai`) -- Docker: `docker run -p 8787:8787 ghcr.io/chopratejas/headroom:latest` +- Docker: `docker run -p 8787:8787 ghcr.io/headroomlabs-ai/headroom:latest` - Run the proxy: `headroom proxy --port 8787` then point any client at `http://127.0.0.1:8787` - Wrap an agent in one command: `headroom wrap claude` (also: `codex`, `copilot`, `cursor`, `aider`, `opencode`, `cline`, `continue`, `goose`, `openhands`, `openclaw`, `vibe`, `omp`) diff --git a/tests/test_release_workflows.py b/tests/test_release_workflows.py index 954e2c90b..207827802 100644 --- a/tests/test_release_workflows.py +++ b/tests/test_release_workflows.py @@ -6,10 +6,62 @@ from pathlib import Path import pytest import yaml +from packaging.requirements import Requirement + +try: + import tomllib +except ModuleNotFoundError: # pragma: no cover - Python 3.10 fallback + import tomli as tomllib # type: ignore[no-redef] ROOT = Path(__file__).resolve().parent.parent +def test_every_published_docker_variant_includes_bedrock_auth_dependencies() -> None: + """Every image that advertises ``--backend bedrock`` must ship botocore. + + Temporary AWS credentials take LiteLLM's botocore-backed authentication + path. The default images previously installed only ``proxy``/``code``, so + the documented Docker Bedrock command failed at runtime with + ``No module named 'botocore'`` (#1551). Keep the standalone Dockerfile and + every bake target on the existing ``bedrock`` package extra. + """ + dockerfile = (ROOT / "Dockerfile").read_text(encoding="utf-8") + assert "ARG HEADROOM_EXTRAS=proxy,code,bedrock" in dockerfile + + bake = (ROOT / "docker-bake.hcl").read_text(encoding="utf-8") + extras_lines = [ + line.strip() for line in bake.splitlines() if line.strip().startswith("HEADROOM_EXTRAS =") + ] + assert len(extras_lines) == 9 + assert all("bedrock" in line for line in extras_lines), extras_lines + + project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8")) + bedrock_names = { + Requirement(requirement).name + for requirement in project["project"]["optional-dependencies"]["bedrock"] + } + assert {"boto3", "botocore"} <= bedrock_names + + +def test_public_docker_instructions_use_the_current_organization_package() -> None: + """Do not send users back to the personal GHCR package frozen at 0.27.0.""" + public_docs = ( + "README.md", + "llms.txt", + "docker-compose.yml", + "TESTING-copilot-subscription.md", + "wiki/cli.md", + "wiki/docker-install.md", + ) + deprecated = "ghcr.io/chopratejas/headroom" + current = "ghcr.io/headroomlabs-ai/headroom" + + for relative_path in public_docs: + content = (ROOT / relative_path).read_text(encoding="utf-8") + assert deprecated not in content, relative_path + assert current in content, relative_path + + def test_docker_workflow_normalizes_repository_name_for_signing() -> None: content = (ROOT / ".github" / "workflows" / "docker.yml").read_text(encoding="utf-8") diff --git a/wiki/cli.md b/wiki/cli.md index 369936666..42a591960 100644 --- a/wiki/cli.md +++ b/wiki/cli.md @@ -637,7 +637,7 @@ Options: (already the default). --image TEXT Docker image to use when runtime=docker or preset=persistent-docker. [default: - ghcr.io/chopratejas/headroom:latest] + ghcr.io/headroomlabs-ai/headroom:latest] -?, --help Show this message and exit. ``` @@ -665,7 +665,7 @@ headroom install apply --preset persistent-docker --scope user | `--memory` | off | Enable persistent memory in the managed runtime | | `--telemetry` | off | Opt in to anonymous telemetry (off by default) | | `--no-telemetry` | off | Force anonymous telemetry off (already the default) | -| `--image` | `ghcr.io/chopratejas/headroom:latest` | Docker image for Docker-backed installs | +| `--image` | `ghcr.io/headroomlabs-ai/headroom:latest` | Docker image for Docker-backed installs | `apply` stores a manifest under `${HEADROOM_WORKSPACE_DIR}/deploy//manifest.json` (default diff --git a/wiki/docker-install.md b/wiki/docker-install.md index f134eb0cb..de3956275 100644 --- a/wiki/docker-install.md +++ b/wiki/docker-install.md @@ -27,7 +27,7 @@ irm https://raw.githubusercontent.com/chopratejas/headroom/main/scripts/install. ## What the installer does 1. Verifies Docker is installed and available. -2. Pulls `ghcr.io/chopratejas/headroom:latest` by default, or reuses / pulls `HEADROOM_DOCKER_IMAGE` when you set a custom image override. +2. Pulls `ghcr.io/headroomlabs-ai/headroom:latest` by default, or reuses / pulls `HEADROOM_DOCKER_IMAGE` when you set a custom image override. 3. Installs a `headroom` wrapper into `~/.local/bin` or `~/bin`. 4. Updates shell startup files so the wrapper directory is on `PATH`. @@ -41,7 +41,7 @@ The wrapper keeps Headroom inside Docker and mounts host state back into the con Port `8787` stays the default, so `http://localhost:8787` works the same way as a native install. -Published releases also push versioned GHCR tags such as `ghcr.io/chopratejas/headroom:0.5.26`, and those images are built with the same synced package version used for the matching PyPI and npm release. +Published releases also push versioned GHCR tags such as `ghcr.io/headroomlabs-ai/headroom:0.35.0`, and those images are built with the same synced package version used for the matching PyPI and npm release. ## How the wrapper behaves @@ -63,7 +63,7 @@ docker run --rm -it \ -p 8787:8787 \ -v "$PWD:/workspace" \ -w /workspace \ - ghcr.io/chopratejas/headroom:latest \ + ghcr.io/headroomlabs-ai/headroom:latest \ headroom proxy --host 0.0.0.0 --port 8787 ```