fix(workbench): keep running timing stable on admission (#1987)

Co-authored-by: root <root@lyon.remote>
This commit is contained in:
Lyon
2026-06-23 21:28:08 +08:00
committed by GitHub
parent d63b08c492
commit f9b9402af4
+16 -1
View File
@@ -1428,7 +1428,7 @@ function nonBlockingProjection(projection: ProjectionDiagnostic | null): Project
const base = { ...message, traceId: canonicalTraceId, runnerTrace, updatedAt: new Date().toISOString() };
if (message.role === "user" && userMessageId) return { ...base, id: userMessageId, messageId: userMessageId, turnId };
if (message.role === "agent") {
const next = { ...base, ...admissionTiming };
const next = { ...base, ...stableAdmissionTimingPatchForRunningMessage(message, admissionTiming) };
return {
...next,
...(assistantMessageId ? { id: assistantMessageId, messageId: assistantMessageId } : {}),
@@ -1440,6 +1440,21 @@ function nonBlockingProjection(projection: ProjectionDiagnostic | null): Project
return canonicalTraceId;
}
function stableAdmissionTimingPatchForRunningMessage(message: ChatMessage, patch: Partial<ChatMessage>): Partial<ChatMessage> {
const incoming = patch.timing;
const existing = message.timing;
if (!incoming || !existing?.startedAt || !isRunningMessage(message)) return patch;
const timing = {
...incoming,
startedAt: existing.startedAt,
lastEventAt: existing.lastEventAt ?? incoming.lastEventAt ?? existing.startedAt,
finishedAt: null,
durationMs: null,
valuesRedacted: incoming.valuesRedacted !== false,
} as WorkbenchTurnTimingProjection;
return { ...patch, timing, startedAt: timing.startedAt ?? null, lastEventAt: timing.lastEventAt ?? null, finishedAt: null, durationMs: null };
}
function optimisticAdmissionTimingPatch(lifecycle: AgentChatResponse): Partial<ChatMessage> {
const patch = messageTimingPatch(lifecycle);
if (patch.timing?.startedAt && patch.timing?.lastEventAt) return patch;