@qvac/registry-client 0.1.6 → 0.2.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/NOTICE +455 -1
- package/README.md +39 -10
- package/bin/cli.js +2 -2
- package/index.d.ts +13 -1
- package/lib/client.js +148 -22
- package/lib/compat/fs.js +3 -0
- package/lib/compat/os.js +3 -0
- package/lib/compat/path.js +3 -0
- package/lib/config.js +3 -3
- package/package.json +16 -5
package/NOTICE
CHANGED
|
@@ -1,4 +1,458 @@
|
|
|
1
1
|
@qvac/registry-client
|
|
2
2
|
Copyright 2026 Tether Data, S.A. de C.V.
|
|
3
3
|
|
|
4
|
-
This product includes
|
|
4
|
+
This product includes third-party components under their
|
|
5
|
+
respective licenses. @qvac/registry-client itself is licensed under
|
|
6
|
+
Apache-2.0; bundled dependencies are governed by the licenses
|
|
7
|
+
listed below.
|
|
8
|
+
|
|
9
|
+
=========================================================================
|
|
10
|
+
Required Attribution Notices
|
|
11
|
+
=========================================================================
|
|
12
|
+
|
|
13
|
+
Gemma is provided under and subject to the Gemma Terms of Use found
|
|
14
|
+
at ai.google.dev/gemma/terms
|
|
15
|
+
|
|
16
|
+
Additional requirements per Section 3.1:
|
|
17
|
+
Distribution must be accompanied by the Gemma Terms of Use.
|
|
18
|
+
Use is subject to the Gemma Prohibited Use Policy at
|
|
19
|
+
ai.google.dev/gemma/prohibited_use_policy
|
|
20
|
+
|
|
21
|
+
HAI-DEF is provided under and subject to the Health AI Developer
|
|
22
|
+
Foundations Terms of Use found at
|
|
23
|
+
https://developers.google.com/health-ai-developer-foundations/terms
|
|
24
|
+
|
|
25
|
+
Additional requirements per Section 3.1:
|
|
26
|
+
Distribution must be accompanied by the HAI-DEF Terms of Use.
|
|
27
|
+
Clinical use requires Health Regulatory Authorization from the
|
|
28
|
+
relevant authority (Section 3.1.3).
|
|
29
|
+
Use is subject to the HAI-DEF Prohibited Use Policy at
|
|
30
|
+
developers.google.com/health-ai-developer-foundations/prohibited-use-policy
|
|
31
|
+
|
|
32
|
+
Llama 3.2 is licensed under the Llama 3.2 Community License,
|
|
33
|
+
Copyright (c) Meta Platforms, Inc. All Rights Reserved.
|
|
34
|
+
|
|
35
|
+
Additional requirements per license Section 1.b.i:
|
|
36
|
+
Products or services distributing or containing Llama 3.2 materials
|
|
37
|
+
must prominently display "Built with Llama" on a related website,
|
|
38
|
+
user interface, blog post, about page, or product documentation.
|
|
39
|
+
|
|
40
|
+
=========================================================================
|
|
41
|
+
Third-Party Model Licenses
|
|
42
|
+
=========================================================================
|
|
43
|
+
|
|
44
|
+
--- apache-2.0 (Apache License 2.0) ---
|
|
45
|
+
|
|
46
|
+
de-tiny-ggml-model-f16
|
|
47
|
+
https://huggingface.co/primeline/whisper-tiny-german-1224
|
|
48
|
+
en-base-ggml-model-f16
|
|
49
|
+
https://huggingface.co/openai/whisper-base
|
|
50
|
+
fr-base-ggml-model-f16
|
|
51
|
+
https://huggingface.co/personalizedrefrigerator/whisper-base-fr
|
|
52
|
+
fr-tiny-ggml-model-f16
|
|
53
|
+
https://huggingface.co/JaepaX/whisper-tiny-fr
|
|
54
|
+
ggml-opus-ar-en
|
|
55
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-ar-en
|
|
56
|
+
ggml-opus-de-en
|
|
57
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-de-en
|
|
58
|
+
ggml-opus-de-fr
|
|
59
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-de-fr
|
|
60
|
+
ggml-opus-en-ar
|
|
61
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-ar
|
|
62
|
+
ggml-opus-en-es
|
|
63
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-es
|
|
64
|
+
ggml-opus-en-fr
|
|
65
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-fr
|
|
66
|
+
ggml-opus-en-it
|
|
67
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-it
|
|
68
|
+
ggml-opus-en-ru
|
|
69
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-ru
|
|
70
|
+
ggml-opus-en-zh
|
|
71
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-zh
|
|
72
|
+
ggml-opus-es-en
|
|
73
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-es-en
|
|
74
|
+
ggml-opus-es-fr
|
|
75
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-es-fr
|
|
76
|
+
ggml-opus-fr-de
|
|
77
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-fr-de
|
|
78
|
+
ggml-opus-fr-en
|
|
79
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-fr-en
|
|
80
|
+
ggml-opus-fr-es
|
|
81
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-fr-es
|
|
82
|
+
ggml-opus-it-en
|
|
83
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-it-en
|
|
84
|
+
ggml-opus-ja-en
|
|
85
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-ja-en
|
|
86
|
+
ggml-opus-mt-en-roa-f16
|
|
87
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-roa
|
|
88
|
+
ggml-opus-mt-roa-en-f16
|
|
89
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-roa-en
|
|
90
|
+
gpt-oss-20b-GGUF
|
|
91
|
+
https://huggingface.co/unsloth/gpt-oss-20b-GGUF
|
|
92
|
+
it-base-ggml-model-f16
|
|
93
|
+
https://huggingface.co/gustavv-andrzejewski/distil-whisper-base-it
|
|
94
|
+
it-tiny-ggml-model-f16
|
|
95
|
+
https://huggingface.co/luigisaetta/whisper-tiny-it
|
|
96
|
+
ja-base-ggml-model-f16
|
|
97
|
+
https://huggingface.co/bygreencn/whisper-base-ja
|
|
98
|
+
ja-tiny-ggml-model-f16
|
|
99
|
+
https://huggingface.co/CheeLi03/whisper-tiny-ja-puct-4k
|
|
100
|
+
laser-dolphin-mixtral-2x7b-dpo-GGUF
|
|
101
|
+
https://huggingface.co/jmb95/laser-dolphin-mixtral-2x7b-dpo-GGUF
|
|
102
|
+
Llama_3.2_1B_Intruct_Tool_Calling_V2-GGUF
|
|
103
|
+
https://huggingface.co/mav23/Llama_3.2_1B_Intruct_Tool_Calling_V2-GGUF
|
|
104
|
+
nb-tiny-ggml-model
|
|
105
|
+
https://huggingface.co/NbAiLab/nb-whisper-tiny
|
|
106
|
+
pt-base-ggml-model-f16
|
|
107
|
+
https://huggingface.co/mariana-coelho-9/whisper-base-pt
|
|
108
|
+
Qwen3-0.6B-GGUF
|
|
109
|
+
https://huggingface.co/unsloth/Qwen3-0.6B-GGUF
|
|
110
|
+
Qwen3-1.7B-GGUF
|
|
111
|
+
https://huggingface.co/unsloth/Qwen3-1.7B-GGUF
|
|
112
|
+
Qwen3-4B-Q4_0-00001-of-00005
|
|
113
|
+
https://huggingface.co/unsloth/Qwen3-4B-GGUF
|
|
114
|
+
Qwen3-4B-Q4_K_M
|
|
115
|
+
https://huggingface.co/Qwen/Qwen3-4B-GGUF
|
|
116
|
+
Qwen3-8B-GGUF
|
|
117
|
+
https://huggingface.co/Qwen/Qwen3-8B-GGUF
|
|
118
|
+
Qwen3-VL-2B-Instruct-GGUF
|
|
119
|
+
https://huggingface.co/Qwen/Qwen3-VL-2B-Instruct-GGUF
|
|
120
|
+
recognizer_latin
|
|
121
|
+
https://www.jaided.ai/easyocr/modelhub/
|
|
122
|
+
ru-base-ggml-model-f16
|
|
123
|
+
https://huggingface.co/CheeLi03/whisper-base-rus-8
|
|
124
|
+
ru-tiny-ggml-model-f16
|
|
125
|
+
https://huggingface.co/yaroslav0530/whisper-tiny-ru
|
|
126
|
+
salamandraTA-2B-instruct-GGUF
|
|
127
|
+
https://huggingface.co/BSC-LT/salamandraTA-2B-instruct-GGUF
|
|
128
|
+
SmolVLM2-500M-Video-Instruct-GGUF
|
|
129
|
+
https://huggingface.co/ggml-org/SmolVLM2-500M-Video-Instruct-GGUF
|
|
130
|
+
|
|
131
|
+
--- cc-by-4.0 (Creative Commons Attribution 4.0 International) ---
|
|
132
|
+
|
|
133
|
+
ggml-opus-en-de
|
|
134
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-en-de
|
|
135
|
+
ggml-opus-en-pt
|
|
136
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-tc-big-en-pt
|
|
137
|
+
ggml-opus-ru-en
|
|
138
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-ru-en
|
|
139
|
+
ggml-opus-zh-en
|
|
140
|
+
https://huggingface.co/Helsinki-NLP/opus-mt-zh-en
|
|
141
|
+
|
|
142
|
+
--- gemma (Gemma Terms of Use) ---
|
|
143
|
+
|
|
144
|
+
embeddinggemma-300m-GGUF
|
|
145
|
+
https://huggingface.co/unsloth/embeddinggemma-300m-GGUF
|
|
146
|
+
|
|
147
|
+
--- health-ai-developer-foundations (HAI-DEF Terms of Use) ---
|
|
148
|
+
|
|
149
|
+
medgemma-4b-it-GGUF
|
|
150
|
+
https://huggingface.co/unsloth/medgemma-4b-it-GGUF
|
|
151
|
+
|
|
152
|
+
--- llama3.2 (Llama 3.2 Community License) ---
|
|
153
|
+
|
|
154
|
+
Llama-3.2-1B-Instruct-GGUF
|
|
155
|
+
https://huggingface.co/unsloth/Llama-3.2-1B-Instruct-GGUF
|
|
156
|
+
Llama-3.2-1B-Instruct-Q4_0-00001-of-00008
|
|
157
|
+
https://huggingface.co/bartowski/Llama-3.2-1B-Instruct-GGUF
|
|
158
|
+
|
|
159
|
+
--- mit (MIT License) ---
|
|
160
|
+
|
|
161
|
+
chatterbox-turbo-ONNX
|
|
162
|
+
https://huggingface.co/ResembleAI/chatterbox-turbo-ONNX
|
|
163
|
+
de-base-ggml-model-f16
|
|
164
|
+
https://huggingface.co/aware-ai/whisper-base-german
|
|
165
|
+
es-tiny-ggml-model-f16
|
|
166
|
+
https://huggingface.co/JaepaX/whisper-tiny-es
|
|
167
|
+
ggml-indictrans2-en-indic-1B-f16
|
|
168
|
+
https://huggingface.co/ai4bharat/indictrans2-en-indic-1B
|
|
169
|
+
ggml-indictrans2-en-indic-dist-200M-f16
|
|
170
|
+
https://huggingface.co/ai4bharat/indictrans2-en-indic-dist-200M
|
|
171
|
+
ggml-indictrans2-indic-en-1B-f16
|
|
172
|
+
https://huggingface.co/ai4bharat/indictrans2-indic-en-1B
|
|
173
|
+
ggml-indictrans2-indic-en-dist-200M-f16
|
|
174
|
+
https://huggingface.co/ai4bharat/indictrans2-indic-en-dist-200M
|
|
175
|
+
ggml-indictrans2-indic-indic-1B-f16
|
|
176
|
+
https://huggingface.co/ai4bharat/indictrans2-indic-indic-1B
|
|
177
|
+
ggml-indictrans2-indic-indic-dist-320M-f16
|
|
178
|
+
https://huggingface.co/ai4bharat/indictrans2-indic-indic-dist-320M
|
|
179
|
+
gte-large-gguf
|
|
180
|
+
https://huggingface.co/ChristianAzinn/gte-large-gguf
|
|
181
|
+
pt-tiny-ggml-model-f16
|
|
182
|
+
https://huggingface.co/DavyCosta701/whisper-tiny-pt-bpra
|
|
183
|
+
tiny_acft_q8_0
|
|
184
|
+
https://voiceinput.futo.org/VoiceInput/tiny_en_acft_q8_0.bin
|
|
185
|
+
whisper-vad
|
|
186
|
+
https://huggingface.co/ggml-org/whisper-vad
|
|
187
|
+
whisper.cpp
|
|
188
|
+
https://huggingface.co/ggerganov/whisper.cpp
|
|
189
|
+
|
|
190
|
+
--- mpl-2.0 (Mozilla Public License 2.0) ---
|
|
191
|
+
|
|
192
|
+
lex.50.50.aren.s2t
|
|
193
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/aren
|
|
194
|
+
lex.50.50.csen.s2t
|
|
195
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/csen
|
|
196
|
+
lex.50.50.enar.s2t
|
|
197
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/enar
|
|
198
|
+
lex.50.50.encs.s2t
|
|
199
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/encs
|
|
200
|
+
lex.50.50.enes.s2t
|
|
201
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/enes
|
|
202
|
+
lex.50.50.enfr.s2t
|
|
203
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/enfr
|
|
204
|
+
lex.50.50.enit.s2t
|
|
205
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/tiny/enit
|
|
206
|
+
lex.50.50.enja.s2t
|
|
207
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/enja
|
|
208
|
+
lex.50.50.enpt.s2t
|
|
209
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/enpt
|
|
210
|
+
lex.50.50.enru.s2t
|
|
211
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/enru
|
|
212
|
+
lex.50.50.enzh.s2t
|
|
213
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/enzh
|
|
214
|
+
lex.50.50.esen.s2t
|
|
215
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/tiny/esen
|
|
216
|
+
lex.50.50.fren.s2t
|
|
217
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/fren
|
|
218
|
+
lex.50.50.iten.s2t
|
|
219
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/iten
|
|
220
|
+
lex.50.50.jaen.s2t
|
|
221
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/jaen
|
|
222
|
+
lex.50.50.pten.s2t
|
|
223
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/pten
|
|
224
|
+
lex.50.50.ruen.s2t
|
|
225
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/tiny/ruen
|
|
226
|
+
lex.50.50.zhen.s2t
|
|
227
|
+
https://github.com/mozilla/firefox-translations-models/tree/main/models/base-memory/zhen
|
|
228
|
+
|
|
229
|
+
--- openrail ---
|
|
230
|
+
|
|
231
|
+
Supertonic-TTS-ONNX
|
|
232
|
+
https://huggingface.co/onnx-community/Supertonic-TTS-ONNX
|
|
233
|
+
|
|
234
|
+
=========================================================================
|
|
235
|
+
Modification Notice
|
|
236
|
+
=========================================================================
|
|
237
|
+
|
|
238
|
+
Models listed above may have been converted from original model
|
|
239
|
+
weights into optimized inference formats (GGUF, GGML, ONNX, or
|
|
240
|
+
Bergamot intgemm). These conversions involve format transformation
|
|
241
|
+
and/or weight quantization. No architectural changes were made to
|
|
242
|
+
the underlying models.
|
|
243
|
+
|
|
244
|
+
Source URLs for original weights are recorded in each model's
|
|
245
|
+
metadata entry within the registry.
|
|
246
|
+
|
|
247
|
+
=========================================================================
|
|
248
|
+
JavaScript Dependencies
|
|
249
|
+
=========================================================================
|
|
250
|
+
|
|
251
|
+
--- apache-2.0 (Apache License 2.0) ---
|
|
252
|
+
|
|
253
|
+
@hyperswarm/secret-stream@6.9.1
|
|
254
|
+
https://github.com/holepunchto/hyperswarm-secret-stream
|
|
255
|
+
@qvac/error@0.1.1
|
|
256
|
+
@qvac/registry-schema@0.1.1
|
|
257
|
+
adaptive-timeout@1.0.1
|
|
258
|
+
https://github.com/holepunchto/adaptive-timeout
|
|
259
|
+
b4a@1.7.3
|
|
260
|
+
https://github.com/holepunchto/b4a
|
|
261
|
+
bare-addon-resolve@1.9.7
|
|
262
|
+
https://github.com/holepunchto/bare-addon-resolve
|
|
263
|
+
bare-env@3.0.0
|
|
264
|
+
https://github.com/holepunchto/bare-env
|
|
265
|
+
bare-events@2.8.2
|
|
266
|
+
https://github.com/holepunchto/bare-events
|
|
267
|
+
bare-fs@4.5.4
|
|
268
|
+
https://github.com/holepunchto/bare-fs
|
|
269
|
+
bare-hrtime@2.1.1
|
|
270
|
+
https://github.com/holepunchto/bare-hrtime
|
|
271
|
+
bare-module-resolve@1.12.1
|
|
272
|
+
https://github.com/holepunchto/bare-module-resolve
|
|
273
|
+
bare-node-fs@1.0.2
|
|
274
|
+
https://github.com/holepunchto/bare-node
|
|
275
|
+
bare-node-os@1.0.1
|
|
276
|
+
https://github.com/holepunchto/bare-node
|
|
277
|
+
bare-node-path@1.0.1
|
|
278
|
+
https://github.com/holepunchto/bare-node
|
|
279
|
+
bare-node-process@1.0.1
|
|
280
|
+
https://github.com/holepunchto/bare-node
|
|
281
|
+
bare-os@3.6.2
|
|
282
|
+
https://github.com/holepunchto/bare-os
|
|
283
|
+
bare-path@3.0.0
|
|
284
|
+
https://github.com/holepunchto/bare-path
|
|
285
|
+
bare-pipe@4.1.3
|
|
286
|
+
https://github.com/holepunchto/bare-pipe
|
|
287
|
+
bare-process@4.2.2
|
|
288
|
+
https://github.com/holepunchto/bare-process
|
|
289
|
+
bare-semver@1.0.2
|
|
290
|
+
https://github.com/holepunchto/bare-semver
|
|
291
|
+
bare-signals@4.2.0
|
|
292
|
+
https://github.com/holepunchto/bare-signals
|
|
293
|
+
bare-stream@2.7.0
|
|
294
|
+
https://github.com/holepunchto/bare-stream
|
|
295
|
+
bare-tty@5.0.3
|
|
296
|
+
https://github.com/holepunchto/bare-tty
|
|
297
|
+
bare-url@2.3.2
|
|
298
|
+
https://github.com/holepunchto/bare-url
|
|
299
|
+
blind-relay@1.4.0
|
|
300
|
+
https://github.com/holepunchto/blind-relay
|
|
301
|
+
compact-encoding@2.18.0
|
|
302
|
+
https://github.com/compact-encoding/compact-encoding
|
|
303
|
+
device-file@2.3.1
|
|
304
|
+
https://github.com/holepunchto/device-file
|
|
305
|
+
events-universal@1.0.1
|
|
306
|
+
https://github.com/holepunchto/events-universal
|
|
307
|
+
fd-lock@2.1.1
|
|
308
|
+
https://github.com/holepunchto/fd-lock
|
|
309
|
+
fs-native-extensions@1.4.5
|
|
310
|
+
https://github.com/holepunchto/fs-native-extensions
|
|
311
|
+
hyperblobs@2.8.0
|
|
312
|
+
https://github.com/holepunchto/hyperblobs
|
|
313
|
+
hypercore-errors@1.5.0
|
|
314
|
+
https://github.com/holepunchto/hypercore-errors
|
|
315
|
+
hypercore-id-encoding@1.3.0
|
|
316
|
+
https://github.com/holepunchto/hypercore-id-encoding
|
|
317
|
+
hypercore-storage@2.4.1
|
|
318
|
+
hyperdb@4.22.3
|
|
319
|
+
https://github.com/holepunchto/hyperdb
|
|
320
|
+
hyperdispatch@1.4.4
|
|
321
|
+
https://github.com/holepunchto/hyperdispatch
|
|
322
|
+
hyperschema@1.19.0
|
|
323
|
+
https://github.com/holepunchto/hyperschema
|
|
324
|
+
index-encoder@3.4.0
|
|
325
|
+
https://github.com/holepunchto/index-encoder
|
|
326
|
+
noise-handshake@4.2.0
|
|
327
|
+
https://github.com/holepunchto/noise-handshake
|
|
328
|
+
paparam@1.10.0
|
|
329
|
+
https://github.com/holepunchto/paparam
|
|
330
|
+
quickbit-native@2.4.8
|
|
331
|
+
https://github.com/holepunchto/quickbit-native
|
|
332
|
+
rache@1.0.0
|
|
333
|
+
https://github.com/holepunchto/rache
|
|
334
|
+
refcounter@1.0.0
|
|
335
|
+
https://github.com/holepunchto/refcounter
|
|
336
|
+
require-addon@1.2.0
|
|
337
|
+
https://github.com/holepunchto/require-addon
|
|
338
|
+
resource-on-exit@1.0.0
|
|
339
|
+
https://github.com/holepunchto/bare-teardown
|
|
340
|
+
rocksdb-native@3.12.0
|
|
341
|
+
https://github.com/holepunchto/rocksdb-native
|
|
342
|
+
scope-lock@1.2.4
|
|
343
|
+
https://github.com/holepunchto/scope-lock
|
|
344
|
+
simdle-native@1.3.9
|
|
345
|
+
https://github.com/holepunchto/simdle-native
|
|
346
|
+
text-decoder@1.2.3
|
|
347
|
+
https://github.com/holepunchto/text-decoder
|
|
348
|
+
udx-native@1.19.2
|
|
349
|
+
https://github.com/holepunchto/udx-native
|
|
350
|
+
unslab@1.3.0
|
|
351
|
+
https://github.com/holepunchto/unslab
|
|
352
|
+
which-runtime@1.3.2
|
|
353
|
+
https://github.com/holepunchto/which-runtime
|
|
354
|
+
|
|
355
|
+
--- isc (ISC License) ---
|
|
356
|
+
|
|
357
|
+
bits-to-bytes@1.3.0
|
|
358
|
+
https://github.com/holepunchto/bits-to-bytes
|
|
359
|
+
compact-encoding-bitfield@1.0.0
|
|
360
|
+
https://github.com/compact-encoding/compact-encoding-bitfield
|
|
361
|
+
compact-encoding-net@1.2.0
|
|
362
|
+
https://github.com/compact-encoding/compact-encoding-net
|
|
363
|
+
nanoassert@2.0.0
|
|
364
|
+
https://github.com/emilbayes/nanoassert
|
|
365
|
+
noise-curve-ed@2.1.0
|
|
366
|
+
https://github.com/chm-diederichs/noise-curve-ed
|
|
367
|
+
quickbit-universal@2.2.0
|
|
368
|
+
https://github.com/holepunchto/quickbit-universal
|
|
369
|
+
simdle-universal@1.1.2
|
|
370
|
+
https://github.com/holepunchto/simdle-universal
|
|
371
|
+
|
|
372
|
+
--- mit (MIT License) ---
|
|
373
|
+
|
|
374
|
+
big-sparse-array@1.0.3
|
|
375
|
+
https://github.com/mafintosh/big-sparse-array
|
|
376
|
+
bogon@1.2.0
|
|
377
|
+
https://github.com/mafintosh/bogon
|
|
378
|
+
codecs@3.1.0
|
|
379
|
+
https://github.com/mafintosh/codecs
|
|
380
|
+
corestore@7.8.0
|
|
381
|
+
https://github.com/holepunchto/corestore
|
|
382
|
+
debounceify@1.1.0
|
|
383
|
+
https://github.com/mafintosh/debounceify
|
|
384
|
+
dht-rpc@6.24.2
|
|
385
|
+
https://github.com/mafintosh/dht-rpc
|
|
386
|
+
fast-fifo@1.3.2
|
|
387
|
+
https://github.com/mafintosh/fast-fifo
|
|
388
|
+
flat-tree@1.13.0
|
|
389
|
+
https://github.com/mafintosh/flat-tree
|
|
390
|
+
generate-object-property@2.0.0
|
|
391
|
+
https://github.com/mafintosh/generate-object-property
|
|
392
|
+
generate-string@1.0.1
|
|
393
|
+
https://github.com/mafintosh/generate-string
|
|
394
|
+
hyperbee@2.27.3
|
|
395
|
+
https://github.com/holepunchto/hyperbee
|
|
396
|
+
hypercore@11.24.0
|
|
397
|
+
https://github.com/holepunchto/hypercore
|
|
398
|
+
hypercore-crypto@3.6.1
|
|
399
|
+
https://github.com/mafintosh/hypercore-crypto
|
|
400
|
+
hyperdht@6.29.0
|
|
401
|
+
https://github.com/holepunchto/hyperdht
|
|
402
|
+
hyperswarm@4.16.0
|
|
403
|
+
https://github.com/holepunchto/hyperswarm
|
|
404
|
+
is-options@1.0.2
|
|
405
|
+
https://github.com/mafintosh/is-options
|
|
406
|
+
is-property@1.0.2
|
|
407
|
+
https://github.com/mikolalysenko/is-property
|
|
408
|
+
kademlia-routing-table@1.0.6
|
|
409
|
+
https://github.com/mafintosh/kademlia-routing-table
|
|
410
|
+
mutexify@1.4.0
|
|
411
|
+
https://github.com/mafintosh/mutexify
|
|
412
|
+
nat-sampler@1.0.1
|
|
413
|
+
https://github.com/mafintosh/nat-sampler
|
|
414
|
+
protocol-buffers-encodings@1.2.0
|
|
415
|
+
https://github.com/mafintosh/protocol-buffers-encodings
|
|
416
|
+
protomux@3.10.1
|
|
417
|
+
https://github.com/mafintosh/protomux
|
|
418
|
+
queue-tick@1.0.1
|
|
419
|
+
https://github.com/mafintosh/queue-tick
|
|
420
|
+
random-array-iterator@1.0.0
|
|
421
|
+
https://github.com/mafintosh/random-array-iterator
|
|
422
|
+
ready-resource@1.2.0
|
|
423
|
+
https://github.com/holepunchto/ready-resource
|
|
424
|
+
record-cache@1.2.0
|
|
425
|
+
https://github.com/mafintosh/record-cache
|
|
426
|
+
resolve-reject-promise@1.1.0
|
|
427
|
+
https://github.com/mafintosh/resolve-reject-promise
|
|
428
|
+
safety-catch@1.0.2
|
|
429
|
+
https://github.com/mafintosh/safety-catch
|
|
430
|
+
shuffled-priority-queue@2.1.0
|
|
431
|
+
https://github.com/mafintosh/shuffled-priority-queue
|
|
432
|
+
signal-promise@1.0.3
|
|
433
|
+
https://github.com/mafintosh/signal-promise
|
|
434
|
+
signed-varint@2.0.1
|
|
435
|
+
https://github.com/dominictarr/signed-varint
|
|
436
|
+
sodium-native@5.0.10
|
|
437
|
+
https://github.com/holepunchto/sodium-native
|
|
438
|
+
sodium-secretstream@1.2.0
|
|
439
|
+
https://github.com/mafintosh/sodium-secretstream
|
|
440
|
+
sodium-universal@5.0.1
|
|
441
|
+
https://github.com/holepunchto/sodium-universal
|
|
442
|
+
speedometer@1.1.0
|
|
443
|
+
https://github.com/mafintosh/speedometer
|
|
444
|
+
streamx@2.23.0
|
|
445
|
+
https://github.com/mafintosh/streamx
|
|
446
|
+
time-ordered-set@2.0.1
|
|
447
|
+
https://github.com/mafintosh/time-ordered-set
|
|
448
|
+
timeout-refresh@2.0.1
|
|
449
|
+
https://github.com/mafintosh/timeout-refresh
|
|
450
|
+
unordered-set@2.0.1
|
|
451
|
+
https://github.com/mafintosh/unordered-set
|
|
452
|
+
varint@5.0.0
|
|
453
|
+
https://github.com/chrisdickinson/varint
|
|
454
|
+
xache@1.2.1
|
|
455
|
+
https://github.com/mafintosh/xache
|
|
456
|
+
z32@1.1.0
|
|
457
|
+
https://github.com/mafintosh/z32
|
|
458
|
+
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @qvac/registry-client
|
|
2
2
|
|
|
3
3
|
Read-only client library for querying the QVAC Registry. It replicates the registry HyperDB via Hyperswarm and provides APIs for searching and retrieving model information.
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ Read-only client library for querying the QVAC Registry. It replicates the regis
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npm install @
|
|
16
|
+
npm install @qvac/registry-client
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Ensure the registry core key is available via environment variables or provided via options.
|
|
@@ -24,7 +24,7 @@ Ensure the registry core key is available via environment variables or provided
|
|
|
24
24
|
|
|
25
25
|
```javascript
|
|
26
26
|
'use strict'
|
|
27
|
-
const { QVACRegistryClient } = require('@
|
|
27
|
+
const { QVACRegistryClient } = require('@qvac/registry-client')
|
|
28
28
|
|
|
29
29
|
async function main () {
|
|
30
30
|
const client = new QVACRegistryClient({
|
|
@@ -106,18 +106,45 @@ const fs = require('fs')
|
|
|
106
106
|
result.artifact.stream.pipe(fs.createWriteStream('./model.ggml'))
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
+
#### Direct Blob Download
|
|
110
|
+
|
|
111
|
+
- `downloadBlob(blobBinding, options)`: Downloads a blob directly using known blob coordinates, bypassing the metadata core lookup. Useful when `coreKey`, `blockOffset`, `blockLength`, and `byteLength` are already known (e.g., from a previous query or generated model constants).
|
|
112
|
+
- `blobBinding`: `{ coreKey, blockOffset, blockLength, byteOffset, byteLength }` — `coreKey` accepts Buffer, hex, or z-base-32 strings
|
|
113
|
+
- `options`:
|
|
114
|
+
- `timeout`: Download timeout in ms (default: 30000)
|
|
115
|
+
- `outputFile`: Optional file path to save directly to disk
|
|
116
|
+
- `onProgress`: Callback `({ downloaded, total, cachedBlocks, totalBlocks }) => void`
|
|
117
|
+
- `signal`: `AbortSignal` for cancellation
|
|
118
|
+
- Returns: `{ artifact: { path, totalSize } | { stream, totalSize } }`
|
|
119
|
+
|
|
120
|
+
This method only waits for the network layer (Corestore + Hyperswarm) — it does not wait for the metadata core to sync, making it faster for known blob coordinates.
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
const result = await client.downloadBlob({
|
|
124
|
+
coreKey: 'ey46cahego89xox118uhyryakz47bcs8bbxu97tnnpmuwmgi5wmo',
|
|
125
|
+
blockOffset: 0,
|
|
126
|
+
blockLength: 665,
|
|
127
|
+
byteOffset: 0,
|
|
128
|
+
byteLength: 43537433
|
|
129
|
+
}, {
|
|
130
|
+
outputFile: './downloaded/ggml-tiny-q8_0.bin',
|
|
131
|
+
timeout: 60000
|
|
132
|
+
})
|
|
133
|
+
console.log('Downloaded to:', result.artifact.path)
|
|
134
|
+
```
|
|
135
|
+
|
|
109
136
|
## CLI
|
|
110
137
|
|
|
111
138
|
The package includes a CLI for querying and downloading models from the registry.
|
|
112
139
|
|
|
113
140
|
### Install
|
|
114
141
|
|
|
115
|
-
The package is hosted on
|
|
142
|
+
The package is hosted on npm. Configure npm to use the registry for the `@qvac` scope, then install globally:
|
|
116
143
|
|
|
117
144
|
```bash
|
|
118
|
-
echo "@
|
|
119
|
-
echo "//
|
|
120
|
-
npm install -g @
|
|
145
|
+
echo "@qvac:registry=https://registry.npmjs.org" >> ~/.npmrc
|
|
146
|
+
echo "//registry.npmjs.org/:_authToken=YOUR_NPM_TOKEN" >> ~/.npmrc
|
|
147
|
+
npm install -g @qvac/registry-client
|
|
121
148
|
```
|
|
122
149
|
|
|
123
150
|
Verify installation:
|
|
@@ -220,7 +247,8 @@ $ qvac-registry list --engine @qvac/transcription-whispercpp --json | jq '.[0].p
|
|
|
220
247
|
See the `examples/` folder for complete working examples:
|
|
221
248
|
|
|
222
249
|
- `example.js`: List models, query by engine/name/quantization, find shards
|
|
223
|
-
- `download-model.js`: Download a single model to disk
|
|
250
|
+
- `download-model.js`: Download a single model to disk via metadata lookup
|
|
251
|
+
- `download-blob.js`: Download a blob directly using known blob coordinates
|
|
224
252
|
- `download-all-models.js`: Download all models in the registry
|
|
225
253
|
|
|
226
254
|
Run examples:
|
|
@@ -229,6 +257,7 @@ Run examples:
|
|
|
229
257
|
cd client
|
|
230
258
|
node examples/example.js
|
|
231
259
|
node examples/download-model.js
|
|
260
|
+
node examples/download-blob.js
|
|
232
261
|
node examples/download-all-models.js
|
|
233
262
|
```
|
|
234
263
|
|
|
@@ -271,8 +300,8 @@ The client uses custom error codes in the range 19001-20000. All errors extend `
|
|
|
271
300
|
### Error Handling Example
|
|
272
301
|
|
|
273
302
|
```javascript
|
|
274
|
-
const { QVACRegistryClient } = require('@
|
|
275
|
-
const { QvacErrorRegistryClient } = require('@
|
|
303
|
+
const { QVACRegistryClient } = require('@qvac/registry-client')
|
|
304
|
+
const { QvacErrorRegistryClient } = require('@qvac/registry-client/utils/error')
|
|
276
305
|
|
|
277
306
|
async function handleErrors () {
|
|
278
307
|
const client = new QVACRegistryClient({
|
package/bin/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const { command, flag, arg, summary, header, footer, description } = require('paparam')
|
|
5
5
|
const { QVACRegistryClient } = require('../index')
|
|
6
6
|
const IdEnc = require('hypercore-id-encoding')
|
|
7
|
-
const path = require('path')
|
|
7
|
+
const path = require('#path')
|
|
8
8
|
|
|
9
9
|
const VERSION = require('../package.json').version
|
|
10
10
|
|
|
@@ -23,7 +23,7 @@ function createClient (parentFlags) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function getRootFlags (cmd) {
|
|
26
|
-
let current = cmd
|
|
26
|
+
let current = cmd.command || cmd
|
|
27
27
|
while (current.parent) current = current.parent
|
|
28
28
|
return current.flags || {}
|
|
29
29
|
}
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export interface QVACBlobBinding {
|
|
2
|
-
coreKey: Buffer
|
|
2
|
+
coreKey: Buffer | string
|
|
3
3
|
blockOffset: number
|
|
4
4
|
blockLength: number
|
|
5
5
|
byteOffset: number
|
|
@@ -43,6 +43,17 @@ export interface QVACDownloadOptions {
|
|
|
43
43
|
outputFile?: string
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
export interface QVACBlobDownloadOptions {
|
|
47
|
+
timeout?: number
|
|
48
|
+
outputFile?: string
|
|
49
|
+
onProgress?: (progress: { downloaded: number, total: number, cachedBlocks: number, totalBlocks: number }) => void
|
|
50
|
+
signal?: AbortSignal
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface QVACBlobDownloadResult {
|
|
54
|
+
artifact: QVACDownloadedArtifact & { totalSize: number }
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
export interface QVACRegistryClientOptions {
|
|
47
58
|
storage?: string
|
|
48
59
|
registryCoreKey?: string
|
|
@@ -75,6 +86,7 @@ export class QVACRegistryClient {
|
|
|
75
86
|
|
|
76
87
|
getModel (path: string, source: string): Promise<QVACModelEntry | null>
|
|
77
88
|
downloadModel (path: string, source: string, options?: QVACDownloadOptions): Promise<QVACDownloadResult>
|
|
89
|
+
downloadBlob (blobBinding: QVACBlobBinding, options?: QVACBlobDownloadOptions): Promise<QVACBlobDownloadResult>
|
|
78
90
|
|
|
79
91
|
findBy (params?: FindByParams): Promise<QVACModelEntry[]>
|
|
80
92
|
findModels (query?: QVACModelQuery): Promise<QVACModelEntry[]>
|
package/lib/client.js
CHANGED
|
@@ -9,8 +9,8 @@ const Corestore = require('corestore')
|
|
|
9
9
|
const Hyperswarm = require('hyperswarm')
|
|
10
10
|
const Hyperblobs = require('hyperblobs')
|
|
11
11
|
const IdEnc = require('hypercore-id-encoding')
|
|
12
|
-
const path = require('path')
|
|
13
|
-
const fs = require('fs')
|
|
12
|
+
const path = require('#path')
|
|
13
|
+
const fs = require('#fs')
|
|
14
14
|
|
|
15
15
|
class QVACRegistryClient extends ReadyResource {
|
|
16
16
|
constructor (opts = {}) {
|
|
@@ -23,6 +23,7 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
23
23
|
this.corestore = null
|
|
24
24
|
this.hyperswarm = null
|
|
25
25
|
this._connectionHandler = null
|
|
26
|
+
this._metadataReady = null
|
|
26
27
|
|
|
27
28
|
this.storage = this.registryConfig.getRegistryStorage(opts.storage)
|
|
28
29
|
this.registryCoreKey = this.registryConfig.getRegistryCoreKey(opts.registryCoreKey)
|
|
@@ -38,11 +39,6 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
38
39
|
async _open () {
|
|
39
40
|
this.logger.debug('_open called')
|
|
40
41
|
|
|
41
|
-
if (!this.registryCoreKey) {
|
|
42
|
-
this.logger.error('Missing registry core key for read mode')
|
|
43
|
-
throw new QvacErrorRegistryClient({ code: ERR_CODES.FAILED_TO_CONNECT, adds: 'Missing registry core key. Set QVAC_REGISTRY_CORE_KEY environment variable.' })
|
|
44
|
-
}
|
|
45
|
-
|
|
46
42
|
this.logger.debug('Creating corestore for open')
|
|
47
43
|
this.corestore = new Corestore(this.storage)
|
|
48
44
|
await this.corestore.ready()
|
|
@@ -56,6 +52,15 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
56
52
|
}
|
|
57
53
|
this.hyperswarm.on('connection', this._connectionHandler)
|
|
58
54
|
|
|
55
|
+
this._metadataReady = this._connectMetadataCore()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async _connectMetadataCore () {
|
|
59
|
+
if (!this.registryCoreKey) {
|
|
60
|
+
this.logger.error('Missing registry core key for read mode')
|
|
61
|
+
throw new QvacErrorRegistryClient({ code: ERR_CODES.FAILED_TO_CONNECT, adds: 'Missing registry core key. Set QVAC_REGISTRY_CORE_KEY environment variable.' })
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
const viewKey = IdEnc.decode(this.registryCoreKey)
|
|
60
65
|
const viewCore = this.corestore.get({ key: viewKey })
|
|
61
66
|
await viewCore.ready()
|
|
@@ -65,28 +70,37 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
65
70
|
discoveryKey: IdEnc.normalize(viewCore.discoveryKey)
|
|
66
71
|
})
|
|
67
72
|
|
|
73
|
+
const foundPeers = viewCore.findingPeers()
|
|
68
74
|
this.hyperswarm.join(viewCore.discoveryKey, { client: true, server: false })
|
|
69
|
-
|
|
75
|
+
this.hyperswarm.flush().then(() => foundPeers())
|
|
70
76
|
|
|
71
77
|
this.logger.debug('Waiting for view core sync')
|
|
72
|
-
await viewCore.update(
|
|
78
|
+
await viewCore.update()
|
|
73
79
|
|
|
74
80
|
this.logger.debug('Creating RegistryDatabase from view core')
|
|
75
81
|
this.db = new RegistryDatabase(viewCore, { extension: false })
|
|
76
82
|
await this.db.ready()
|
|
77
83
|
|
|
78
|
-
this.logger.debug('QVACRegistryClient ready', {
|
|
84
|
+
this.logger.debug('QVACRegistryClient metadata ready', {
|
|
79
85
|
length: viewCore.length
|
|
80
86
|
})
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
async _ensureMetadata () {
|
|
90
|
+
await this.ready()
|
|
91
|
+
await this._metadataReady
|
|
92
|
+
if (!this.db) {
|
|
93
|
+
throw new QvacErrorRegistryClient({ code: ERR_CODES.FAILED_TO_CONNECT, adds: 'Registry database not available.' })
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
83
97
|
async getModel (path, source) {
|
|
84
98
|
this._validateString(path, 'path')
|
|
85
99
|
this._validateString(source, 'source')
|
|
86
100
|
|
|
87
101
|
try {
|
|
88
102
|
this.logger.info('Getting model', { path, source })
|
|
89
|
-
await this.
|
|
103
|
+
await this._ensureMetadata()
|
|
90
104
|
|
|
91
105
|
const result = await this.db.getModel(path, source)
|
|
92
106
|
this.logger.debug('getModel result', { result })
|
|
@@ -98,7 +112,7 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
98
112
|
}
|
|
99
113
|
|
|
100
114
|
async findModels (query = {}, opts = {}) {
|
|
101
|
-
await this.
|
|
115
|
+
await this._ensureMetadata()
|
|
102
116
|
const { includeDeprecated = false } = opts
|
|
103
117
|
this.logger.debug('findModels called', { query, includeDeprecated })
|
|
104
118
|
|
|
@@ -112,19 +126,19 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
112
126
|
}
|
|
113
127
|
|
|
114
128
|
async findModelsByEngine (query = {}) {
|
|
115
|
-
await this.
|
|
129
|
+
await this._ensureMetadata()
|
|
116
130
|
this.logger.debug('findModelsByEngine called', { query })
|
|
117
131
|
return this.db.findModelsByEngine(query).toArray()
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
async findModelsByName (query = {}) {
|
|
121
|
-
await this.
|
|
135
|
+
await this._ensureMetadata()
|
|
122
136
|
this.logger.debug('findModelsByName called', { query })
|
|
123
137
|
return this.db.findModelsByName(query).toArray()
|
|
124
138
|
}
|
|
125
139
|
|
|
126
140
|
async findModelsByQuantization (query = {}) {
|
|
127
|
-
await this.
|
|
141
|
+
await this._ensureMetadata()
|
|
128
142
|
this.logger.debug('findModelsByQuantization called', { query })
|
|
129
143
|
return this.db.findModelsByQuantization(query).toArray()
|
|
130
144
|
}
|
|
@@ -140,7 +154,7 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
140
154
|
* @returns {Promise<Array>} Array of matching models
|
|
141
155
|
*/
|
|
142
156
|
async findBy (params = {}) {
|
|
143
|
-
await this.
|
|
157
|
+
await this._ensureMetadata()
|
|
144
158
|
this.logger.debug('findBy called', { params })
|
|
145
159
|
return this.db.findBy(params)
|
|
146
160
|
}
|
|
@@ -169,9 +183,14 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
169
183
|
}
|
|
170
184
|
|
|
171
185
|
async _getBlobsCore (blobsCoreKey) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
186
|
+
let keyBuffer
|
|
187
|
+
if (Buffer.isBuffer(blobsCoreKey)) {
|
|
188
|
+
keyBuffer = blobsCoreKey
|
|
189
|
+
} else if (typeof blobsCoreKey === 'object' && blobsCoreKey.data) {
|
|
190
|
+
keyBuffer = Buffer.from(blobsCoreKey.data)
|
|
191
|
+
} else {
|
|
192
|
+
keyBuffer = IdEnc.decode(blobsCoreKey)
|
|
193
|
+
}
|
|
175
194
|
|
|
176
195
|
this.logger.debug('Creating hyperblobs core', {
|
|
177
196
|
blobCore: IdEnc.normalize(keyBuffer)
|
|
@@ -198,7 +217,7 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
198
217
|
|
|
199
218
|
try {
|
|
200
219
|
this.logger.info('Downloading model', { path, source })
|
|
201
|
-
await this.
|
|
220
|
+
await this._ensureMetadata()
|
|
202
221
|
|
|
203
222
|
const model = await this.getModel(path, source)
|
|
204
223
|
if (!model) {
|
|
@@ -219,10 +238,11 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
219
238
|
discoveryKey: IdEnc.normalize(core.discoveryKey)
|
|
220
239
|
})
|
|
221
240
|
|
|
241
|
+
const foundBlobPeers = core.findingPeers()
|
|
222
242
|
this.hyperswarm.join(core.discoveryKey, { client: true, server: false })
|
|
223
|
-
|
|
243
|
+
this.hyperswarm.flush().then(() => foundBlobPeers())
|
|
224
244
|
|
|
225
|
-
await core.update(
|
|
245
|
+
await core.update()
|
|
226
246
|
this.logger.debug('Blobs core updated')
|
|
227
247
|
|
|
228
248
|
const totalSize = model.blobBinding.byteLength
|
|
@@ -290,6 +310,107 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
290
310
|
}
|
|
291
311
|
}
|
|
292
312
|
|
|
313
|
+
async downloadBlob (blobBinding, options = {}) {
|
|
314
|
+
if (!blobBinding || !blobBinding.coreKey) {
|
|
315
|
+
throw new Error('Invalid blobBinding: coreKey is required')
|
|
316
|
+
}
|
|
317
|
+
if (typeof blobBinding.blockOffset !== 'number' ||
|
|
318
|
+
typeof blobBinding.blockLength !== 'number' ||
|
|
319
|
+
typeof blobBinding.byteLength !== 'number') {
|
|
320
|
+
throw new Error('Invalid blobBinding: blockOffset, blockLength, and byteLength are required numbers')
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (options && typeof options !== 'object') {
|
|
324
|
+
throw new Error(`Invalid options: ${typeof options}`)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
let core, blobs
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
this.logger.info('Downloading blob directly', {
|
|
331
|
+
coreKey: typeof blobBinding.coreKey === 'string' ? blobBinding.coreKey.slice(0, 12) + '...' : '(buffer)',
|
|
332
|
+
blockOffset: blobBinding.blockOffset,
|
|
333
|
+
blockLength: blobBinding.blockLength,
|
|
334
|
+
byteLength: blobBinding.byteLength
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
await this.ready()
|
|
338
|
+
|
|
339
|
+
const blobsCore = await this._getBlobsCore(blobBinding.coreKey)
|
|
340
|
+
core = blobsCore.core
|
|
341
|
+
blobs = blobsCore.blobs
|
|
342
|
+
|
|
343
|
+
this.logger.debug('Joining swarm for blobs core (direct)', {
|
|
344
|
+
discoveryKey: IdEnc.normalize(core.discoveryKey)
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
const foundBlobPeers = core.findingPeers()
|
|
348
|
+
this.hyperswarm.join(core.discoveryKey, { client: true, server: false })
|
|
349
|
+
this.hyperswarm.flush().then(() => foundBlobPeers())
|
|
350
|
+
|
|
351
|
+
await core.update()
|
|
352
|
+
this.logger.debug('Blobs core updated (direct)')
|
|
353
|
+
|
|
354
|
+
const pointer = {
|
|
355
|
+
blockOffset: blobBinding.blockOffset,
|
|
356
|
+
blockLength: blobBinding.blockLength,
|
|
357
|
+
byteOffset: blobBinding.byteOffset || 0,
|
|
358
|
+
byteLength: blobBinding.byteLength
|
|
359
|
+
}
|
|
360
|
+
const totalSize = blobBinding.byteLength
|
|
361
|
+
|
|
362
|
+
let artifact
|
|
363
|
+
if (options.outputFile) {
|
|
364
|
+
await this._streamBlobToFile(blobs, core, pointer, options.outputFile, options)
|
|
365
|
+
artifact = { path: options.outputFile, totalSize }
|
|
366
|
+
|
|
367
|
+
if (blobs) await blobs.close()
|
|
368
|
+
if (core) await core.close()
|
|
369
|
+
} else {
|
|
370
|
+
const stream = blobs.createReadStream(pointer, {
|
|
371
|
+
wait: true,
|
|
372
|
+
timeout: options.timeout || 30000
|
|
373
|
+
})
|
|
374
|
+
artifact = { stream, totalSize }
|
|
375
|
+
|
|
376
|
+
const cleanup = async () => {
|
|
377
|
+
if (blobs) {
|
|
378
|
+
try { await blobs.close() } catch (e) {
|
|
379
|
+
this.logger.warn('Error closing blob instance', { error: e.message })
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (core) {
|
|
383
|
+
try { await core.close() } catch (e) {
|
|
384
|
+
this.logger.warn('Error closing blob core', { error: e.message })
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
this.logger.debug('Blob resources closed after stream end')
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
stream.on('close', cleanup)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
this.logger.info('Blob download complete (direct)')
|
|
394
|
+
|
|
395
|
+
return { artifact }
|
|
396
|
+
} catch (error) {
|
|
397
|
+
this.logger.error('Error downloading blob directly', error)
|
|
398
|
+
|
|
399
|
+
if (blobs) {
|
|
400
|
+
try { await blobs.close() } catch (e) {
|
|
401
|
+
this.logger.warn('Error closing blob instance on error', { error: e.message })
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (core) {
|
|
405
|
+
try { await core.close() } catch (e) {
|
|
406
|
+
this.logger.warn('Error closing blob core on error', { error: e.message })
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
throw error
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
293
414
|
async _streamBlobToFile (blobs, core, blobPointer, filePath, options) {
|
|
294
415
|
const { cachedBlocks, totalBlocks, totalBytes } = await this._checkBlobProgress(core, blobPointer)
|
|
295
416
|
|
|
@@ -368,6 +489,11 @@ class QVACRegistryClient extends ReadyResource {
|
|
|
368
489
|
async _close () {
|
|
369
490
|
this.logger.debug('_close called')
|
|
370
491
|
|
|
492
|
+
if (this._metadataReady) {
|
|
493
|
+
await this._metadataReady.catch(() => {})
|
|
494
|
+
this._metadataReady = null
|
|
495
|
+
}
|
|
496
|
+
|
|
371
497
|
if (this.db) {
|
|
372
498
|
this.logger.debug('Closing database')
|
|
373
499
|
await this.db.close()
|
package/lib/compat/fs.js
ADDED
package/lib/compat/os.js
ADDED
package/lib/config.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
const { getEnv } = require('../utils/env')
|
|
4
4
|
const { ENV_KEYS } = require('@qvac/registry-schema')
|
|
5
5
|
const Logger = require('./logger')
|
|
6
|
-
const os = require('os')
|
|
7
|
-
const path = require('path')
|
|
6
|
+
const os = require('#os')
|
|
7
|
+
const path = require('#path')
|
|
8
8
|
|
|
9
|
-
const DEFAULT_REGISTRY_CORE_KEY = '
|
|
9
|
+
const DEFAULT_REGISTRY_CORE_KEY = 'uf1fm44uzockp6azhcdiqt1esjgm65fwtimsh946e8kwysdes9ko'
|
|
10
10
|
|
|
11
11
|
class RegistryConfig {
|
|
12
12
|
constructor (opts = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/registry-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "QVAC Registry client library for read-only queries via Hyperswarm",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -12,6 +12,20 @@
|
|
|
12
12
|
".": "./index.js",
|
|
13
13
|
"./types": "./index.d.ts"
|
|
14
14
|
},
|
|
15
|
+
"imports": {
|
|
16
|
+
"#os": {
|
|
17
|
+
"bare": "bare-os",
|
|
18
|
+
"default": "./lib/compat/os.js"
|
|
19
|
+
},
|
|
20
|
+
"#path": {
|
|
21
|
+
"bare": "bare-path",
|
|
22
|
+
"default": "./lib/compat/path.js"
|
|
23
|
+
},
|
|
24
|
+
"#fs": {
|
|
25
|
+
"bare": "bare-fs",
|
|
26
|
+
"default": "./lib/compat/fs.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
15
29
|
"files": [
|
|
16
30
|
"index.js",
|
|
17
31
|
"index.d.ts",
|
|
@@ -36,17 +50,14 @@
|
|
|
36
50
|
"b4a": "^1.6.7",
|
|
37
51
|
"bare-fs": "^4.5.2",
|
|
38
52
|
"bare-os": "^3.6.2",
|
|
53
|
+
"bare-path": "^3.0.0",
|
|
39
54
|
"bare-process": "^4.2.2",
|
|
40
55
|
"corestore": "^7.4.5",
|
|
41
|
-
"fs": "npm:bare-node-fs",
|
|
42
56
|
"hyperblobs": "^2.8.0",
|
|
43
57
|
"hypercore-id-encoding": "^1.3.0",
|
|
44
58
|
"hyperdb": "^4.16.1",
|
|
45
59
|
"hyperswarm": "^4.14.0",
|
|
46
|
-
"os": "npm:bare-node-os",
|
|
47
60
|
"paparam": "^1.10.0",
|
|
48
|
-
"path": "npm:bare-node-path",
|
|
49
|
-
"process": "npm:bare-node-process",
|
|
50
61
|
"ready-resource": "^1.0.1"
|
|
51
62
|
},
|
|
52
63
|
"devDependencies": {
|