fix(workbench): keep provider retry diagnostics non-terminal

This commit is contained in:
lyon
2026-06-21 07:12:33 +08:00
parent 4dc6e24abd
commit eedd8b6bfb
2 changed files with 28 additions and 4 deletions
+19 -1
View File
@@ -2473,6 +2473,7 @@ function mapAgentRunEvent(event, mapping = {}) {
function agentRunProviderRetryEvent({ base = {}, payload = {}, status = "retrying", label = "agentrun:provider-retry" } = {}) {
const failureKind = normalizedFailureKind(payload.failureKind ?? payload.errorCode ?? "provider-stream-disconnected");
const retryMessage = providerRetryMessage(textPayload(payload, "Provider stream disconnected; AgentRun will retry."), payload);
return {
...base,
type: "provider_retry",
@@ -2491,11 +2492,28 @@ function agentRunProviderRetryEvent({ base = {}, payload = {}, status = "retryin
nextRetryAt: firstNonEmpty(payload.nextRetryAt) || null,
retryOf: payload.retryOf ?? null,
terminalStatus: payload.terminalStatus ?? null,
message: textPayload(payload, "Provider stream disconnected; AgentRun will retry."),
message: retryMessage,
valuesPrinted: false
};
}
function providerRetryMessage(message, payload = {}) {
const attempt = numberOrNull(payload.retryAttempt);
const max = numberOrNull(payload.retryMax);
const delayMs = numberOrNull(payload.retryDelayMs);
const nextRetryAt = firstNonEmpty(payload.nextRetryAt) || null;
const parts = [];
if (attempt !== null && max !== null) parts.push(`retry ${attempt}/${max}`);
else if (attempt !== null) parts.push(`retry attempt ${attempt}`);
else if (max !== null) parts.push(`retry max ${max}`);
if (delayMs !== null) parts.push(`after ${delayMs}ms`);
if (nextRetryAt) parts.push(`next=${nextRetryAt}`);
if (parts.length === 0) return message;
const text = String(message || "Provider stream disconnected; AgentRun will retry.").trim();
if (attempt !== null && max !== null && text.includes(`${attempt}/${max}`)) return text;
return text.replace(/[.。]\s*$/u, "") + `; ${parts.join(" ")}.`;
}
function isRetryableProviderInterruptionPayload(payload = {}, options = {}) {
const kind = normalizedFailureKind(payload?.failureKind ?? payload?.errorCode ?? payload?.code);
if (kind === "provider-stream-disconnected") return payload?.willRetry === true;
+9 -3
View File
@@ -117,12 +117,17 @@ export function projectionDiagnostics({ traceId = null, projection = null, resul
const turn = projection ?? createWorkbenchTurnProjection({ traceId, result, trace });
const sealedCompleted = turn.terminal === true && turn.status === "completed" && Boolean(turn.finalResponse?.text);
const source = sealedCompleted ? null : projectionDiagnosticSource(trace);
const blocker = sealedCompleted ? null : refreshError ?? source?.blocker ?? trace?.blocker ?? result?.blocker ?? result?.error ?? null;
const rawBlocker = sealedCompleted ? null : refreshError ?? source?.blocker ?? trace?.blocker ?? result?.blocker ?? result?.error ?? null;
const retryingProviderInterruption = !sealedCompleted && turn.running === true ? retryableProviderInterruptionEvidence(rawBlocker) : null;
const blocker = retryingProviderInterruption ? null : rawBlocker;
const hasProjectionInput = hasTraceProjection(trace) || Boolean(result || result?.agentRun);
const sourceStatus = sealedCompleted ? null : normalizeProjectionStatus(source?.projectionStatus ?? trace?.projectionStatus);
const status = sealedCompleted ? "caught-up" : sourceStatus ?? (blocker ? "blocked" : turn.terminal ? "caught-up" : hasProjectionInput ? "projecting" : "unknown");
const effectiveSourceStatus = retryingProviderInterruption && sourceStatus === "blocked" ? "projecting" : sourceStatus;
const status = sealedCompleted ? "caught-up" : effectiveSourceStatus ?? (blocker ? "blocked" : turn.terminal ? "caught-up" : hasProjectionInput ? "projecting" : "unknown");
const diagnostic = blocker ? diagnosticBlocker(blocker) : null;
const projectionHealth = sealedCompleted ? "healthy" : normalizeProjectionHealth(source?.projectionHealth ?? trace?.projectionHealth)
const sourceHealth = sealedCompleted ? null : normalizeProjectionHealth(source?.projectionHealth ?? trace?.projectionHealth);
const effectiveSourceHealth = retryingProviderInterruption && (sourceHealth === "degraded" || sourceHealth === "unavailable" || sourceHealth === "stalled") ? "projecting" : sourceHealth;
const projectionHealth = sealedCompleted ? "healthy" : effectiveSourceHealth
?? projectionHealthFor({ status, turn, hasProjectionInput, blocker: diagnostic });
const staleMs = sealedCompleted ? null : projectionStaleMs(source?.staleMs ?? trace?.staleMs, turn.updatedAt ?? trace?.updatedAt ?? result?.updatedAt);
return {
@@ -133,6 +138,7 @@ export function projectionDiagnostics({ traceId = null, projection = null, resul
sourceCommandId: turn.sourceCommandId ?? null,
staleMs,
blocker: diagnostic,
retryingProviderInterruption,
updatedAt: turn.updatedAt ?? null,
valuesRedacted: true
};