diff --git a/headroom/cli/wrap.py b/headroom/cli/wrap.py index 17ee01d76..863a777ef 100644 --- a/headroom/cli/wrap.py +++ b/headroom/cli/wrap.py @@ -263,6 +263,19 @@ def _print_telemetry_notice() -> None: click.echo(notice) +def _prepend_rtk_bin_to_path(env: dict[str, str]) -> None: + """Ensure wrapped shells can resolve Headroom-managed `rtk`.""" + + from headroom.rtk import RTK_BIN_DIR + + rtk_bin = str(RTK_BIN_DIR) + path_key = next((key for key in env if key.lower() == "path"), "PATH") + current_path = env.get(path_key, "") + path_entries = current_path.split(os.pathsep) if current_path else [] + if rtk_bin not in path_entries: + env[path_key] = f"{rtk_bin}{os.pathsep}{current_path}" if current_path else rtk_bin + + # Proxy health check (reused from evals/suite_runner.py pattern) @@ -2498,6 +2511,7 @@ def _launch_tool( signal.signal(signal.SIGTERM, cleanup) try: + _prepend_rtk_bin_to_path(env) click.echo() padded = f"HEADROOM WRAP: {tool_label}".center(47) click.echo(" ╔═══════════════════════════════════════════════╗") diff --git a/tests/test_cli/test_wrap_helpers.py b/tests/test_cli/test_wrap_helpers.py index 81cf1cf50..4d86dda7d 100644 --- a/tests/test_cli/test_wrap_helpers.py +++ b/tests/test_cli/test_wrap_helpers.py @@ -93,6 +93,46 @@ def test_print_wrap_banner_title_is_centered_or_near_centered() -> None: ) +def test_prepend_rtk_bin_to_path_injects_managed_bin_dir(monkeypatch: pytest.MonkeyPatch) -> None: + managed_dir = Path("/tmp/headroom-bin") + monkeypatch.setattr("headroom.rtk.RTK_BIN_DIR", managed_dir) + + env = {"PATH": "/usr/bin:/bin"} + + wrap_mod._prepend_rtk_bin_to_path(env) + + assert env["PATH"].split(os.pathsep)[0] == str(managed_dir) + assert "/usr/bin" in env["PATH"] + + +def test_prepend_rtk_bin_to_path_updates_windows_style_path_key( + monkeypatch: pytest.MonkeyPatch, +) -> None: + managed_dir = Path("/tmp/headroom-bin") + monkeypatch.setattr("headroom.rtk.RTK_BIN_DIR", managed_dir) + + env = {"Path": "C:\\Windows\\System32"} + + wrap_mod._prepend_rtk_bin_to_path(env) + + assert env["Path"].split(os.pathsep)[0] == str(managed_dir) + assert "PATH" not in env + + +def test_prepend_rtk_bin_to_path_does_not_duplicate_windows_style_path_key( + monkeypatch: pytest.MonkeyPatch, +) -> None: + managed_dir = Path("/tmp/headroom-bin") + monkeypatch.setattr("headroom.rtk.RTK_BIN_DIR", managed_dir) + + env = {"Path": f"{managed_dir}{os.pathsep}C:\\Windows\\System32"} + + wrap_mod._prepend_rtk_bin_to_path(env) + + assert env["Path"] == f"{managed_dir}{os.pathsep}C:\\Windows\\System32" + assert env["Path"].split(os.pathsep).count(str(managed_dir)) == 1 + + # --------------------------------------------------------------------------- # _setup_context_tool_for_agent — all five branches: # 1. lean-ctx mode → calls _setup_lean_ctx_agent, returns None