Repository navigation
v0.5.0
This release redesigns the cache-control API around a first-class sha256 option: bytes are verified when stored, the hash is recorded on the entry, and later cache hits are decided by a plain string comparison — so multi-GB models no longer need a full re-hash on every startup. This is a breaking release — see Migrating from 0.4.0 in the README for the upgrade path.
💥 Breaking Changes
cacheNameis gone. The namespace is a single fixed"fetch-cache". The HF layer's old"fetch-cache-hf"namespace is no longer referenced — reclaim the space once withcaches.delete("fetch-cache-hf"). The admin APIs (clearCache/listCachedUrls) no longer take a positionalcacheName; they take an options object ({ caches }) instead. Careful in plain JS:clearCache("...")does not error — the string is ignored and the default namespace is cleared.cacheName-based partitioning has no direct successor.evictprefixes only address the HF content keys; to partition per app / per tenant, pass a customcachesimplementation (e.g. a thin wrapper remappingopen(name)) to every call, or keep the URLs distinct.verifiedMarker/trustCachedSha256are gone, absorbed bysha256+recheck— and the default is reversed: 0.4.0 validated every hit unless you opted in; 0.5.0 trusts a matching recorded hash unless you passrecheck: true. The oldx-fetch-cache-verifiedheader is not read (treated as "no record"): such entries are re-hashed once on their first verified read and the record is backfilled, after which hits are string comparisons again.- HF default cache keys changed. Files that declare a
sha256are cached under a content key["hf", kind, repo, path, sha256]— a README-only revision bump is still a cache hit, and switching revisions keeps both contents side by side. Entries cached by 0.4.0 simply miss and are re-downloaded (it is a cache; no data is lost). - An explicit
expectedBytesnow fails loud when the receive buffer cannot be allocated, throwing before a single byte is read instead of downloading everything and failing at the end for the same reason (ADR 0007). A server-declared content-length still degrades as before.
✨ Features
- First-class
sha256with a recorded hash —fetchBytesnow takessha256directly (0.4.0 had it only in the HF layer): verify on download, record the hash on the entry, and decide later hits by string comparison. A mismatching record means "the content changed" and self-heals (evict + refetch);recheck: truere-hashes the bytes when you don't want to trust local storage. Entries without a record are hashed once on their first verified read and backfilled. prefetchUrl/prefetchHfFilenow bake the recorded hash into entries they verify in flight (replacing the 0.4.0 marker), and compare an existing entry's record against the expectation — a stale or unverified entry is re-warmed with verification, and a failed re-warm leaves the existing entry intact.- Prefix management — new
evict(prefix)/listKeys(prefix)operate on the HF content keys (evict(["hf", "model", "owner/name"])frees a repo's sha256-declared files). Files fetched without asha256are URL-keyed; sweep them withlistCachedUrls+evictUrl(recipe in the README). cachesinjection on all five admin APIs (CacheAdminOptions) — for test isolation, fault injection, and partitioning../hfnow re-exports the cache-layer types used in its public signatures (FetchProgress,CacheErrorContext,ValidateBytes,DecodeBytes).
🐛 Fixes
- The single-flight join key now matches the Cache API's URL normalization — concurrent calls for differently-spelled URLs of the same resource (uppercase host, default port, fragment) join one download instead of fetching twice.
- The HF entry points validate the file spec (sha256 format) before the revision-resolution request — a malformed declaration no longer reaches the network (0.4.0 leaked one resolution request for mutable refs, and
fetchHfFilescould start sibling downloads). - A trailing slash in
hubUrlis absorbed (no more double-slash URLs causing 404s or duplicate cache keys). - A failing insurance delete in
prefetchUrlis no longer swallowed; it is reported together with the integrity error as anAggregateError. - A caller joining an in-flight download during a progress notification no longer receives the same progress event twice.
📝 Docs
- README fully rewritten for the 0.5.0 API, with a new Migrating from 0.4.0 section. Design decisions are recorded in ADR 0006–0008.
Full Changelog: v0.4.0...v0.5.0