From b97fe005afb7008c3dc97d503251663ff96a2ef9 Mon Sep 17 00:00:00 2001 From: tbphp Date: Wed, 12 Aug 2026 09:16:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(monitor):=20=E6=94=B6=E7=B4=A7=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AF=A6=E6=83=85=E9=97=B4=E8=B7=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/features/monitor/LogDetailDrawer.vue | 130 ++++++++----------- web/src/features/monitor/log-format.ts | 10 +- 2 files changed, 63 insertions(+), 77 deletions(-) diff --git a/web/src/features/monitor/LogDetailDrawer.vue b/web/src/features/monitor/LogDetailDrawer.vue index 66f49ba8..58101d07 100644 --- a/web/src/features/monitor/LogDetailDrawer.vue +++ b/web/src/features/monitor/LogDetailDrawer.vue @@ -25,9 +25,8 @@ import { formatCacheHitRate } from '@/lib/cache-rate' import { formatLogDuration, formatLogOutputRate, - formatLogReasoningBudget, formatLogTokenCount, - reasoningBudgetSemantic, + formatRequestLogReasoning, requestLogCostDisplayState, requestLogUsageDisplayState, } from './log-format' @@ -195,26 +194,16 @@ function upstreamAPILabel(upstreamAPI: RequestLogAttemptDto['upstream_api']): st return upstreamAPI } -function appliedReasoningLabel(reasoning: RequestLogAttemptDto['reasoning']): string { - if (reasoning === null) return t('monitor.logs.drawer.reasoningNotSpecified') - const details: string[] = [] - if (reasoning.mode !== null) details.push(reasoning.mode) - if (reasoning.effort !== null) details.push(reasoning.effort) - if (reasoning.budget_tokens !== null) { - const semantic = reasoningBudgetSemantic(reasoning.budget_tokens) - if (semantic === 'dynamic') { - details.push(t('monitor.logs.drawer.reasoningBudgetDynamic')) - } else if (semantic === 'disabled') { - details.push(t('monitor.logs.drawer.reasoningBudgetDisabled')) - } else { - details.push( - t('monitor.logs.drawer.reasoningBudgetValue', { - value: formatLogReasoningBudget(reasoning.budget_tokens, locale.value), - }), - ) - } - } - return details.join(' · ') +function reasoningLabel(reasoning: RequestLogAttemptDto['reasoning']): string { + const value = formatRequestLogReasoning(reasoning, locale.value) + return value ? `[${value}]` : '' +} + +function upstreamReasoningLabel( + reasoning: RequestLogAttemptDto['reasoning'], + routeMode: RequestLogAttemptDto['route_mode'], +): string { + return reasoningLabel(routeMode === 'converted' ? reasoning : (log.value?.reasoning ?? null)) } function isFinalAttempt(attempt: RequestLogAttemptDto): boolean { @@ -433,44 +422,13 @@ function toggleAttemptErrorMessage(sequence: number): void {
{{ t('monitor.logs.drawer.clientModel') }}
-
- {{ log.client_model ?? '—' }} +
+ {{ log.client_model ?? '—' }}{{ + reasoningLabel(log.reasoning) + }}
- -
-
{{ t('monitor.logs.drawer.reasoningConfig') }}
-
{{ t('monitor.logs.drawer.reasoningNotSpecified') }}
-
@@ -495,14 +453,25 @@ function toggleAttemptErrorMessage(sequence: number): void {
{{ t('monitor.logs.drawer.upstreamModel') }}
-
- {{ log.upstream_model ?? '—' }} +
+ {{ log.upstream_model ?? '—' }}{{ + upstreamReasoningLabel( + finalAttempt?.reasoning ?? null, + finalAttempt?.route_mode ?? null, + ) + }}
-
-
{{ t('monitor.logs.drawer.appliedReasoning') }}
-
{{ appliedReasoningLabel(finalAttempt.reasoning) }}
-
-
+
{{ t('monitor.logs.drawer.upstreamModel') }}
-
- {{ attempt.upstream_model ?? '—' }} +
+ {{ attempt.upstream_model ?? '—' }}{{ upstreamReasoningLabel(attempt.reasoning, attempt.route_mode) }}
-
-
{{ t('monitor.logs.drawer.appliedReasoning') }}
-
{{ appliedReasoningLabel(attempt.reasoning) }}
-
{{ t('monitor.logs.drawer.operation') }}
@@ -790,6 +760,10 @@ function toggleAttemptErrorMessage(sequence: number): void { padding: 16px 0; } +.log-detail__attempt-section { + padding: 8px 0; +} + .log-detail__section h3 { margin: 0 0 12px; font-size: var(--text-sm); @@ -819,6 +793,12 @@ function toggleAttemptErrorMessage(sequence: number): void { overflow-wrap: anywhere; } +.log-detail__reasoning { + color: var(--color-text-faint); + font-size: var(--text-label-xs); + font-weight: 400; +} + .log-detail__protocol { display: flex; min-width: 0; @@ -926,7 +906,7 @@ function toggleAttemptErrorMessage(sequence: number): void { .log-attempt-chain summary { display: flex; - min-height: 28px; + min-height: 24px; align-items: center; gap: 6px; color: var(--color-text); @@ -957,7 +937,7 @@ function toggleAttemptErrorMessage(sequence: number): void { } .log-attempt-chain[open] .log-attempt:first-of-type { - margin-top: 10px; + margin-top: 4px; } .log-attempt + .log-attempt { @@ -965,7 +945,7 @@ function toggleAttemptErrorMessage(sequence: number): void { } .log-attempt { - padding: 13px 0; + padding: 8px 0; } .log-error-message--attempt { @@ -984,7 +964,7 @@ function toggleAttemptErrorMessage(sequence: number): void { align-items: center; justify-content: space-between; gap: 10px; - margin-bottom: 12px; + margin-bottom: 8px; color: var(--color-text); font-size: var(--text-sm); } diff --git a/web/src/features/monitor/log-format.ts b/web/src/features/monitor/log-format.ts index 044ff528..161aca8b 100644 --- a/web/src/features/monitor/log-format.ts +++ b/web/src/features/monitor/log-format.ts @@ -1,4 +1,4 @@ -import type { RequestLogItemDto } from '@/app/resources/request-logs' +import type { RequestLogItemDto, RequestLogReasoningDto } from '@/app/resources/request-logs' export type RequestLogUsageDisplayState = 'reported' | 'missing' | 'not_applicable' export type RequestLogCostDisplayState = 'complete' | 'unpriced' | 'not_applicable' @@ -42,7 +42,13 @@ export function formatLogTokenCount(value: string, locale: string): string { } export function formatLogReasoning(log: RequestLogItemDto, locale: string): string { - const value = log.reasoning + return formatRequestLogReasoning(log.reasoning, locale) +} + +export function formatRequestLogReasoning( + value: RequestLogReasoningDto | null, + locale: string, +): string { if (value === null) return '' const details: string[] = [] if (