fix(web): keep terminal duration sealed (#1917)

This commit is contained in:
Lyon
2026-06-22 20:07:20 +08:00
committed by GitHub
parent 356a35e9b0
commit 7b96397511
@@ -27,6 +27,7 @@ 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 sealedDurationMs = new Map<string, number>();
const visibleMessages = computed(() => workbench.sessionDetailLoading ? [] : workbench.activeMessages);
const hasRunningAgentMessages = computed(() => visibleMessages.value.some(isRunningMessage));
const { nowMs } = useWorkbenchNowTicker(hasRunningAgentMessages);
@@ -62,6 +63,9 @@ watch(visibleMessages, (messages) => {
for (const key of Array.from(displayedDurationFloorMs.keys())) {
if (!visibleKeys.has(key)) displayedDurationFloorMs.delete(key);
}
for (const key of Array.from(sealedDurationMs.keys())) {
if (!visibleKeys.has(key)) sealedDurationMs.delete(key);
}
}, { immediate: true });
function openDetails(message: ChatMessage): void {
@@ -256,13 +260,14 @@ function messageDurationMeta(message: ChatMessage): { text: string; label: strin
if (message.role !== "agent") return null;
const timing = messageTimingForDisplay(message);
const rawDurationMs = isRunningMessage(message) ? durationSince(timing?.startedAt) : terminalMessageDurationMs(message, timing);
if (rawDurationMs === null) return null;
const durationMs = isRunningMessage(message) ? monotonicDisplayDurationMs(message, rawDurationMs) : sealedDisplayDurationMs(message, rawDurationMs);
if (durationMs === null) return null;
const value = formatDuration(durationMs);
return { text: `耗时 ${value}`, label: `总耗时:${value}` };
}
function monotonicDisplayDurationMs(message: ChatMessage, durationMs: number): number {
function monotonicDisplayDurationMs(message: ChatMessage, durationMs: number | null): number | null {
if (durationMs === null) return null;
const key = messageDurationFloorKey(message);
const previous = displayedDurationFloorMs.get(key);
const next = previous === undefined ? durationMs : Math.max(previous, durationMs);
@@ -270,8 +275,13 @@ function monotonicDisplayDurationMs(message: ChatMessage, durationMs: number): n
return next;
}
function sealedDisplayDurationMs(message: ChatMessage, durationMs: number): number {
displayedDurationFloorMs.delete(messageDurationFloorKey(message));
function sealedDisplayDurationMs(message: ChatMessage, durationMs: number | null): number | null {
const key = messageDurationFloorKey(message);
displayedDurationFloorMs.delete(key);
const previous = sealedDurationMs.get(key);
if (previous !== undefined) return previous;
if (durationMs === null) return null;
sealedDurationMs.set(key, durationMs);
return durationMs;
}
@@ -302,10 +312,11 @@ function terminalMessageDurationMs(message: ChatMessage, timing: ChatMessage["ti
}
function elapsedTerminalDurationMs(message: ChatMessage, timing: ChatMessage["timing"]): number | null {
const messageRecord = message as Record<string, unknown>;
const trace = message.runnerTrace as Record<string, unknown> | null | undefined;
const traceTiming = trace?.timing as Record<string, unknown> | null | undefined;
const startedAt = timestampMs(timing?.startedAt ?? message.startedAt ?? traceTiming?.startedAt ?? trace?.startedAt);
const endedAt = timestampMs(timing?.finishedAt ?? message.finishedAt ?? traceTiming?.finishedAt ?? trace?.finishedAt ?? timing?.lastEventAt ?? message.lastEventAt ?? traceTiming?.lastEventAt ?? trace?.lastEventAt);
const endedAt = timestampMs(timing?.finishedAt ?? message.finishedAt ?? messageRecord.completedAt ?? traceTiming?.finishedAt ?? trace?.finishedAt ?? traceTiming?.completedAt ?? trace?.completedAt);
if (startedAt === null || endedAt === null || endedAt < startedAt) return null;
return Math.trunc(endedAt - startedAt);
}