@hasna/models 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -2806,6 +2806,15 @@ import { pipeline } from "stream/promises";
2806
2806
  import { Readable } from "stream";
2807
2807
  import { randomUUID } from "crypto";
2808
2808
  var HF_ENDPOINT = process.env["HF_ENDPOINT"] || "https://huggingface.co";
2809
+
2810
+ class HuggingFaceApiError extends Error {
2811
+ status;
2812
+ constructor(response, body) {
2813
+ super(`Hugging Face request failed ${response.status} ${response.statusText}: ${body.slice(0, 300)}`);
2814
+ this.name = "HuggingFaceApiError";
2815
+ this.status = response.status;
2816
+ }
2817
+ }
2809
2818
  function apiBase() {
2810
2819
  return HF_ENDPOINT.replace(/\/+$/, "");
2811
2820
  }
@@ -2823,7 +2832,7 @@ async function hfJson(path, init) {
2823
2832
  });
2824
2833
  if (!response.ok) {
2825
2834
  const text = await response.text().catch(() => "");
2826
- throw new Error(`Hugging Face request failed ${response.status} ${response.statusText}: ${text.slice(0, 300)}`);
2835
+ throw new HuggingFaceApiError(response, text);
2827
2836
  }
2828
2837
  return response.json();
2829
2838
  }
@@ -2901,7 +2910,7 @@ function safeDestinationPath(root, filePath) {
2901
2910
  }
2902
2911
  return destination;
2903
2912
  }
2904
- function normalizeEntry(raw, kind) {
2913
+ function normalizeEntry(raw, kind, fallbackRevision = "main") {
2905
2914
  const repoId = String(raw.id ?? raw.modelId ?? "");
2906
2915
  const tags = Array.isArray(raw.tags) ? raw.tags.map(String) : [];
2907
2916
  const cardData = raw.cardData;
@@ -2909,7 +2918,7 @@ function normalizeEntry(raw, kind) {
2909
2918
  provider: "huggingface",
2910
2919
  entityKind: kind,
2911
2920
  repoId,
2912
- revision: String(raw.sha ?? "main"),
2921
+ revision: String(raw.sha ?? fallbackRevision),
2913
2922
  canonicalUrl: canonicalUrl(kind, repoId),
2914
2923
  title: repoId,
2915
2924
  author: typeof raw.author === "string" ? raw.author : repoId.split("/")[0],
@@ -2992,17 +3001,21 @@ async function searchHuggingFace(input = {}) {
2992
3001
  }
2993
3002
  async function getHuggingFaceInfo(refOrInput, defaultKind = "model") {
2994
3003
  const ref = typeof refOrInput === "string" ? parseProviderRef(refOrInput, defaultKind) : refOrInput;
2995
- const raw = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}`);
2996
- return normalizeEntry(raw, ref.entityKind);
3004
+ const revision = ref.revision || "main";
3005
+ const raw = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/revision/${encodeURIComponent(revision)}`);
3006
+ return normalizeEntry(raw, ref.entityKind, revision);
2997
3007
  }
2998
3008
  async function listHuggingFaceFiles(refOrInput, defaultKind = "model") {
2999
3009
  const ref = typeof refOrInput === "string" ? parseProviderRef(refOrInput, defaultKind) : refOrInput;
3000
- const treePath = `/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/tree/${encodeURIComponent(ref.revision)}?recursive=1&expand=1`;
3010
+ const revision = ref.revision || "main";
3011
+ const treePath = `/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/tree/${encodeURIComponent(revision)}?recursive=1&expand=1`;
3001
3012
  try {
3002
3013
  const raw = await hfJson(treePath);
3003
3014
  return raw.map((entry) => normalizeTreeFile(entry, ref)).filter((entry) => Boolean(entry));
3004
- } catch {
3005
- const info = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}`);
3015
+ } catch (error) {
3016
+ if (!(error instanceof HuggingFaceApiError) || error.status !== 404)
3017
+ throw error;
3018
+ const info = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/revision/${encodeURIComponent(revision)}`);
3006
3019
  const siblings = Array.isArray(info.siblings) ? info.siblings : [];
3007
3020
  return siblings.map((entry) => normalizeSibling(entry, ref)).filter((entry) => Boolean(entry));
3008
3021
  }
package/dist/index.js CHANGED
@@ -430,6 +430,15 @@ import { pipeline } from "stream/promises";
430
430
  import { Readable } from "stream";
431
431
  import { randomUUID } from "crypto";
432
432
  var HF_ENDPOINT = process.env["HF_ENDPOINT"] || "https://huggingface.co";
433
+
434
+ class HuggingFaceApiError extends Error {
435
+ status;
436
+ constructor(response, body) {
437
+ super(`Hugging Face request failed ${response.status} ${response.statusText}: ${body.slice(0, 300)}`);
438
+ this.name = "HuggingFaceApiError";
439
+ this.status = response.status;
440
+ }
441
+ }
433
442
  function apiBase() {
434
443
  return HF_ENDPOINT.replace(/\/+$/, "");
435
444
  }
@@ -447,7 +456,7 @@ async function hfJson(path, init) {
447
456
  });
448
457
  if (!response.ok) {
449
458
  const text = await response.text().catch(() => "");
450
- throw new Error(`Hugging Face request failed ${response.status} ${response.statusText}: ${text.slice(0, 300)}`);
459
+ throw new HuggingFaceApiError(response, text);
451
460
  }
452
461
  return response.json();
453
462
  }
@@ -525,7 +534,7 @@ function safeDestinationPath(root, filePath) {
525
534
  }
526
535
  return destination;
527
536
  }
528
- function normalizeEntry(raw, kind) {
537
+ function normalizeEntry(raw, kind, fallbackRevision = "main") {
529
538
  const repoId = String(raw.id ?? raw.modelId ?? "");
530
539
  const tags = Array.isArray(raw.tags) ? raw.tags.map(String) : [];
531
540
  const cardData = raw.cardData;
@@ -533,7 +542,7 @@ function normalizeEntry(raw, kind) {
533
542
  provider: "huggingface",
534
543
  entityKind: kind,
535
544
  repoId,
536
- revision: String(raw.sha ?? "main"),
545
+ revision: String(raw.sha ?? fallbackRevision),
537
546
  canonicalUrl: canonicalUrl(kind, repoId),
538
547
  title: repoId,
539
548
  author: typeof raw.author === "string" ? raw.author : repoId.split("/")[0],
@@ -616,17 +625,21 @@ async function searchHuggingFace(input = {}) {
616
625
  }
617
626
  async function getHuggingFaceInfo(refOrInput, defaultKind = "model") {
618
627
  const ref = typeof refOrInput === "string" ? parseProviderRef(refOrInput, defaultKind) : refOrInput;
619
- const raw = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}`);
620
- return normalizeEntry(raw, ref.entityKind);
628
+ const revision = ref.revision || "main";
629
+ const raw = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/revision/${encodeURIComponent(revision)}`);
630
+ return normalizeEntry(raw, ref.entityKind, revision);
621
631
  }
622
632
  async function listHuggingFaceFiles(refOrInput, defaultKind = "model") {
623
633
  const ref = typeof refOrInput === "string" ? parseProviderRef(refOrInput, defaultKind) : refOrInput;
624
- const treePath = `/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/tree/${encodeURIComponent(ref.revision)}?recursive=1&expand=1`;
634
+ const revision = ref.revision || "main";
635
+ const treePath = `/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/tree/${encodeURIComponent(revision)}?recursive=1&expand=1`;
625
636
  try {
626
637
  const raw = await hfJson(treePath);
627
638
  return raw.map((entry) => normalizeTreeFile(entry, ref)).filter((entry) => Boolean(entry));
628
- } catch {
629
- const info = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}`);
639
+ } catch (error) {
640
+ if (!(error instanceof HuggingFaceApiError) || error.status !== 404)
641
+ throw error;
642
+ const info = await hfJson(`/api/${apiKind(ref.entityKind)}/${encodeRepoId(ref.repoId)}/revision/${encodeURIComponent(revision)}`);
630
643
  const siblings = Array.isArray(info.siblings) ? info.siblings : [];
631
644
  return siblings.map((entry) => normalizeSibling(entry, ref)).filter((entry) => Boolean(entry));
632
645
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/models",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "CLI-first local model and dataset lifecycle tool for open-source/open-weight catalogs",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",