Skip to content

feat(completions): ensure prompt tokens are always calculated - #588

Merged
steebchen merged 6 commits into
mainfrom
cursor/ensure-prompt-tokens-are-always-calculated-d64b
Aug 8, 2025
Merged

steebchen merged 6 commits into
mainfrom
cursor/ensure-prompt-tokens-are-always-calculated-d64b

Conversation

@steebchen

@steebchen steebchen commented Aug 7, 2025 •

Copy link
Copy Markdown
Member

This pull request contains changes generated by Cursor background composer.

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling to ensure prompt token counts in usage information are never reported as zero, even when the provider returns zero.
    • Enhanced fallback and estimation logic to guarantee prompt token and total token counts are always at least one in both streaming and non-streaming responses.
  • Tests

    • Added new end-to-end and unit tests to verify correct prompt token calculation and fallback behavior in various scenarios, including edge cases.
  • Chores

    • Updated mock server to simulate cases where providers return zero prompt tokens for more robust testing.
  • Chores

    • Removed test skip flags from provider model definitions to reflect updated test status.

Co-authored-by: contact <contact@polarlights.llc>
@cursor

cursor Bot commented Aug 7, 2025

Copy link
Copy Markdown

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@coderabbitai

coderabbitai Bot commented Aug 7, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

This change set introduces robust fallback logic to ensure that prompt token counts in chat completion usage reporting are never zero, even if the underlying provider returns zero. It updates chat handling logic, enhances the mock server for testing, and adds comprehensive tests for both streaming and non-streaming scenarios, as well as for the internal token calculation logic.

Changes

Cohort / File(s) Change Summary
E2E & Streaming Token Count Tests
apps/gateway/src/api.e2e.ts
Adds two end-to-end tests verifying that prompt token counts in usage are never zero, for both streaming and non-streaming chat completions, even when the provider returns zero tokens.
Chat Token Usage Logic
apps/gateway/src/chat/chat.ts
Updates internal logic to enforce a minimum of one for prompt and total token counts in usage reporting, adds fallback estimation using message content length, and refines handling for streaming and provider-specific cases.
Prompt Token Calculation Unit Tests
apps/gateway/src/lib/prompt-tokens.spec.ts
Introduces a new test suite covering prompt token fallback calculation logic, ensuring minimum values and correct estimation when provider data is missing or zero.
Mock Server for Testing
apps/gateway/src/test-utils/mock-openai-server.ts
Enhances the mock OpenAI server to simulate cases where the provider returns zero prompt tokens, enabling realistic testing of fallback logic in the main code and tests.
Model Configuration Cleanup
packages/models/src/models/zai.ts
Removes "test": "skip" flags from provider objects in the zaiModels array without altering other model properties.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Gateway
    participant Provider

    Client->>Gateway: Send chat completion request (may trigger ZERO_TOKENS)
    Gateway->>Provider: Forward request
    Provider-->>Gateway: Respond with usage (possibly zero prompt_tokens)
    alt prompt_tokens is zero or missing
        Gateway->>Gateway: Estimate prompt_tokens via fallback logic
        Gateway->>Gateway: Ensure prompt_tokens >= 1
    end
    Gateway-->>Client: Respond with usage (prompt_tokens >= 1)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

A token here, a token there,
But zero? That just isn’t fair!
With fallback tricks and tests anew,
We count each prompt, as rabbits do.
Now every chat, both stream and not,
Will never leave a token spot
Uncounted in our bunny plot! 🐇✨

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1a1fe7 and 44670c5.

📒 Files selected for processing (1)
  • packages/models/src/models/zai.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/models/src/models/zai.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: e2e / run
  • GitHub Check: build / run
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/ensure-prompt-tokens-are-always-calculated-d64b

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (1)
apps/gateway/src/chat/chat.ts (1)

1013-1045: Same critical issues in duplicated code block

This block has the same undefined messages variable issue and needs the same fixes as mentioned above.

🧹 Nitpick comments (3)
apps/gateway/src/chat/chat.ts (3)

651-651: Simplify redundant fallback in prompt_tokens calculation

The expression Math.max(1, promptTokens || 1) is redundant. If promptTokens is falsy, it defaults to 1, making the Math.max(1, 1) unnecessary.

-					prompt_tokens: Math.max(1, promptTokens || 1),
+					prompt_tokens: Math.max(1, promptTokens || 0),

692-692: Simplify redundant fallback in prompt_tokens calculation (Anthropic)

Same issue as above - the expression Math.max(1, promptTokens || 1) has redundant fallback logic.

-					prompt_tokens: Math.max(1, promptTokens || 1),
+					prompt_tokens: Math.max(1, promptTokens || 0),

3032-3040: Improve readability of complex token calculations

The nested ternary operators make this code hard to read and maintain.

+ const finalPromptTokens = (promptTokens && promptTokens > 0) 
+   ? promptTokens 
+   : (calculatedPromptTokens || 1);
+ const finalCompletionTokens = completionTokens || calculatedCompletionTokens || 0;
+ const finalTotalTokens = totalTokens || calculatedTotalTokens || finalPromptTokens;
+
  usage: {
-   prompt_tokens: Math.max(1, Math.round(
-     (promptTokens && promptTokens > 0) ? promptTokens : calculatedPromptTokens || 1,
-   )),
-   completion_tokens: Math.round(
-     completionTokens || calculatedCompletionTokens || 0,
-   ),
-   total_tokens: Math.round(
-     totalTokens || calculatedTotalTokens || Math.max(1, (promptTokens && promptTokens > 0) ? promptTokens : calculatedPromptTokens || 1),
-   ),
+   prompt_tokens: Math.max(1, Math.round(finalPromptTokens)),
+   completion_tokens: Math.round(finalCompletionTokens),
+   total_tokens: Math.max(1, Math.round(finalTotalTokens)),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea446b1 and f730412.

📒 Files selected for processing (4)
  • apps/gateway/src/api.e2e.ts (1 hunks)
  • apps/gateway/src/chat/chat.ts (8 hunks)
  • apps/gateway/src/lib/prompt-tokens.spec.ts (1 hunks)
  • apps/gateway/src/test-utils/mock-openai-server.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

Use localStorage instead of cookies for client-side data persistence

Files:

  • apps/gateway/src/test-utils/mock-openai-server.ts
  • apps/gateway/src/chat/chat.ts
  • apps/gateway/src/lib/prompt-tokens.spec.ts
  • apps/gateway/src/api.e2e.ts
**/*.{js,ts}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.{js,ts}: Use drizzle with the latest object syntax for database operations
For read queries, always use db().query.<table>.findMany() or db().query.<table>.findFirst()

Files:

  • apps/gateway/src/test-utils/mock-openai-server.ts
  • apps/gateway/src/chat/chat.ts
  • apps/gateway/src/lib/prompt-tokens.spec.ts
  • apps/gateway/src/api.e2e.ts
{apps/api,apps/gateway,packages/db}/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

{apps/api,apps/gateway,packages/db}/**/*.ts: Use Drizzle ORM with latest object syntax for database operations
For reads, use db().query.<table>.findMany() or db().query.<table>.findFirst()

Files:

  • apps/gateway/src/test-utils/mock-openai-server.ts
  • apps/gateway/src/chat/chat.ts
  • apps/gateway/src/lib/prompt-tokens.spec.ts
  • apps/gateway/src/api.e2e.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/general.mdc)

Never use as any or : any in TypeScript files.

Files:

  • apps/gateway/src/test-utils/mock-openai-server.ts
  • apps/gateway/src/chat/chat.ts
  • apps/gateway/src/lib/prompt-tokens.spec.ts
  • apps/gateway/src/api.e2e.ts
🧠 Learnings (2)
📚 Learning: after adding features, make sure that the tests pass using `pnpm test:unit`...
Learnt from: CR
PR: theopenco/llmgateway#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-23T19:33:40.639Z
Learning: After adding features, make sure that the tests pass using `pnpm test:unit`

Applied to files:

  • apps/gateway/src/lib/prompt-tokens.spec.ts
  • apps/gateway/src/api.e2e.ts
📚 Learning: run `pnpm test:unit` and `pnpm test:e2e` after adding features...
Learnt from: CR
PR: theopenco/llmgateway#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-23T19:33:55.702Z
Learning: Run `pnpm test:unit` and `pnpm test:e2e` after adding features

Applied to files:

  • apps/gateway/src/api.e2e.ts
🧬 Code Graph Analysis (1)
apps/gateway/src/chat/chat.ts (1)
apps/ui/src/hooks/useChats.ts (1)
  • ChatMessage (16-22)
🪛 GitHub Check: generate / run
apps/gateway/src/chat/chat.ts

[warning] 973-973:
'error' is defined but never used


[failure] 973-973:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[warning] 956-956:
'error' is defined but never used


[failure] 956-956:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[failure] 1041-1041:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[warning] 1024-1024:
'error' is defined but never used


[failure] 1024-1024:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

apps/gateway/src/lib/prompt-tokens.spec.ts

[failure] 31-31:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 GitHub Check: lint / run
apps/gateway/src/chat/chat.ts

[warning] 973-973:
'error' is defined but never used


[failure] 973-973:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[warning] 956-956:
'error' is defined but never used


[failure] 956-956:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[failure] 1041-1041:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[warning] 1024-1024:
'error' is defined but never used


[failure] 1024-1024:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

apps/gateway/src/lib/prompt-tokens.spec.ts

[failure] 31-31:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 GitHub Check: autofix
apps/gateway/src/chat/chat.ts

[warning] 973-973:
'error' is defined but never used


[failure] 973-973:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[warning] 956-956:
'error' is defined but never used


[failure] 956-956:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[failure] 1041-1041:
'error' is defined but never used. Allowed unused caught errors must match /^_/u


[warning] 1024-1024:
'error' is defined but never used


[failure] 1024-1024:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

apps/gateway/src/lib/prompt-tokens.spec.ts

[failure] 31-31:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 ESLint
apps/gateway/src/chat/chat.ts

[error] 956-956: 'error' is defined but never used. Allowed unused caught errors must match /^_/u.

(no-unused-vars)


[error] 973-973: 'error' is defined but never used. Allowed unused caught errors must match /^_/u.

(no-unused-vars)


[error] 1024-1024: 'error' is defined but never used. Allowed unused caught errors must match /^_/u.

(no-unused-vars)


[error] 1041-1041: 'error' is defined but never used. Allowed unused caught errors must match /^_/u.

(no-unused-vars)

apps/gateway/src/lib/prompt-tokens.spec.ts

[error] 31-31: 'error' is defined but never used. Allowed unused caught errors must match /^_/u.

(no-unused-vars)

🪛 GitHub Actions: ci
apps/gateway/src/chat/chat.ts

[warning] 327-327: ESLint: '_e' is defined but never used (unused-imports/no-unused-vars)


[error] 956-956: ESLint: 'error' is defined but never used. Allowed unused caught errors must match /^_/u (no-unused-vars)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e / run
🔇 Additional comments (7)
apps/gateway/src/test-utils/mock-openai-server.ts (2)

56-59: LGTM! Consistent pattern for test scenario detection.

The implementation follows the same pattern as the existing error trigger logic and correctly detects messages containing "ZERO_TOKENS" for testing the zero prompt tokens scenario.


77-81: LGTM! Proper usage override for zero tokens testing.

The conditional usage override correctly simulates the scenario where a provider returns zero prompt tokens while maintaining realistic completion token counts. This supports the e2e tests for verifying fallback token calculation logic.

apps/gateway/src/lib/prompt-tokens.spec.ts (2)

3-44: LGTM! Comprehensive test coverage for prompt token calculation.

The test suite thoroughly covers the fallback logic scenarios:

  • Calculates tokens when provider returns 0
  • Preserves existing non-zero token counts
  • Uses realistic token estimation (character length / 4)
  • Ensures minimum fallback of 1 token

The test implementation correctly mirrors the expected production logic.


46-78: LGTM! Excellent edge case coverage.

The tests properly handle:

  • Minimum token guarantee regardless of input
  • Type safety with null/undefined values
  • Empty message arrays and content
  • Consistent Math.max(1, ...) pattern for minimum enforcement

This comprehensive coverage ensures robust token calculation behavior.

apps/gateway/src/api.e2e.ts (2)

994-1035: LGTM! Comprehensive non-streaming zero tokens test.

The test correctly:

  • Uses mock-token to trigger mock server behavior
  • Sends "ZERO_TOKENS" message to simulate provider returning 0 tokens
  • Verifies all usage fields exist and have correct types
  • Ensures prompt_tokens > 0 despite provider returning 0
  • Validates total_tokens consistency

This validates the core requirement that prompt tokens are never zero.


1037-1069: LGTM! Streaming zero tokens validation.

The streaming test properly:

  • Uses streaming request with ZERO_TOKENS trigger
  • Analyzes stream chunks to find usage information
  • Verifies prompt tokens are calculated and > 0 in streaming responses
  • Ensures type safety

This complements the non-streaming test to ensure complete coverage of both response modes.

apps/gateway/src/chat/chat.ts (1)

649-658: Good fix for ensuring non-zero prompt tokens

The additional check for finalPromptTokens === 0 ensures that zero prompt tokens trigger the fallback calculation, preventing zero values in usage reporting. This aligns well with the PR objectives.

Also applies to: 2688-2690

Comment thread apps/gateway/src/api.e2e.ts Outdated
Comment on lines 730 to -732
usage: data.usageMetadata
? {
prompt_tokens: data.usageMetadata.promptTokenCount || 0,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor repeated token normalization logic

The same token normalization pattern is repeated across multiple providers. Consider extracting this into a helper function to follow DRY principles.

Create a helper function:

function normalizeTokenUsage(
  promptTokens: number | null,
  completionTokens: number | null,
  totalTokens: number | null
) {
  const normalizedPrompt = Math.max(1, promptTokens || 0);
  const normalizedCompletion = completionTokens || 0;
  const normalizedTotal = Math.max(1, totalTokens || normalizedPrompt);
  
  return {
    prompt_tokens: normalizedPrompt,
    completion_tokens: normalizedCompletion,
    total_tokens: normalizedTotal,
  };
}

Then use it in all provider cases:

 usage: {
-  prompt_tokens: Math.max(1, promptTokens || 1),
-  completion_tokens: completionTokens || 0,
-  total_tokens: Math.max(1, totalTokens || Math.max(1, promptTokens || 1)),
+  ...normalizeTokenUsage(promptTokens, completionTokens, totalTokens),
   // ... other fields
 },
🤖 Prompt for AI Agents
In apps/gateway/src/chat/chat.ts around lines 730 to 732, the token
normalization logic is repeated for multiple providers. Extract this repeated
logic into a single helper function named normalizeTokenUsage that takes
promptTokens, completionTokens, and totalTokens as parameters and returns an
object with normalized prompt_tokens, completion_tokens, and total_tokens
values. Replace all instances of the repeated normalization code with calls to
this helper function to adhere to DRY principles and improve maintainability.

Comment thread apps/gateway/src/chat/chat.ts Outdated
Comment thread apps/gateway/src/chat/chat.ts Outdated
Comment on lines +956 to +959
(data.usageMetadata.promptTokenCount > 0
? data.usageMetadata.promptTokenCount
: (() => {
try {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix linting errors for unused error variables

Static analysis correctly identified unused error variables that don't match the required pattern /^_/u.

-} catch (error) {
+} catch (_error) {

Apply this fix to all four occurrences in the streaming chunk transformation logic.

Also applies to: 973-976, 1024-1027, 1041-1044

🧰 Tools
🪛 GitHub Check: generate / run

[warning] 956-956:
'error' is defined but never used


[failure] 956-956:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 GitHub Check: lint / run

[warning] 956-956:
'error' is defined but never used


[failure] 956-956:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 GitHub Check: autofix

[warning] 956-956:
'error' is defined but never used


[failure] 956-956:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 ESLint

[error] 956-956: 'error' is defined but never used. Allowed unused caught errors must match /^_/u.

(no-unused-vars)

🪛 GitHub Actions: ci

[error] 956-956: ESLint: 'error' is defined but never used. Allowed unused caught errors must match /^_/u (no-unused-vars)

🤖 Prompt for AI Agents
In apps/gateway/src/chat/chat.ts at lines 956-959 and similarly at 973-976,
1024-1027, and 1041-1044, the catch blocks declare an error variable that is
unused, causing linting errors. To fix this, rename each unused error variable
to start with an underscore (e.g., change "error" to "_error") to comply with
the linting rule for unused variables. This change should be applied
consistently to all four specified catch blocks.

Comment thread apps/gateway/src/lib/prompt-tokens.spec.ts Outdated
… missing

- Fixed Google providers to calculate prompt tokens when missing or 0
- Added helper function calculatePromptTokensFromMessages for better code reuse
- Updated transformToOpenAIFormat to ensure Math.max(1, promptTokens || 1)
- Fixed streaming responses to calculate tokens when needed
- Added comprehensive test coverage for token calculation logic
- Fixed TypeScript compilation errors with proper type annotations
- Tests verify tokens are always > 0 even when provider returns 0

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/gateway/src/chat/chat.ts (1)

651-653: Token normalization logic still needs refactoring

The same token normalization pattern is repeated across multiple providers. A previous reviewer already suggested extracting this into a helper function to follow DRY principles.

Also applies to: 692-694, 730-732

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f730412 and 3558f62.

📒 Files selected for processing (2)
  • apps/gateway/src/api.e2e.ts (1 hunks)
  • apps/gateway/src/chat/chat.ts (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/gateway/src/api.e2e.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

Use localStorage instead of cookies for client-side data persistence

Files:

  • apps/gateway/src/chat/chat.ts
**/*.{js,ts}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.{js,ts}: Use drizzle with the latest object syntax for database operations
For read queries, always use db().query.<table>.findMany() or db().query.<table>.findFirst()

Files:

  • apps/gateway/src/chat/chat.ts
{apps/api,apps/gateway,packages/db}/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

{apps/api,apps/gateway,packages/db}/**/*.ts: Use Drizzle ORM with latest object syntax for database operations
For reads, use db().query.<table>.findMany() or db().query.<table>.findFirst()

Files:

  • apps/gateway/src/chat/chat.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/general.mdc)

Never use as any or : any in TypeScript files.

Files:

  • apps/gateway/src/chat/chat.ts
🪛 ESLint
apps/gateway/src/chat/chat.ts

[error] 758-758: 'error' is defined but never used. Allowed unused caught errors must match /^_/u.

(no-unused-vars)

🪛 GitHub Check: generate / run
apps/gateway/src/chat/chat.ts

[warning] 758-758:
'error' is defined but never used


[failure] 758-758:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 GitHub Check: lint / run
apps/gateway/src/chat/chat.ts

[warning] 758-758:
'error' is defined but never used


[failure] 758-758:
'error' is defined but never used. Allowed unused caught errors must match /^_/u

🪛 GitHub Actions: ci
apps/gateway/src/chat/chat.ts

[warning] 327-327: ESLint: '_e' is defined but never used (unused-imports/no-unused-vars)


[error] 758-758: ESLint: 'error' is defined but never used. Allowed unused caught errors must match /^_/u (no-unused-vars)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e / run
🔇 Additional comments (5)
apps/gateway/src/chat/chat.ts (5)

767-767: Good fix for the undefined messages variable

Adding the messages parameter to the function signature correctly resolves the runtime error that would have occurred when referencing the undefined messages variable.


960-962: Excellent fallback logic for Google provider token handling

The implementation correctly uses the helper function to calculate prompt tokens when the provider returns zero or missing values, ensuring prompt tokens are never zero in streaming responses.

Also applies to: 966-969, 1005-1007, 1011-1014


2618-2618: Proper zero token handling in streaming

The condition change to include || finalPromptTokens === 0 ensures estimation is triggered even when providers return zero tokens, and the Math.max(1, ...) calls guarantee minimum token values in the final usage chunk.

Also applies to: 2657-2657, 2659-2659


3002-3004: Comprehensive token normalization with proper fallbacks

The logic correctly preserves original prompt tokens when valid (> 0) and falls back to calculated values when zero or missing, ensuring minimum token values are always maintained.

Also applies to: 3009-3009


2707-2707: Correct parameter passing for updated function signature

The messages parameter is properly passed to match the updated function signature.

Comment thread apps/gateway/src/chat/chat.ts
@steebchen steebchen changed the title Ensure prompt tokens are always calculated feat(completions): ensure prompt tokens are always calculated Aug 7, 2025
Updated authorization tokens in e2e tests to use real tokens instead of mock tokens for better accuracy during testing.
Cleaned up unused `test: "skip"` flags from Zai model providers, improving readability and maintaining consistent configuration.
@steebchen
steebchen added this pull request to the merge queue Aug 8, 2025
Merged via the queue into main with commit 92d0126 Aug 8, 2025
9 checks passed
@steebchen
steebchen deleted the cursor/ensure-prompt-tokens-are-always-calculated-d64b branch August 8, 2025 14:06
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