mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-04-28 11:30:03 +00:00
Phase 7 - Optimization handlers: - Create api/optimization_handlers.py with try_prefix_detection, try_quota_mock, try_title_skip, try_suggestion_skip, try_filepath_mock - Add try_optimizations() that runs handlers in order - Refactor routes.create_message to use try_optimizations() - Update test_routes_optimizations patch targets Phase 8 - Request utils split: - Create api/detection.py: is_quota_check_request, is_title_generation_request, is_prefix_detection_request, is_suggestion_mode_request, is_filepath_extraction_request - Create api/command_utils.py: extract_command_prefix, extract_filepaths_from_command - Slim request_utils.py to get_token_count + re-exports for backward compat Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>
93 lines
3 KiB
Python
93 lines
3 KiB
Python
"""Request utility functions for API route handlers.
|
|
|
|
Contains token counting and re-exports detection/command utilities.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
from typing import List, Optional, Union
|
|
|
|
import tiktoken
|
|
|
|
from .models.anthropic import MessagesRequest
|
|
from .detection import (
|
|
is_quota_check_request,
|
|
is_title_generation_request,
|
|
is_prefix_detection_request,
|
|
is_suggestion_mode_request,
|
|
is_filepath_extraction_request,
|
|
)
|
|
from .command_utils import extract_command_prefix, extract_filepaths_from_command
|
|
|
|
logger = logging.getLogger(__name__)
|
|
ENCODER = tiktoken.get_encoding("cl100k_base")
|
|
|
|
__all__ = [
|
|
"is_quota_check_request",
|
|
"is_title_generation_request",
|
|
"is_prefix_detection_request",
|
|
"is_suggestion_mode_request",
|
|
"is_filepath_extraction_request",
|
|
"extract_command_prefix",
|
|
"extract_filepaths_from_command",
|
|
"get_token_count",
|
|
]
|
|
|
|
|
|
def get_token_count(
|
|
messages: List,
|
|
system: Optional[Union[str, List]] = None,
|
|
tools: Optional[List] = None,
|
|
) -> int:
|
|
"""Estimate token count for a request.
|
|
|
|
Uses tiktoken cl100k_base encoding to estimate token usage.
|
|
Includes system prompt, messages, tools, and per-message overhead.
|
|
"""
|
|
total_tokens = 0
|
|
|
|
if system:
|
|
if isinstance(system, str):
|
|
total_tokens += len(ENCODER.encode(system))
|
|
elif isinstance(system, list):
|
|
for block in system:
|
|
if hasattr(block, "text"):
|
|
total_tokens += len(ENCODER.encode(block.text))
|
|
|
|
for msg in messages:
|
|
if isinstance(msg.content, str):
|
|
total_tokens += len(ENCODER.encode(msg.content))
|
|
elif isinstance(msg.content, list):
|
|
for block in msg.content:
|
|
b_type = getattr(block, "type", None)
|
|
|
|
if b_type == "text":
|
|
total_tokens += len(ENCODER.encode(getattr(block, "text", "")))
|
|
elif b_type == "thinking":
|
|
total_tokens += len(ENCODER.encode(getattr(block, "thinking", "")))
|
|
elif b_type == "tool_use":
|
|
name = getattr(block, "name", "")
|
|
inp = getattr(block, "input", {})
|
|
total_tokens += len(ENCODER.encode(name))
|
|
total_tokens += len(ENCODER.encode(json.dumps(inp)))
|
|
total_tokens += 10
|
|
elif b_type == "tool_result":
|
|
content = getattr(block, "content", "")
|
|
if isinstance(content, str):
|
|
total_tokens += len(ENCODER.encode(content))
|
|
else:
|
|
total_tokens += len(ENCODER.encode(json.dumps(content)))
|
|
total_tokens += 5
|
|
|
|
if tools:
|
|
for tool in tools:
|
|
tool_str = (
|
|
tool.name + (tool.description or "") + json.dumps(tool.input_schema)
|
|
)
|
|
total_tokens += len(ENCODER.encode(tool_str))
|
|
|
|
total_tokens += len(messages) * 3
|
|
if tools:
|
|
total_tokens += len(tools) * 5
|
|
|
|
return max(1, total_tokens)
|