2026-04-10 17:44:55 +08:00
|
|
|
type UsageTokenLike = {
|
|
|
|
|
effective_input_tokens?: number | null
|
|
|
|
|
input_tokens?: number | null
|
2026-04-19 02:46:28 +08:00
|
|
|
cache_creation_input_tokens?: number | null
|
|
|
|
|
cache_creation_ephemeral_5m_input_tokens?: number | null
|
|
|
|
|
cache_creation_ephemeral_1h_input_tokens?: number | null
|
2026-04-10 17:44:55 +08:00
|
|
|
cache_read_input_tokens?: number | null
|
|
|
|
|
api_format?: string | null
|
|
|
|
|
endpoint_api_format?: string | null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toNonNegativeNumber(value: number | null | undefined): number {
|
|
|
|
|
return typeof value === 'number' && Number.isFinite(value) ? Math.max(value, 0) : 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function apiFamily(apiFormat: string | null | undefined): string {
|
|
|
|
|
return String(apiFormat || '')
|
|
|
|
|
.split(':', 1)[0]
|
|
|
|
|
.trim()
|
|
|
|
|
.toLowerCase()
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-19 02:46:28 +08:00
|
|
|
export function getCacheCreationTokens(usage: UsageTokenLike): number {
|
|
|
|
|
const explicit = toNonNegativeNumber(usage.cache_creation_input_tokens)
|
|
|
|
|
const classified = toNonNegativeNumber(usage.cache_creation_ephemeral_5m_input_tokens)
|
|
|
|
|
+ toNonNegativeNumber(usage.cache_creation_ephemeral_1h_input_tokens)
|
|
|
|
|
if (explicit === 0 && classified > 0) {
|
|
|
|
|
return classified
|
|
|
|
|
}
|
|
|
|
|
return explicit
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 09:53:32 +08:00
|
|
|
export function getCacheReadTokens(usage: UsageTokenLike): number {
|
|
|
|
|
return toNonNegativeNumber(usage.cache_read_input_tokens)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-10 17:44:55 +08:00
|
|
|
export function getEffectiveInputTokens(usage: UsageTokenLike): number {
|
|
|
|
|
const explicit = toNonNegativeNumber(usage.effective_input_tokens)
|
|
|
|
|
if (explicit > 0) {
|
|
|
|
|
return explicit
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const inputTokens = toNonNegativeNumber(usage.input_tokens)
|
|
|
|
|
const cacheReadTokens = toNonNegativeNumber(usage.cache_read_input_tokens)
|
|
|
|
|
if (inputTokens === 0 || cacheReadTokens === 0) {
|
|
|
|
|
return inputTokens
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (apiFamily(usage.endpoint_api_format || usage.api_format)) {
|
|
|
|
|
case 'openai':
|
|
|
|
|
case 'gemini':
|
|
|
|
|
case 'google':
|
|
|
|
|
return Math.max(inputTokens - cacheReadTokens, 0)
|
|
|
|
|
default:
|
|
|
|
|
return inputTokens
|
|
|
|
|
}
|
|
|
|
|
}
|