Documentation / guides
Usage translation
Normalize provider usage fields and cache subsets into Usage.
The normalized alias is intentionally small:
type Usage struct {
InputTokens content.TokenCount
OutputTokens content.TokenCount
CacheReadTokens content.TokenCount
CacheCreationTokens content.TokenCount
ReasoningTokens content.TokenCount
}
Fields
| Provider field | Normalized field | Rule |
|---|---|---|
OpenAI prompt_tokens | input plus cache subsets | subtract cached_tokens and cache_write_tokens |
Responses input_tokens | input plus cache read and cache write | subtract input_tokens_details.cached_tokens and cache_write_tokens |
Anthropic input_tokens | input | cache fields are separate |
Gemini promptTokenCount | input | subtract cachedContentTokenCount, then add toolUsePromptTokenCount |
Bedrock inputTokens | input | cache fields are separate |
Output and reasoning are normalized similarly. Gemini adds candidate and thought
counts for OutputTokens; its totalTokenCount is validated as a well-formed
count but is deliberately not reconciled against those components. Missing usage remains nil, not a fabricated zero measurement.
Invariants
usagenorm rejects negative, null-invalid, fractional, or out-of-range counts.
Cache subsets cannot exceed the provider’s gross input count, and addition uses
checked arithmetic. Reasoning greater than output is not an invariant: it is
reported as received and observable through
content.Usage.ReasoningWithinOutput.
u := content.Usage{InputTokens: 10, CacheReadTokens: 2, OutputTokens: 4}
contextTokens, err := u.ContextTokens() // 12
if err != nil {
return err
}
_ = contextTokens
Source and proof
Run go test ./usage ./codec/....