import { invoke } from "@tauri-apps/api/core"; import { createDefaultRuntimeSnapshot, createRuntimeLifecycleResult } from "./runtime-utils"; import type { HuggingFaceDownloadProgress, ModelLibraryState, HuggingFaceModelResult, RuntimeConfig, RuntimeGpuInfo, RuntimeModelFile, RuntimePickDirResult, RuntimeSnapshot, } from "./types"; const STORAGE_KEY = "forgelm_runtime_snapshot_v1"; export const HUGGING_FACE_DOWNLOAD_EVENT = "hugging-face-download-progress"; function canUseLocalStorage(): boolean { return typeof window !== "undefined" && typeof window.localStorage !== "undefined"; } function readFallbackSnapshot(): RuntimeSnapshot { if (!canUseLocalStorage()) { return createDefaultRuntimeSnapshot(); } const raw = window.localStorage.getItem(STORAGE_KEY); if (!raw) { return createDefaultRuntimeSnapshot(); } try { return { ...createDefaultRuntimeSnapshot(), ...JSON.parse(raw) } as RuntimeSnapshot; } catch { return createDefaultRuntimeSnapshot(); } } function writeFallbackSnapshot(snapshot: RuntimeSnapshot): RuntimeSnapshot { if (canUseLocalStorage()) { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(snapshot)); } return snapshot; } export async function bootstrapRuntime(): Promise { try { return await invoke("bootstrap_runtime_command"); } catch { return readFallbackSnapshot(); } } export async function getRuntimeSnapshot(): Promise { try { return await invoke("get_runtime_snapshot_command"); } catch { return readFallbackSnapshot(); } } export async function saveRuntimeConfig(config: RuntimeConfig): Promise { try { return await invoke("save_runtime_config_command_handler", { config }); } catch { const snapshot = readFallbackSnapshot(); return writeFallbackSnapshot({ ...snapshot, active_command: "idle", last_command_result: createRuntimeLifecycleResult("save", "Save completed."), config, }); } } export async function startRuntime(): Promise { try { return await invoke("start_runtime_command"); } catch { const snapshot = readFallbackSnapshot(); return writeFallbackSnapshot({ ...snapshot, status: "error", active_command: "idle", last_command_result: createRuntimeLifecycleResult( "start", "Local runtime control requires the Tauri desktop app.", "failed", ), last_error: { code: "tauri_unavailable", message: "Local runtime control requires the Tauri desktop app." }, }); } } export async function stopRuntime(): Promise { try { return await invoke("stop_runtime_command"); } catch { const snapshot = readFallbackSnapshot(); return writeFallbackSnapshot({ ...snapshot, status: "stopped", process_running: false, ready: false, active_command: "idle", last_command_result: createRuntimeLifecycleResult("stop", "Local API stopped."), }); } } export async function queryRuntimeGpu(): Promise { try { return await invoke("query_gpu"); } catch { return null; } } export async function scanRuntimeModels(dir: string): Promise { return invoke("scan_models", { dir }); } export async function pickRuntimeModelsDir(): Promise { try { return await invoke("pick_models_dir"); } catch (error) { if (String(error) === "cancelled") { return null; } throw error; } } export async function pickRuntimeModelFiles(): Promise { try { return await invoke("pick_model_files"); } catch (error) { if (String(error) === "cancelled") { return []; } throw error; } } export async function searchHuggingFaceModels(query: string, token = ""): Promise { return invoke("search_hugging_face_models_command", { query, token: token.trim() || null, }); } export async function startHuggingFaceDownload(repo: string, fileName: string, token = ""): Promise { try { return await invoke("start_hugging_face_download_command", { repo, fileName, token: token.trim() || null, }); } catch (err) { console.error("[api] startHuggingFaceDownload failed:", err); throw err; } } export async function cancelHuggingFaceDownload(downloadId: string): Promise { try { return await invoke("cancel_hugging_face_download_command", { downloadId, }); } catch (err) { console.error("[api] cancelHuggingFaceDownload failed:", err); throw err; } } export async function getModelLibraryState(): Promise { return invoke("get_model_library_state_command"); } /// Hot-swap: stop runtime → update model_path → restart. export async function swapModel(newModelPath: string): Promise { try { return await invoke("swap_model_command", { newModelPath }); } catch (err) { console.error("[api] swapModel failed:", err); throw err; } } /// Delete a local .gguf model file from disk. export async function deleteModelFile(filePath: string): Promise { try { return await invoke("delete_model_file", { filePath }); } catch (err) { console.error("[api] deleteModelFile failed:", err); throw err; } } /// Open the folder containing a model in the native file explorer. export async function openModelFolder(filePath: string): Promise { try { return await invoke("open_model_folder_command", { filePath }); } catch (err) { console.error("[api] openModelFolder failed:", err); throw err; } } export type { HuggingFaceDownloadProgress };