| 1 | import type { Translator } from "./i18n"; |
| 2 | |
| 3 | export interface RecoveryStatus { |
| 4 | state?: "recovery_required" | string; |
| 5 | call_id?: string; |
| 6 | attempt_id?: string; |
| 7 | requires_user_decision?: boolean; |
| 8 | read_only?: boolean; |
| 9 | phase?: string; |
| 10 | reason?: string; |
| 11 | next_attempt_at?: number; |
| 12 | waited_ms?: number; |
| 13 | wait_budget_ms?: number; |
| 14 | waiting?: boolean; |
| 15 | } |
| 16 | |
| 17 | export interface RecoveryRetry { |
| 18 | attempt: number; |
| 19 | max: number; |
| 20 | recovery?: RecoveryStatus; |
| 21 | } |
| 22 | |
| 23 | export interface RecoveryEventFields { |
| 24 | recovery?: RecoveryStatus; |
| 25 | retryAttempt?: number; |
| 26 | retryMax?: number; |
| 27 | } |
| 28 | |
| 29 | export function recoveryNextAttemptSeconds(recovery: RecoveryStatus, now: number): number { |
| 30 | return Math.max(0, Math.ceil(((recovery.next_attempt_at ?? now) - now) / 1000)); |
| 31 | } |
| 32 | |
| 33 | export function recoveryStatusText(t: Translator, retry: RecoveryRetry, now: number): string { |
| 34 | if (!retry.recovery?.waiting) return t("status.retrying", { attempt: retry.attempt, max: retry.max }); |
| 35 | const phase = t(retry.recovery.phase === "connect" ? "status.recoveryNetwork" : "status.recoveryProvider"); |
| 36 | return t("status.recoveryWaiting", { seconds: recoveryNextAttemptSeconds(retry.recovery, now), phase }); |
| 37 | } |
| 38 |