fix(app): back off and offer retry when timeline sync is refused
A host can refuse a timeline read for as long as it likes. Codex does this whenever another writer holds the thread: every catch-up fails with "already has an active writer" until the other session lets go. The app retried that on a fixed 1s timer with no ceiling, so an idle window sat there issuing a request and logging a warning every second, indefinitely. The refusal is normal lifecycle; the traffic was the bug. Catch-up and subscription retries now double from 1s to a 30s ceiling, resetting on success, reconnect, delivery-mode change, and visibility change so recovery stays immediate once the condition clears. Backing off alone would leave the user waiting up to 30s with no way in, so both failure surfaces get a retry they can press. Background retries stay silent; a retry the user asked for is a fallible user action and owns its pending state, so "retrying" is a status the sync model publishes rather than a React boolean. The blocking "Failed to load agent" screen was the worse half: its load effect self-gates on the error state, so a refused first resume was terminal until the user navigated away. Its retry resets the state to idle, which re-arms the effect.
This commit is contained in:
@@ -215,7 +215,8 @@ export const ar: TranslationResources = {
|
||||
notFound: "لم يتم العثور على Agent",
|
||||
failedToLoad: "فشل تحميل الوكيل",
|
||||
reconnecting: "جارٍ إعادة الاتصال",
|
||||
timelineSyncFailed: "تعذر تحديث سجل الوكيل. جارٍ إعادة المحاولة…",
|
||||
timelineSyncFailed: "تعذر تحديث سجل الوكيل.",
|
||||
timelineSyncRetrying: "جارٍ إعادة المحاولة…",
|
||||
archivingTitle: "وكيل الارشيف...",
|
||||
archivingSubtitle: "الرجاء الانتظار بينما نقوم بأرشفة هذا الوكيل.",
|
||||
},
|
||||
|
||||
@@ -212,7 +212,8 @@ export const en = {
|
||||
notFound: "Agent not found",
|
||||
failedToLoad: "Failed to load agent",
|
||||
reconnecting: "Reconnecting",
|
||||
timelineSyncFailed: "Couldn't refresh agent history. Retrying…",
|
||||
timelineSyncFailed: "Couldn't refresh agent history.",
|
||||
timelineSyncRetrying: "Retrying…",
|
||||
archivingTitle: "Archiving agent...",
|
||||
archivingSubtitle: "Please wait while we archive this agent.",
|
||||
},
|
||||
|
||||
@@ -215,7 +215,8 @@ export const es: TranslationResources = {
|
||||
notFound: "Agentno encontrado",
|
||||
failedToLoad: "No se pudo cargar el agente",
|
||||
reconnecting: "Reconectando",
|
||||
timelineSyncFailed: "No se pudo actualizar el historial del agente. Reintentando…",
|
||||
timelineSyncFailed: "No se pudo actualizar el historial del agente.",
|
||||
timelineSyncRetrying: "Reintentando…",
|
||||
archivingTitle: "Agente de archivo...",
|
||||
archivingSubtitle: "Espere mientras archivamos este agente.",
|
||||
},
|
||||
|
||||
@@ -217,7 +217,8 @@ export const fr: TranslationResources = {
|
||||
notFound: "Agentintrouvable",
|
||||
failedToLoad: "Échec du chargement de l'agent",
|
||||
reconnecting: "Reconnexion",
|
||||
timelineSyncFailed: "Impossible d’actualiser l’historique de l’agent. Nouvelle tentative…",
|
||||
timelineSyncFailed: "Impossible d’actualiser l’historique de l’agent.",
|
||||
timelineSyncRetrying: "Nouvelle tentative…",
|
||||
archivingTitle: "Agent d'archivage...",
|
||||
archivingSubtitle: "Veuillez patienter pendant que nous archivons cet agent.",
|
||||
},
|
||||
|
||||
@@ -215,7 +215,8 @@ export const ja: TranslationResources = {
|
||||
notFound: "エージェントが見つかりません",
|
||||
failedToLoad: "エージェントの読み込みに失敗しました",
|
||||
reconnecting: "再接続中",
|
||||
timelineSyncFailed: "エージェントの履歴を更新できませんでした。再試行しています…",
|
||||
timelineSyncFailed: "エージェントの履歴を更新できませんでした。",
|
||||
timelineSyncRetrying: "再試行しています…",
|
||||
archivingTitle: "エージェントをアーカイブ中...",
|
||||
archivingSubtitle: "このエージェントをアーカイブするまでお待ちください。",
|
||||
},
|
||||
|
||||
@@ -215,7 +215,8 @@ export const ko: TranslationResources = {
|
||||
notFound: "에이전트를 찾을 수 없습니다",
|
||||
failedToLoad: "에이전트를 불러오지 못했습니다",
|
||||
reconnecting: "다시 연결하는 중",
|
||||
timelineSyncFailed: "에이전트 기록을 새로고침할 수 없습니다. 재시도 중…",
|
||||
timelineSyncFailed: "에이전트 기록을 새로고침할 수 없습니다.",
|
||||
timelineSyncRetrying: "재시도 중…",
|
||||
archivingTitle: "에이전트 보관 중...",
|
||||
archivingSubtitle: "이 에이전트를 보관하는 동안 잠시 기다려 주세요.",
|
||||
},
|
||||
|
||||
@@ -215,7 +215,8 @@ export const ptBR: TranslationResources = {
|
||||
notFound: "Agente não encontrado",
|
||||
failedToLoad: "Falha ao carregar agente",
|
||||
reconnecting: "Reconectando",
|
||||
timelineSyncFailed: "Não foi possível atualizar o histórico do agente. Tentando novamente…",
|
||||
timelineSyncFailed: "Não foi possível atualizar o histórico do agente.",
|
||||
timelineSyncRetrying: "Tentando novamente…",
|
||||
archivingTitle: "Arquivando agente...",
|
||||
archivingSubtitle: "Aguarde enquanto arquivamos este agente.",
|
||||
},
|
||||
|
||||
@@ -215,7 +215,8 @@ export const ru: TranslationResources = {
|
||||
notFound: "Agent не найден",
|
||||
failedToLoad: "Не удалось загрузить агент",
|
||||
reconnecting: "Повторное подключение",
|
||||
timelineSyncFailed: "Не удалось обновить историю агента. Повторная попытка…",
|
||||
timelineSyncFailed: "Не удалось обновить историю агента.",
|
||||
timelineSyncRetrying: "Повторная попытка…",
|
||||
archivingTitle: "Архивный агент...",
|
||||
archivingSubtitle: "Пожалуйста, подождите, пока мы архивируем этого агента.",
|
||||
},
|
||||
|
||||
@@ -215,7 +215,8 @@ export const zhCN: TranslationResources = {
|
||||
notFound: "未找到 Agent",
|
||||
failedToLoad: "加载 Agent 失败",
|
||||
reconnecting: "正在重连",
|
||||
timelineSyncFailed: "无法刷新代理历史记录。正在重试…",
|
||||
timelineSyncFailed: "无法刷新代理历史记录。",
|
||||
timelineSyncRetrying: "正在重试…",
|
||||
archivingTitle: "正在归档 Agent...",
|
||||
archivingSubtitle: "请稍候,我们正在归档这个 Agent。",
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user