mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -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>
This commit is contained in:
parent
f03e77bec0
commit
500ec2b7fa
8 changed files with 102 additions and 11 deletions
|
|
@ -424,7 +424,11 @@ def test_ensure_claude_hooks_rewrites_existing_entries(monkeypatch, tmp_path: Pa
|
|||
init_cli._ensure_claude_hooks(settings_path, "init-local-demo", 9001)
|
||||
|
||||
payload = json.loads(settings_path.read_text(encoding="utf-8"))
|
||||
assert payload["env"] == {"KEEP": "1", "ANTHROPIC_BASE_URL": "http://127.0.0.1:9001"}
|
||||
assert payload["env"] == {
|
||||
"KEEP": "1",
|
||||
"ANTHROPIC_BASE_URL": "http://127.0.0.1:9001",
|
||||
"ENABLE_TOOL_SEARCH": "true",
|
||||
}
|
||||
session_entries = payload["hooks"]["SessionStart"]
|
||||
assert session_entries[0] == "not-a-dict"
|
||||
assert session_entries[1] == {"hooks": "not-a-list"}
|
||||
|
|
|
|||
42
tests/test_cli/test_init_enable_tool_search.py
Normal file
42
tests/test_cli/test_init_enable_tool_search.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"""`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")
|
||||
Loading…
Add table
Add a link
Reference in a new issue