From e75a1078bdd43e7f6a2fd2cd56c3af989534f593 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 1 Jul 2026 21:43:13 +0800 Subject: [PATCH] fix(ui): retry autonomous runtime control readback --- .../tabs/automation-inventory-tab.tsx | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx index 774aedfaa..ec5648f31 100644 --- a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx +++ b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx @@ -361,6 +361,12 @@ function settledPublicValue(result: PromiseSettledResult): T | null { return result.status === 'fulfilled' ? sanitizePublicSnapshot(result.value) : null } +const AUTONOMOUS_RUNTIME_CONTROL_RETRY_DELAYS_MS = [1500, 5000, 12000, 25000] as const + +function hasAutonomousRuntimeControlDeployMarker(snapshot: AiAgentAutonomousRuntimeControlSnapshot | null): boolean { + return Boolean(snapshot?.program_status?.deploy_readback_marker) +} + function toneColor(tone: 'ok' | 'warn' | 'danger' | 'neutral') { if (tone === 'ok') return '#22C55E' if (tone === 'warn') return '#F59E0B' @@ -1546,6 +1552,39 @@ export function AutomationInventoryTab() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []) + useEffect(() => { + let cancelled = false + let retryTimeout: number | null = null + + const scheduleReadback = (attemptIndex: number) => { + const delayMs = AUTONOMOUS_RUNTIME_CONTROL_RETRY_DELAYS_MS[attemptIndex] + retryTimeout = window.setTimeout(() => { + if (cancelled) return + apiClient.getAiAgentAutonomousRuntimeControl() + .then(value => { + if (cancelled) return + const nextSnapshot = sanitizePublicSnapshot(value) + setAutonomousRuntimeControl(nextSnapshot) + if (!hasAutonomousRuntimeControlDeployMarker(nextSnapshot) && attemptIndex + 1 < AUTONOMOUS_RUNTIME_CONTROL_RETRY_DELAYS_MS.length) { + scheduleReadback(attemptIndex + 1) + } + }) + .catch(() => { + if (!cancelled && attemptIndex + 1 < AUTONOMOUS_RUNTIME_CONTROL_RETRY_DELAYS_MS.length) { + scheduleReadback(attemptIndex + 1) + } + }) + }, delayMs) + } + + scheduleReadback(0) + + return () => { + cancelled = true + if (retryTimeout !== null) window.clearTimeout(retryTimeout) + } + }, []) + const groupedAssets = useMemo(() => { const groups = new Map() if (!snapshot) return []