Merge pull request #1781 from pikasTech/fix/1770-turn-timing-floor-20260621045327

fix: keep visible workbench duration monotonic
This commit is contained in:
Lyon
2026-06-21 04:54:52 +08:00
committed by GitHub
@@ -26,6 +26,7 @@ const clipboard = useClipboard();
const panelRef = ref<HTMLElement | null>(null); const panelRef = ref<HTMLElement | null>(null);
const { following, keepBottomAfterUpdate, onScroll: onPanelScroll, scrollToBottom } = useBottomFollowScroll(panelRef, { threshold: 56 }); const { following, keepBottomAfterUpdate, onScroll: onPanelScroll, scrollToBottom } = useBottomFollowScroll(panelRef, { threshold: 56 });
const detailMessageId = ref<string | null>(null); const detailMessageId = ref<string | null>(null);
const displayedDurationFloorMs = new Map<string, number>();
const visibleMessages = computed(() => workbench.sessionDetailLoading ? [] : workbench.activeMessages); const visibleMessages = computed(() => workbench.sessionDetailLoading ? [] : workbench.activeMessages);
const hasRunningAgentMessages = computed(() => visibleMessages.value.some(isRunningMessage)); const hasRunningAgentMessages = computed(() => visibleMessages.value.some(isRunningMessage));
const { nowMs } = useWorkbenchNowTicker(hasRunningAgentMessages); const { nowMs } = useWorkbenchNowTicker(hasRunningAgentMessages);
@@ -56,6 +57,13 @@ watch(() => workbench.sessionDetailLoading, async () => {
acknowledgeVisibleMessages(); 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 { function openDetails(message: ChatMessage): void {
detailMessageId.value = message.id; detailMessageId.value = message.id;
} }
@@ -234,12 +242,25 @@ function traceForDisplay(message: ChatMessage): ChatMessage["runnerTrace"] {
function messageDurationMeta(message: ChatMessage): { text: string; label: string } | null { function messageDurationMeta(message: ChatMessage): { text: string; label: string } | null {
if (message.role !== "agent") return null; if (message.role !== "agent") return null;
const timing = messageTimingForDisplay(message); const timing = messageTimingForDisplay(message);
const durationMs = isRunningMessage(message) ? durationSince(timing?.startedAt) : finiteDurationMs(timing?.durationMs); const rawDurationMs = isRunningMessage(message) ? durationSince(timing?.startedAt) : finiteDurationMs(timing?.durationMs);
if (durationMs === null) return null; if (rawDurationMs === null) return null;
const durationMs = monotonicDisplayDurationMs(message, rawDurationMs);
const value = formatDuration(durationMs); const value = formatDuration(durationMs);
return { text: `耗时 ${value}`, label: `总耗时:${value}` }; 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 { function messageActivityMeta(message: ChatMessage): { text: string; label: string } | null {
if (!isRunningMessage(message)) return null; if (!isRunningMessage(message)) return null;
const timing = messageTimingForDisplay(message); const timing = messageTimingForDisplay(message);