"""Live-API smoke test. Runs only when ANTHROPIC_API_KEY is set in the env (or .env). Sends one real turn, verifies we get back a non-empty assistant text and usage counts. Marked ``real_api`` so it is excluded from the default suite — opt in with ``pytest -m real_api``. """ from __future__ import annotations import os import pytest from dotenv import dotenv_values from relay.anthropic_client import AnthropicClient from relay.config import REPO_ROOT def _api_key_available() -> str | None: env_values = dotenv_values(REPO_ROOT / ".env") return ( env_values.get("ANTHROPIC_API_KEY") or os.environ.get("ANTHROPIC_API_KEY") or "" ).strip() or None @pytest.mark.real_api @pytest.mark.skipif(_api_key_available() is None, reason="ANTHROPIC_API_KEY not configured") def test_real_round_trip_against_haiku() -> None: """One round-trip against the Haiku model — cheapest available, ~$0.0001 per call. Skips (rather than fails) on credit-balance errors so the test is honest about why it didn't run. Real authentication errors (401) still fail loudly. """ import anthropic api_key = _api_key_available() assert api_key is not None client = AnthropicClient( api_key=api_key, model="claude-haiku-4-5-20251001", max_output_tokens=64 ) try: result = client.send( system_prompt="You are a terse echo. Reply with exactly 'pong' and nothing else.", messages=[{"role": "user", "content": "ping"}], ) except anthropic.BadRequestError as exc: msg = str(exc).lower() if "credit balance" in msg or "billing" in msg: pytest.skip(f"Anthropic API key has no credit balance: {exc}") raise assert result.text.strip().lower() == "pong" assert result.input_tokens > 0 assert result.output_tokens > 0 assert result.estimated_cost_usd > 0