Merge pull request #6188 from JialinLiu-codedance/feat/usage-requested-reasoning-effort

feat(usage): 使用记录展示映射前的推理强度
This commit is contained in:
Wesley Liddick
2026-08-28 16:18:50 +08:00
committed by GitHub
41 changed files with 1020 additions and 106 deletions
@@ -91,7 +91,15 @@
</template>
<template #cell-reasoning_effort="{ row }">
<span class="text-sm text-gray-900 dark:text-white">
<div v-if="hasReasoningEffortMapping(row)" data-testid="reasoning-effort-cell" class="space-y-0.5 text-xs">
<div class="font-medium text-gray-900 dark:text-white">
{{ formatReasoningEffort(row.reasoning_effort) }}
</div>
<div class="text-gray-500 dark:text-gray-400">
<span class="mr-0.5">↳</span>{{ formatReasoningEffort(row.upstream_reasoning_effort) }}
</div>
</div>
<span v-else data-testid="reasoning-effort-cell" class="text-sm text-gray-900 dark:text-white">
{{ formatReasoningEffort(row.reasoning_effort) }}
</span>
</template>
@@ -500,7 +508,7 @@
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAppStore } from '@/stores/app'
import { formatDateTime, formatReasoningEffort } from '@/utils/format'
import { formatDateTime, formatReasoningEffort, reasoningEffortValuesEqual } from '@/utils/format'
import { formatCacheTokens, formatMultiplier } from '@/utils/formatters'
import { formatTokenPricePerMillion } from '@/utils/usagePricing'
import { getUsageServiceTierLabel } from '@/utils/usageServiceTier'
@@ -587,6 +595,12 @@ const ipGeoBatchLoading = ref(false)
const showIpGeoToolbar = computed(() => props.columns.some((col) => col.key === 'ip_address'))
const hasReasoningEffortMapping = (row: AdminUsageLog): boolean => {
const requested = row.reasoning_effort?.trim() || ''
const forwarded = row.upstream_reasoning_effort?.trim() || ''
return requested !== '' && forwarded !== '' && !reasoningEffortValuesEqual(requested, forwarded)
}
const sentUpstreamModel = (row: AdminUsageLog): string => row.upstream_model?.trim() || row.model?.trim() || ''
const normalizeModelVariant = (model: string): string => model
@@ -84,6 +84,7 @@ const DataTableStub = {
<div>
<div v-for="row in data" :key="row.request_id">
<slot name="cell-model" :row="row" :value="row.model" />
<slot name="cell-reasoning_effort" :row="row" :value="row.reasoning_effort" />
<slot name="cell-billing_mode" :row="row" />
<slot name="cell-tokens" :row="row" />
<slot name="cell-cost" :row="row" />
@@ -256,6 +257,86 @@ describe('admin UsageTable tooltip', () => {
expect(text).toContain('claude-sonnet-4-20250514')
})
it('shows requested and forwarded reasoning effort separately when they differ', () => {
const wrapper = mount(UsageTable, {
props: {
data: [{
request_id: 'req-admin-effort-1',
model: 'gpt-5.4',
reasoning_effort: 'max',
upstream_reasoning_effort: 'xhigh',
}],
loading: false,
columns: [],
},
global: {
stubs: {
DataTable: DataTableStub,
EmptyState: true,
Icon: true,
Teleport: true,
},
},
})
const text = wrapper.text()
expect(text).toContain('Max')
expect(text).toContain('XHigh')
expect(text).toContain('↳')
})
it('shows a single reasoning effort when requested matches forwarded', () => {
const wrapper = mount(UsageTable, {
props: {
data: [{
request_id: 'req-admin-effort-2',
model: 'gpt-5.6-sol',
reasoning_effort: 'max',
}],
loading: false,
columns: [],
},
global: {
stubs: {
DataTable: DataTableStub,
EmptyState: true,
Icon: true,
Teleport: true,
},
},
})
const text = wrapper.text()
expect(text).toContain('Max')
expect(text).not.toContain('↳')
})
it('hides mapped reasoning effort for user rows that only have the requested value', () => {
const wrapper = mount(UsageTable, {
props: {
data: [{
request_id: 'req-user-effort-1',
model: 'gpt-5.4',
reasoning_effort: 'max',
}],
loading: false,
columns: [],
},
global: {
stubs: {
DataTable: DataTableStub,
EmptyState: true,
Icon: true,
Teleport: true,
},
},
})
expect(wrapper.text()).toContain('Max')
expect(wrapper.text()).not.toContain('XHigh')
expect(wrapper.text()).not.toContain('↳')
})
it.each([
{
name: 'possible version variant',
@@ -561,6 +642,7 @@ const DataTableStubWithUser = {
<div v-for="row in data" :key="row.request_id">
<slot name="cell-user" :row="row" />
<slot name="cell-model" :row="row" :value="row.model" />
<slot name="cell-reasoning_effort" :row="row" :value="row.reasoning_effort" />
<slot name="cell-billing_mode" :row="row" />
<slot name="cell-tokens" :row="row" />
<slot name="cell-cost" :row="row" />