50 lines
1.9 KiB
Python
50 lines
1.9 KiB
Python
"""Fallback rebuilds retain the credential source, not its last token."""
|
|
from types import SimpleNamespace
|
|
|
|
import httpx
|
|
import pytest
|
|
from openai import OpenAI
|
|
|
|
from agent.client_lifecycle import _swap_fallback_clients
|
|
|
|
|
|
@pytest.mark.parametrize("mode", ["chat_completions", "codex_responses"])
|
|
@pytest.mark.parametrize("dynamic", [False, True])
|
|
def test_fallback_rebuild_preserves_rotating_and_static_credentials(mode, dynamic):
|
|
token = ["first-token"]
|
|
source = (lambda: token[0]) if dynamic else token[0]
|
|
captured = []
|
|
|
|
def respond(request):
|
|
captured.append(request.headers.get("Authorization"))
|
|
return httpx.Response(200, json={"id": "fixture", "choices": []})
|
|
|
|
client = OpenAI(api_key=source, base_url="http://localhost:1234/v1")
|
|
agent = SimpleNamespace()
|
|
_swap_fallback_clients(agent, client, "fixture", "fixture", str(client.base_url), mode)
|
|
rebuilt = OpenAI(**agent._client_kwargs, http_client=httpx.Client(transport=httpx.MockTransport(respond)))
|
|
try:
|
|
for value in ("first-token", "rotated-token"):
|
|
token[0] = value
|
|
rebuilt.chat.completions.create(model="fixture", messages=[])
|
|
expected = ["Bearer first-token", "Bearer rotated-token" if dynamic else "Bearer first-token"]
|
|
assert captured == expected
|
|
assert agent.api_key is source
|
|
finally:
|
|
client.close()
|
|
rebuilt.close()
|
|
|
|
|
|
def test_anthropic_fallback_keeps_callable_without_treating_it_as_oauth_text():
|
|
source = lambda: "fixture-token" # noqa: E731
|
|
client = OpenAI(api_key=source, base_url="http://localhost:1234/v1")
|
|
agent = SimpleNamespace()
|
|
try:
|
|
_swap_fallback_clients(agent, client, "anthropic", "fixture", str(client.base_url), "anthropic_messages")
|
|
assert agent.api_key is source
|
|
assert agent._anthropic_api_key is source
|
|
assert agent._is_anthropic_oauth is False
|
|
agent._anthropic_client.close()
|
|
finally:
|
|
client.close()
|