fix: stabilize live activity updates

This commit is contained in:
wuyang6
2026-05-26 11:58:13 +08:00
parent 902c9c86c2
commit 20c1946a3c
2 changed files with 50 additions and 8 deletions
@@ -165,20 +165,29 @@ export function ActivityPanel({ asDrawer = false }: { asDrawer?: boolean } = {})
() => collectLiveRunItems(liveRunStatus), () => collectLiveRunItems(liveRunStatus),
[liveRunStatus], [liveRunStatus],
); );
const selectedMessageId = selectedId ? activityMessageId(selectedId) : null;
const liveRunActive = hasActiveRun(liveRunStatus) && liveItems.length > 0; const liveRunActive = hasActiveRun(liveRunStatus) && liveItems.length > 0;
const mergedItems = useMemo(
() =>
liveRunActive
? mergeActivityItems(messageItems, liveItems)
: messageItems,
[liveRunActive, messageItems, liveItems],
);
const selectedMessageId = selectedId ? activityMessageId(selectedId) : null;
const selectedMessageItems = selectedMessageId const selectedMessageItems = selectedMessageId
? messageItems.filter( ? mergedItems.filter(
(item) => activityMessageId(item.id) === selectedMessageId, (item) => activityMessageId(item.id) === selectedMessageId,
) )
: []; : [];
const shouldUseLiveItems = Boolean(activeSessionId && liveRunActive); const shouldUseLiveItems = Boolean(activeSessionId && liveRunActive);
const items = shouldUseLiveItems ? liveItems : messageItems; const items = shouldUseLiveItems ? mergedItems : messageItems;
const selectedItems = selectedMessageId const selectedItems = selectedMessageId
? items.filter((item) => activityMessageId(item.id) === selectedMessageId) ? items.filter((item) => activityMessageId(item.id) === selectedMessageId)
: []; : [];
const visibleItems = shouldUseLiveItems const visibleItems = shouldUseLiveItems
? liveItems ? selectedMessageId && selectedMessageItems.length > 0
? selectedMessageItems
: items
: selectedMessageId && selectedMessageItems.length > 0 : selectedMessageId && selectedMessageItems.length > 0
? selectedMessageItems ? selectedMessageItems
: selectedMessageId && selectedItems.length > 0 : selectedMessageId && selectedItems.length > 0
@@ -1013,6 +1022,37 @@ function collectLiveRunItems(runStatus: ClawRunStatus | null) {
return items; return items;
} }
function mergeActivityItems(
messageItems: readonly ActivityItem[],
liveItems: readonly ActivityItem[],
) {
if (!liveItems.length) return [...messageItems];
if (!messageItems.length) return [...liveItems];
const merged = [...messageItems];
const seen = new Set(
messageItems.map((item) =>
[
item.kind,
item.title,
item.argsText ?? "",
item.summary,
].join("\u0000"),
),
);
for (const item of liveItems) {
const key = [
item.kind,
item.title,
item.argsText ?? "",
item.summary,
].join("\u0000");
if (seen.has(key)) continue;
seen.add(key);
merged.push(item);
}
return merged;
}
function summarizeLiveRunEvents( function summarizeLiveRunEvents(
runStatus: ClawRunStatus, runStatus: ClawRunStatus,
events: readonly LiveRunEvent[], events: readonly LiveRunEvent[],
@@ -2079,12 +2079,14 @@ const ActivityChainSummary: FC<{
setElapsedMs(storedElapsedMs); setElapsedMs(storedElapsedMs);
return; return;
} }
const explicitStartedAt = const authoritativeStartedAt =
metadataRunStartedAtMs ?? contentRunStartedAtMs ?? messageCreatedAtMs; metadataRunStartedAtMs ?? contentRunStartedAtMs;
if (explicitStartedAt !== null) { if (authoritativeStartedAt !== null) {
liveStartedAtRef.current = explicitStartedAt; liveStartedAtRef.current = authoritativeStartedAt;
} else if (liveStartedAtRef.current === null && storedElapsedMs !== null) { } else if (liveStartedAtRef.current === null && storedElapsedMs !== null) {
liveStartedAtRef.current = Date.now() - storedElapsedMs; liveStartedAtRef.current = Date.now() - storedElapsedMs;
} else if (liveStartedAtRef.current === null && messageCreatedAtMs !== null) {
liveStartedAtRef.current = messageCreatedAtMs;
} }
const startedAt = liveStartedAtRef.current; const startedAt = liveStartedAtRef.current;
if (startedAt === null) { if (startedAt === null) {