Skip to content

fix(server): usage prices long-context requests at above-tier rates - #25430

Open
juliusmarminge wants to merge 2 commits into
mainfrom
fix/issue-25414
Open

juliusmarminge wants to merge 2 commits into
mainfrom
fix/issue-25414

Conversation

@juliusmarminge

Copy link
Copy Markdown
Member

Problem

Usage estimated requests above LiteLLM's long-context thresholds at base rates. A Codex rollout with 300,000 input tokens (280,000 cached) and 1,000 output tokens on gpt-6-sol cost $0.106 instead of $0.207; Claude's 100K tier and priority long-context rates were also ignored.

Change

Parse LiteLLM's context tiers and select the rate from each request's uncached, cached, and cache-creation input total before aggregating costs. Apply the same tier to category costs, cache savings, and speed premiums. Existing raw rate documents and per-request scan caches are repriced on read; custom price overrides remain flat.

Scope and approval

Fixes #25414

Triaged bug via the automated issue flow. GitCafe: #25414. Reproduced in the real web app against an explicitly isolated server home. Scope is server pricing and its regression tests.

Verification

  • Red tests first: Codex $0.106 versus $0.207, Claude above 100K, and priority above 272K failed on main. Reproduction transcript.
  • Focused changed-file tests: 68 passed across UsageService, usagePricing, and usageAggregation; covers threshold boundaries, mixed short/long requests, overrides, missing rates, and persisted cache restoration.
  • Real server/browser, same rollout and isolated --home-dir: cost $0.106 → $0.207; 301K processed tokens, 280K cached, 20K uncached, and 1K output unchanged. After categories: input $0.080, cache read $0.112, output $0.015. Before response · After response · Reproduction seed.
  • Evidence index; server-only change, capture matrix [], independently audited sufficient.
  • vp run check:changed: format, lint, GraphQL validation, and focused tests passed. The overall run failed on a stale local TypeScript executable and knip's mobile Metro configuration loader/unrelated unused export. A retry was stopped when VM load reached 25. Complete check output.
  • After removing stale generated compiler shims, vp run --filter t3 typecheck passed (exit 0). The overall changed-file run still has no complete green result.
  • Web, desktop, mobile, and remote clients consume the same server estimate; no client or wire changes. No platform-specific verification is needed for this server calculation.

Models: GPT-6.1 Sol through Codex and Claude Opus 5.5 through Claude Code, in T3 Code.

juliusmarminge and others added 2 commits October 26, 2026 09:10
…(red)

Failing tests for #25414: a Codex gpt-6-sol turn above
272K prompt tokens, a Claude prompt above 100K, and a priority request
above 272K are all priced at base rates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Requests whose prompt (input + cache read + cache write) exceeds a
model's LiteLLM *_above_<N>k_tokens threshold now bill at that tier,
including its _priority/_ultrafast variants. The tier is chosen per
record, so many small requests stay at base rates. Fields a tier omits
fall back to base rates; overrides and untiered models are unchanged.

Fixes #25414

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 26, 2026
!sameTokenRates(fast, b.fast ?? fast) ||
!sameTokenRates(ultrafast, b.ultrafast ?? ultrafast)
!sameTokenRates(ultrafast, b.ultrafast ?? ultrafast) ||
(b.contextTiers.length > 0 && !sameContextTiers(contextTiers, b.contextTiers))

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.

🟡 Medium usage/usagePricing.ts:214

A bare alias is rejected even when both providers agree on its standard context-tier price, so priceUsage reports short standard requests as unpriced. sameContextTiers treats a missing fast or ultrafast rate as a conflict instead of filling it from the other matching tier; merge those missing speed variants before checking for conflicts.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/usage/usagePricing.ts around line 214:

A bare alias is rejected even when both providers agree on its standard context-tier price, so `priceUsage` reports short standard requests as unpriced. `sameContextTiers` treats a missing `fast` or `ultrafast` rate as a conflict instead of filling it from the other matching tier; merge those missing speed variants before checking for conflicts.

@macroscopeapp

macroscopeapp Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — This production change alters customer-visible usage pricing, cache savings, speed premiums, and persisted usage repricing for long-context requests. Its billing/metering impact, together with an unresolved Medium pricing concern around aliases, warrants human review.

Needs human approval because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 20.9 KiB 20.9 KiB 0 B (0.0%) 29.3 KiB ✅
Codex Live turn messages 2 2 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB −7 B (−0.1%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB −7 B (−0.6%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.2 KiB 21.2 KiB 0 B (0.0%) 29.3 KiB ✅
Claude Live turn messages 2 2 0 (0.0%) 8 ✅

Baseline: 1316d48 · PR result: f5a43a8 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@coderabbitai

coderabbitai Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 1316d48 and f5a43a8.

Files selected for processing: 4
  • apps/server/src/usage/UsageService.test.ts
  • apps/server/src/usage/usageAggregation.test.ts
  • apps/server/src/usage/usagePricing.test.ts
  • apps/server/src/usage/usagePricing.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

Walkthrough

Usage pricing now parses long-context rate tiers and selects rates from each record’s prompt-token total and speed. Tests cover tier thresholds, fallback rates, aggregation, and service behavior when the rates endpoint returns either success or failure.

Changes: Long-context usage pricing

Layer / File(s) Summary
Parse context-tier rates
apps/server/src/usage/usagePricing.ts
ModelRate now includes context tiers. Rate parsing reads tier-specific standard and speed rates, applies base-rate fallbacks for omitted fields, and sorts tiers by threshold.
Select rates by prompt size
apps/server/src/usage/usagePricing.ts, apps/server/src/usage/usagePricing.test.ts
Alias merging includes context tiers. Pricing and cache-savings calculations select rates using prompt-token totals and record speed. Tests cover Claude and GPT thresholds, priority rates, missing tier fields, flat-rate models, and price overrides.
Verify aggregate and service pricing
apps/server/src/usage/usageAggregation.test.ts, apps/server/src/usage/UsageService.test.ts
Aggregation tests check that higher rates apply to the long request. Service tests check the expected $0.207 cost when the rates endpoint returns 200 or 500.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: t3dotgg, maria-rcks

Merge Risk: Minimal · up to f5a43

No concrete issue in the supplied evidence prevents merging after normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title is concise, conventional, and clearly describes the server pricing fix for long-context requests using above-tier rates.
Description check Passed The description includes complete Problem, Change, Scope and approval, and Verification sections. It provides the issue link, implementation scope, focused test results, runtime evidence, and known ve…
Linked Issues check Passed Issue [#25414] requires above-threshold pricing for GPT-family, Claude, and priority requests without changing token totals. parseRateTable reads above_Nk_tokens tiers, fills omitted tier fields f…
Out of Scope Changes check Passed The whole-PR diff contains changes only in server usage pricing and its regression tests: apps/server/src/usage/usagePricing.ts, usagePricing.test.ts, usageAggregation.test.ts, and `UsageService…
Full details: Description check

Explanation

The description includes complete Problem, Change, Scope and approval, and Verification sections. It provides the issue link, implementation scope, focused test results, runtime evidence, and known verification limitations.

Full details: Linked Issues check

Explanation

Issue [#25414] requires above-threshold pricing for GPT-family, Claude, and priority requests without changing token totals. parseRateTable reads above_Nk_tokens tiers, fills omitted tier fields from base rates, and preserves speed-specific tiers. ratesAt selects a tier when combined uncached, cached, and cache-creation input tokens exceed the threshold. priceUsage applies that tier to input, cache, output, category costs, and speed premiums. cacheSavingsUsd uses the same tier. Overrides remain flat. The added tests cover Claude above 100K, GPT above 272K, priority rates, threshold boundaries, fallback fields, overrides, mixed request aggregation, and persisted UsageService pricing. The changed files are within the issue's apps/server scope.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff contains changes only in server usage pricing and its regression tests: apps/server/src/usage/usagePricing.ts, usagePricing.test.ts, usageAggregation.test.ts, and UsageService.test.ts. The implementation and tests directly support issue [#25414]. No client, wire, unrelated feature, or unrelated cleanup changes are present.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@juliusmarminge juliusmarminge added bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed labels Oct 28, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Usage prices long-context requests at base rates and ignores LiteLLM's above_272k / above_100k tiers

1 participant