Persist active run state for replay
This commit is contained in:
@@ -69,6 +69,10 @@ export type ClawRunStatus = {
|
||||
| "interrupted";
|
||||
current_stage?: string;
|
||||
started_at?: number;
|
||||
updated_at?: number;
|
||||
finished_at?: number;
|
||||
elapsed_ms?: number;
|
||||
cancellable?: boolean;
|
||||
pending_prompt?: string;
|
||||
events?: ClawRunEvent[];
|
||||
};
|
||||
@@ -590,8 +594,9 @@ function buildActiveRunParts(runStatus: ClawActiveRunStatus) {
|
||||
: runStatus.current_stage || "后端正在执行这个会话。";
|
||||
const reasoningText = eventLines.length ? eventLines.join("\n") : fallback;
|
||||
const runStartedAtMs = resolveRunStartedAtMs(runStatus);
|
||||
const elapsedMs = normalizeElapsedMs(runStatus.elapsed_ms);
|
||||
return [
|
||||
{ type: "reasoning", text: reasoningText, runStartedAtMs },
|
||||
{ type: "reasoning", text: reasoningText, runStartedAtMs, elapsedMs },
|
||||
...buildRunToolParts(runStatus.events ?? []),
|
||||
];
|
||||
}
|
||||
@@ -795,6 +800,12 @@ function resolveRunStartedAtMs(runStatus: ClawRunStatus) {
|
||||
const direct = normalizeRunTimestampMs(runStatus.started_at);
|
||||
if (direct !== undefined) return direct;
|
||||
|
||||
const updatedAt = normalizeRunTimestampMs(runStatus.updated_at);
|
||||
const elapsedMs = normalizeElapsedMs(runStatus.elapsed_ms);
|
||||
if (updatedAt !== undefined && elapsedMs !== undefined) {
|
||||
return Math.max(0, updatedAt - elapsedMs);
|
||||
}
|
||||
|
||||
for (const event of runStatus.events ?? []) {
|
||||
if (event.type !== "run_started") continue;
|
||||
const eventStarted = normalizeRunTimestampMs(event.started_at);
|
||||
|
||||
@@ -1884,7 +1884,6 @@ const ActivityChainSummary: FC<{
|
||||
partIndex: number | undefined;
|
||||
}> = ({ messageId, partIndex }) => {
|
||||
const { openItem } = useActivityPanel();
|
||||
const startedAtRef = useRef(Date.now());
|
||||
const metadataRunStartedAtMs = useAuiState((s) => {
|
||||
const value = readMetadataValue(s.message.metadata, "runStartedAtMs");
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
||||
@@ -1933,9 +1932,11 @@ const ActivityChainSummary: FC<{
|
||||
const startedAt =
|
||||
metadataRunStartedAtMs ??
|
||||
contentRunStartedAtMs ??
|
||||
(storedElapsedMs === null
|
||||
? startedAtRef.current
|
||||
: Date.now() - storedElapsedMs);
|
||||
(storedElapsedMs === null ? null : Date.now() - storedElapsedMs);
|
||||
if (startedAt === null) {
|
||||
setElapsedMs(storedElapsedMs);
|
||||
return;
|
||||
}
|
||||
setElapsedMs(Math.max(0, Date.now() - startedAt));
|
||||
const timer = window.setInterval(() => {
|
||||
setElapsedMs(Math.max(0, Date.now() - startedAt));
|
||||
@@ -2021,11 +2022,12 @@ function summarizeActivityChainLabel(
|
||||
(isGenericActivityLine(lastReasoningLine) ? "" : lastReasoningLine);
|
||||
|
||||
if (status === "running") {
|
||||
const elapsed = `用时 ${formatActivityDuration(elapsedMs ?? 0)}`;
|
||||
const elapsed =
|
||||
elapsedMs === null ? "" : `,用时 ${formatActivityDuration(elapsedMs)}`;
|
||||
if (activeDetail) {
|
||||
return `${compactActivityLabel(activeDetail, 15)},${elapsed}`;
|
||||
return `${compactActivityLabel(activeDetail, 15)}${elapsed}`;
|
||||
}
|
||||
return `思考中,${elapsed}`;
|
||||
return elapsed ? `思考中${elapsed}` : "思考中";
|
||||
}
|
||||
|
||||
const label = compactActivityLabel(
|
||||
|
||||
Reference in New Issue
Block a user