litellm/tests/claude_code/count_tokens/test_vertex_ai.py
mateo-berri 184af8776b chore(claude_code): commit remaining deployed working-tree state
Everything under tests/claude_code/ that the daily cron run shims into
the stable-tag worktree but that existed only on the cron VM's disk:
check_regressions.py (required by run_daily.sh's auto-merge gate, was
untracked), the count_tokens and long_context_1m test refinements,
http_probe/matrix_builder updates, and the cron_vm README + env
example matching the deployed direct-publish flow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 20:56:48 +00:00

104 lines
3.5 KiB
Python

"""count_tokens x Vertex AI.
HTTP-probe row. Unlike the CLI-driven rows, this test never invokes
the `claude` CLI: it `POST`s directly to
`{proxy}/v1/messages/count_tokens` for each Claude tier and asserts
the response is shaped `{"input_tokens": <positive int>}`.
The (feature, provider) for this cell is inferred from the file path by
`tests/claude_code/conftest.py`:
tests/claude_code/count_tokens/test_vertex_ai.py
^^^^^^^^^^^^ ^^^^^^^^^
feature_id provider
Why HTTP probe instead of CLI:
Claude Code calls `count_tokens` internally to compute budget /
context-window usage display, but the result is consumed by the CLI
in-process and never appears in stream-json events. There is no CLI
flag that emits the count to stdout in a way our existing
stream-json parser can pick up, so we can't test the endpoint round
trip through the CLI surface.
The proxy *is* expected to expose `/v1/messages/count_tokens` for
every Claude-style provider it routes to -- LiteLLM has historically
had provider-specific bugs in this endpoint (Vertex AI `count_tokens`
returned 400 to proxy gateways; see Claude Code release notes 2.1.121).
Treating it as a matrix row keeps regressions in the cron's daily
diff.
The cell goes red if *any* tier's probe fails the minimal shape
check; the matrix's per-cell aggregator handles that automatically.
Three tiers run sequentially because count_tokens is cheap (<100ms
per request typical) and the parallelization that matters for the
CLI rows isn't useful here.
"""
from __future__ import annotations
import os
import pytest
from tests.claude_code.http_probe import (
assert_count_tokens_shape,
count_tokens_unsupported_reason,
probe_count_tokens,
)
PROXY_BASE_URL_ENV = "LITELLM_PROXY_BASE_URL"
PROXY_API_KEY_ENV = "LITELLM_PROXY_API_KEY"
VERTEX_AI_MODELS = [
"claude-haiku-4-5-vertex",
"claude-sonnet-4-6-vertex",
"claude-opus-4-7-vertex",
]
def test_count_tokens_vertex_ai(compat_result):
"""Probe `/v1/messages/count_tokens` for each Vertex AI tier and
assert the response shape."""
base_url = os.environ.get(PROXY_BASE_URL_ENV)
api_key = os.environ.get(PROXY_API_KEY_ENV)
if not base_url or not api_key:
compat_result.set(
{
"status": "fail",
"error": (
f"missing required env: set {PROXY_BASE_URL_ENV} and "
f"{PROXY_API_KEY_ENV} to point at a running LiteLLM proxy"
),
}
)
pytest.fail(
f"{PROXY_BASE_URL_ENV} / {PROXY_API_KEY_ENV} not configured",
pytrace=False,
)
failures = []
for model in VERTEX_AI_MODELS:
result = probe_count_tokens(base_url=base_url, api_key=api_key, model=model)
unsupported = count_tokens_unsupported_reason(result)
if unsupported is not None:
compat_result.add(
{
"status": "not_applicable",
"reason": f"[{model}] {unsupported}",
}
)
continue
shape_error = assert_count_tokens_shape(result)
if shape_error is not None:
error = f"[{model}] count_tokens probe failed: {shape_error}"
compat_result.add({"status": "fail", "error": error})
failures.append(error)
continue
compat_result.add({"status": "pass"})
if failures:
pytest.fail("; ".join(failures), pytrace=False)