fix: dismiss validating model toast correctly on setupScreen

This commit is contained in:
Vanalite
2025-11-28 17:23:05 +07:00
parent 2ab36273e5
commit e8be39b8be
5 changed files with 56 additions and 20 deletions

View File

@@ -12,6 +12,7 @@ interface DownloadItem {
proxy?: Record<string, string | string[] | boolean>
sha256?: string
size?: number
model_id?: string
}
type DownloadEvent = {

View File

@@ -278,11 +278,14 @@ export async function downloadBackend(
? `https://github.com/janhq/llama.cpp/releases/download/${version}/llama-${version}-bin-${backend}.tar.gz`
: `https://catalog.jan.ai/llama.cpp/releases/${version}/llama-${version}-bin-${backend}.tar.gz`
const taskId = `llamacpp-${version}-${backend}`.replace(/\./g, '-')
const downloadItems = [
{
url: backendUrl,
save_path: await joinPath([backendDir, 'backend.tar.gz']),
proxy: proxyConfig,
model_id: taskId,
},
]
@@ -298,6 +301,7 @@ export async function downloadBackend(
: `https://catalog.jan.ai/llama.cpp/releases/${version}/cudart-llama-bin-${platformName}-cu11.7-x64.tar.gz`,
save_path: await joinPath([backendDir, 'build', 'bin', 'cuda11.tar.gz']),
proxy: proxyConfig,
model_id: taskId,
})
} else if (
(backend.includes('cu12.0') || backend.includes('cuda-12')) &&
@@ -310,6 +314,7 @@ export async function downloadBackend(
: `https://catalog.jan.ai/llama.cpp/releases/${version}/cudart-llama-bin-${platformName}-cu12.0-x64.tar.gz`,
save_path: await joinPath([backendDir, 'build', 'bin', 'cuda12.tar.gz']),
proxy: proxyConfig,
model_id: taskId,
})
} else if (
backend.includes('cuda-13') &&
@@ -322,10 +327,9 @@ export async function downloadBackend(
: `https://catalog.jan.ai/llama.cpp/releases/${version}/cudart-llama-bin-${platformName}-cu13.0-x64.tar.gz`,
save_path: await joinPath([backendDir, 'build', 'bin', 'cuda12.tar.gz']),
proxy: proxyConfig,
model_id: taskId,
})
}
const taskId = `llamacpp-${version}-${backend}`.replace(/\./g, '-')
const downloadType = 'Engine'
console.log(

View File

@@ -102,6 +102,7 @@ interface DownloadItem {
proxy?: Record<string, string | string[] | boolean>
sha256?: string
size?: number
model_id?: string
}
interface ModelConfig {
@@ -1436,6 +1437,7 @@ export default class llamacpp_extension extends AIEngine {
sha256:
saveName === 'model.gguf' ? opts.modelSha256 : opts.mmprojSha256,
size: saveName === 'model.gguf' ? opts.modelSize : opts.mmprojSize,
model_id: modelId,
})
return localPath
}

View File

@@ -27,6 +27,7 @@ async fn validate_downloaded_file(
save_path: &Path,
app: &tauri::AppHandle<impl Runtime>,
cancel_token: &CancellationToken,
emit_event: bool,
) -> Result<(), String> {
// Skip validation if no verification data is provided
if item.sha256.is_none() && item.size.is_none() {
@@ -37,25 +38,27 @@ async fn validate_downloaded_file(
return Ok(());
}
// Extract model ID from save path for validation events
// Use model_id from item if available, otherwise extract from save path
// Path structure: llamacpp/models/{modelId}/model.gguf or llamacpp/models/{modelId}/mmproj.gguf
let model_id = save_path
.parent() // get parent directory (modelId folder)
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
.unwrap_or("unknown");
let model_id = item.model_id.as_ref().map(|s| s.as_str()).unwrap_or_else(|| {
save_path
.parent() // get parent directory (modelId folder)
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
.unwrap_or("unknown")
});
// Emit validation started event
app.emit(
"onModelValidationStarted",
serde_json::json!({
"modelId": model_id,
"downloadType": "Model",
}),
)
.unwrap();
log::info!("Starting validation for model: {model_id}");
if emit_event {
app.emit(
"onModelValidationStarted",
serde_json::json!({
"modelId": model_id,
"downloadType": "Model",
}),
)
.unwrap();
log::info!("Starting validation for model: {model_id}");
}
// Validate size if provided (fast check first)
if let Some(expected_size) = &item.size {
@@ -392,7 +395,7 @@ pub async fn _download_files_internal(
let path_clone = downloaded_path.clone();
let cancel_token_clone = cancel_token.clone();
let validation_task = tokio::spawn(async move {
validate_downloaded_file(&item_clone, &path_clone, &app_clone, &cancel_token_clone).await
validate_downloaded_file(&item_clone, &path_clone, &app_clone, &cancel_token_clone, false).await
});
validation_tasks.push((validation_task, downloaded_path, item.clone()));
}
@@ -400,6 +403,31 @@ pub async fn _download_files_internal(
}
}
let model_id = items.iter()
.find_map(|item| item.model_id.as_ref())
.map(|s| s.as_str())
.or_else(|| {
items.first().and_then(|item| {
std::path::Path::new(&item.save_path)
.parent()
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
})
})
.unwrap_or("unknown");
if !validation_tasks.is_empty() && items.iter().any(|item| item.sha256.is_some() || item.size.is_some()) {
app.emit(
"onModelValidationStarted",
serde_json::json!({
"modelId": model_id,
"downloadType": "Model",
}),
)
.unwrap();
log::info!("Starting validation for model: {model_id}");
}
// Wait for all validations to complete
for (validation_task, save_path, _item) in validation_tasks {
let validation_result = validation_task

View File

@@ -24,6 +24,7 @@ pub struct DownloadItem {
pub proxy: Option<ProxyConfig>,
pub sha256: Option<String>,
pub size: Option<u64>,
pub model_id: Option<String>,
}
#[derive(serde::Serialize, Clone, Debug)]