Preserve elapsed time in replay activity parts

This commit is contained in:
武阳
2026-05-08 21:09:32 +08:00
parent b5a4c208d5
commit 39635617ae
2 changed files with 14 additions and 3 deletions
@@ -442,7 +442,7 @@ export function toReplayRepository(
id, id,
role: message.role, role: message.role,
createdAt: new Date(), createdAt: new Date(),
content: toThreadMessageContent(parts), content: toThreadMessageContent(parts, elapsedMs),
...(message.role === "assistant" ...(message.role === "assistant"
? { ? {
status: { type: "complete", reason: "stop" }, status: { type: "complete", reason: "stop" },
@@ -797,9 +797,11 @@ function attachStageNote(input: unknown, stageNote?: string) {
return { value: input, __claw_stage_note: note }; return { value: input, __claw_stage_note: note };
} }
function toThreadMessageContent(parts: UIMessage["parts"]) { function toThreadMessageContent(parts: UIMessage["parts"], elapsedMs?: number) {
return parts.map((part) => { return parts.map((part) => {
if (part.type === "text" || part.type === "reasoning") return part; const elapsedPayload = elapsedMs === undefined ? {} : { elapsedMs };
if (part.type === "text") return part;
if (part.type === "reasoning") return { ...part, ...elapsedPayload };
if (part.type === "dynamic-tool") { if (part.type === "dynamic-tool") {
return { return {
type: "tool-call", type: "tool-call",
@@ -807,6 +809,7 @@ function toThreadMessageContent(parts: UIMessage["parts"]) {
toolCallId: part.toolCallId, toolCallId: part.toolCallId,
args: part.input ?? {}, args: part.input ?? {},
argsText: JSON.stringify(part.input ?? {}), argsText: JSON.stringify(part.input ?? {}),
...elapsedPayload,
...(part.state === "output-available" ? { result: part.output } : {}), ...(part.state === "output-available" ? { result: part.output } : {}),
}; };
} }
@@ -1316,6 +1316,13 @@ const ActivityChainSummary: FC<{
); );
const storedElapsedMs = useAuiState((s) => { const storedElapsedMs = useAuiState((s) => {
const value = readMetadataValue(s.message.metadata, "elapsedMs"); const value = readMetadataValue(s.message.metadata, "elapsedMs");
const contentValue = findNumberInActivityParts(
s.message.content,
"elapsedMs",
);
if (typeof value !== "number" || !Number.isFinite(value)) {
return contentValue;
}
return typeof value === "number" && Number.isFinite(value) return typeof value === "number" && Number.isFinite(value)
? Math.max(0, Math.round(value)) ? Math.max(0, Math.round(value))
: null; : null;
@@ -1376,6 +1383,7 @@ type ActivitySummaryPart = {
args?: unknown; args?: unknown;
toolName?: string; toolName?: string;
runStartedAtMs?: unknown; runStartedAtMs?: unknown;
elapsedMs?: unknown;
}; };
function findNumberInActivityParts( function findNumberInActivityParts(