fix(agent): preserve copilot routed headers

This commit is contained in:
konsisumer 2026-06-04 17:20:58 +02:00 committed by Teknium
parent b6a4638b6d
commit 3e354b61db
4 changed files with 53 additions and 0 deletions

View file

@ -808,6 +808,8 @@ def init_agent(
# _custom_headers; older/mocked clients may expose
# _default_headers instead.
_routed_headers = getattr(_routed_client, "_custom_headers", None)
if not _routed_headers:
_routed_headers = getattr(_routed_client, "default_headers", None)
if not _routed_headers:
_routed_headers = getattr(_routed_client, "_default_headers", None)
if _routed_headers:
@ -861,6 +863,8 @@ def init_agent(
if _provider_timeout is not None:
client_kwargs["timeout"] = _provider_timeout
_fb_headers = getattr(_fb_client, "_custom_headers", None)
if not _fb_headers:
_fb_headers = getattr(_fb_client, "default_headers", None)
if not _fb_headers:
_fb_headers = getattr(_fb_client, "_default_headers", None)
if _fb_headers:

View file

@ -3557,6 +3557,9 @@ class AIAgent:
import httpx as _httpx
import socket as _socket
if "api.githubcopilot.com" in str(base_url or "").lower():
return _httpx.Client()
_sock_opts = [(_socket.SOL_SOCKET, _socket.SO_KEEPALIVE, 1)]
if hasattr(_socket, "TCP_KEEPIDLE"):
_sock_opts.append((_socket.IPPROTO_TCP, _socket.TCP_KEEPIDLE, 30))

View file

@ -145,6 +145,27 @@ def test_create_openai_client_no_proxy_when_env_unset(mock_openai, monkeypatch):
http_client.close()
@patch("run_agent.OpenAI")
def test_create_openai_client_uses_plain_httpx_client_for_copilot(mock_openai, monkeypatch):
"""Copilot Claude chat-completions rejects the custom socket-options transport."""
for key in ("HTTPS_PROXY", "HTTP_PROXY", "ALL_PROXY",
"https_proxy", "http_proxy", "all_proxy"):
monkeypatch.delenv(key, raising=False)
agent = _make_agent()
kwargs = {
"api_key": "test-key",
"base_url": "https://api.githubcopilot.com",
}
agent._create_openai_client(kwargs, reason="test", shared=False)
forwarded = mock_openai.call_args.kwargs
http_client = _extract_http_client(forwarded)
assert isinstance(http_client, httpx.Client)
assert getattr(http_client._transport._pool, "_socket_options", None) is None
http_client.close()
def test_get_proxy_for_base_url_returns_none_when_host_bypassed(monkeypatch):
"""NO_PROXY must suppress the proxy for matching base_urls.

View file

@ -109,6 +109,31 @@ def test_routed_client_preserves_openai_sdk_custom_headers(mock_openai):
assert headers["X-BILLING-INVOKE-ORIGIN"] == "HermesAgent"
@patch("run_agent.OpenAI")
def test_routed_client_preserves_openai_sdk_default_headers(mock_openai):
mock_openai.return_value = MagicMock()
routed_client = SimpleNamespace(
api_key="test-key",
base_url="https://api.githubcopilot.com",
default_headers={"copilot-integration-id": "vscode-chat"},
)
with patch("agent.auxiliary_client.resolve_provider_client", return_value=(
routed_client,
"claude-opus-4.7",
)):
agent = AIAgent(
provider="copilot",
model="claude-opus-4.7",
quiet_mode=True,
skip_context_files=True,
skip_memory=True,
)
headers = agent._client_kwargs["default_headers"]
assert headers["copilot-integration-id"] == "vscode-chat"
@patch("run_agent.OpenAI")
def test_gmi_base_url_picks_up_profile_user_agent(mock_openai):
"""GMI declares User-Agent on its ProviderProfile.default_headers.