Skip to content

Commit b7b5d07

Browse files
committed
fix(token-count): include Antigravity preprompt tokens in count
Token counting endpoints (/v1/token-count and /v1/messages/count_tokens) were returning inaccurate counts because they didn't include the Antigravity preprompts that get injected during actual API calls. - Add get_antigravity_preprompt_text() helper to expose preprompt text - Update RotatingClient.token_count() to add preprompt tokens for Antigravity provider models Signed-off-by: Moeeze Hassan <[email protected]>
1 parent 67ffea5 commit b7b5d07

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

src/rotator_library/client.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2464,21 +2464,46 @@ def aembedding(
24642464
)
24652465

24662466
def token_count(self, **kwargs) -> int:
2467-
"""Calculates the number of tokens for a given text or list of messages."""
2467+
"""Calculates the number of tokens for a given text or list of messages.
2468+
2469+
For Antigravity provider models, this also includes the preprompt tokens
2470+
that get injected during actual API calls (agent instruction + identity override).
2471+
This ensures token counts match actual usage.
2472+
"""
24682473
kwargs = self._convert_model_params(**kwargs)
24692474
model = kwargs.get("model")
24702475
text = kwargs.get("text")
24712476
messages = kwargs.get("messages")
24722477

24732478
if not model:
24742479
raise ValueError("'model' is a required parameter.")
2480+
2481+
# Calculate base token count
24752482
if messages:
2476-
return token_counter(model=model, messages=messages)
2483+
base_count = token_counter(model=model, messages=messages)
24772484
elif text:
2478-
return token_counter(model=model, text=text)
2485+
base_count = token_counter(model=model, text=text)
24792486
else:
24802487
raise ValueError("Either 'text' or 'messages' must be provided.")
24812488

2489+
# Add preprompt tokens for Antigravity provider
2490+
# The Antigravity provider injects system instructions during actual API calls,
2491+
# so we need to account for those tokens in the count
2492+
provider = model.split("/")[0] if "/" in model else ""
2493+
if provider == "antigravity":
2494+
try:
2495+
from .providers.antigravity_provider import get_antigravity_preprompt_text
2496+
2497+
preprompt_text = get_antigravity_preprompt_text()
2498+
if preprompt_text:
2499+
preprompt_tokens = token_counter(model=model, text=preprompt_text)
2500+
base_count += preprompt_tokens
2501+
except ImportError:
2502+
# Provider not available, skip preprompt token counting
2503+
pass
2504+
2505+
return base_count
2506+
24822507
async def get_available_models(self, provider: str) -> List[str]:
24832508
"""Returns a list of available models for a specific provider, with caching."""
24842509
lib_logger.info(f"Getting available models for provider: {provider}")

src/rotator_library/providers/antigravity_provider.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,42 @@ def _is_valid_thinking_signature(signature):
449449
# =============================================================================
450450

451451

452+
def get_antigravity_preprompt_text() -> str:
453+
"""
454+
Get the combined Antigravity preprompt text that gets injected into requests.
455+
456+
This function returns the exact text that gets prepended to system instructions
457+
during actual API calls. It respects the current configuration settings:
458+
- PREPEND_INSTRUCTION: Whether to include any preprompt at all
459+
- USE_SHORT_ANTIGRAVITY_PROMPTS: Whether to use short or full versions
460+
- INJECT_IDENTITY_OVERRIDE: Whether to include the identity override
461+
462+
This is useful for accurate token counting - the token count endpoints should
463+
include these preprompts to match what actually gets sent to the API.
464+
465+
Returns:
466+
The combined preprompt text, or empty string if prepending is disabled.
467+
"""
468+
if not PREPEND_INSTRUCTION:
469+
return ""
470+
471+
# Choose prompt versions based on USE_SHORT_ANTIGRAVITY_PROMPTS setting
472+
if USE_SHORT_ANTIGRAVITY_PROMPTS:
473+
agent_instruction = ANTIGRAVITY_AGENT_SYSTEM_INSTRUCTION_SHORT
474+
override_instruction = ANTIGRAVITY_IDENTITY_OVERRIDE_INSTRUCTION_SHORT
475+
else:
476+
agent_instruction = ANTIGRAVITY_AGENT_SYSTEM_INSTRUCTION
477+
override_instruction = ANTIGRAVITY_IDENTITY_OVERRIDE_INSTRUCTION
478+
479+
# Build the combined preprompt
480+
parts = [agent_instruction]
481+
482+
if INJECT_IDENTITY_OVERRIDE:
483+
parts.append(override_instruction)
484+
485+
return "\n".join(parts)
486+
487+
452488
def _sanitize_headers(headers: Dict[str, str]) -> Dict[str, str]:
453489
"""
454490
Strip identifiable client headers for privacy/security.

0 commit comments

Comments
 (0)