From c18ddb5475696b8eb8e8152efeeba1c24fce0f44 Mon Sep 17 00:00:00 2001 From: infosave2007 Date: Tue, 21 Jul 2026 23:35:14 +0300 Subject: [PATCH] =?UTF-8?q?chore(release):=20v0.2.28=20=E2=80=94=20auto-de?= =?UTF-8?q?tect=20ready=20CMF=20quant=20&=20update=20section=20title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 +++++- Cargo.lock | 2 +- Cargo.toml | 2 +- src/import.rs | 38 ++++++++++++++++++++++++++++++++++---- web/js/i18n/en.js | 2 +- web/js/i18n/ru.js | 2 +- 6 files changed, 43 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e754b2..e2d71c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,11 @@ All notable changes to this project are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/). -## [0.2.27] - 2026-07-21 +## [0.2.28] - 2026-07-21 + +### Fixed +- **Quantization Badge & Title for Pre-Converted Models**: Automatically detect quantization (`Q1`, `Q1T`) for ready-to-run `.cmf` models (e.g. `infosave/Bonsai-27Bcmf`) from repo name and downloaded filename, resolving default `Q8_2F` badge fallback. Updated section title to "Загрузки / Конвертации" ("Downloads & Conversions"). + ### Fixed - **Automatic CMF Local Server Lifecycle**: Registering an imported `.cmf` model automatically adds it to `[[cmf.servers]]` and reloads the runtime (`cmf_runtime::manage`), automatically spawning `cortiq serve` on port 8090 so chat completion requests route seamlessly without `upstream unavailable` errors. diff --git a/Cargo.lock b/Cargo.lock index 80af982..bd1d0a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -285,7 +285,7 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "cortiq-gateway" -version = "0.2.27" +version = "0.2.28" dependencies = [ "anyhow", "arc-swap", diff --git a/Cargo.toml b/Cargo.toml index ae114ed..215e105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cortiq-gateway" -version = "0.2.27" +version = "0.2.28" edition = "2021" rust-version = "1.75" license = "Apache-2.0" diff --git a/src/import.rs b/src/import.rs index 1cca9c3..e18090e 100644 --- a/src/import.rs +++ b/src/import.rs @@ -160,6 +160,14 @@ impl JobStore { } } } + fn update_quant(&self, id: &str, quant: String) { + if let Some(j) = self.jobs.lock().unwrap().get_mut(id) { + j.quant = quant.clone(); + if !j.log.is_empty() && j.log[0].starts_with("→ downloading ready .cmf model") { + j.log[0] = format!("→ downloading ready .cmf model {} ({})", j.repo, quant); + } + } + } fn set_state(&self, id: &str, state: &str) { if let Some(j) = self.jobs.lock().unwrap().get_mut(id) { j.state = state.into(); @@ -321,6 +329,21 @@ async fn download_cmf_repo( } }; + let path_lower = cmf_path.to_ascii_lowercase(); + let detected_quant = + if path_lower.contains("-q1t.") || repo.to_ascii_lowercase().contains("2bit") { + "Q1T".to_string() + } else if path_lower.contains("-q1.") || repo.to_ascii_lowercase().contains("cmf") { + "Q1".to_string() + } else if path_lower.contains("-q4.") { + "Q4".to_string() + } else if path_lower.contains("-q8.") { + "Q8".to_string() + } else { + "READY_CMF".to_string() + }; + store.update_quant(&id, detected_quant); + store.push_line(&id, format!("→ downloading {cmf_path} from HuggingFace...")); store.set_progress(&id, 0.05, "downloading".into()); @@ -464,12 +487,19 @@ pub fn start_import(store: Arc, cfg: &CmfCfg, p: ImportParams) -> Resu let id = gen_id(&p.repo); let is_cmf = is_cmf_repo(&p.repo); - let quant_display = if p.quant.is_empty() || p.quant == "auto" { - if is_cmf { - "READY_CMF".to_string() + let quant_display = if is_cmf { + let r = p.repo.to_lowercase(); + if r.contains("2bit") || r.contains("q1t") { + "Q1T".to_string() + } else if r.contains("1.7bcmf") || r.contains("27bcmf") || r.contains("cmf") { + "Q1".to_string() + } else if p.quant.is_empty() || p.quant == "auto" || p.quant == "Q8_2F" { + "Q1".to_string() } else { - "q8".to_string() + p.quant.clone() } + } else if p.quant.is_empty() || p.quant == "auto" { + "q8".to_string() } else { p.quant.clone() }; diff --git a/web/js/i18n/en.js b/web/js/i18n/en.js index dcac5d2..c21cd0d 100644 --- a/web/js/i18n/en.js +++ b/web/js/i18n/en.js @@ -374,7 +374,7 @@ export default { "import.failed": "Conversion failed — see the log.", "import.register": "Register as local model", "import.registered": "Registered as '{id}'. Run cortiq-server to serve it.", - "import.jobs": "Conversions", + "import.jobs": "Downloads & Conversions", "import.cancel": "Cancel", "import.cancelling": "Cancelling — cleaning up partial output…", "import.delete": "Delete", diff --git a/web/js/i18n/ru.js b/web/js/i18n/ru.js index d8dd9e7..8db2116 100644 --- a/web/js/i18n/ru.js +++ b/web/js/i18n/ru.js @@ -373,7 +373,7 @@ export default { "import.failed": "Конвертация не удалась — смотрите лог.", "import.register": "Подключить как локальную модель", "import.registered": "Подключено как '{id}'. Запустите cortiq-server для обслуживания.", - "import.jobs": "Конвертации", + "import.jobs": "Загрузки / Конвертации", "import.cancel": "Отменить", "import.cancelling": "Отмена — удаляю недописанный файл…", "import.delete": "Удалить",