fix(workbench): preserve message timing authority (#1984)

Co-authored-by: root <root@lyon.remote>
This commit is contained in:
Lyon
2026-06-23 20:15:10 +08:00
committed by GitHub
parent 4f7b53f36f
commit e3a8c20fda
+7 -30
View File
@@ -1810,36 +1810,13 @@ function messageTimingPatch(value: unknown): Partial<ChatMessage> {
}
function messageTimingPatchForMerge(message: ChatMessage, value: unknown): Partial<ChatMessage> {
const patch = messageTimingPatch(value);
if (!patch.timing) return patch;
const terminal = timingPatchIsTerminal(value, patch.timing);
const durationMs = terminal
? terminalTimingDurationMsForMerge(message, patch.timing)
: maxFiniteNumber(patch.timing.durationMs, message.durationMs, message.timing?.durationMs, message.runnerTrace?.durationMs, message.runnerTrace?.timing?.durationMs);
const timing = { ...patch.timing, durationMs } as WorkbenchTurnTimingProjection;
return { timing, startedAt: timing.startedAt ?? null, lastEventAt: timing.lastEventAt ?? null, finishedAt: timing.finishedAt ?? null, durationMs };
}
function terminalTimingDurationMsForMerge(message: ChatMessage, timing: WorkbenchTurnTimingProjection): number | null {
const elapsed = elapsedTimingDurationMs(timing);
const maximum = maxFiniteNumber(timing.durationMs, elapsed, message.durationMs, message.timing?.durationMs, message.runnerTrace?.durationMs, message.runnerTrace?.timing?.durationMs);
if (maximum !== null) return maximum;
return firstFiniteNumber(timing.durationMs, elapsed, message.durationMs, message.timing?.durationMs, message.runnerTrace?.durationMs, message.runnerTrace?.timing?.durationMs);
}
function timingPatchIsTerminal(value: unknown, timing: WorkbenchTurnTimingProjection): boolean {
const record = recordValue(value);
const trace = recordValue(record?.runnerTrace);
const status = normalizedStatusText(record?.status ?? record?.traceStatus ?? trace?.status ?? trace?.traceStatus);
return Boolean(timing.finishedAt || isTerminalMessageStatus(status));
}
function elapsedTimingDurationMs(timing: WorkbenchTurnTimingProjection): number | null {
const start = timing.startedAt ? Date.parse(timing.startedAt) : NaN;
const endedAt = timing.finishedAt ?? timing.lastEventAt;
const end = endedAt ? Date.parse(endedAt) : NaN;
if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) return null;
return Math.trunc(end - start);
void value;
// Trace/result hydration may update runnerTrace and TraceTimeline, but the
// main Code Agent card timing is a durable message projection field. Do not
// let trace snapshots or terminal result polling rewrite message.timing;
// otherwise visible card elapsed can jump or diverge from the sealed message
// projection when trace rows arrive out of order.
return messageTimingPatch(message);
}
function firstPositiveFiniteNumber(...values: unknown[]): number | null {