fix(claude_desktop): remove blocking Kompress pre-warm, use proxy's own background loader

Codex flagged that the synchronous pre-warm (up to 300s) blocked the proxy port bind, defeating the terminal wrapper's health-check fallback and, combined with the new settings-managed ANTHROPIC_BASE_URL, could send terminal Claude Code launches to a proxy that was not listening yet.

The proxy already has a non-blocking answer to a cold cache: content_router.py calls compressor.ensure_background_load() on first use and passes the request through uncompressed until the model lands, so the port always binds immediately. Persisting HF_HOME alone is enough -- Kompress self-heals within the first couple of requests on a cold boot and loads instantly (eager preload) on every boot after.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
alexbelgium
2026-07-16 08:20:50 +02:00
parent b8c7cc3815
commit b3c27024d8
2 changed files with 10 additions and 16 deletions

View File

@@ -1,7 +1,7 @@
## 1.27 (15-07-2026) ## 1.27 (15-07-2026)
- Route Claude Desktop cowork/local-agent-mode sessions through the Headroom proxy. Desktop spawns its bundled Claude Code binary at an absolute path (bypassing the add-on's PATH wrapper) with `ANTHROPIC_BASE_URL` pinned to the production endpoint, so those sessions never produced proxy savings. The add-on now manages `env.ANTHROPIC_BASE_URL` in `~/.claude/settings.json` — settings `env` entries replace inherited environment values at CLI startup — gated on `headroom_wrap_claude_code` and never overwriting a user-customized endpoint. - Route Claude Desktop cowork/local-agent-mode sessions through the Headroom proxy. Desktop spawns its bundled Claude Code binary at an absolute path (bypassing the add-on's PATH wrapper) with `ANTHROPIC_BASE_URL` pinned to the production endpoint, so those sessions never produced proxy savings. The add-on now manages `env.ANTHROPIC_BASE_URL` in `~/.claude/settings.json` — settings `env` entries replace inherited environment values at CLI startup — gated on `headroom_wrap_claude_code` and never overwriting a user-customized endpoint.
- Fix Headroom's Kompress compression engine never activating, which made even proxied traffic record zero token savings (e.g. 175 requests, 0 saved). The proxy's startup preload is deliberately cache-only, but the HuggingFace model cache defaulted to `~/.cache` — tmpfs in this add-on, wiped every restart — so the ONNX model (plus the separately fetched `answerdotai/ModernBERT-base` tokenizer) was never cached and the engine idled in "deferred" mode forever, misleadingly logged as `Kompress: not installed`. `svc-headroom` now points `HF_HOME` at persistent storage (`~/.headroom/hf`, ~270 MB) and pre-warms the cache once at startup (bounded at 300 s, so an offline install still starts the proxy in pass-through mode and retries next boot). The already-installed `proxy` extra's ONNX runtime is sufficient — the multi-gigabyte PyTorch `ml` extra is deliberately not installed. - Fix Headroom's Kompress compression engine never activating, which made even proxied traffic record zero token savings (e.g. 175 requests, 0 saved). The proxy's startup preload is deliberately cache-only, but the HuggingFace model cache defaulted to `~/.cache` — tmpfs in this add-on, wiped every restart — so the ONNX model (plus the separately fetched `answerdotai/ModernBERT-base` tokenizer) was never cached and the engine idled in "deferred" mode forever, misleadingly logged as `Kompress: not installed`. `svc-headroom` now points `HF_HOME` at persistent storage (`~/.headroom/hf`, ~270 MB); the proxy's own request path already downloads a missing model in the background on first use and passes requests through uncompressed until it lands, so no blocking startup pre-warm is needed — the port binds immediately either way, and Kompress activates within the first couple of requests on the first boot, then loads instantly on every boot after. The already-installed `proxy` extra's ONNX runtime is sufficient — the multi-gigabyte PyTorch `ml` extra is deliberately not installed.
## 1.26 (15-07-2026) ## 1.26 (15-07-2026)

View File

@@ -13,24 +13,18 @@ if bashio::config.true 'install_headroom' && command -v headroom > /dev/null 2>&
# Kompress (the ONNX compression engine) needs its model in the local HF cache: the # Kompress (the ONNX compression engine) needs its model in the local HF cache: the
# proxy's startup preload is deliberately cache-only, and the default HF cache lands # proxy's startup preload is deliberately cache-only, and the default HF cache lands
# under ~/.cache, which the add-on points at tmpfs (/tmp/cache) — wiped on every # under ~/.cache, which the add-on points at tmpfs (/tmp/cache) — wiped on every
# restart. Without a warm persistent cache the proxy runs forever in "deferred" mode # restart. Without a warm persistent cache the proxy ran forever in "deferred" mode
# and records zero compression savings. Cache on persistent storage and pre-warm it # and recorded zero compression savings. Point the cache at persistent storage;
# once (bounded so an offline install still starts the proxy, in pass-through mode, # nothing else is needed here — the proxy's own request path already downloads a
# and retries the download on the next start). # missing model in the background on first use (ensure_background_load) and passes
# requests through uncompressed until it lands, so this self-heals within a couple of
# requests on the first boot and loads instantly (eager preload) on every boot after.
# A synchronous pre-warm was tried here and removed: it blocked the port bind for up
# to the download's duration, which left the settings-managed ANTHROPIC_BASE_URL
# (see 82-claude_tools.sh) pointing at a proxy that wasn't listening yet.
export HF_HOME="${HOME}/.headroom/hf" export HF_HOME="${HOME}/.headroom/hf"
mkdir -p "$HF_HOME" mkdir -p "$HF_HOME"
chown abc:abc "$HF_HOME" 2> /dev/null || true chown abc:abc "$HF_HOME" 2> /dev/null || true
# headroom lives in the lsiopy virtualenv; plain `python3` does not see its packages,
# so derive the venv interpreter from the resolved headroom entry script.
headroom_python="$(dirname "$(readlink -f "$(command -v headroom)")")/python3"
if ! s6-setuidgid abc "$headroom_python" -c \
'from headroom.transforms.kompress_compressor import _load_kompress; _load_kompress(allow_download=False)' \
> /dev/null 2>&1; then
bashio::log.info "svc-headroom: pre-warming the Kompress model cache (one-time download)"
timeout 300 s6-setuidgid abc "$headroom_python" -c \
'from headroom.transforms.kompress_compressor import _load_kompress; _load_kompress()' \
|| bashio::log.warning "svc-headroom: Kompress pre-warm failed; compression stays deferred until the model can be downloaded"
fi
bashio::log.info "svc-headroom: starting local Headroom proxy on ${host}:${port}" bashio::log.info "svc-headroom: starting local Headroom proxy on ${host}:${port}"
exec s6-setuidgid abc headroom proxy --host "${host}" --port "${port}" --code-aware exec s6-setuidgid abc headroom proxy --host "${host}" --port "${port}" --code-aware
fi fi