import { invoke } from "@tauri-apps/api/core"; import { hasTauriRuntime } from "$lib/utils/runtime.js"; /// Visible LLM state for the status chip (brief item #31). /// off — user has settings.aiTier === "off"; chip hidden. /// warming — model download or load in progress. /// ready — model loaded, idle. /// generating — an active cleanup_transcript_text_cmd call is in flight. /// error — last health check or generation failed. export type LlmStatusKind = "off" | "warming" | "ready" | "generating" | "error"; export interface LlmStatusState { kind: LlmStatusKind; /// Optional short phrase for the chip to surface (e.g. "Loading Qwen3.5 4B"). detail: string | null; } export const llmStatus = $state({ kind: "off", detail: null }); /// Poll `get_llm_status` once. Cheap enough to call on layout mount, on /// recording start, and on Settings-panel open. Keeps the chip in sync /// with loads / unloads that happen outside the frontend's observation /// path (first-run, background reload). The `aiTier` input short-circuits /// to "off" so we don't show a chip when the user has opted out. export async function refreshLlmStatus(aiTier: string): Promise { if (aiTier === "off") { llmStatus.kind = "off"; llmStatus.detail = null; return; } if (!hasTauriRuntime()) { // Running in a pure-browser preview (vite dev without tauri) — leave // the chip off rather than asserting a loaded state we can't verify. llmStatus.kind = "off"; llmStatus.detail = null; return; } try { const loaded = await invoke("get_llm_status"); // Don't clobber a "generating" state with "ready" — a parallel // cleanup call in flight is a truer signal than the load status. if (llmStatus.kind === "generating") return; llmStatus.kind = loaded ? "ready" : "warming"; llmStatus.detail = null; } catch (err) { llmStatus.kind = "error"; llmStatus.detail = typeof err === "string" ? err : (err as Error)?.message ?? "Unknown error"; } } export function markGenerating(detail: string | null = null): void { llmStatus.kind = "generating"; llmStatus.detail = detail; } export function markGenerationDone(success: boolean, detail: string | null = null): void { if (success) { llmStatus.kind = "ready"; llmStatus.detail = null; } else { llmStatus.kind = "error"; llmStatus.detail = detail; } }