@livekit/agents-plugin-livekit 0.1.3 → 1.0.0-next.0
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/hf_utils.cjs +272 -0
- package/dist/hf_utils.cjs.map +1 -0
- package/dist/hf_utils.d.cts +40 -0
- package/dist/hf_utils.d.ts +40 -0
- package/dist/hf_utils.d.ts.map +1 -0
- package/dist/hf_utils.js +237 -0
- package/dist/hf_utils.js.map +1 -0
- package/dist/hf_utils.test.cjs +330 -0
- package/dist/hf_utils.test.cjs.map +1 -0
- package/dist/hf_utils.test.d.cts +2 -0
- package/dist/hf_utils.test.d.ts +2 -0
- package/dist/hf_utils.test.d.ts.map +1 -0
- package/dist/hf_utils.test.js +307 -0
- package/dist/hf_utils.test.js.map +1 -0
- package/dist/index.cjs +27 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -6
- package/dist/index.js.map +1 -1
- package/dist/turn_detector/base.cjs +202 -0
- package/dist/turn_detector/base.cjs.map +1 -0
- package/dist/turn_detector/base.d.cts +52 -0
- package/dist/turn_detector/base.d.ts +52 -0
- package/dist/turn_detector/base.d.ts.map +1 -0
- package/dist/turn_detector/base.js +172 -0
- package/dist/turn_detector/base.js.map +1 -0
- package/dist/turn_detector/constants.cjs +44 -0
- package/dist/turn_detector/constants.cjs.map +1 -0
- package/dist/turn_detector/constants.d.cts +7 -0
- package/dist/turn_detector/constants.d.ts +7 -0
- package/dist/turn_detector/constants.d.ts.map +1 -0
- package/dist/turn_detector/constants.js +16 -0
- package/dist/turn_detector/constants.js.map +1 -0
- package/dist/turn_detector/english.cjs +52 -0
- package/dist/turn_detector/english.cjs.map +1 -0
- package/dist/turn_detector/english.d.cts +11 -0
- package/dist/turn_detector/english.d.ts +11 -0
- package/dist/turn_detector/english.d.ts.map +1 -0
- package/dist/turn_detector/english.js +26 -0
- package/dist/turn_detector/english.js.map +1 -0
- package/dist/turn_detector/index.cjs +53 -0
- package/dist/turn_detector/index.cjs.map +1 -0
- package/dist/turn_detector/index.d.cts +5 -0
- package/dist/turn_detector/index.d.ts +5 -0
- package/dist/turn_detector/index.d.ts.map +1 -0
- package/dist/turn_detector/index.js +23 -0
- package/dist/turn_detector/index.js.map +1 -0
- package/dist/turn_detector/multilingual.cjs +144 -0
- package/dist/turn_detector/multilingual.cjs.map +1 -0
- package/dist/turn_detector/multilingual.d.cts +15 -0
- package/dist/turn_detector/multilingual.d.ts +15 -0
- package/dist/turn_detector/multilingual.d.ts.map +1 -0
- package/dist/turn_detector/multilingual.js +118 -0
- package/dist/turn_detector/multilingual.js.map +1 -0
- package/dist/turn_detector/utils.cjs +54 -0
- package/dist/turn_detector/utils.cjs.map +1 -0
- package/dist/turn_detector/utils.d.cts +35 -0
- package/dist/turn_detector/utils.d.ts +35 -0
- package/dist/turn_detector/utils.d.ts.map +1 -0
- package/dist/turn_detector/utils.js +29 -0
- package/dist/turn_detector/utils.js.map +1 -0
- package/dist/turn_detector/utils.test.cjs +196 -0
- package/dist/turn_detector/utils.test.cjs.map +1 -0
- package/dist/turn_detector/utils.test.d.cts +2 -0
- package/dist/turn_detector/utils.test.d.ts +2 -0
- package/dist/turn_detector/utils.test.d.ts.map +1 -0
- package/dist/turn_detector/utils.test.js +195 -0
- package/dist/turn_detector/utils.test.js.map +1 -0
- package/package.json +5 -4
- package/src/hf_utils.test.ts +392 -0
- package/src/hf_utils.ts +365 -0
- package/src/index.ts +32 -9
- package/src/turn_detector/base.ts +238 -0
- package/src/turn_detector/constants.ts +16 -0
- package/src/turn_detector/english.ts +27 -0
- package/src/turn_detector/index.ts +21 -0
- package/src/turn_detector/multilingual.ts +145 -0
- package/src/turn_detector/utils.test.ts +231 -0
- package/src/turn_detector/utils.ts +76 -0
- package/dist/turn_detector.cjs +0 -129
- package/dist/turn_detector.cjs.map +0 -1
- package/dist/turn_detector.d.cts +0 -22
- package/dist/turn_detector.d.ts +0 -22
- package/dist/turn_detector.d.ts.map +0 -1
- package/dist/turn_detector.js +0 -102
- package/dist/turn_detector.js.map +0 -1
- package/dist/turn_detector.onnx +0 -0
- package/src/turn_detector.onnx +0 -0
- package/src/turn_detector.ts +0 -121
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hf_utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Fixed version of HuggingFace's downloadFileToCacheDir that matches Python's behavior\n *\n * Key fix: Uses branch/tag HEAD commit for snapshot paths, not file's last commit\n * This ensures all files from the same revision end up in the same snapshot folder\n */\nimport type { CommitInfo, PathInfo, RepoDesignation } from '@huggingface/hub';\nimport { downloadFile, listCommits, pathsInfo } from '@huggingface/hub';\nimport { log } from '@livekit/agents';\nimport { createWriteStream, writeFileSync } from 'node:fs';\nimport { lstat, mkdir, rename, stat } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { Readable } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\nimport type { ReadableStream } from 'node:stream/web';\n\n// Define CredentialsParams if not exported\ninterface CredentialsParams {\n accessToken?: string;\n}\n\nexport const REGEX_COMMIT_HASH: RegExp = new RegExp('^[0-9a-f]{40}$');\n\n// Helper functions from HuggingFace's cache-management\nfunction getHFHubCachePath(customCacheDir?: string): string {\n return customCacheDir || join(homedir(), '.cache', 'huggingface', 'hub');\n}\n\nfunction getRepoFolderName(repoId: string): string {\n return `models--${repoId.replace(/\\//g, '--')}`;\n}\n\nfunction toRepoId(repo: RepoDesignation | string): string {\n if (typeof repo === 'string') {\n return repo;\n }\n return `${repo.name}`;\n}\n\n/**\n * Get the HEAD commit hash for a branch/tag (matching Python's behavior)\n */\nasync function getBranchHeadCommit(\n repo: RepoDesignation,\n revision: string,\n params: { accessToken?: string; hubUrl?: string; fetch?: typeof fetch },\n): Promise<string | null> {\n const logger = log();\n\n try {\n // If already a commit hash, return it\n if (REGEX_COMMIT_HASH.test(revision)) {\n return revision;\n }\n\n // Get the first commit from listCommits - this is the HEAD\n for await (const commit of listCommits({\n repo,\n revision,\n ...params,\n })) {\n // The commit object structure varies, so we check multiple possible properties\n const commitHash = (commit as any).oid || (commit as any).id || (commit as any).commitId;\n if (commitHash) {\n return commitHash;\n }\n break; // Only need the first one\n }\n\n logger.error({ repo: toRepoId(repo), revision }, 'No commits found for revision');\n return null;\n } catch (error) {\n logger.error(\n { error: (error as Error).message, repo: toRepoId(repo), revision },\n 'Error getting HEAD commit',\n );\n throw error;\n }\n}\n\n/**\n * Create a symbolic link following HuggingFace's implementation\n */\nasync function createSymlink(sourcePath: string, targetPath: string): Promise<void> {\n const logger = log();\n const { symlink, rm, copyFile } = await import('node:fs/promises');\n\n // Expand ~ to home directory\n function expandUser(path: string): string {\n if (path.startsWith('~')) {\n return path.replace('~', homedir());\n }\n return path;\n }\n\n const absSrc = resolve(expandUser(sourcePath));\n const absDst = resolve(expandUser(targetPath));\n\n // Remove existing file/symlink if it exists\n try {\n await rm(absDst);\n } catch {\n // Ignore - file might not exist\n }\n\n try {\n // Create relative symlink (better for portability)\n const relativePath = relative(dirname(absDst), absSrc);\n await symlink(relativePath, absDst);\n logger.debug({ source: absSrc, target: absDst, relative: relativePath }, 'Created symlink');\n } catch (symlinkError) {\n // Symlink failed (common on Windows without admin rights)\n // Fall back to copying the file\n logger.warn({ source: absSrc, target: absDst }, 'Symlink not supported, falling back to copy');\n try {\n await copyFile(absSrc, absDst);\n logger.debug({ source: absSrc, target: absDst }, 'File copied successfully');\n } catch (copyError) {\n logger.error(\n { error: (copyError as Error).message, source: absSrc, target: absDst },\n 'Failed to copy file',\n );\n // If copy also fails, throw the original symlink error\n throw symlinkError;\n }\n }\n}\n\nfunction getFilePointer(storageFolder: string, revision: string, relativeFilename: string): string {\n const snapshotPath = join(storageFolder, 'snapshots');\n return join(snapshotPath, revision, relativeFilename);\n}\n\n/**\n * handy method to check if a file exists, or the pointer of a symlinks exists\n */\nasync function exists(path: string, followSymlinks?: boolean): Promise<boolean> {\n try {\n if (followSymlinks) {\n await stat(path);\n } else {\n await lstat(path);\n }\n return true;\n } catch (err: unknown) {\n return false;\n }\n}\n\nasync function saveRevisionMapping({\n storageFolder,\n revision,\n commitHash,\n}: {\n storageFolder: string;\n revision: string;\n commitHash: string;\n}): Promise<void> {\n if (!REGEX_COMMIT_HASH.test(revision) && revision !== commitHash) {\n const refsPath = join(storageFolder, 'refs');\n await mkdir(refsPath, { recursive: true });\n writeFileSync(join(refsPath, revision), commitHash);\n }\n}\n\n/**\n * Download a given file if it's not already present in the local cache.\n * Matches Python's hf_hub_download behavior by using branch HEAD commits.\n */\nexport async function downloadFileToCacheDir(\n params: {\n repo: RepoDesignation;\n path: string;\n /**\n * If true, will download the raw git file.\n */\n raw?: boolean;\n /**\n * An optional Git revision id which can be a branch name, a tag, or a commit hash.\n * @default \"main\"\n */\n revision?: string;\n hubUrl?: string;\n cacheDir?: string;\n /**\n * Custom fetch function to use instead of the default one\n */\n fetch?: typeof fetch;\n /**\n * If true, only return cached files, don't download\n */\n localFileOnly?: boolean;\n } & Partial<CredentialsParams>,\n): Promise<string> {\n const logger = log();\n\n // get revision provided or default to main\n const revision = params.revision ?? 'main';\n const cacheDir = params.cacheDir ?? getHFHubCachePath();\n // get repo id\n const repoId = toRepoId(params.repo);\n // get storage folder\n const storageFolder = join(cacheDir, getRepoFolderName(repoId));\n\n let branchHeadCommit: string | undefined;\n\n // if user provides a commitHash as revision, use it directly\n if (REGEX_COMMIT_HASH.test(revision)) {\n branchHeadCommit = revision;\n const pointerPath = getFilePointer(storageFolder, revision, params.path);\n if (await exists(pointerPath, true)) {\n logger.debug(\n { pointerPath, commitHash: branchHeadCommit },\n 'File found in cache (commit hash)',\n );\n return pointerPath;\n }\n }\n\n // If localFileOnly, check cache without making API calls\n if (params.localFileOnly) {\n logger.debug({ repoId, path: params.path, revision }, 'Local file only mode - checking cache');\n\n // Check with revision as-is (in case it's a commit hash)\n const directPath = getFilePointer(storageFolder, revision, params.path);\n if (await exists(directPath, true)) {\n logger.debug({ directPath }, 'File found in cache (direct path)');\n return directPath;\n }\n\n // If revision is not a commit hash, try to resolve from refs\n if (!REGEX_COMMIT_HASH.test(revision)) {\n const refsPath = join(storageFolder, 'refs', revision);\n try {\n const { readFileSync } = await import('fs');\n const resolvedHash = readFileSync(refsPath, 'utf-8').trim();\n const resolvedPath = getFilePointer(storageFolder, resolvedHash, params.path);\n if (await exists(resolvedPath, true)) {\n logger.debug({ resolvedPath, resolvedHash }, 'File found in cache (via refs)');\n return resolvedPath;\n }\n } catch {\n logger.debug({ revision }, 'No ref mapping found for revision');\n }\n }\n\n const error = `File not found in cache: ${repoId}/${params.path} (revision: ${revision}). Make sure to run the download-files command before running the agent worker.`;\n logger.error({ repoId, path: params.path, revision }, error);\n throw new Error(error);\n }\n\n // Get the branch HEAD commit if not already a commit hash\n if (!branchHeadCommit) {\n const headCommit = await getBranchHeadCommit(params.repo, revision, params);\n if (!headCommit) {\n throw new Error(`Failed to resolve revision ${revision} to commit hash`);\n }\n branchHeadCommit = headCommit;\n }\n\n // Check if file exists with the branch HEAD commit\n const pointerPath = getFilePointer(storageFolder, branchHeadCommit, params.path);\n if (await exists(pointerPath, true)) {\n logger.debug({ pointerPath, branchHeadCommit }, 'File found in cache (branch HEAD)');\n\n await saveRevisionMapping({\n storageFolder,\n revision,\n commitHash: branchHeadCommit,\n });\n\n return pointerPath;\n }\n\n // Now get file metadata to download it\n logger.debug(\n { repoId, path: params.path, revision: branchHeadCommit },\n 'Fetching path info from HF API',\n );\n const pathsInformation: (PathInfo & { lastCommit: CommitInfo })[] = await pathsInfo({\n ...params,\n paths: [params.path],\n revision: branchHeadCommit, // Use HEAD commit for consistency\n expand: true,\n });\n\n if (!pathsInformation || pathsInformation.length !== 1) {\n const error = `cannot get path info for ${params.path}`;\n logger.error({ repoId, path: params.path, pathsInfoLength: pathsInformation?.length }, error);\n throw new Error(error);\n }\n\n const pathInfo = pathsInformation[0];\n if (!pathInfo) {\n const error = `No path info returned for ${params.path}`;\n logger.error({ repoId, path: params.path }, error);\n throw new Error(error);\n }\n\n let etag: string;\n if (pathInfo.lfs) {\n etag = pathInfo.lfs.oid; // get the LFS pointed file oid\n logger.debug({ etag, path: params.path }, 'File is LFS pointer');\n } else {\n etag = pathInfo.oid; // get the repo file if not a LFS pointer\n logger.debug({ etag, path: params.path }, 'File is regular git object');\n }\n\n const blobPath = join(storageFolder, 'blobs', etag);\n\n logger.debug({ branchHeadCommit, pointerPath, blobPath }, 'Computed cache paths');\n\n // mkdir blob and pointer path parent directory\n await mkdir(dirname(blobPath), { recursive: true });\n await mkdir(dirname(pointerPath), { recursive: true });\n\n // We might already have the blob but not the pointer\n // shortcut the download if needed\n if (await exists(blobPath)) {\n logger.debug({ blobPath, etag }, 'Blob already exists in cache, creating symlink only');\n // create symlinks in snapshot folder to blob object\n await createSymlink(blobPath, pointerPath);\n return pointerPath;\n }\n\n const incomplete = `${blobPath}.incomplete`;\n logger.debug({ path: params.path, incomplete }, 'Starting file download');\n\n // Use enhanced download with retry - use branch HEAD commit for download\n const blob: Blob | null = await downloadFile({\n ...params,\n revision: branchHeadCommit,\n });\n\n if (!blob) {\n const error = `invalid response for file ${params.path}`;\n logger.error({ path: params.path }, error);\n throw new Error(error);\n }\n\n logger.debug({ size: blob.size }, 'Writing blob to disk');\n await pipeline(Readable.fromWeb(blob.stream() as ReadableStream), createWriteStream(incomplete));\n\n // rename .incomplete file to expected blob\n await rename(incomplete, blobPath);\n logger.debug({ blobPath }, 'Renamed incomplete file to final blob');\n\n // create symlinks in snapshot folder to blob object\n await createSymlink(blobPath, pointerPath);\n logger.debug({ blobPath, pointerPath }, 'Created symlink from snapshot to blob');\n\n await saveRevisionMapping({\n storageFolder,\n revision,\n commitHash: branchHeadCommit,\n });\n\n logger.debug({ pointerPath, size: blob.size }, 'File download completed successfully');\n return pointerPath;\n}\n"],"mappings":"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","names":["pointerPath"]}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var import_agents = require("@livekit/agents");
|
|
25
|
+
var import_fs = require("fs");
|
|
26
|
+
var import_os = require("os");
|
|
27
|
+
var import_path = require("path");
|
|
28
|
+
var import_vitest = require("vitest");
|
|
29
|
+
var import_hf_utils = require("./hf_utils.cjs");
|
|
30
|
+
function getCachePath(repo, cacheDir) {
|
|
31
|
+
const baseCacheDir = cacheDir || (0, import_path.join)((0, import_os.homedir)(), ".cache", "huggingface", "hub");
|
|
32
|
+
return (0, import_path.join)(baseCacheDir, `models--${repo.replace(/\//g, "--")}`);
|
|
33
|
+
}
|
|
34
|
+
function clearCache(repo, cacheDir) {
|
|
35
|
+
const repoPath = getCachePath(repo, cacheDir);
|
|
36
|
+
if ((0, import_fs.existsSync)(repoPath)) {
|
|
37
|
+
(0, import_fs.rmSync)(repoPath, { recursive: true, force: true });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
(0, import_vitest.describe)("HuggingFace Download Fixed Implementation", () => {
|
|
41
|
+
(0, import_agents.initializeLogger)({ pretty: true, level: "debug" });
|
|
42
|
+
const TEST_REPO = "livekit/turn-detector";
|
|
43
|
+
const TEST_CACHE_DIR = (0, import_path.join)(process.cwd(), ".test-cache");
|
|
44
|
+
(0, import_vitest.beforeAll)(() => {
|
|
45
|
+
clearCache(TEST_REPO, TEST_CACHE_DIR);
|
|
46
|
+
});
|
|
47
|
+
(0, import_vitest.afterAll)(() => {
|
|
48
|
+
if ((0, import_fs.existsSync)(TEST_CACHE_DIR)) {
|
|
49
|
+
(0, import_fs.rmSync)(TEST_CACHE_DIR, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
(0, import_vitest.describe)("Basic Downloads", () => {
|
|
53
|
+
(0, import_vitest.it)("should download a standard file in subdirectory", async () => {
|
|
54
|
+
const result = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
55
|
+
repo: TEST_REPO,
|
|
56
|
+
path: "onnx/model_q8.onnx",
|
|
57
|
+
revision: "v1.2.2-en",
|
|
58
|
+
cacheDir: TEST_CACHE_DIR
|
|
59
|
+
});
|
|
60
|
+
(0, import_vitest.expect)(result).toBeTruthy();
|
|
61
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(result)).toBe(true);
|
|
62
|
+
const stats = (0, import_fs.statSync)(result);
|
|
63
|
+
const sizeMB = stats.size / 1024 / 1024;
|
|
64
|
+
(0, import_vitest.expect)(sizeMB).toBeCloseTo(62.67, 1);
|
|
65
|
+
});
|
|
66
|
+
(0, import_vitest.it)("should download a large file with retry logic", async () => {
|
|
67
|
+
const result = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
68
|
+
repo: TEST_REPO,
|
|
69
|
+
path: "onnx/model.onnx",
|
|
70
|
+
revision: "v1.2.2-en",
|
|
71
|
+
cacheDir: TEST_CACHE_DIR
|
|
72
|
+
});
|
|
73
|
+
(0, import_vitest.expect)(result).toBeTruthy();
|
|
74
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(result)).toBe(true);
|
|
75
|
+
const stats = (0, import_fs.statSync)(result);
|
|
76
|
+
const sizeMB = stats.size / 1024 / 1024;
|
|
77
|
+
(0, import_vitest.expect)(sizeMB).toBeCloseTo(249.96, 1);
|
|
78
|
+
});
|
|
79
|
+
(0, import_vitest.it)("should download a very small file", async () => {
|
|
80
|
+
const result = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
81
|
+
repo: TEST_REPO,
|
|
82
|
+
path: "languages.json",
|
|
83
|
+
revision: "v1.2.2-en",
|
|
84
|
+
cacheDir: TEST_CACHE_DIR
|
|
85
|
+
});
|
|
86
|
+
(0, import_vitest.expect)(result).toBeTruthy();
|
|
87
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(result)).toBe(true);
|
|
88
|
+
const stats = (0, import_fs.statSync)(result);
|
|
89
|
+
(0, import_vitest.expect)(stats.size).toBeLessThan(200);
|
|
90
|
+
});
|
|
91
|
+
(0, import_vitest.it)("should download from different revision", async () => {
|
|
92
|
+
const result = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
93
|
+
repo: TEST_REPO,
|
|
94
|
+
path: "tokenizer.json",
|
|
95
|
+
revision: "v0.2.0-intl",
|
|
96
|
+
cacheDir: TEST_CACHE_DIR
|
|
97
|
+
});
|
|
98
|
+
(0, import_vitest.expect)(result).toBeTruthy();
|
|
99
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(result)).toBe(true);
|
|
100
|
+
const stats = (0, import_fs.statSync)(result);
|
|
101
|
+
const sizeMB = stats.size / 1024 / 1024;
|
|
102
|
+
(0, import_vitest.expect)(sizeMB).toBeGreaterThan(3);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
(0, import_vitest.describe)("Cache Behavior", () => {
|
|
106
|
+
(0, import_vitest.it)("should use cache on second download", async () => {
|
|
107
|
+
const firstPath = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
108
|
+
repo: TEST_REPO,
|
|
109
|
+
path: "onnx/model_q8.onnx",
|
|
110
|
+
revision: "v1.2.2-en",
|
|
111
|
+
cacheDir: TEST_CACHE_DIR
|
|
112
|
+
});
|
|
113
|
+
const startTime = Date.now();
|
|
114
|
+
const secondPath = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
115
|
+
repo: TEST_REPO,
|
|
116
|
+
path: "onnx/model_q8.onnx",
|
|
117
|
+
revision: "v1.2.2-en",
|
|
118
|
+
cacheDir: TEST_CACHE_DIR
|
|
119
|
+
});
|
|
120
|
+
const cacheTime = Date.now() - startTime;
|
|
121
|
+
(0, import_vitest.expect)(secondPath).toBe(firstPath);
|
|
122
|
+
(0, import_vitest.expect)(cacheTime).toBeLessThan(500);
|
|
123
|
+
});
|
|
124
|
+
(0, import_vitest.it)("should respect localFileOnly flag when file is cached", async () => {
|
|
125
|
+
await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
126
|
+
repo: TEST_REPO,
|
|
127
|
+
path: "tokenizer.json",
|
|
128
|
+
revision: "v0.2.0-intl",
|
|
129
|
+
cacheDir: TEST_CACHE_DIR
|
|
130
|
+
});
|
|
131
|
+
const cachedPath = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
132
|
+
repo: TEST_REPO,
|
|
133
|
+
path: "tokenizer.json",
|
|
134
|
+
revision: "v0.2.0-intl",
|
|
135
|
+
cacheDir: TEST_CACHE_DIR,
|
|
136
|
+
localFileOnly: true
|
|
137
|
+
});
|
|
138
|
+
(0, import_vitest.expect)(cachedPath).toBeTruthy();
|
|
139
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(cachedPath)).toBe(true);
|
|
140
|
+
});
|
|
141
|
+
(0, import_vitest.it)("should throw error with localFileOnly when file is not cached", async () => {
|
|
142
|
+
await (0, import_vitest.expect)(
|
|
143
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
144
|
+
repo: TEST_REPO,
|
|
145
|
+
path: "non-existent-file.txt",
|
|
146
|
+
revision: "main",
|
|
147
|
+
cacheDir: TEST_CACHE_DIR,
|
|
148
|
+
localFileOnly: true
|
|
149
|
+
})
|
|
150
|
+
).rejects.toThrow(/File not found in cache/);
|
|
151
|
+
});
|
|
152
|
+
(0, import_vitest.it)("should save revision-to-commit mappings", async () => {
|
|
153
|
+
await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
154
|
+
repo: TEST_REPO,
|
|
155
|
+
path: "languages.json",
|
|
156
|
+
revision: "v1.2.2-en",
|
|
157
|
+
cacheDir: TEST_CACHE_DIR
|
|
158
|
+
});
|
|
159
|
+
const refsPath = (0, import_path.join)(getCachePath(TEST_REPO, TEST_CACHE_DIR), "refs", "v1.2.2-en");
|
|
160
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(refsPath)).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
(0, import_vitest.it)("should handle multiple files from same revision without overwriting refs", async () => {
|
|
163
|
+
const file1Path = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
164
|
+
repo: TEST_REPO,
|
|
165
|
+
path: "onnx/model_q8.onnx",
|
|
166
|
+
revision: "v1.2.2-en",
|
|
167
|
+
cacheDir: TEST_CACHE_DIR
|
|
168
|
+
});
|
|
169
|
+
const file2Path = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
170
|
+
repo: TEST_REPO,
|
|
171
|
+
path: "languages.json",
|
|
172
|
+
revision: "v1.2.2-en",
|
|
173
|
+
cacheDir: TEST_CACHE_DIR
|
|
174
|
+
});
|
|
175
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(file1Path)).toBe(true);
|
|
176
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(file2Path)).toBe(true);
|
|
177
|
+
const cachedFile1 = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
178
|
+
repo: TEST_REPO,
|
|
179
|
+
path: "onnx/model_q8.onnx",
|
|
180
|
+
revision: "v1.2.2-en",
|
|
181
|
+
cacheDir: TEST_CACHE_DIR,
|
|
182
|
+
localFileOnly: true
|
|
183
|
+
});
|
|
184
|
+
const cachedFile2 = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
185
|
+
repo: TEST_REPO,
|
|
186
|
+
path: "languages.json",
|
|
187
|
+
revision: "v1.2.2-en",
|
|
188
|
+
cacheDir: TEST_CACHE_DIR,
|
|
189
|
+
localFileOnly: true
|
|
190
|
+
});
|
|
191
|
+
(0, import_vitest.expect)(cachedFile1).toBe(file1Path);
|
|
192
|
+
(0, import_vitest.expect)(cachedFile2).toBe(file2Path);
|
|
193
|
+
const match1 = file1Path.match(/snapshots\/([a-f0-9]{40})\//);
|
|
194
|
+
const match2 = file2Path.match(/snapshots\/([a-f0-9]{40})\//);
|
|
195
|
+
(0, import_vitest.expect)(match1).toBeTruthy();
|
|
196
|
+
(0, import_vitest.expect)(match2).toBeTruthy();
|
|
197
|
+
const commitHash1 = match1[1];
|
|
198
|
+
const commitHash2 = match2[1];
|
|
199
|
+
(0, import_vitest.expect)(commitHash1).toBe(commitHash2);
|
|
200
|
+
const { readFileSync } = await import("fs");
|
|
201
|
+
const refsPath = (0, import_path.join)(getCachePath(TEST_REPO, TEST_CACHE_DIR), "refs", "v1.2.2-en");
|
|
202
|
+
const refsContent = readFileSync(refsPath, "utf-8").trim();
|
|
203
|
+
(0, import_vitest.expect)(refsContent).toMatch(/^[a-f0-9]{40}$/);
|
|
204
|
+
(0, import_vitest.expect)(refsContent).toBe(commitHash1);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
(0, import_vitest.describe)("Error Handling", () => {
|
|
208
|
+
(0, import_vitest.it)("should handle invalid repository gracefully", async () => {
|
|
209
|
+
await (0, import_vitest.expect)(
|
|
210
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
211
|
+
repo: "non-existent-org/non-existent-repo",
|
|
212
|
+
path: "file.txt",
|
|
213
|
+
revision: "main",
|
|
214
|
+
cacheDir: TEST_CACHE_DIR
|
|
215
|
+
})
|
|
216
|
+
).rejects.toThrow();
|
|
217
|
+
});
|
|
218
|
+
(0, import_vitest.it)("should handle invalid file path gracefully", async () => {
|
|
219
|
+
await (0, import_vitest.expect)(
|
|
220
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
221
|
+
repo: TEST_REPO,
|
|
222
|
+
path: "non-existent-file-path.xyz",
|
|
223
|
+
revision: "v1.2.2-en",
|
|
224
|
+
cacheDir: TEST_CACHE_DIR
|
|
225
|
+
})
|
|
226
|
+
).rejects.toThrow();
|
|
227
|
+
});
|
|
228
|
+
(0, import_vitest.it)("should handle invalid revision gracefully", async () => {
|
|
229
|
+
await (0, import_vitest.expect)(
|
|
230
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
231
|
+
repo: TEST_REPO,
|
|
232
|
+
path: "tokenizer.json",
|
|
233
|
+
revision: "non-existent-revision",
|
|
234
|
+
cacheDir: TEST_CACHE_DIR
|
|
235
|
+
})
|
|
236
|
+
).rejects.toThrow();
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
(0, import_vitest.describe)("Cache Structure", () => {
|
|
240
|
+
(0, import_vitest.it)("should create proper cache directory structure", async () => {
|
|
241
|
+
await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
242
|
+
repo: TEST_REPO,
|
|
243
|
+
path: "onnx/model_q8.onnx",
|
|
244
|
+
revision: "v1.2.2-en",
|
|
245
|
+
cacheDir: TEST_CACHE_DIR
|
|
246
|
+
});
|
|
247
|
+
const cachePath = getCachePath(TEST_REPO, TEST_CACHE_DIR);
|
|
248
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)((0, import_path.join)(cachePath, "blobs"))).toBe(true);
|
|
249
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)((0, import_path.join)(cachePath, "snapshots"))).toBe(true);
|
|
250
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)((0, import_path.join)(cachePath, "refs"))).toBe(true);
|
|
251
|
+
});
|
|
252
|
+
(0, import_vitest.it)("should handle commit hash revisions", async () => {
|
|
253
|
+
const tagResult = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
254
|
+
repo: TEST_REPO,
|
|
255
|
+
path: "onnx/model_q8.onnx",
|
|
256
|
+
revision: "v1.2.2-en",
|
|
257
|
+
cacheDir: TEST_CACHE_DIR
|
|
258
|
+
});
|
|
259
|
+
const match = tagResult.match(/snapshots\/([a-f0-9]{40})\//);
|
|
260
|
+
(0, import_vitest.expect)(match).toBeTruthy();
|
|
261
|
+
const commitHash = match[1];
|
|
262
|
+
const result = await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
263
|
+
repo: TEST_REPO,
|
|
264
|
+
path: "onnx/model_q8.onnx",
|
|
265
|
+
revision: commitHash,
|
|
266
|
+
cacheDir: TEST_CACHE_DIR
|
|
267
|
+
});
|
|
268
|
+
(0, import_vitest.expect)(result).toBeTruthy();
|
|
269
|
+
(0, import_vitest.expect)(result).toContain(commitHash);
|
|
270
|
+
});
|
|
271
|
+
(0, import_vitest.it)("should store files as content-addressed blobs", async () => {
|
|
272
|
+
await (0, import_hf_utils.downloadFileToCacheDir)({
|
|
273
|
+
repo: TEST_REPO,
|
|
274
|
+
path: "languages.json",
|
|
275
|
+
revision: "v1.2.2-en",
|
|
276
|
+
cacheDir: TEST_CACHE_DIR
|
|
277
|
+
});
|
|
278
|
+
const blobsPath = (0, import_path.join)(getCachePath(TEST_REPO, TEST_CACHE_DIR), "blobs");
|
|
279
|
+
const { readdirSync } = await import("fs");
|
|
280
|
+
const blobs = readdirSync(blobsPath);
|
|
281
|
+
(0, import_vitest.expect)(blobs.length).toBeGreaterThan(0);
|
|
282
|
+
(0, import_vitest.expect)(blobs[0]).toMatch(/^[a-f0-9]{64}$/);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
(0, import_vitest.describe)("Performance", () => {
|
|
286
|
+
(0, import_vitest.it)("should download files in parallel efficiently", async () => {
|
|
287
|
+
const startTime = Date.now();
|
|
288
|
+
const promises = [
|
|
289
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
290
|
+
repo: TEST_REPO,
|
|
291
|
+
path: "onnx/model_q8.onnx",
|
|
292
|
+
revision: "v1.2.2-en",
|
|
293
|
+
cacheDir: TEST_CACHE_DIR
|
|
294
|
+
}),
|
|
295
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
296
|
+
repo: TEST_REPO,
|
|
297
|
+
path: "languages.json",
|
|
298
|
+
revision: "v1.2.2-en",
|
|
299
|
+
cacheDir: TEST_CACHE_DIR
|
|
300
|
+
}),
|
|
301
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
302
|
+
repo: TEST_REPO,
|
|
303
|
+
path: "tokenizer.json",
|
|
304
|
+
revision: "v0.2.0-intl",
|
|
305
|
+
cacheDir: TEST_CACHE_DIR
|
|
306
|
+
})
|
|
307
|
+
];
|
|
308
|
+
const results = await Promise.all(promises);
|
|
309
|
+
const totalTime = Date.now() - startTime;
|
|
310
|
+
results.forEach((result) => {
|
|
311
|
+
(0, import_vitest.expect)(result).toBeTruthy();
|
|
312
|
+
(0, import_vitest.expect)((0, import_fs.existsSync)(result)).toBe(true);
|
|
313
|
+
});
|
|
314
|
+
console.log(`Parallel download took ${totalTime}ms`);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
(0, import_vitest.describe)("Failures", () => {
|
|
318
|
+
(0, import_vitest.it)("should handle non-existent file", async () => {
|
|
319
|
+
await (0, import_vitest.expect)(
|
|
320
|
+
(0, import_hf_utils.downloadFileToCacheDir)({
|
|
321
|
+
repo: TEST_REPO,
|
|
322
|
+
path: "onnx/model_non_existent.onnx",
|
|
323
|
+
revision: "v1.2.2-en",
|
|
324
|
+
cacheDir: TEST_CACHE_DIR
|
|
325
|
+
})
|
|
326
|
+
).rejects.toThrow("cannot get path info for onnx/model_non_existent.onnx");
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
//# sourceMappingURL=hf_utils.test.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hf_utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { initializeLogger } from '@livekit/agents';\nimport { existsSync, rmSync, statSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { afterAll, beforeAll, describe, expect, it } from 'vitest';\nimport { downloadFileToCacheDir } from './hf_utils.js';\n\nfunction getCachePath(repo: string, cacheDir?: string): string {\n const baseCacheDir = cacheDir || join(homedir(), '.cache', 'huggingface', 'hub');\n return join(baseCacheDir, `models--${repo.replace(/\\//g, '--')}`);\n}\n\nfunction clearCache(repo: string, cacheDir?: string): void {\n const repoPath = getCachePath(repo, cacheDir);\n if (existsSync(repoPath)) {\n rmSync(repoPath, { recursive: true, force: true });\n }\n}\n\ndescribe('HuggingFace Download Fixed Implementation', () => {\n initializeLogger({ pretty: true, level: 'debug' });\n\n const TEST_REPO = 'livekit/turn-detector';\n const TEST_CACHE_DIR = join(process.cwd(), '.test-cache');\n\n beforeAll(() => {\n // Clear test cache before all tests\n clearCache(TEST_REPO, TEST_CACHE_DIR);\n });\n\n afterAll(() => {\n // Clean up test cache after all tests\n if (existsSync(TEST_CACHE_DIR)) {\n rmSync(TEST_CACHE_DIR, { recursive: true, force: true });\n }\n });\n\n describe('Basic Downloads', () => {\n it('should download a standard file in subdirectory', async () => {\n const result = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n expect(result).toBeTruthy();\n expect(existsSync(result)).toBe(true);\n\n const stats = statSync(result);\n const sizeMB = stats.size / 1024 / 1024;\n expect(sizeMB).toBeCloseTo(62.67, 1); // ~62.67 MB\n });\n\n it('should download a large file with retry logic', async () => {\n const result = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n expect(result).toBeTruthy();\n expect(existsSync(result)).toBe(true);\n\n const stats = statSync(result);\n const sizeMB = stats.size / 1024 / 1024;\n expect(sizeMB).toBeCloseTo(249.96, 1); // ~250 MB\n });\n\n it('should download a very small file', async () => {\n const result = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'languages.json',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n expect(result).toBeTruthy();\n expect(existsSync(result)).toBe(true);\n\n const stats = statSync(result);\n expect(stats.size).toBeLessThan(200); // Very small file (102 bytes)\n });\n\n it('should download from different revision', async () => {\n const result = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'tokenizer.json',\n revision: 'v0.2.0-intl',\n cacheDir: TEST_CACHE_DIR,\n });\n\n expect(result).toBeTruthy();\n expect(existsSync(result)).toBe(true);\n\n const stats = statSync(result);\n const sizeMB = stats.size / 1024 / 1024;\n expect(sizeMB).toBeGreaterThan(3); // Should be around 3.36 MB or more\n });\n });\n\n describe('Cache Behavior', () => {\n it('should use cache on second download', async () => {\n // First download\n const firstPath = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n // Second download (should be from cache)\n const startTime = Date.now();\n const secondPath = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n const cacheTime = Date.now() - startTime;\n\n expect(secondPath).toBe(firstPath);\n expect(cacheTime).toBeLessThan(500); // Should be very fast if from cache\n });\n\n it('should respect localFileOnly flag when file is cached', async () => {\n // Ensure file is cached first\n await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'tokenizer.json',\n revision: 'v0.2.0-intl',\n cacheDir: TEST_CACHE_DIR,\n });\n\n // Now try with localFileOnly\n const cachedPath = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'tokenizer.json',\n revision: 'v0.2.0-intl',\n cacheDir: TEST_CACHE_DIR,\n localFileOnly: true,\n });\n\n expect(cachedPath).toBeTruthy();\n expect(existsSync(cachedPath)).toBe(true);\n });\n\n it('should throw error with localFileOnly when file is not cached', async () => {\n await expect(\n downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'non-existent-file.txt',\n revision: 'main',\n cacheDir: TEST_CACHE_DIR,\n localFileOnly: true,\n }),\n ).rejects.toThrow(/File not found in cache/);\n });\n\n it('should save revision-to-commit mappings', async () => {\n await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'languages.json',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n // Check if refs file was created\n const refsPath = join(getCachePath(TEST_REPO, TEST_CACHE_DIR), 'refs', 'v1.2.2-en');\n expect(existsSync(refsPath)).toBe(true);\n });\n\n it('should handle multiple files from same revision without overwriting refs', async () => {\n // Download two different files from the same revision\n const file1Path = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n const file2Path = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'languages.json',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n // Both files should exist\n expect(existsSync(file1Path)).toBe(true);\n expect(existsSync(file2Path)).toBe(true);\n\n // Now test that both files can be retrieved with localFileOnly\n const cachedFile1 = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n localFileOnly: true,\n });\n\n const cachedFile2 = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'languages.json',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n localFileOnly: true,\n });\n\n // Both should be found in cache\n expect(cachedFile1).toBe(file1Path);\n expect(cachedFile2).toBe(file2Path);\n\n // Check that both files are in the same snapshot folder (same commit hash)\n // Extract commit hash from paths\n const match1 = file1Path.match(/snapshots\\/([a-f0-9]{40})\\//);\n const match2 = file2Path.match(/snapshots\\/([a-f0-9]{40})\\//);\n\n expect(match1).toBeTruthy();\n expect(match2).toBeTruthy();\n\n const commitHash1 = match1![1];\n const commitHash2 = match2![1];\n\n // FIXED: All files from the same revision should use the same HEAD commit\n expect(commitHash1).toBe(commitHash2);\n\n // Check that the refs file contains the single HEAD commit\n const { readFileSync } = await import('fs');\n const refsPath = join(getCachePath(TEST_REPO, TEST_CACHE_DIR), 'refs', 'v1.2.2-en');\n const refsContent = readFileSync(refsPath, 'utf-8').trim();\n\n // The refs file should contain just the commit hash, not a JSON mapping\n expect(refsContent).toMatch(/^[a-f0-9]{40}$/);\n expect(refsContent).toBe(commitHash1);\n });\n });\n\n describe('Error Handling', () => {\n it('should handle invalid repository gracefully', async () => {\n await expect(\n downloadFileToCacheDir({\n repo: 'non-existent-org/non-existent-repo',\n path: 'file.txt',\n revision: 'main',\n cacheDir: TEST_CACHE_DIR,\n }),\n ).rejects.toThrow();\n });\n\n it('should handle invalid file path gracefully', async () => {\n await expect(\n downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'non-existent-file-path.xyz',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n }),\n ).rejects.toThrow();\n });\n\n it('should handle invalid revision gracefully', async () => {\n await expect(\n downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'tokenizer.json',\n revision: 'non-existent-revision',\n cacheDir: TEST_CACHE_DIR,\n }),\n ).rejects.toThrow();\n });\n });\n\n describe('Cache Structure', () => {\n it('should create proper cache directory structure', async () => {\n await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n const cachePath = getCachePath(TEST_REPO, TEST_CACHE_DIR);\n\n // Check expected directories exist\n expect(existsSync(join(cachePath, 'blobs'))).toBe(true);\n expect(existsSync(join(cachePath, 'snapshots'))).toBe(true);\n expect(existsSync(join(cachePath, 'refs'))).toBe(true);\n });\n\n it('should handle commit hash revisions', async () => {\n // We'll use the actual commit hash from the v1.2.2-en tag\n // First, download to ensure we have the commit hash mapping\n const tagResult = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n // Extract the commit hash from the path\n const match = tagResult.match(/snapshots\\/([a-f0-9]{40})\\//);\n expect(match).toBeTruthy();\n const commitHash = match![1];\n\n // Now download with commit hash directly\n const result = await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: commitHash,\n cacheDir: TEST_CACHE_DIR,\n });\n\n expect(result).toBeTruthy();\n expect(result).toContain(commitHash);\n });\n\n it('should store files as content-addressed blobs', async () => {\n await downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'languages.json',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n });\n\n const blobsPath = join(getCachePath(TEST_REPO, TEST_CACHE_DIR), 'blobs');\n const { readdirSync } = await import('fs');\n const blobs = readdirSync(blobsPath);\n\n // Should have at least one blob with SHA256 hash name\n expect(blobs.length).toBeGreaterThan(0);\n expect(blobs[0]).toMatch(/^[a-f0-9]{64}$/);\n });\n });\n\n describe('Performance', () => {\n it('should download files in parallel efficiently', async () => {\n const startTime = Date.now();\n\n // Download multiple files in parallel\n const promises = [\n downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_q8.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n }),\n downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'languages.json',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n }),\n downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'tokenizer.json',\n revision: 'v0.2.0-intl',\n cacheDir: TEST_CACHE_DIR,\n }),\n ];\n\n const results = await Promise.all(promises);\n const totalTime = Date.now() - startTime;\n\n // All should succeed\n results.forEach((result) => {\n expect(result).toBeTruthy();\n expect(existsSync(result)).toBe(true);\n });\n\n // Should be faster than downloading sequentially\n console.log(`Parallel download took ${totalTime}ms`);\n });\n });\n\n describe('Failures', () => {\n it('should handle non-existent file', async () => {\n await expect(\n downloadFileToCacheDir({\n repo: TEST_REPO,\n path: 'onnx/model_non_existent.onnx',\n revision: 'v1.2.2-en',\n cacheDir: TEST_CACHE_DIR,\n }),\n ).rejects.toThrow('cannot get path info for onnx/model_non_existent.onnx');\n });\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hf_utils.test.d.ts","sourceRoot":"","sources":["../src/hf_utils.test.ts"],"names":[],"mappings":""}
|