chore: expurgo de blobs excedentes e realinhamento de estado
release.yml (push) Invalid workflow file
release.yml (push) Invalid workflow file
This commit is contained in:
1 parent
593efd42e0
commit
a7cbd1a3b4
114 files changed
+20716
-4258
No files matched your search
@@ -0,0 +1,366 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
|
||||
export interface SetupWizardState {
|
||||
currentStep: number;
|
||||
completedSteps: number[];
|
||||
ollamaInstalled: boolean;
|
||||
ollamaRunning: boolean;
|
||||
modelDownloaded: boolean;
|
||||
modelName: string | null;
|
||||
lastError: string | null;
|
||||
progressMessage: string | null;
|
||||
progressStatus: string | null;
|
||||
}
|
||||
|
||||
const CHECKPOINT_KEY = 'ollahub_setup_wizard_checkpoint';
|
||||
const DEFAULT_MODEL = 'llama3.2:1b';
|
||||
const MAX_STEPS = 4;
|
||||
const MIN_STEP = 1;
|
||||
|
||||
function getDefaultState(): SetupWizardState {
|
||||
return {
|
||||
currentStep: 1,
|
||||
completedSteps: [],
|
||||
ollamaInstalled: false,
|
||||
ollamaRunning: false,
|
||||
modelDownloaded: false,
|
||||
modelName: null,
|
||||
lastError: null,
|
||||
progressMessage: null,
|
||||
progressStatus: null,
|
||||
};
|
||||
}
|
||||
|
||||
function validateWizardState(state: unknown): SetupWizardState | null {
|
||||
// Verificar se é um objeto
|
||||
if (!state || typeof state !== 'object' || Array.isArray(state)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const stateObj = state as Record<string, unknown>;
|
||||
|
||||
// Validar currentStep
|
||||
const currentStep = typeof stateObj.currentStep === 'number'
|
||||
? Math.max(MIN_STEP, Math.min(MAX_STEPS, Math.round(stateObj.currentStep)))
|
||||
: MIN_STEP;
|
||||
|
||||
// Validar completedSteps
|
||||
const completedSteps = Array.isArray(stateObj.completedSteps)
|
||||
? stateObj.completedSteps
|
||||
.filter((step: unknown) => typeof step === 'number' && step >= MIN_STEP && step <= MAX_STEPS)
|
||||
.map((step: unknown) => Math.round(step as number))
|
||||
.filter((step: number, index: number, arr: number[]) => arr.indexOf(step) === index) // Remover duplicatas
|
||||
: [];
|
||||
|
||||
// Validar tipos dos campos booleanos
|
||||
const ollamaInstalled = typeof stateObj.ollamaInstalled === 'boolean' ? stateObj.ollamaInstalled : false;
|
||||
const ollamaRunning = typeof stateObj.ollamaRunning === 'boolean' ? stateObj.ollamaRunning : false;
|
||||
const modelDownloaded = typeof stateObj.modelDownloaded === 'boolean' ? stateObj.modelDownloaded : false;
|
||||
|
||||
// Validar modelName (pode ser null ou string)
|
||||
const modelName = stateObj.modelName === null || typeof stateObj.modelName === 'string'
|
||||
? stateObj.modelName as string | null
|
||||
: null;
|
||||
|
||||
// Validar lastError (pode ser null ou string)
|
||||
const lastError = stateObj.lastError === null || typeof stateObj.lastError === 'string'
|
||||
? stateObj.lastError as string | null
|
||||
: null;
|
||||
|
||||
// Validar progressMessage (pode ser null ou string)
|
||||
const progressMessage = stateObj.progressMessage === null || typeof stateObj.progressMessage === 'string'
|
||||
? stateObj.progressMessage as string | null
|
||||
: null;
|
||||
|
||||
// Validar progressStatus (pode ser null ou string)
|
||||
const progressStatus = stateObj.progressStatus === null || typeof stateObj.progressStatus === 'string'
|
||||
? stateObj.progressStatus as string | null
|
||||
: null;
|
||||
|
||||
return {
|
||||
currentStep,
|
||||
completedSteps,
|
||||
ollamaInstalled,
|
||||
ollamaRunning,
|
||||
modelDownloaded,
|
||||
modelName,
|
||||
lastError,
|
||||
progressMessage,
|
||||
progressStatus,
|
||||
};
|
||||
}
|
||||
|
||||
export function useSetupWizard() {
|
||||
const [state, setState] = useState<SetupWizardState>(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const saved = localStorage.getItem(CHECKPOINT_KEY);
|
||||
if (saved) {
|
||||
try {
|
||||
const parsed = JSON.parse(saved);
|
||||
const validated = validateWizardState(parsed);
|
||||
|
||||
if (validated) {
|
||||
return validated;
|
||||
} else {
|
||||
// Estado inválido, remover do localStorage e usar estado inicial
|
||||
console.warn('Estado do wizard inválido detectado, resetando para estado inicial');
|
||||
localStorage.removeItem(CHECKPOINT_KEY);
|
||||
}
|
||||
} catch (error) {
|
||||
// Se falhar ao fazer parse, remover item corrompido
|
||||
console.error('Erro ao fazer parse do estado do wizard:', error);
|
||||
localStorage.removeItem(CHECKPOINT_KEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getDefaultState();
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CHECKPOINT_KEY, JSON.stringify(state));
|
||||
}
|
||||
}, [state]);
|
||||
|
||||
useEffect(() => {
|
||||
const unlistenPromise = listen<{ status: string; message: string }>('setup-progress', (event) => {
|
||||
const { status, message } = event.payload;
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
progressStatus: status,
|
||||
progressMessage: message,
|
||||
}));
|
||||
});
|
||||
|
||||
return () => {
|
||||
unlistenPromise.then(unlisten => unlisten());
|
||||
};
|
||||
}, []);
|
||||
|
||||
const checkSetupState = useCallback(async () => {
|
||||
try {
|
||||
const setupState = await invoke<{
|
||||
ollama_installed: boolean;
|
||||
ollama_running: boolean;
|
||||
default_model_downloaded: boolean;
|
||||
default_model_name: string | null;
|
||||
}>('get_setup_state_command');
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
ollamaInstalled: setupState.ollama_installed,
|
||||
ollamaRunning: setupState.ollama_running,
|
||||
modelDownloaded: setupState.default_model_downloaded,
|
||||
modelName: setupState.default_model_name || DEFAULT_MODEL,
|
||||
}));
|
||||
|
||||
let initialStep = 1;
|
||||
if (setupState.ollama_installed && setupState.ollama_running) {
|
||||
initialStep = 2;
|
||||
if (setupState.default_model_downloaded) {
|
||||
initialStep = 4;
|
||||
} else {
|
||||
initialStep = 3;
|
||||
}
|
||||
}
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
currentStep: Math.max(prev.currentStep, initialStep),
|
||||
}));
|
||||
|
||||
return setupState;
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
lastError: errorMsg,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const nextStep = useCallback(() => {
|
||||
setState(prev => {
|
||||
const next = prev.currentStep + 1;
|
||||
return {
|
||||
...prev,
|
||||
currentStep: next,
|
||||
completedSteps: [...prev.completedSteps, prev.currentStep],
|
||||
lastError: null,
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
const previousStep = useCallback(() => {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
currentStep: Math.max(1, prev.currentStep - 1),
|
||||
lastError: null,
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const goToStep = useCallback((step: number) => {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
currentStep: Math.max(1, Math.min(4, step)),
|
||||
lastError: null,
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const checkChocolatey = useCallback(async (): Promise<boolean> => {
|
||||
try {
|
||||
return await invoke<boolean>('check_chocolatey_installed_command');
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar Chocolatey:', error);
|
||||
return false;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const installChocolatey = useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
progressMessage: 'Instalando Chocolatey...',
|
||||
progressStatus: 'installing_chocolatey',
|
||||
lastError: null,
|
||||
}));
|
||||
|
||||
await invoke('install_chocolatey_command');
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
progressMessage: 'Chocolatey instalado com sucesso',
|
||||
progressStatus: null,
|
||||
}));
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Erro ao instalar Chocolatey';
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
lastError: errorMsg,
|
||||
progressStatus: null,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const installOllamaViaChoco = useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
progressMessage: 'Instalando Ollama via Chocolatey...',
|
||||
progressStatus: 'installing_ollama',
|
||||
lastError: null,
|
||||
}));
|
||||
|
||||
await invoke('install_ollama_choco_command');
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
progressMessage: 'Ollama instalado com sucesso',
|
||||
progressStatus: null,
|
||||
}));
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Erro ao instalar Ollama via Chocolatey';
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
lastError: errorMsg,
|
||||
progressStatus: null,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const installOllama = useCallback(async (installerPath?: string) => {
|
||||
try {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
lastError: null,
|
||||
progressMessage: 'Iniciando instalação do Ollama...',
|
||||
progressStatus: 'installing_ollama',
|
||||
}));
|
||||
|
||||
await invoke('install_ollama_silently_command', {
|
||||
installerPath: installerPath || null,
|
||||
});
|
||||
|
||||
await checkSetupState();
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
ollamaInstalled: true,
|
||||
ollamaRunning: true,
|
||||
progressMessage: 'Ollama instalado e rodando!',
|
||||
progressStatus: 'ollama_ready',
|
||||
}));
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
lastError: errorMsg,
|
||||
progressMessage: `Erro: ${errorMsg}`,
|
||||
progressStatus: 'error',
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}, [checkSetupState]);
|
||||
|
||||
const downloadModel = useCallback(async (modelName: string = DEFAULT_MODEL) => {
|
||||
try {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
lastError: null,
|
||||
progressMessage: `Baixando modelo ${modelName}...`,
|
||||
progressStatus: 'downloading_model',
|
||||
}));
|
||||
|
||||
await invoke('download_default_model_command', { modelName });
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
modelDownloaded: true,
|
||||
modelName,
|
||||
progressMessage: `Modelo ${modelName} baixado com sucesso!`,
|
||||
progressStatus: 'model_ready',
|
||||
}));
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
lastError: errorMsg,
|
||||
progressMessage: `Erro ao baixar modelo: ${errorMsg}`,
|
||||
progressStatus: 'error',
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const resetWizard = useCallback(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.removeItem(CHECKPOINT_KEY);
|
||||
}
|
||||
setState(getDefaultState());
|
||||
}, []);
|
||||
|
||||
const isStepComplete = useCallback((step: number) => {
|
||||
return state.completedSteps.includes(step);
|
||||
}, [state.completedSteps]);
|
||||
|
||||
return {
|
||||
state,
|
||||
checkSetupState,
|
||||
nextStep,
|
||||
previousStep,
|
||||
goToStep,
|
||||
checkChocolatey,
|
||||
installChocolatey,
|
||||
installOllamaViaChoco,
|
||||
installOllama,
|
||||
downloadModel,
|
||||
resetWizard,
|
||||
isStepComplete,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user