mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-10 14:27:00 -04:00
## Description Claude Code disables on-demand tool loading (Tool Search) when `ANTHROPIC_BASE_URL` is a custom host and `ENABLE_TOOL_SEARCH` is unset, materializing all MCP/system tool schemas into its context window (#746). With many MCP servers this overflows the window — breaking sub-agent spawns ("prompt too long, ~214k > 200k") and forcing constant compaction. `headroom wrap claude` already sets it; `init`/install did not. Refs #746. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) ## Changes Made - Keep tool deferral on at both entry points, sharing one `TOOL_SEARCH_ENV` / `TOOL_SEARCH_DEFAULT` constant from the Claude provider package (`providers/claude/runtime.py`) so the key/default can't drift: - `init` (`_ensure_claude_hooks`): sets `ENABLE_TOOL_SEARCH=true` via `setdefault`, respecting a pre-existing user-provided value. - `install` (`build_install_env`): always writes `ENABLE_TOOL_SEARCH=true`. This is the headroom-managed install env (recorded and reverted on uninstall), so it is authoritative rather than deferring to an existing value. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ pytest tests/test_cli/test_init_enable_tool_search.py -q 3 passed in 0.63s ``` ## Real Behavior Proof - Environment: Python 3.14, headroom proxy on :8799, ~19 MCP servers connected - Exact command / steps: launched `claude` through the proxy with vs without `ENABLE_TOOL_SEARCH=true`, asked each to spawn 5 parallel sub-agents - Observed result: without it, all 5 sub-agents fail ("prompt too long, ~214k > 200k"); with `ENABLE_TOOL_SEARCH=true` all 5 succeed and traffic compresses - Not tested: non-Claude-Code agents ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
42 lines
1.7 KiB
Python
42 lines
1.7 KiB
Python
"""`headroom init claude` must set ENABLE_TOOL_SEARCH (GH #746).
|
|
|
|
Claude Code disables on-demand tool loading when ANTHROPIC_BASE_URL is a custom
|
|
host and ENABLE_TOOL_SEARCH is unset, materializing all MCP/system tool schemas
|
|
into the context window — which breaks sub-agent spawns and forces compaction.
|
|
`headroom wrap claude` already sets it; `init` (and the persistent install) must
|
|
too, otherwise init-wired users silently get eager tools.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from headroom.cli import init as init_cli
|
|
from headroom.providers.claude import install as claude_install
|
|
|
|
|
|
def test_ensure_claude_hooks_sets_enable_tool_search(tmp_path: Path) -> None:
|
|
settings = tmp_path / "settings.json"
|
|
init_cli._ensure_claude_hooks(settings, profile="init-user", port=8787)
|
|
|
|
env = json.loads(settings.read_text(encoding="utf-8"))["env"]
|
|
assert env["ANTHROPIC_BASE_URL"] == "http://127.0.0.1:8787"
|
|
assert env["ENABLE_TOOL_SEARCH"] == "true"
|
|
|
|
|
|
def test_ensure_claude_hooks_respects_user_tool_search_value(tmp_path: Path) -> None:
|
|
settings = tmp_path / "settings.json"
|
|
settings.write_text(
|
|
json.dumps({"env": {"ENABLE_TOOL_SEARCH": "auto"}}) + "\n", encoding="utf-8"
|
|
)
|
|
init_cli._ensure_claude_hooks(settings, profile="init-user", port=8787)
|
|
|
|
env = json.loads(settings.read_text(encoding="utf-8"))["env"]
|
|
assert env["ENABLE_TOOL_SEARCH"] == "auto" # setdefault preserves the user's choice
|
|
|
|
|
|
def test_build_install_env_includes_enable_tool_search() -> None:
|
|
env = claude_install.build_install_env(port=8787, backend="anthropic")
|
|
assert env["ENABLE_TOOL_SEARCH"] == "true"
|
|
assert env["ANTHROPIC_BASE_URL"].endswith(":8787")
|