Buckets:
| import { createEffect, createMemo, createSignal, on, onCleanup, Show } from "solid-js" | |
| import type { SessionStatus } from "@opencode-ai/sdk/v2/client" | |
| import { useI18n } from "../context/i18n" | |
| import { Card } from "./card" | |
| import { Tooltip } from "./tooltip" | |
| import { Spinner } from "./spinner" | |
| export function SessionRetry(props: { status: SessionStatus; show?: boolean }) { | |
| const i18n = useI18n() | |
| const retry = createMemo(() => { | |
| if (props.status.type !== "retry") return | |
| return props.status | |
| }) | |
| const [seconds, setSeconds] = createSignal(0) | |
| createEffect( | |
| on(retry, (current) => { | |
| if (!current) return | |
| const update = () => { | |
| const next = retry()?.next | |
| if (!next) return | |
| setSeconds(Math.round((next - Date.now()) / 1000)) | |
| } | |
| update() | |
| const timer = setInterval(update, 1000) | |
| onCleanup(() => clearInterval(timer)) | |
| }), | |
| ) | |
| const message = createMemo(() => { | |
| const current = retry() | |
| if (!current) return "" | |
| if (current.message.includes("exceeded your current quota") && current.message.includes("gemini")) { | |
| return i18n.t("ui.sessionTurn.retry.geminiHot") | |
| } | |
| if (current.message.length > 80) return current.message.slice(0, 80) + "..." | |
| return current.message | |
| }) | |
| const truncated = createMemo(() => { | |
| const current = retry() | |
| if (!current) return false | |
| return current.message.length > 80 | |
| }) | |
| const info = createMemo(() => { | |
| const current = retry() | |
| if (!current) return "" | |
| const count = Math.max(0, seconds()) | |
| const delay = count > 0 ? i18n.t("ui.sessionTurn.retry.inSeconds", { seconds: count }) : "" | |
| const retrying = i18n.t("ui.sessionTurn.retry.retrying") | |
| const line = [retrying, delay].filter(Boolean).join(" ") | |
| if (!line) return i18n.t("ui.sessionTurn.retry.attempt", { attempt: current.attempt }) | |
| return i18n.t("ui.sessionTurn.retry.attemptLine", { line, attempt: current.attempt }) | |
| }) | |
| return ( | |
| <Show when={retry() && (props.show ?? true)}> | |
| <div data-slot="session-turn-retry"> | |
| <Card variant="error" class="error-card"> | |
| <div class="flex items-start gap-2"> | |
| <Spinner class="size-4 mt-0.5" /> | |
| <div class="min-w-0"> | |
| <Show when={truncated()} fallback={<div data-slot="session-turn-retry-message">{message()}</div>}> | |
| <Tooltip value={retry()?.message ?? ""} placement="top"> | |
| <div data-slot="session-turn-retry-message" class="cursor-help truncate"> | |
| {message()} | |
| </div> | |
| </Tooltip> | |
| </Show> | |
| <Show when={info()}>{(line) => <div data-slot="session-turn-retry-info">{line()}</div>}</Show> | |
| </div> | |
| </div> | |
| </Card> | |
| </div> | |
| </Show> | |
| ) | |
| } | |
Xet Storage Details
- Size:
- 2.81 kB
- Xet hash:
- 67b3b73502fe82d0aab5318bc1d0a3d21ace527c70c89415069bca29a214a2b3
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.