diff --git a/openless-all/app/crates/openless-core/src/model_store.rs b/openless-all/app/crates/openless-core/src/model_store.rs index a87aa0a4..ab61b181 100644 --- a/openless-all/app/crates/openless-core/src/model_store.rs +++ b/openless-all/app/crates/openless-core/src/model_store.rs @@ -2485,10 +2485,10 @@ fn parse_hf_tree_page_for_entry( Ok(files) } +/// The Hugging Face tree API returns `lfs.oid` as a bare SHA-256 hex digest; +/// the `sha256:`-prefixed form (as in Git LFS pointer files) is accepted too. fn parse_lfs_sha256(oid: &str) -> Result { - let digest = oid - .strip_prefix("sha256:") - .ok_or_else(|| invalid("unsupported Hugging Face LFS oid"))?; + let digest = oid.strip_prefix("sha256:").unwrap_or(oid); if digest.len() != 64 || !digest.bytes().all(|byte| byte.is_ascii_hexdigit()) { return Err(invalid("invalid Hugging Face LFS sha256 oid")); } @@ -2940,6 +2940,31 @@ mod tests { .is_err()); } + #[test] + fn hf_tree_accepts_bare_lfs_oid_from_live_api() { + // Shape returned by huggingface.co and hf-mirror.com for Qwen/Qwen3-ASR-0.6B + // (2026-09-13): `lfs.oid` is the bare hex digest, without a `sha256:` prefix. + let entries = vec![serde_json::json!({ + "type": "file", + "oid": "3d4b2a1f0e9c8b7a6d5e4f3a2b1c0d9e8f7a6b5c", + "size": 1876091704u64, + "path": "model.safetensors", + "lfs": { + "oid": "79d6cbd4c98c7bbffe9db2edac07f56cd6637d0d5944b27f6c2b8353840323ea", + "size": 1876091704u64, + "pointerSize": 135 + } + })]; + let files = parse_hf_tree_page("Qwen/Qwen3-ASR-0.6B", "qwen3-asr-0.6b", &entries).unwrap(); + assert_eq!(files.len(), 1); + assert_eq!(files[0].path, "model.safetensors"); + assert_eq!(files[0].size_bytes, 1_876_091_704); + assert_eq!( + files[0].sha256.as_deref(), + Some("79d6cbd4c98c7bbffe9db2edac07f56cd6637d0d5944b27f6c2b8353840323ea") + ); + } + #[test] fn hf_link_pagination_accepts_same_origin_and_rejects_redirected_origin() { let current = "https://huggingface.co/api/models/org/model/tree/main?limit=1000";