Skip to content

add a new unified route for count_tokens endpoint #1293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

narengogi
Copy link
Collaborator

@narengogi narengogi commented Aug 20, 2025

Tested by making request to count tokens (attached curls for reference)

**NOTE : ** Bedrock does not support counting tokens

vertex

curl --location 'http://localhost:8787/v1/messages/count_tokens' \
--header 'x-portkey-provider: vertex-ai' \
--header 'x-portkey-vertex-region: us-east5' \
--header 'x-portkey-vertex-service-account-json: "" \
--header 'Content-Type: application/json' \
--data-raw '{
    "model": "anthropic.claude-3-7-sonnet@20250219",
    "messages": [
        {
            "role": "user",
            "content": "What is the weather like in San Francisco?"
        }
    ]
}'

anthropic

curl --location 'http://localhost:8787/v1/messages/count_tokens' \
--header 'x-portkey-provider: anthropic' \
--header 'Authorization: sk-ant-api03' \
--header 'Content-Type: application/json' \
--data '{
      "model": "claude-opus-4-1-20250805",
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather in a given location",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city and state, e.g. San Francisco, CA"
              }
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "Whats the weather like in Chennai?"
        }
      ]
    }'

@narengogi narengogi requested review from roh26it and VisargD August 20, 2025 07:40
Copy link

Code Quality new feature Security Enhancement Reliability

Description

Summary By MatterAI MatterAI logo

🔄 What Changed

A new unified /v1/messages/count_tokens route and its corresponding handler (messagesCountTokensHandler.ts) have been introduced. This handler is responsible for processing incoming token counting requests, constructing configuration from request headers, and recursively attempting to forward these requests to appropriate AI providers (Anthropic, Google Vertex AI). The necessary provider configurations (anthropic/api.ts, anthropic/index.ts, google-vertex-ai/api.ts, google-vertex-ai/index.ts, google-vertex-ai/messagesCountTokens.ts) and the MappedFunctions type (types.ts) have been updated to support this new functionality.

🔍 Impact of the Change

This change adds a dedicated and standardized endpoint for token counting, significantly enhancing the gateway's capabilities by providing a consistent method to estimate token usage across various AI models. It centralizes the token counting logic, which improves maintainability and simplifies future integrations with additional providers.

📁 Total Files Changed

  • src/handlers/messagesCountTokensHandler.ts: New handler for processing token count requests.
  • src/index.ts: Registers the new /v1/messages/count_tokens API route.
  • src/providers/anthropic/api.ts: Extends API path mapping for messagesCountTokens.
  • src/providers/anthropic/index.ts: Updates Anthropic provider configuration to include messagesCountTokens.
  • src/providers/google-vertex-ai/api.ts: Extends API path mapping for messagesCountTokens.
  • src/providers/google-vertex-ai/index.ts: Updates Google Vertex AI provider configuration to include messagesCountTokens.
  • src/providers/google-vertex-ai/messagesCountTokens.ts: New configuration for Google Vertex AI token counting.
  • src/providers/types.ts: Updates MappedFunctions type to include messagesCountTokens.

🧪 Test Added

N/A

🔒Security Vulnerabilities

Potential for unvalidated input in messagesCountTokensHandler before forwarding to external services, which could lead to unexpected behavior or vulnerabilities if the request payload is not properly sanitized.

Motivation

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)

How Has This Been Tested?

  • Unit Tests
  • Integration Tests
  • Manual Testing

Screenshots (if applicable)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Related Issues

.

Tip

Quality Recommendations

  1. Implement robust input validation for the request body within messagesCountTokensHandler to prevent malformed requests or potential injection issues before forwarding to external providers.

  2. Add dedicated unit and integration tests for the new messagesCountTokensHandler and the /v1/messages/count_tokens route to ensure correct functionality and error handling.

  3. Enhance error logging in messagesCountTokensHandler to include more specific details about the error, such as the original request payload (sanitized), target provider, and full error stack, for improved debugging.

Tanka Poem ♫

New route takes flight,
Tokens counted, swift and true,
Data flows with grace.
AI's wisdom, now measured,
Efficiency's sweet embrace. ✨

Sequence Diagram

sequenceDiagram
    participant U as User
    participant HonoApp as Hono App
    participant MCH as MessagesCountTokensHandler
    participant HU as HandlerUtils
    participant EAP as External AI Provider

    U->>HonoApp: POST /v1/messages/count_tokens (requestBody, headers)
    Note over HonoApp: Route matched

    HonoApp->>MCH: handle(c: Context)
    MCH->>MCH: Parse request body (await c.req.json())
    MCH->>MCH: Extract raw headers (Object.fromEntries(c.req.raw.headers))

    MCH->>HU: constructConfigFromRequestHeaders(requestHeaders)
    HU-->>MCH: camelCaseConfig

    MCH->>HU: tryTargetsRecursively(c, camelCaseConfig, request, requestHeaders, 'messagesCountTokens', 'POST', 'config')
    Note over HU: Selects provider based on config

    HU->>EAP: POST /messages/count_tokens (or provider-specific endpoint)
    EAP-->>HU: tokenCountResponse

    HU-->>MCH: tryTargetsResponse
    MCH-->>HonoApp: tryTargetsResponse
    HonoApp-->>U: tokenCountResponse

    alt Error Handling
        MCH->>MCH: catch (err: any)
        Note over MCH: Log error: console.log('messagesCountTokens error', err.message)
        MCH-->>HonoApp: Error Response (status: 400/500, message)
        HonoApp-->>U: Error Response
    end
Loading

Copy link

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code quality is good with proper error handling and consistent patterns. Found minor documentation mismatch and potential optimization opportunity.

Comment on lines +8 to +15
/**
* Handles the '/messages' API request by selecting the appropriate provider(s) and making the request to them.
*
* @param {Context} c - The Cloudflare Worker context.
* @returns {Promise<Response>} - The response from the provider.
* @throws Will throw an error if no provider options can be determined or if the request to the provider(s) fails.
* @throws Will throw an 500 error if the handler fails due to some reasons
*/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Documentation Gap

Issue: JSDoc comment describes '/messages' API but function handles '/messages/count_tokens' endpoint
Fix: Update documentation to match actual functionality
Impact: Prevents developer confusion about handler purpose

Suggested change
/**
* Handles the '/messages' API request by selecting the appropriate provider(s) and making the request to them.
*
* @param {Context} c - The Cloudflare Worker context.
* @returns {Promise<Response>} - The response from the provider.
* @throws Will throw an error if no provider options can be determined or if the request to the provider(s) fails.
* @throws Will throw an 500 error if the handler fails due to some reasons
*/
/**
* Handles the '/messages/count_tokens' API request by selecting the appropriate provider(s) and making the request to them.
*
* @param {Context} c - The Cloudflare Worker context.
* @returns {Promise<Response>} - The response from the provider.
* @throws Will throw an error if no provider options can be determined or if the request to the provider(s) fails.
* @throws Will throw an 500 error if the handler fails due to some reasons
*/

): Promise<Response> {
try {
let request = await c.req.json();
let requestHeaders = Object.fromEntries(c.req.raw.headers);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚡️ Performance Improvement

Issue: Object.fromEntries creates unnecessary object copy when headers are already iterable
Fix: Pass headers directly to constructConfigFromRequestHeaders if it accepts Headers object
Impact: Reduces object creation overhead and improves memory efficiency

Suggested change
let requestHeaders = Object.fromEntries(c.req.raw.headers);
let requestHeaders = c.req.raw.headers;

Copy link
Collaborator

@roh26it roh26it left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have snitch tests for this? The PR looks good to me. The 2 comments from Matter seem valid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants