mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
`.gitattributes` declares `*.py text eol=lf` and `*.sh text eol=lf`, but 74 files (73 .py, 1 .sh) are stored in the index with CRLF line endings, violating that contract. Every macOS/Linux clone reports these files as "modified" on fresh checkout because git's diff engine sees the stored bytes don't match the attribute contract, even though the working tree and index match byte-for-byte. Running `git add --renormalize .` rewrites each affected blob so the stored form matches the attribute declaration. No semantic changes — every affected file's diff is "N insertions, N deletions" with inserts and deletes being the same lines modulo line endings. Follow-up commit adds `.git-blame-ignore-revs` so `git blame` / GitHub blame skip this mechanical commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
124 lines
4.7 KiB
Python
124 lines
4.7 KiB
Python
from __future__ import annotations
|
|
|
|
import io
|
|
import json
|
|
import urllib.error
|
|
from unittest.mock import patch
|
|
|
|
import click
|
|
import pytest
|
|
|
|
from headroom.providers.copilot.wrap import (
|
|
build_launch_env,
|
|
detect_running_proxy_backend,
|
|
model_configured,
|
|
provider_key_source,
|
|
query_proxy_config,
|
|
resolve_provider_type,
|
|
validate_configuration,
|
|
)
|
|
|
|
|
|
def test_query_proxy_config_handles_success_and_invalid_payload() -> None:
|
|
payload = io.BytesIO(json.dumps({"config": {"backend": "anyllm"}}).encode("utf-8"))
|
|
payload_missing = io.BytesIO(json.dumps({"status": "ok"}).encode("utf-8"))
|
|
|
|
with patch("urllib.request.urlopen", return_value=payload):
|
|
assert query_proxy_config(8787) == {"backend": "anyllm"}
|
|
with patch("urllib.request.urlopen", return_value=payload_missing):
|
|
assert query_proxy_config(8787) is None
|
|
with patch("urllib.request.urlopen", side_effect=urllib.error.URLError("down")):
|
|
assert query_proxy_config(8787) is None
|
|
|
|
|
|
def test_detect_running_proxy_backend_requires_string_backend(monkeypatch) -> None:
|
|
monkeypatch.setattr(
|
|
"headroom.providers.copilot.wrap.query_proxy_config",
|
|
lambda port: {"backend": 123} if port == 8787 else None,
|
|
)
|
|
|
|
assert detect_running_proxy_backend(8787) is None
|
|
assert detect_running_proxy_backend(9999) is None
|
|
|
|
|
|
def test_resolve_provider_type_prefers_explicit_and_env() -> None:
|
|
assert resolve_provider_type("anthropic", "openai") == "openai"
|
|
assert resolve_provider_type(None, "auto", {"HEADROOM_BACKEND": "anthropic"}) == "anthropic"
|
|
assert resolve_provider_type(None, "auto", {"HEADROOM_BACKEND": "anyllm"}) == "openai"
|
|
|
|
|
|
def test_validate_configuration_accepts_supported_combinations() -> None:
|
|
validate_configuration(provider_type="openai", wire_api="responses", backend=None)
|
|
validate_configuration(provider_type="openai", wire_api="completions", backend="anyllm")
|
|
|
|
|
|
def test_validate_configuration_rejects_invalid_combinations() -> None:
|
|
with pytest.raises(click.ClickException, match="--wire-api is only valid"):
|
|
validate_configuration(provider_type="anthropic", wire_api="responses", backend=None)
|
|
|
|
with pytest.raises(click.ClickException, match="not supported with translated backends"):
|
|
validate_configuration(provider_type="openai", wire_api="responses", backend="anyllm")
|
|
|
|
|
|
def test_provider_key_source_and_build_launch_env_cover_anthropic_and_openai() -> None:
|
|
assert provider_key_source("anthropic") == "ANTHROPIC_API_KEY"
|
|
assert provider_key_source("openai") == "OPENAI_API_KEY"
|
|
|
|
anthropic_env, anthropic_lines = build_launch_env(
|
|
port=8787,
|
|
provider_type="anthropic",
|
|
wire_api="responses",
|
|
environ={
|
|
"ANTHROPIC_API_KEY": "sk-ant-test",
|
|
"COPILOT_PROVIDER_WIRE_API": "stale",
|
|
},
|
|
)
|
|
openai_env, openai_lines = build_launch_env(
|
|
port=8787,
|
|
provider_type="openai",
|
|
wire_api=None,
|
|
environ={"OPENAI_API_KEY": "sk-proj-test"},
|
|
)
|
|
|
|
assert anthropic_env["COPILOT_PROVIDER_TYPE"] == "anthropic"
|
|
assert anthropic_env["COPILOT_PROVIDER_BASE_URL"] == "http://127.0.0.1:8787"
|
|
assert anthropic_env["COPILOT_PROVIDER_API_KEY"] == "sk-ant-test"
|
|
assert "COPILOT_PROVIDER_WIRE_API" not in anthropic_env
|
|
assert anthropic_lines == [
|
|
"COPILOT_PROVIDER_TYPE=anthropic",
|
|
"COPILOT_PROVIDER_BASE_URL=http://127.0.0.1:8787",
|
|
]
|
|
|
|
assert openai_env["COPILOT_PROVIDER_TYPE"] == "openai"
|
|
assert openai_env["COPILOT_PROVIDER_BASE_URL"] == "http://127.0.0.1:8787/v1"
|
|
assert openai_env["COPILOT_PROVIDER_WIRE_API"] == "completions"
|
|
assert openai_env["COPILOT_PROVIDER_API_KEY"] == "sk-proj-test"
|
|
assert openai_lines[-1] == "COPILOT_PROVIDER_WIRE_API=completions"
|
|
|
|
|
|
def test_build_launch_env_keeps_existing_provider_key_and_allows_missing_source_key() -> None:
|
|
existing_env, _existing_lines = build_launch_env(
|
|
port=8787,
|
|
provider_type="openai",
|
|
wire_api="responses",
|
|
environ={
|
|
"COPILOT_PROVIDER_API_KEY": "existing-provider-key",
|
|
"OPENAI_API_KEY": "sk-proj-test",
|
|
},
|
|
)
|
|
missing_env, _missing_lines = build_launch_env(
|
|
port=8787,
|
|
provider_type="openai",
|
|
wire_api="responses",
|
|
environ={},
|
|
)
|
|
|
|
assert existing_env["COPILOT_PROVIDER_API_KEY"] == "existing-provider-key"
|
|
assert "COPILOT_PROVIDER_API_KEY" not in missing_env
|
|
|
|
|
|
def test_model_configured_detects_env_and_cli_variants() -> None:
|
|
assert model_configured((), {"COPILOT_MODEL": "gpt-4o"}) is True
|
|
assert model_configured(("--model", "gpt-4o"), {}) is True
|
|
assert model_configured(("--model=gpt-4o",), {}) is True
|
|
assert model_configured(("--other", "value"), {}) is False
|