import { Effect, Result } from "effect"; import type { Dispatch, SetStateAction } from "react"; import api from "@/lib/api/client"; import type { EngineJob, RuntimeTarget, StarterPreset, StudioDiagnostics, StudioSettings, } from "@/lib/types"; import { CONTROLLER_UNREACHABLE_MESSAGE, formatLoadWarning, requestEffect, setupErrorMessage, withSetupTimeoutEffect, } from "./use-setup-effects"; type RuntimeStateSetters = { setRuntimeTargets: Dispatch>; setRuntimeJobs: Dispatch>; }; export type SetupLoadSetters = RuntimeStateSetters & { setLoading: Dispatch>; setError: Dispatch>; setLoadWarning: Dispatch>; setSettings: Dispatch>; setModelsDir: Dispatch>; setDiagnostics: Dispatch>; setMaxVram: Dispatch>; setPresets: Dispatch>; }; export function refreshRuntimeStateEffect({ setRuntimeTargets, setRuntimeJobs, }: RuntimeStateSetters) { return Effect.gen(function* () { const [targetPayload, jobPayload] = yield* Effect.all([ requestEffect(() => api.getRuntimeTargets()).pipe( Effect.catch(() => Effect.succeed({ targets: [] })), ), requestEffect(() => api.getRuntimeJobs()).pipe( Effect.catch(() => Effect.succeed({ jobs: [] })), ), ] as const); setRuntimeTargets(targetPayload.targets); setRuntimeJobs(jobPayload.jobs); }); } export function loadSecondarySetupDataEffect( initialWarnings: string[], { setPresets, setMaxVram, setRuntimeTargets, setRuntimeJobs, setLoadWarning }: SetupLoadSetters, ) { return Effect.gen(function* () { const warnings = [...initialWarnings]; const [presetsResult, targetResult, jobResult] = yield* Effect.all([ Effect.result(withSetupTimeoutEffect(api.getStarterPresets(), "starter presets")), Effect.result(withSetupTimeoutEffect(api.getRuntimeTargets(), "runtime targets")), Effect.result(withSetupTimeoutEffect(api.getRuntimeJobs(), "runtime jobs")), ] as const); if (Result.isSuccess(presetsResult)) { setPresets(presetsResult.success.presets || []); setMaxVram(presetsResult.success.max_vram_gb ?? 0); } else { setPresets([]); setMaxVram(0); warnings.push(`starter presets: ${setupErrorMessage(presetsResult.failure)}`); } if (Result.isSuccess(targetResult)) { setRuntimeTargets(targetResult.success.targets); } else { setRuntimeTargets([]); warnings.push(`runtime targets: ${setupErrorMessage(targetResult.failure)}`); } if (Result.isSuccess(jobResult)) { setRuntimeJobs(jobResult.success.jobs); } else { setRuntimeJobs([]); warnings.push(`runtime jobs: ${setupErrorMessage(jobResult.failure)}`); } setLoadWarning(formatLoadWarning(warnings)); }); } export function loadSetupDataEffect( { setLoading, setError, setLoadWarning, setSettings, setModelsDir, setDiagnostics, setMaxVram, setRuntimeTargets, setRuntimeJobs, }: SetupLoadSetters, loadSecondarySetupData: (initialWarnings: string[]) => Promise, ) { return Effect.gen(function* () { setLoading(true); setError(null); setLoadWarning(null); const warnings: string[] = []; const [settingsResult, diagnosticsResult] = yield* Effect.all([ Effect.result(withSetupTimeoutEffect(api.getStudioSettings(), "settings")), Effect.result(withSetupTimeoutEffect(api.getStudioDiagnostics(), "controller diagnostics")), ] as const); if (Result.isSuccess(settingsResult)) { setSettings(settingsResult.success); setModelsDir(settingsResult.success.effective.models_dir); } else { setSettings(null); warnings.push(`settings: ${setupErrorMessage(settingsResult.failure)}`); } if (Result.isSuccess(diagnosticsResult)) { setDiagnostics(diagnosticsResult.success); if (Result.isFailure(settingsResult)) { setModelsDir(diagnosticsResult.success.config.models_dir || ""); } } else { setDiagnostics(null); warnings.push(`controller diagnostics: ${setupErrorMessage(diagnosticsResult.failure)}`); } if (Result.isFailure(settingsResult) && Result.isFailure(diagnosticsResult)) { setError(CONTROLLER_UNREACHABLE_MESSAGE); return; } setMaxVram(0); setRuntimeTargets([]); setRuntimeJobs([]); setLoadWarning(formatLoadWarning(warnings)); void loadSecondarySetupData(warnings); }).pipe( Effect.ensuring( Effect.sync(() => { setLoading(false); }), ), ); }