{{ message }}
Repository navigation
fix(gateway): a semantic or conditional cache hit is no longer billed as a provider call - #3578
Open
fabriziosalmi wants to merge 1 commit into
Open
fabriziosalmi wants to merge 1 commit into
fabriziosalmi wants to merge 1 commit into
Conversation
… as a provider call The engine skips SkipOnCacheHit plugins (cost, credits) only when cache_status is "hit_exact". The cache plugin also answers with "hit_semantic" and "hit_conditional", and marks all three with rc.Flags.CacheHit. A semantic hit makes no provider call, but the cached response still carries the usage of the call that filled the cache, so the cost plugin priced it at full rate and the credits plugin deducted that amount from the managed key's balance. The engine now reads rc.Flags.CacheHit, the signal the rate limiter already reads for the same reason since 720ed01. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 tasks done
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
A response served from the semantic cache is priced and deducted from a managed key as if the provider had been called.
RunPostPluginsskips theSkipOnCacheHitplugins (cost, credits) only whencache_status == "hit_exact", but the cache plugin also answers withhit_semanticandhit_conditional, and setsrc.Flags.CacheHitfor all three. The cached response keeps the usage of the call that filled the cache, so a semantic hit is billed at the full price of that call. The engine now readsrc.Flags.CacheHit, which is what the rate limiter already reads for the same reason since 720ed01 (#3570).Linked issues
Closes #3579
AI use
AI use: Claude Code found the bug while reading the gateway, and wrote the fix and both tests. I reviewed the diff, reproduced the failure on
dev, and ran the checks below.Type of change
E2E coverage
E2E: exempt (gateway-internal)
1) What changes were done
A. Engine
internal/pipeline/engine.go:isCacheHitisrc.Flags.ShortCircuited && rc.Flags.CacheHitinstead of matching one value ofcache_status.B. Comment
internal/plugins/ratelimit/ratelimit.go: the comment said the engine only honourshit_exact. That is no longer true, so it now only states that every cache layer sets the flag. No code change there.2) Why the changes were done
cost.cache_statussays which layer answered.CacheHitsays whether any layer did, which is what the skip decision needs. Reading the flag also covers any future cache layer without touching the engine.3) Tests written + scenarios each covers
internal/pipeline/engine_test.goTestRunPostPluginsSkipsEveryCacheHitKind: aSkipOnCacheHitplugin is skipped forhit_exact,hit_semanticandhit_conditional, and still runs on amiss.TestRunPostPluginsSkipOnCacheHitTimings: the existing fixture set onlycache_status. It now also setsCacheHit, as the real cache plugin does.internal/plugins/credits/cache_hit_test.goTestCacheHitDeductsNoCredits: the real cache plugin (exact and semantic store), cost plugin and credits plugin in one engine, with a managed key. A miss calls the provider and is deducted. An exact hit and a semantic hit make no provider call, set nocostand leave the balance unchanged.Both new tests fail on
dev:With the fix:
Not run: the backend
bin/teststack and the e2e harness, since nothing outsideagentcc-gatewaychanges and the e2e gateway config cannot enable the semantic cache or managed keys.Generated with Claude Code