@hasna/models 0.0.2 → 0.0.4
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 +51 -26
- package/dist/index.js +5 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2574,34 +2574,56 @@ var source_default = chalk;
|
|
|
2574
2574
|
|
|
2575
2575
|
// src/cli/index.ts
|
|
2576
2576
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2577
|
-
import { existsSync, readFileSync as
|
|
2578
|
-
import { dirname as
|
|
2579
|
-
import { fileURLToPath } from "url";
|
|
2577
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3, rmSync, statSync as statSync2 } from "fs";
|
|
2578
|
+
import { dirname as dirname5, join as join4 } from "path";
|
|
2579
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2580
2580
|
|
|
2581
2581
|
// src/version.ts
|
|
2582
|
+
import { existsSync, readFileSync } from "fs";
|
|
2583
|
+
import { dirname, join, parse } from "path";
|
|
2584
|
+
import { fileURLToPath } from "url";
|
|
2585
|
+
var cachedVersion = null;
|
|
2582
2586
|
function getPackageVersion() {
|
|
2583
|
-
|
|
2587
|
+
if (cachedVersion)
|
|
2588
|
+
return cachedVersion;
|
|
2589
|
+
let currentDir = dirname(fileURLToPath(import.meta.url));
|
|
2590
|
+
const root = parse(currentDir).root;
|
|
2591
|
+
while (true) {
|
|
2592
|
+
const packageJsonPath = join(currentDir, "package.json");
|
|
2593
|
+
if (existsSync(packageJsonPath)) {
|
|
2594
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
2595
|
+
if (typeof packageJson.version === "string" && packageJson.version.trim()) {
|
|
2596
|
+
cachedVersion = packageJson.version;
|
|
2597
|
+
return cachedVersion;
|
|
2598
|
+
}
|
|
2599
|
+
throw new Error(`Package metadata at ${packageJsonPath} does not declare a version`);
|
|
2600
|
+
}
|
|
2601
|
+
if (currentDir === root)
|
|
2602
|
+
break;
|
|
2603
|
+
currentDir = dirname(currentDir);
|
|
2604
|
+
}
|
|
2605
|
+
throw new Error("Unable to locate package.json for @hasna/models");
|
|
2584
2606
|
}
|
|
2585
2607
|
|
|
2586
2608
|
// src/auth.ts
|
|
2587
|
-
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2588
|
-
import { dirname } from "path";
|
|
2609
|
+
import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
2610
|
+
import { dirname as dirname2 } from "path";
|
|
2589
2611
|
import { spawnSync } from "child_process";
|
|
2590
2612
|
|
|
2591
2613
|
// src/paths.ts
|
|
2592
2614
|
import { homedir } from "os";
|
|
2593
|
-
import { join } from "path";
|
|
2615
|
+
import { join as join2 } from "path";
|
|
2594
2616
|
function getModelsHome() {
|
|
2595
|
-
return process.env["HASNA_MODELS_HOME"] ||
|
|
2617
|
+
return process.env["HASNA_MODELS_HOME"] || join2(homedir(), ".hasna", "models");
|
|
2596
2618
|
}
|
|
2597
2619
|
function getDbPath() {
|
|
2598
|
-
return process.env["HASNA_MODELS_DB"] ||
|
|
2620
|
+
return process.env["HASNA_MODELS_DB"] || join2(getModelsHome(), "models.db");
|
|
2599
2621
|
}
|
|
2600
2622
|
function getAuthConfigPath() {
|
|
2601
|
-
return
|
|
2623
|
+
return join2(getModelsHome(), "auth.json");
|
|
2602
2624
|
}
|
|
2603
2625
|
function getInstallRoot() {
|
|
2604
|
-
return process.env["HASNA_MODELS_INSTALLS"] ||
|
|
2626
|
+
return process.env["HASNA_MODELS_INSTALLS"] || join2(getModelsHome(), "installs");
|
|
2605
2627
|
}
|
|
2606
2628
|
|
|
2607
2629
|
// src/auth.ts
|
|
@@ -2619,14 +2641,14 @@ var DEFAULT_HF_SECRET_KEYS = [
|
|
|
2619
2641
|
var cachedResolution = null;
|
|
2620
2642
|
function readAuthConfig() {
|
|
2621
2643
|
try {
|
|
2622
|
-
return JSON.parse(
|
|
2644
|
+
return JSON.parse(readFileSync2(getAuthConfigPath(), "utf8"));
|
|
2623
2645
|
} catch {
|
|
2624
2646
|
return {};
|
|
2625
2647
|
}
|
|
2626
2648
|
}
|
|
2627
2649
|
function writeAuthConfig(config) {
|
|
2628
2650
|
const path = getAuthConfigPath();
|
|
2629
|
-
mkdirSync(
|
|
2651
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
2630
2652
|
writeFileSync(path, `${JSON.stringify(config, null, 2)}
|
|
2631
2653
|
`);
|
|
2632
2654
|
}
|
|
@@ -2778,8 +2800,8 @@ function safePathSegment(value) {
|
|
|
2778
2800
|
}
|
|
2779
2801
|
|
|
2780
2802
|
// src/huggingface.ts
|
|
2781
|
-
import { createWriteStream, mkdirSync as mkdirSync2, renameSync, unlinkSync } from "fs";
|
|
2782
|
-
import { dirname as
|
|
2803
|
+
import { createWriteStream, mkdirSync as mkdirSync2, renameSync, statSync, unlinkSync } from "fs";
|
|
2804
|
+
import { dirname as dirname3, isAbsolute, join as join3, resolve, sep } from "path";
|
|
2783
2805
|
import { pipeline } from "stream/promises";
|
|
2784
2806
|
import { Readable } from "stream";
|
|
2785
2807
|
import { randomUUID } from "crypto";
|
|
@@ -3015,7 +3037,7 @@ async function createDownloadPlan(input) {
|
|
|
3015
3037
|
const unknownSizeFiles = files.filter((file) => file.size == null).map((file) => file.path);
|
|
3016
3038
|
const totalBytes = unknownSizeFiles.length > 0 ? null : knownBytes;
|
|
3017
3039
|
const maxBytes = input.maxBytes ?? null;
|
|
3018
|
-
const destinationRoot = input.destinationRoot ??
|
|
3040
|
+
const destinationRoot = input.destinationRoot ?? join3(getInstallRoot(), input.ref.provider, input.ref.entityKind, safePathSegment(input.ref.repoId), safePathSegment(input.ref.revision));
|
|
3019
3041
|
return {
|
|
3020
3042
|
ref: input.ref,
|
|
3021
3043
|
files,
|
|
@@ -3037,7 +3059,7 @@ async function downloadPlannedFiles(plan) {
|
|
|
3037
3059
|
for (const file of plan.files) {
|
|
3038
3060
|
const destination = safeDestinationPath(plan.destinationRoot, file.path);
|
|
3039
3061
|
const tempDestination = `${destination}.partial-${randomUUID()}`;
|
|
3040
|
-
mkdirSync2(
|
|
3062
|
+
mkdirSync2(dirname3(destination), { recursive: true });
|
|
3041
3063
|
const response = await fetch(file.downloadUrl, { headers: headers(), redirect: "follow" });
|
|
3042
3064
|
if (!response.ok || !response.body) {
|
|
3043
3065
|
const text = await response.text().catch(() => "");
|
|
@@ -3045,8 +3067,11 @@ async function downloadPlannedFiles(plan) {
|
|
|
3045
3067
|
}
|
|
3046
3068
|
try {
|
|
3047
3069
|
await pipeline(Readable.fromWeb(response.body), createWriteStream(tempDestination));
|
|
3070
|
+
const bytes = statSync(tempDestination).size;
|
|
3071
|
+
if (file.size != null && bytes !== file.size) {
|
|
3072
|
+
throw new Error(`Downloaded size mismatch for ${file.path}: expected ${file.size} bytes, got ${bytes}`);
|
|
3073
|
+
}
|
|
3048
3074
|
renameSync(tempDestination, destination);
|
|
3049
|
-
const bytes = file.size ?? Bun.file(destination).size;
|
|
3050
3075
|
downloaded.push({ path: file.path, bytes, destination });
|
|
3051
3076
|
} catch (error) {
|
|
3052
3077
|
try {
|
|
@@ -3060,14 +3085,14 @@ async function downloadPlannedFiles(plan) {
|
|
|
3060
3085
|
|
|
3061
3086
|
// src/storage.ts
|
|
3062
3087
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
3063
|
-
import { dirname as
|
|
3088
|
+
import { dirname as dirname4 } from "path";
|
|
3064
3089
|
import { Database } from "bun:sqlite";
|
|
3065
3090
|
var SCHEMA_VERSION = 1;
|
|
3066
3091
|
|
|
3067
3092
|
class ModelsStore {
|
|
3068
3093
|
db;
|
|
3069
3094
|
constructor(path = getDbPath()) {
|
|
3070
|
-
mkdirSync3(
|
|
3095
|
+
mkdirSync3(dirname4(path), { recursive: true });
|
|
3071
3096
|
this.db = new Database(path, { create: true });
|
|
3072
3097
|
this.db.run("PRAGMA busy_timeout = 5000");
|
|
3073
3098
|
this.db.run("PRAGMA journal_mode = WAL");
|
|
@@ -3613,7 +3638,7 @@ program2.command("remove").argument("<id-or-repo>", "install id or repo id").des
|
|
|
3613
3638
|
printResult(result, `would remove metadata for ${install.id}${opts.files ? ` and files at ${install.installPath}` : ""}`, opts);
|
|
3614
3639
|
return;
|
|
3615
3640
|
}
|
|
3616
|
-
if (opts.files &&
|
|
3641
|
+
if (opts.files && existsSync2(install.installPath)) {
|
|
3617
3642
|
rmSync(install.installPath, { recursive: true, force: true });
|
|
3618
3643
|
}
|
|
3619
3644
|
store.deleteInstall(install.id);
|
|
@@ -3697,7 +3722,7 @@ program2.command("doctor").description("Check local store, auth, and basic runti
|
|
|
3697
3722
|
const auth = redactAuthStatus(getHuggingFaceAuthStatus());
|
|
3698
3723
|
const checks = [
|
|
3699
3724
|
{ id: "data-dir", status: "ok", detail: dataDir },
|
|
3700
|
-
{ id: "sqlite", status:
|
|
3725
|
+
{ id: "sqlite", status: existsSync2(dbPath) ? "ok" : "warn", detail: dbPath },
|
|
3701
3726
|
{ id: "huggingface-auth", status: auth.available ? "ok" : "warn", detail: auth.available ? `token available via ${auth.source}` : "anonymous Hub access only" },
|
|
3702
3727
|
{ id: "catalog", status: "ok", detail: JSON.stringify(store.catalogStats()) }
|
|
3703
3728
|
];
|
|
@@ -3729,11 +3754,11 @@ program2.command("manual").description("Print the local command manual").option(
|
|
|
3729
3754
|
`), opts);
|
|
3730
3755
|
});
|
|
3731
3756
|
program2.command("goals").description("Print the implementation goal chain").option("-j, --json", "output JSON").action((opts) => {
|
|
3732
|
-
const cliDir =
|
|
3733
|
-
const path =
|
|
3734
|
-
const text =
|
|
3757
|
+
const cliDir = dirname5(fileURLToPath2(import.meta.url));
|
|
3758
|
+
const path = join4(cliDir, "..", "..", "docs", "GOALS.md");
|
|
3759
|
+
const text = existsSync2(path) ? readFileSync3(path, "utf8") : "Goal chain not found.";
|
|
3735
3760
|
if (isJson(opts)) {
|
|
3736
|
-
printJson({ path, bytes:
|
|
3761
|
+
printJson({ path, bytes: existsSync2(path) ? statSync2(path).size : 0, text });
|
|
3737
3762
|
} else {
|
|
3738
3763
|
console.log(text);
|
|
3739
3764
|
}
|
package/dist/index.js
CHANGED
|
@@ -424,7 +424,7 @@ function saveHuggingFaceSecretRef(secretKey) {
|
|
|
424
424
|
return redactAuthStatus({ provider: "huggingface", available: Boolean(readSecret(secretKey)), source: "secrets", secretKey });
|
|
425
425
|
}
|
|
426
426
|
// src/huggingface.ts
|
|
427
|
-
import { createWriteStream, mkdirSync as mkdirSync3, renameSync, unlinkSync } from "fs";
|
|
427
|
+
import { createWriteStream, mkdirSync as mkdirSync3, renameSync, statSync, unlinkSync } from "fs";
|
|
428
428
|
import { dirname as dirname3, isAbsolute, join as join2, resolve, sep } from "path";
|
|
429
429
|
import { pipeline } from "stream/promises";
|
|
430
430
|
import { Readable } from "stream";
|
|
@@ -691,8 +691,11 @@ async function downloadPlannedFiles(plan) {
|
|
|
691
691
|
}
|
|
692
692
|
try {
|
|
693
693
|
await pipeline(Readable.fromWeb(response.body), createWriteStream(tempDestination));
|
|
694
|
+
const bytes = statSync(tempDestination).size;
|
|
695
|
+
if (file.size != null && bytes !== file.size) {
|
|
696
|
+
throw new Error(`Downloaded size mismatch for ${file.path}: expected ${file.size} bytes, got ${bytes}`);
|
|
697
|
+
}
|
|
694
698
|
renameSync(tempDestination, destination);
|
|
695
|
-
const bytes = file.size ?? Bun.file(destination).size;
|
|
696
699
|
downloaded.push({ path: file.path, bytes, destination });
|
|
697
700
|
} catch (error) {
|
|
698
701
|
try {
|