fix: keep visible workbench duration monotonic

This commit is contained in:
lyon
2026-06-21 04:54:23 +08:00
parent ddcc135ac0
commit 95c1e3d8fe
@@ -26,6 +26,7 @@ const clipboard = useClipboard();
const panelRef = ref<HTMLElement | null>(null);
const { following, keepBottomAfterUpdate, onScroll: onPanelScroll, scrollToBottom } = useBottomFollowScroll(panelRef, { threshold: 56 });
const detailMessageId = ref<string | null>(null);
const displayedDurationFloorMs = new Map<string, number>();
const visibleMessages = computed(() => workbench.sessionDetailLoading ? [] : workbench.activeMessages);
const hasRunningAgentMessages = computed(() => visibleMessages.value.some(isRunningMessage));
const { nowMs } = useWorkbenchNowTicker(hasRunningAgentMessages);
@@ -56,6 +57,13 @@ watch(() => workbench.sessionDetailLoading, async () => {
acknowledgeVisibleMessages();
});
watch(visibleMessages, (messages) => {
const visibleKeys = new Set(messages.map(messageDurationFloorKey));
for (const key of Array.from(displayedDurationFloorMs.keys())) {
if (!visibleKeys.has(key)) displayedDurationFloorMs.delete(key);
}
}, { immediate: true });
function openDetails(message: ChatMessage): void {
detailMessageId.value = message.id;
}
@@ -234,12 +242,25 @@ function traceForDisplay(message: ChatMessage): ChatMessage["runnerTrace"] {
function messageDurationMeta(message: ChatMessage): { text: string; label: string } | null {
if (message.role !== "agent") return null;
const timing = messageTimingForDisplay(message);
const durationMs = isRunningMessage(message) ? durationSince(timing?.startedAt) : finiteDurationMs(timing?.durationMs);
if (durationMs === null) return null;
const rawDurationMs = isRunningMessage(message) ? durationSince(timing?.startedAt) : finiteDurationMs(timing?.durationMs);
if (rawDurationMs === null) return null;
const durationMs = monotonicDisplayDurationMs(message, rawDurationMs);
const value = formatDuration(durationMs);
return { text: `耗时 ${value}`, label: `总耗时:${value}` };
}
function monotonicDisplayDurationMs(message: ChatMessage, durationMs: number): number {
const key = messageDurationFloorKey(message);
const previous = displayedDurationFloorMs.get(key);
const next = previous === undefined ? durationMs : Math.max(previous, durationMs);
if (next !== previous) displayedDurationFloorMs.set(key, next);
return next;
}
function messageDurationFloorKey(message: ChatMessage): string {
return firstNonEmptyString(message.id, message.runnerTrace?.traceId, message.traceId) ?? "unknown-agent-message";
}
function messageActivityMeta(message: ChatMessage): { text: string; label: string } | null {
if (!isRunningMessage(message)) return null;
const timing = messageTimingForDisplay(message);