/** * Hugging Face Hub fetcher with browser caching. * * We don't pull in @huggingface/hub: it's a heavy dep with a lot of * upload-side machinery we don't need for a read-only inference * client. The hub URL pattern is stable enough to inline. * * URL pattern: * https://huggingface.co//resolve// * * The ``main`` revision is fine for everyone except library authors; * pin to a commit SHA for reproducibility once the model lands. */ const HF_BASE = 'https://huggingface.co'; export interface HubFile { /** Repo identifier, e.g. ``cp500/infon-coref-pointer``. */ repo: string; /** Path inside the repo, e.g. ``onnx/backbone_bio_fp16.onnx``. */ path: string; /** Branch, tag, or commit SHA. */ revision?: string; } /** Build a downloadable URL for a file in an HF repo. */ export function hubUrl({ repo, path, revision = 'main' }: HubFile): string { return `${HF_BASE}/${repo}/resolve/${revision}/${path}`; } /** * Fetch a file from the Hub as an ``ArrayBuffer``. * * Browsers automatically cache by URL via the HTTP cache, so repeated * loads in the same session reuse the disk copy. For longer-term * caching we use ``caches.open`` (Cache API) when available — that * survives reloads and works offline. */ export async function fetchHubFile( file: HubFile, opts?: { cacheName?: string }, ): Promise { const url = hubUrl(file); const cacheName = opts?.cacheName ?? 'infon-coref-v1'; // Browser Cache API path. if (typeof caches !== 'undefined') { try { const cache = await caches.open(cacheName); const cached = await cache.match(url); if (cached) return await cached.arrayBuffer(); const r = await fetch(url); if (!r.ok) throw new Error(`hub fetch ${url}: ${r.status}`); // Clone before consuming so we can stash it in the cache. cache.put(url, r.clone()).catch(() => { /* cache failures are non-fatal */ }); return await r.arrayBuffer(); } catch (err) { // Cache API exists but write failed (e.g. quota). Fall through // to plain fetch. if (!(err instanceof TypeError)) throw err; } } // Plain fetch (Node 18+ has it; older Node needs polyfill). const r = await fetch(url); if (!r.ok) throw new Error(`hub fetch ${url}: ${r.status}`); return await r.arrayBuffer(); } /** Fetch a file as JSON. */ export async function fetchHubJson(file: HubFile): Promise { const buf = await fetchHubFile(file); return JSON.parse(new TextDecoder().decode(buf)) as T; }