mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
fix(usage): exclude cached tokens from displayed input
Reuse the fresh input calculation across usage records, token details and key usage metrics. Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -4,13 +4,14 @@ import type { UsageListRecord } from '@/api'
|
||||
import { Archive, ArrowDown, ArrowUp } from '@lucide/vue'
|
||||
|
||||
import { computed } from 'vue'
|
||||
import { usageTokenDetails } from '@/components/usage/shared/presenter'
|
||||
import UsageDetailPopover from '@/components/usage/UsageDetailPopover.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
record: Pick<UsageListRecord, 'tokenDetails'>
|
||||
}>()
|
||||
|
||||
const tokenDetails = computed(() => props.record.tokenDetails)
|
||||
const tokenDetails = computed(() => usageTokenDetails(props.record.tokenDetails))
|
||||
const tokenItems = computed(() => [
|
||||
{ label: '输入 Token', value: tokenDetails.value.inputTokensDisplay },
|
||||
{ label: '输出 Token', value: tokenDetails.value.outputTokensDisplay },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UsageListRecord, UsageRecordDetail } from '@/api'
|
||||
import { formatCompactNumber, formatDuration } from '@/utils/format'
|
||||
import type { UsageListRecord, UsageRecordDetail, UsageTokenDetails } from '@/api'
|
||||
import { formatCompactNumber, formatDuration, formatInteger } from '@/utils/format'
|
||||
|
||||
// 列表与详情使用独立读模型,展示函数只依赖两者的公共字段。
|
||||
type UsageCommonRecord = UsageListRecord | UsageRecordDetail
|
||||
@@ -9,6 +9,23 @@ export type UsagePerformanceRecord = UsageLatencyRecord & {
|
||||
tokenDetails: Pick<UsageListRecord['tokenDetails'], 'outputTokens'> | null
|
||||
}
|
||||
|
||||
export function usageFreshInputTokens(input: number, cached: number, written: number) {
|
||||
// 输入总量包含缓存读写,普通输入与缓存明细分开展示
|
||||
return Math.max(0, input - cached - written)
|
||||
}
|
||||
|
||||
export function usageTokenDetails(details: UsageTokenDetails): UsageTokenDetails {
|
||||
const inputTokens = details.inputTokens === null
|
||||
? null
|
||||
: usageFreshInputTokens(details.inputTokens, details.cachedTokens ?? 0, details.cacheWriteTokens ?? 0)
|
||||
|
||||
return {
|
||||
...details,
|
||||
inputTokens,
|
||||
inputTokensDisplay: inputTokens === null ? details.inputTokensDisplay : formatInteger(inputTokens),
|
||||
}
|
||||
}
|
||||
|
||||
export function usageTransportType(transport?: string | null) {
|
||||
if (transport === 'websocket')
|
||||
return 'WS'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { KeyUsageMetrics } from '@/api/modules/key-usage'
|
||||
import { ArrowDown, ArrowUp, Brain, Database, Sparkles } from '@lucide/vue'
|
||||
import { usageFreshInputTokens } from '@/components/usage/shared/presenter'
|
||||
|
||||
// 卡片、曲线和图例共用语义与主题色,避免同一指标出现不同颜色。
|
||||
export const keyUsageTokenMetrics = [
|
||||
@@ -12,11 +13,6 @@ export const keyUsageTokenMetrics = [
|
||||
|
||||
export function keyUsageTokenValue(metrics: KeyUsageMetrics, key: typeof keyUsageTokenMetrics[number]['key']) {
|
||||
return key === 'inputTokens'
|
||||
? freshInput(metrics.inputTokens, metrics.cachedTokens, metrics.cacheWriteTokens)
|
||||
? usageFreshInputTokens(metrics.inputTokens, metrics.cachedTokens, metrics.cacheWriteTokens)
|
||||
: metrics[key]
|
||||
}
|
||||
|
||||
function freshInput(input: number, cached: number, written: number) {
|
||||
// 输入总量已经包含缓存读写,不把缓存再次计入消耗。
|
||||
return Math.max(0, input - cached - written)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
usageLatencyDetails,
|
||||
usageModelDisplay,
|
||||
usageReasoningEffort,
|
||||
usageTokenDetails,
|
||||
usageTransportType,
|
||||
usageUserAgent,
|
||||
} from '@/components/usage/shared/presenter'
|
||||
@@ -37,7 +38,7 @@ const responseText = computed(() => props.record ? visibleResponseText(props.rec
|
||||
const modelDisplay = computed(() => props.record
|
||||
? usageModelDisplay(props.record)
|
||||
: { primary: '—', secondary: '' })
|
||||
const tokenDetails = computed(() => props.record ? props.record.tokenDetails : null)
|
||||
const tokenDetails = computed(() => props.record ? usageTokenDetails(props.record.tokenDetails) : null)
|
||||
const billing = computed(() => props.record ? props.record.billing : null)
|
||||
const latencyDetails = computed(() => props.record ? usageLatencyDetails(props.record) : null)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user