chore: ship the full working frontend + backend
Docker / publish (push) Canceled after 0s
Release / crates-io (push) Canceled after 0s
Release / release (macos-14, aarch64-apple-darwin) (push) Canceled after 0s
Release / release (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Canceled after 0s
Release / release (windows-latest, x86_64-pc-windows-msvc) (push) Canceled after 0s

The crates.io/release build shipped a STALE frontend (committed web/js was behind
the working tree), so the admin console hung on load. Commit the current working
web/js (app, api, dashboard, login, import view, i18n de/es/fr/tr/zh, css) and the
backend WIP (import.rs, admin/assets.rs) so the released console matches the dev
build. Verified: clean `cargo build --release`, empty-pool start, working
dashboard served.
This commit is contained in:
infosave2007
2026-07-08 17:58:31 +03:00
parent 0f89cdaa07
commit 25f93d1a27
15 changed files with 597 additions and 18 deletions
+12 -2
View File
@@ -16,11 +16,18 @@ use rust_embed::RustEmbed;
struct WebAssets;
fn serve_file(path: &str) -> Response {
// The panel is rebuilt often (assets are embedded at compile time and served
// from memory), so tell the browser to always revalidate — otherwise a stale
// cached SPA hides freshly shipped fixes until a hard reload.
const NO_CACHE: &str = "no-store, must-revalidate";
match WebAssets::get(path) {
Some(content) => {
let mime = mime_guess::from_path(path).first_or_octet_stream();
(
[(header::CONTENT_TYPE, mime.as_ref())],
[
(header::CONTENT_TYPE, mime.as_ref()),
(header::CACHE_CONTROL, NO_CACHE),
],
content.data.into_owned(),
)
.into_response()
@@ -29,7 +36,10 @@ fn serve_file(path: &str) -> Response {
// SPA: unknown path under /admin → serve index.html
match WebAssets::get("index.html") {
Some(content) => (
[(header::CONTENT_TYPE, "text/html; charset=utf-8")],
[
(header::CONTENT_TYPE, "text/html; charset=utf-8"),
(header::CACHE_CONTROL, NO_CACHE),
],
content.data.into_owned(),
)
.into_response(),
+24 -8
View File
@@ -223,6 +223,17 @@ fn sanitize(s: &str) -> String {
}
/// Kick off a conversion. Returns the job id immediately; progress streams
/// Map the UI quant label to the native `cortiq` quant flag.
fn map_quant(q: &str) -> &'static str {
match q.to_ascii_uppercase().as_str() {
s if s.starts_with("Q4") => "q4",
"Q8_2F" => "q8_2f",
"F16" | "FP16" => "f16",
"VBIT" => "vbit",
_ => "q8",
}
}
/// into the job log. Fails fast if the converter script is missing.
pub fn start_import(store: Arc<JobStore>, cfg: &CmfCfg, p: ImportParams) -> Result<String, String> {
if p.repo.trim().is_empty() {
@@ -290,18 +301,23 @@ pub fn start_import(store: Arc<JobStore>, cfg: &CmfCfg, p: ImportParams) -> Resu
if p.skip_mtp { a.push("--skip-mtp".into()); }
let wd = conv.parent().map(|d| d.to_path_buf()).unwrap_or_else(|| std::path::PathBuf::from("."));
(cfg.python_bin.clone(), a, wd)
} else if p.repo.to_ascii_lowercase().contains("gguf") {
// GGUF repo → native `cortiq import-gguf` (downloads + dequantizes any
// common ggml quant type: Q4_0/1, Q5_0/1, Q8_0, Q2_K..Q6_K, IQ4_NL/XS).
let mut a = vec![
"import-gguf".into(),
p.repo.clone(),
"--quant".into(), map_quant(&p.quant).into(),
"--output".into(), output_abs.clone(),
];
if let Some(t) = &hf_token { a.push("--hf-token".into()); a.push(t.clone()); }
(cfg.cortiq_bin.clone(), a, std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from(".")))
} else {
// native Rust converter — quant name maps to cortiq's scheme.
let quant = match p.quant.to_ascii_uppercase().as_str() {
s if s.starts_with("Q4") => "q4",
"Q8_2F" => "q8_2f",
"F16" | "FP16" => "f16",
_ => "q8",
};
// safetensors → native `cortiq convert` (dense / MoE / GatedDeltaNet).
let mut a = vec![
"convert".into(),
"--model".into(), p.repo.clone(),
"--quant".into(), quant.into(),
"--quant".into(), map_quant(&p.quant).into(),
"--output".into(), output_abs.clone(),
];
if let Some(t) = &hf_token { a.push("--hf-token".into()); a.push(t.clone()); }