Skip to content

tests: openai cache coverage#5091

Merged
akshaydeo merged 5 commits into
mainfrom
07-10-cp-openai-cache-tests
Jul 10, 2026
Merged

tests: openai cache coverage#5091
akshaydeo merged 5 commits into
mainfrom
07-10-cp-openai-cache-tests

Conversation

@TejasGhatte

@TejasGhatte TejasGhatte commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Cross-Cut Round 31 to the provider harness E2E test suite, covering OpenAI prompt caching across the new gpt-5.6 model family (sol, terra, luna) and legacy models (gpt-4o, gpt-4.1, gpt-5, etc.). The suite validates that prompt_cache_options, prompt_cache_breakpoint, and cache_write_tokens fields are correctly passed through and that cold-write/warm-read cache cycles produce the expected token accounting in both streaming and non-streaming modes.

Changes

  • Added a pcNonce collection variable initialized once per run in the pre-request script so that all write/read request pairs within a run share a stable, unique cache key prefix without colliding across runs.
  • Added a cachePrefix collection variable containing a deliberately verbose, stable system prompt designed to exceed provider minimum token thresholds for prompt caching eligibility.
  • Added Round 31 test group with four sub-groups:
    • 31.1gpt-5.6 (sol, terra, luna) non-streaming: tests prompt_cache_options + prompt_cache_breakpoint + cache_write_tokens on both /v1/chat/completions and /v1/responses endpoints via native and drop-in routes.
    • 31.2gpt-5.6 streaming: same coverage as 31.1 with SSE content-type assertions and streamed usage extraction.
    • 31.3 — Legacy models (gpt-5, gpt-5-mini, gpt-5-nano, gpt-4.1) non-streaming: validates cached_tokens shape and cache hit on automatic (implicit) caching without explicit breakpoints.
    • 31.4 — Legacy models (gpt-4.1-mini, gpt-4.1-nano, gpt-4o, gpt-4o-mini) streaming: same as 31.3 but over SSE.
  • Each test case follows a write→read pattern with a ~1.5 s busy-wait before read requests to allow cache propagation.
  • Write assertions check cache_write_tokens > 0; read assertions check cached_tokens > 0. Responses API write tests additionally assert that prompt_cache_options is echoed back in the response.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

Run the collection via Newman against a live Bifrost instance with valid OpenAI credentials:

newman run tests/e2e/api/collections/provider-harness.json \
  --env-var baseUrl=<your-bifrost-url> \
  --env-var openaiKey=<your-openai-key> \
  --folder "Cross-Cut Round 31: OpenAI Prompt Caching"

Expected outcome: all write requests report cache_write_tokens > 0 on cold cache, and all paired read requests report cached_tokens > 0 confirming a cache hit. Run the suite twice with different pcNonce values to confirm isolation between runs.

Screenshots/Recordings

N/A — no UI changes.

Breaking changes

  • No

Related issues

N/A

Security considerations

The cachePrefix value is a static, non-sensitive string used solely to pad prompts to caching-eligible token lengths. No secrets, PII, or auth material is introduced.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

Fixes a cost calculation bug where Anthropic prompt-cache tokens (both cache read and cache creation) were billed at standard rates even when the request used fast mode. Per Anthropic's pricing model, cache multipliers stack on top of the fast base input rate, meaning cache token costs should scale by the fast/standard input ratio rather than remaining at the standard cache rate.

- Introduced `fastCacheRate`, a helper that scales a standard cache rate to the fast-mode equivalent by multiplying it by the fast/standard input price ratio.
- Applied `fastCacheRate` as an early-return guard in `tieredCacheReadInputTokenRate`, `tieredCacheCreationInputTokenRate`, and `tieredCacheCreationInputAbove1hrTokenRate` so fast-mode requests use the correctly scaled cache rates.
- Updated the existing fast-mode cache test (`TestComputeTextCost_FastMode_CacheStacksOnFastBase`) to reflect the correct expected values (cache tokens now scale 2× when the fast input rate is 2× the standard rate).
- Added a regression test (`TestComputeTextCost_FastMode_Opus48CacheRegression`) pinning the real-world miscalculation observed with Anthropic Opus 4.8 fast mode + `cache_control`, where 44,667 5-minute cache-creation tokens were billed at the standard $6.25/MTok instead of the fast-scaled $12.50/MTok.

- [x] Bug fix

- [x] Core (Go)

```sh
go test ./framework/modelcatalog/datasheet/...
```

The new regression test `TestComputeTextCost_FastMode_Opus48CacheRegression` will fail on the unfixed code and pass after this change. The updated `TestComputeTextCost_FastMode_CacheStacksOnFastBase` validates the general scaling behaviour.

- [x] No

None.

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

TejasGhatte commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


tejas ghatte seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@TejasGhatte TejasGhatte marked this pull request as ready for review July 10, 2026 07:42
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • tests/e2e/api/collections/provider-harness.json
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: acf848d5-4d6d-451b-bdd6-e28591048046

📥 Commits

Reviewing files that changed from the base of the PR and between b610755 and 7176f83.

📒 Files selected for processing (1)
  • tests/e2e/api/collections/provider-harness.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 07-10-cp-openai-cache-tests

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

@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

This is close, but the Responses streaming cases should be fixed before merging.

  • Responses streaming requests assert usage-derived cache fields without ensuring usage is emitted.
  • This can make the new cache tests fail before they check the cache behavior they were added to cover.

tests/e2e/api/collections/provider-harness.json

Important Files Changed

Filename Overview
tests/e2e/api/collections/provider-harness.json Adds Round 31 prompt-caching coverage, but Responses streaming cache requests still omit the usage opt-in that their assertions depend on.

Reviews (4): Last reviewed commit: "tests: openai cache coverage" | Re-trigger Greptile

Comment thread tests/e2e/api/collections/provider-harness.json
Comment thread tests/e2e/api/collections/provider-harness.json
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 10, 2026
## Summary

Adds support for Anthropic's data-residency billing feature (`inference_geo`). When Anthropic serves inference in the US (`inference_geo: "us"`), a 1.1x multiplier is applied to all token and cache costs. This PR propagates the `inference_geo` field through the full response pipeline (chat, responses, streaming, passthrough) and wires it into the cost computation layer, including a new database column and UI override field.

A secondary fix ensures Anthropic server-tool web search request counts (`ServerToolUse.WebSearchRequests`) are correctly forwarded and billed in both streaming and non-streaming paths, where previously the count could be lost when the terminal chunk overwrote the accumulated usage.

## Changes

- **`inference_geo` propagation**: `InferenceGeo *string` added to `BifrostChatResponse`, `BifrostResponsesResponse`, and `BifrostPassthroughUsage`. The field is forwarded from `AnthropicUsage` in all conversion paths: non-streaming chat, non-streaming responses, streaming chat (captured across events and set on the final chunk), streaming responses (`message_delta`), and passthrough.
- **Data-residency multiplier in cost computation**: `serviceTier` gains an `inferenceGeoUS bool` flag. `tierFromResponse` now accepts and evaluates `inferenceGeo`. `computeTextCost` applies `InferenceGeoUSMultiplier` to token/cache costs only — the flat per-search fee is intentionally excluded.
- **Database migration**: `migrationAddInferenceGeoMultiplierColumn` adds `inference_geo_us_multiplier` to `TableModelPricing`. The column is included in the pricing sync update list and mapped through `convertEntryToTablePricing` / `convertTablePricingToEntry`.
- **Web search billing fix**: `accumulateAnthropicResponsesUsage` now carries `ServerToolUse.WebSearchRequests` into the accumulator so the count survives the terminal-chunk overwrite on streamed Responses requests. The non-streaming chat converter also forwards the count into `CompletionTokensDetails.NumSearchQueries`.
- **UI**: `inference_geo_us_multiplier` added to the custom pricing override sheet and `PricingOverridePatch` TypeScript type.
- **Tests**: New unit tests cover the accumulator web-search fix, chat/responses converter forwarding of `InferenceGeo` and web search counts, multiplier application (including the no-multiplier-column safe no-op), and `tierFromResponse` geo detection (case-insensitive).

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [x] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# Core/Transports
go test ./core/providers/anthropic/... ./framework/modelcatalog/datasheet/...

# UI
cd ui
pnpm i || npm i
pnpm build || npm run build
```

To validate end-to-end: send a request to an Anthropic model with data residency enabled. The response should include `inference_geo: "us"` and the computed cost should reflect the 1.1x multiplier on token/cache costs, with the per-search fee unchanged.

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

No auth, secrets, or PII implications. The `inference_geo` value is sourced from Anthropic's API response and used only for billing computation.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

During OpenAI chat completion streaming, the `service_tier` field returned in stream chunks was being discarded, causing the final assembled response to lose priority/flex billing tier information. This PR captures `service_tier` as it appears in stream chunks and propagates it to the final response.

## Changes

- Introduced a `serviceTier` variable to track the `service_tier` value echoed across streaming chunks.
- After the stream completes and the final response is assembled, the captured `service_tier` is applied to the response so priority/flex billing metadata is preserved.

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [x] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Send a streaming chat completion request to an OpenAI endpoint using a `service_tier` (e.g., `"flex"` or `"priority"`). Verify that the final streamed response includes the correct `service_tier` value.

```sh
go test ./...
```

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

No security implications. This change only propagates a billing tier metadata field from stream chunks to the final response object.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
@TejasGhatte TejasGhatte force-pushed the 07-10-cp-openai-cache-write-pricing branch from b1879fc to c59ec94 Compare July 10, 2026 08:33
@TejasGhatte TejasGhatte force-pushed the 07-10-cp-openai-cache-tests branch from fb45714 to c2a13cf Compare July 10, 2026 08:33
@TejasGhatte TejasGhatte force-pushed the 07-10-cp-openai-cache-tests branch from c2a13cf to 7176f83 Compare July 10, 2026 08:48
@TejasGhatte TejasGhatte force-pushed the 07-10-cp-openai-cache-write-pricing branch from c59ec94 to b610755 Compare July 10, 2026 08:48
Comment thread tests/e2e/api/collections/provider-harness.json

akshaydeo commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jul 10, 10:32 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 10, 10:40 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from 07-10-cp-openai-cache-write-pricing to graphite-base/5091 July 10, 2026 10:37
@akshaydeo akshaydeo changed the base branch from graphite-base/5091 to main July 10, 2026 10:40
@akshaydeo akshaydeo dismissed coderabbitai[bot]’s stale review July 10, 2026 10:40

The base branch was changed.

@akshaydeo akshaydeo merged commit 59096c8 into main Jul 10, 2026
10 of 11 checks passed
@akshaydeo akshaydeo deleted the 07-10-cp-openai-cache-tests branch July 10, 2026 10:40
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.

3 participants