@livekit/agents-plugin-livekit 0.1.2 → 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 +7 -6
- 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,392 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { initializeLogger } from '@livekit/agents';
|
|
5
|
+
import { existsSync, rmSync, statSync } from 'fs';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
9
|
+
import { downloadFileToCacheDir } from './hf_utils.js';
|
|
10
|
+
|
|
11
|
+
function getCachePath(repo: string, cacheDir?: string): string {
|
|
12
|
+
const baseCacheDir = cacheDir || join(homedir(), '.cache', 'huggingface', 'hub');
|
|
13
|
+
return join(baseCacheDir, `models--${repo.replace(/\//g, '--')}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function clearCache(repo: string, cacheDir?: string): void {
|
|
17
|
+
const repoPath = getCachePath(repo, cacheDir);
|
|
18
|
+
if (existsSync(repoPath)) {
|
|
19
|
+
rmSync(repoPath, { recursive: true, force: true });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('HuggingFace Download Fixed Implementation', () => {
|
|
24
|
+
initializeLogger({ pretty: true, level: 'debug' });
|
|
25
|
+
|
|
26
|
+
const TEST_REPO = 'livekit/turn-detector';
|
|
27
|
+
const TEST_CACHE_DIR = join(process.cwd(), '.test-cache');
|
|
28
|
+
|
|
29
|
+
beforeAll(() => {
|
|
30
|
+
// Clear test cache before all tests
|
|
31
|
+
clearCache(TEST_REPO, TEST_CACHE_DIR);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterAll(() => {
|
|
35
|
+
// Clean up test cache after all tests
|
|
36
|
+
if (existsSync(TEST_CACHE_DIR)) {
|
|
37
|
+
rmSync(TEST_CACHE_DIR, { recursive: true, force: true });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('Basic Downloads', () => {
|
|
42
|
+
it('should download a standard file in subdirectory', async () => {
|
|
43
|
+
const result = await downloadFileToCacheDir({
|
|
44
|
+
repo: TEST_REPO,
|
|
45
|
+
path: 'onnx/model_q8.onnx',
|
|
46
|
+
revision: 'v1.2.2-en',
|
|
47
|
+
cacheDir: TEST_CACHE_DIR,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(result).toBeTruthy();
|
|
51
|
+
expect(existsSync(result)).toBe(true);
|
|
52
|
+
|
|
53
|
+
const stats = statSync(result);
|
|
54
|
+
const sizeMB = stats.size / 1024 / 1024;
|
|
55
|
+
expect(sizeMB).toBeCloseTo(62.67, 1); // ~62.67 MB
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should download a large file with retry logic', async () => {
|
|
59
|
+
const result = await downloadFileToCacheDir({
|
|
60
|
+
repo: TEST_REPO,
|
|
61
|
+
path: 'onnx/model.onnx',
|
|
62
|
+
revision: 'v1.2.2-en',
|
|
63
|
+
cacheDir: TEST_CACHE_DIR,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
expect(result).toBeTruthy();
|
|
67
|
+
expect(existsSync(result)).toBe(true);
|
|
68
|
+
|
|
69
|
+
const stats = statSync(result);
|
|
70
|
+
const sizeMB = stats.size / 1024 / 1024;
|
|
71
|
+
expect(sizeMB).toBeCloseTo(249.96, 1); // ~250 MB
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should download a very small file', async () => {
|
|
75
|
+
const result = await downloadFileToCacheDir({
|
|
76
|
+
repo: TEST_REPO,
|
|
77
|
+
path: 'languages.json',
|
|
78
|
+
revision: 'v1.2.2-en',
|
|
79
|
+
cacheDir: TEST_CACHE_DIR,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(result).toBeTruthy();
|
|
83
|
+
expect(existsSync(result)).toBe(true);
|
|
84
|
+
|
|
85
|
+
const stats = statSync(result);
|
|
86
|
+
expect(stats.size).toBeLessThan(200); // Very small file (102 bytes)
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should download from different revision', async () => {
|
|
90
|
+
const result = await downloadFileToCacheDir({
|
|
91
|
+
repo: TEST_REPO,
|
|
92
|
+
path: 'tokenizer.json',
|
|
93
|
+
revision: 'v0.2.0-intl',
|
|
94
|
+
cacheDir: TEST_CACHE_DIR,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(result).toBeTruthy();
|
|
98
|
+
expect(existsSync(result)).toBe(true);
|
|
99
|
+
|
|
100
|
+
const stats = statSync(result);
|
|
101
|
+
const sizeMB = stats.size / 1024 / 1024;
|
|
102
|
+
expect(sizeMB).toBeGreaterThan(3); // Should be around 3.36 MB or more
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe('Cache Behavior', () => {
|
|
107
|
+
it('should use cache on second download', async () => {
|
|
108
|
+
// First download
|
|
109
|
+
const firstPath = await downloadFileToCacheDir({
|
|
110
|
+
repo: TEST_REPO,
|
|
111
|
+
path: 'onnx/model_q8.onnx',
|
|
112
|
+
revision: 'v1.2.2-en',
|
|
113
|
+
cacheDir: TEST_CACHE_DIR,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Second download (should be from cache)
|
|
117
|
+
const startTime = Date.now();
|
|
118
|
+
const secondPath = await downloadFileToCacheDir({
|
|
119
|
+
repo: TEST_REPO,
|
|
120
|
+
path: 'onnx/model_q8.onnx',
|
|
121
|
+
revision: 'v1.2.2-en',
|
|
122
|
+
cacheDir: TEST_CACHE_DIR,
|
|
123
|
+
});
|
|
124
|
+
const cacheTime = Date.now() - startTime;
|
|
125
|
+
|
|
126
|
+
expect(secondPath).toBe(firstPath);
|
|
127
|
+
expect(cacheTime).toBeLessThan(500); // Should be very fast if from cache
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should respect localFileOnly flag when file is cached', async () => {
|
|
131
|
+
// Ensure file is cached first
|
|
132
|
+
await downloadFileToCacheDir({
|
|
133
|
+
repo: TEST_REPO,
|
|
134
|
+
path: 'tokenizer.json',
|
|
135
|
+
revision: 'v0.2.0-intl',
|
|
136
|
+
cacheDir: TEST_CACHE_DIR,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Now try with localFileOnly
|
|
140
|
+
const cachedPath = await downloadFileToCacheDir({
|
|
141
|
+
repo: TEST_REPO,
|
|
142
|
+
path: 'tokenizer.json',
|
|
143
|
+
revision: 'v0.2.0-intl',
|
|
144
|
+
cacheDir: TEST_CACHE_DIR,
|
|
145
|
+
localFileOnly: true,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(cachedPath).toBeTruthy();
|
|
149
|
+
expect(existsSync(cachedPath)).toBe(true);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should throw error with localFileOnly when file is not cached', async () => {
|
|
153
|
+
await expect(
|
|
154
|
+
downloadFileToCacheDir({
|
|
155
|
+
repo: TEST_REPO,
|
|
156
|
+
path: 'non-existent-file.txt',
|
|
157
|
+
revision: 'main',
|
|
158
|
+
cacheDir: TEST_CACHE_DIR,
|
|
159
|
+
localFileOnly: true,
|
|
160
|
+
}),
|
|
161
|
+
).rejects.toThrow(/File not found in cache/);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should save revision-to-commit mappings', async () => {
|
|
165
|
+
await downloadFileToCacheDir({
|
|
166
|
+
repo: TEST_REPO,
|
|
167
|
+
path: 'languages.json',
|
|
168
|
+
revision: 'v1.2.2-en',
|
|
169
|
+
cacheDir: TEST_CACHE_DIR,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Check if refs file was created
|
|
173
|
+
const refsPath = join(getCachePath(TEST_REPO, TEST_CACHE_DIR), 'refs', 'v1.2.2-en');
|
|
174
|
+
expect(existsSync(refsPath)).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should handle multiple files from same revision without overwriting refs', async () => {
|
|
178
|
+
// Download two different files from the same revision
|
|
179
|
+
const file1Path = await downloadFileToCacheDir({
|
|
180
|
+
repo: TEST_REPO,
|
|
181
|
+
path: 'onnx/model_q8.onnx',
|
|
182
|
+
revision: 'v1.2.2-en',
|
|
183
|
+
cacheDir: TEST_CACHE_DIR,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const file2Path = await downloadFileToCacheDir({
|
|
187
|
+
repo: TEST_REPO,
|
|
188
|
+
path: 'languages.json',
|
|
189
|
+
revision: 'v1.2.2-en',
|
|
190
|
+
cacheDir: TEST_CACHE_DIR,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Both files should exist
|
|
194
|
+
expect(existsSync(file1Path)).toBe(true);
|
|
195
|
+
expect(existsSync(file2Path)).toBe(true);
|
|
196
|
+
|
|
197
|
+
// Now test that both files can be retrieved with localFileOnly
|
|
198
|
+
const cachedFile1 = await downloadFileToCacheDir({
|
|
199
|
+
repo: TEST_REPO,
|
|
200
|
+
path: 'onnx/model_q8.onnx',
|
|
201
|
+
revision: 'v1.2.2-en',
|
|
202
|
+
cacheDir: TEST_CACHE_DIR,
|
|
203
|
+
localFileOnly: true,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const cachedFile2 = await downloadFileToCacheDir({
|
|
207
|
+
repo: TEST_REPO,
|
|
208
|
+
path: 'languages.json',
|
|
209
|
+
revision: 'v1.2.2-en',
|
|
210
|
+
cacheDir: TEST_CACHE_DIR,
|
|
211
|
+
localFileOnly: true,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Both should be found in cache
|
|
215
|
+
expect(cachedFile1).toBe(file1Path);
|
|
216
|
+
expect(cachedFile2).toBe(file2Path);
|
|
217
|
+
|
|
218
|
+
// Check that both files are in the same snapshot folder (same commit hash)
|
|
219
|
+
// Extract commit hash from paths
|
|
220
|
+
const match1 = file1Path.match(/snapshots\/([a-f0-9]{40})\//);
|
|
221
|
+
const match2 = file2Path.match(/snapshots\/([a-f0-9]{40})\//);
|
|
222
|
+
|
|
223
|
+
expect(match1).toBeTruthy();
|
|
224
|
+
expect(match2).toBeTruthy();
|
|
225
|
+
|
|
226
|
+
const commitHash1 = match1![1];
|
|
227
|
+
const commitHash2 = match2![1];
|
|
228
|
+
|
|
229
|
+
// FIXED: All files from the same revision should use the same HEAD commit
|
|
230
|
+
expect(commitHash1).toBe(commitHash2);
|
|
231
|
+
|
|
232
|
+
// Check that the refs file contains the single HEAD commit
|
|
233
|
+
const { readFileSync } = await import('fs');
|
|
234
|
+
const refsPath = join(getCachePath(TEST_REPO, TEST_CACHE_DIR), 'refs', 'v1.2.2-en');
|
|
235
|
+
const refsContent = readFileSync(refsPath, 'utf-8').trim();
|
|
236
|
+
|
|
237
|
+
// The refs file should contain just the commit hash, not a JSON mapping
|
|
238
|
+
expect(refsContent).toMatch(/^[a-f0-9]{40}$/);
|
|
239
|
+
expect(refsContent).toBe(commitHash1);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
describe('Error Handling', () => {
|
|
244
|
+
it('should handle invalid repository gracefully', async () => {
|
|
245
|
+
await expect(
|
|
246
|
+
downloadFileToCacheDir({
|
|
247
|
+
repo: 'non-existent-org/non-existent-repo',
|
|
248
|
+
path: 'file.txt',
|
|
249
|
+
revision: 'main',
|
|
250
|
+
cacheDir: TEST_CACHE_DIR,
|
|
251
|
+
}),
|
|
252
|
+
).rejects.toThrow();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should handle invalid file path gracefully', async () => {
|
|
256
|
+
await expect(
|
|
257
|
+
downloadFileToCacheDir({
|
|
258
|
+
repo: TEST_REPO,
|
|
259
|
+
path: 'non-existent-file-path.xyz',
|
|
260
|
+
revision: 'v1.2.2-en',
|
|
261
|
+
cacheDir: TEST_CACHE_DIR,
|
|
262
|
+
}),
|
|
263
|
+
).rejects.toThrow();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should handle invalid revision gracefully', async () => {
|
|
267
|
+
await expect(
|
|
268
|
+
downloadFileToCacheDir({
|
|
269
|
+
repo: TEST_REPO,
|
|
270
|
+
path: 'tokenizer.json',
|
|
271
|
+
revision: 'non-existent-revision',
|
|
272
|
+
cacheDir: TEST_CACHE_DIR,
|
|
273
|
+
}),
|
|
274
|
+
).rejects.toThrow();
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe('Cache Structure', () => {
|
|
279
|
+
it('should create proper cache directory structure', async () => {
|
|
280
|
+
await downloadFileToCacheDir({
|
|
281
|
+
repo: TEST_REPO,
|
|
282
|
+
path: 'onnx/model_q8.onnx',
|
|
283
|
+
revision: 'v1.2.2-en',
|
|
284
|
+
cacheDir: TEST_CACHE_DIR,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const cachePath = getCachePath(TEST_REPO, TEST_CACHE_DIR);
|
|
288
|
+
|
|
289
|
+
// Check expected directories exist
|
|
290
|
+
expect(existsSync(join(cachePath, 'blobs'))).toBe(true);
|
|
291
|
+
expect(existsSync(join(cachePath, 'snapshots'))).toBe(true);
|
|
292
|
+
expect(existsSync(join(cachePath, 'refs'))).toBe(true);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should handle commit hash revisions', async () => {
|
|
296
|
+
// We'll use the actual commit hash from the v1.2.2-en tag
|
|
297
|
+
// First, download to ensure we have the commit hash mapping
|
|
298
|
+
const tagResult = await downloadFileToCacheDir({
|
|
299
|
+
repo: TEST_REPO,
|
|
300
|
+
path: 'onnx/model_q8.onnx',
|
|
301
|
+
revision: 'v1.2.2-en',
|
|
302
|
+
cacheDir: TEST_CACHE_DIR,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// Extract the commit hash from the path
|
|
306
|
+
const match = tagResult.match(/snapshots\/([a-f0-9]{40})\//);
|
|
307
|
+
expect(match).toBeTruthy();
|
|
308
|
+
const commitHash = match![1];
|
|
309
|
+
|
|
310
|
+
// Now download with commit hash directly
|
|
311
|
+
const result = await downloadFileToCacheDir({
|
|
312
|
+
repo: TEST_REPO,
|
|
313
|
+
path: 'onnx/model_q8.onnx',
|
|
314
|
+
revision: commitHash,
|
|
315
|
+
cacheDir: TEST_CACHE_DIR,
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
expect(result).toBeTruthy();
|
|
319
|
+
expect(result).toContain(commitHash);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('should store files as content-addressed blobs', async () => {
|
|
323
|
+
await downloadFileToCacheDir({
|
|
324
|
+
repo: TEST_REPO,
|
|
325
|
+
path: 'languages.json',
|
|
326
|
+
revision: 'v1.2.2-en',
|
|
327
|
+
cacheDir: TEST_CACHE_DIR,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
const blobsPath = join(getCachePath(TEST_REPO, TEST_CACHE_DIR), 'blobs');
|
|
331
|
+
const { readdirSync } = await import('fs');
|
|
332
|
+
const blobs = readdirSync(blobsPath);
|
|
333
|
+
|
|
334
|
+
// Should have at least one blob with SHA256 hash name
|
|
335
|
+
expect(blobs.length).toBeGreaterThan(0);
|
|
336
|
+
expect(blobs[0]).toMatch(/^[a-f0-9]{64}$/);
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
describe('Performance', () => {
|
|
341
|
+
it('should download files in parallel efficiently', async () => {
|
|
342
|
+
const startTime = Date.now();
|
|
343
|
+
|
|
344
|
+
// Download multiple files in parallel
|
|
345
|
+
const promises = [
|
|
346
|
+
downloadFileToCacheDir({
|
|
347
|
+
repo: TEST_REPO,
|
|
348
|
+
path: 'onnx/model_q8.onnx',
|
|
349
|
+
revision: 'v1.2.2-en',
|
|
350
|
+
cacheDir: TEST_CACHE_DIR,
|
|
351
|
+
}),
|
|
352
|
+
downloadFileToCacheDir({
|
|
353
|
+
repo: TEST_REPO,
|
|
354
|
+
path: 'languages.json',
|
|
355
|
+
revision: 'v1.2.2-en',
|
|
356
|
+
cacheDir: TEST_CACHE_DIR,
|
|
357
|
+
}),
|
|
358
|
+
downloadFileToCacheDir({
|
|
359
|
+
repo: TEST_REPO,
|
|
360
|
+
path: 'tokenizer.json',
|
|
361
|
+
revision: 'v0.2.0-intl',
|
|
362
|
+
cacheDir: TEST_CACHE_DIR,
|
|
363
|
+
}),
|
|
364
|
+
];
|
|
365
|
+
|
|
366
|
+
const results = await Promise.all(promises);
|
|
367
|
+
const totalTime = Date.now() - startTime;
|
|
368
|
+
|
|
369
|
+
// All should succeed
|
|
370
|
+
results.forEach((result) => {
|
|
371
|
+
expect(result).toBeTruthy();
|
|
372
|
+
expect(existsSync(result)).toBe(true);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// Should be faster than downloading sequentially
|
|
376
|
+
console.log(`Parallel download took ${totalTime}ms`);
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
describe('Failures', () => {
|
|
381
|
+
it('should handle non-existent file', async () => {
|
|
382
|
+
await expect(
|
|
383
|
+
downloadFileToCacheDir({
|
|
384
|
+
repo: TEST_REPO,
|
|
385
|
+
path: 'onnx/model_non_existent.onnx',
|
|
386
|
+
revision: 'v1.2.2-en',
|
|
387
|
+
cacheDir: TEST_CACHE_DIR,
|
|
388
|
+
}),
|
|
389
|
+
).rejects.toThrow('cannot get path info for onnx/model_non_existent.onnx');
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
});
|