@qvac/sdk 0.9.2 → 0.10.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.
Files changed (333) hide show
  1. package/NOTICE +15 -68
  2. package/dist/client/api/cancel.d.ts +1 -1
  3. package/dist/client/api/cancel.js +1 -1
  4. package/dist/client/api/completion-stream.d.ts +51 -12
  5. package/dist/client/api/completion-stream.js +129 -56
  6. package/dist/client/api/delete-cache.d.ts +1 -0
  7. package/dist/client/api/delete-cache.js +1 -0
  8. package/dist/client/api/diffusion.d.ts +17 -2
  9. package/dist/client/api/diffusion.js +21 -4
  10. package/dist/client/api/embed.d.ts +4 -0
  11. package/dist/client/api/finetune.d.ts +21 -0
  12. package/dist/client/api/get-loaded-model-info.d.ts +25 -0
  13. package/dist/client/api/get-loaded-model-info.js +36 -0
  14. package/dist/client/api/get-model-info.d.ts +9 -1
  15. package/dist/client/api/get-model-info.js +8 -0
  16. package/dist/client/api/heartbeat.d.ts +2 -2
  17. package/dist/client/api/heartbeat.js +2 -2
  18. package/dist/client/api/index.d.ts +3 -1
  19. package/dist/client/api/index.js +3 -1
  20. package/dist/client/api/invoke-plugin.d.ts +16 -0
  21. package/dist/client/api/invoke-plugin.js +16 -0
  22. package/dist/client/api/load-model.d.ts +36 -3
  23. package/dist/client/api/load-model.js +31 -10
  24. package/dist/client/api/provide.d.ts +11 -5
  25. package/dist/client/api/provide.js +11 -6
  26. package/dist/client/api/rag.d.ts +9 -0
  27. package/dist/client/api/rag.js +9 -0
  28. package/dist/client/api/registry.d.ts +26 -0
  29. package/dist/client/api/registry.js +26 -0
  30. package/dist/client/api/resume.d.ts +20 -4
  31. package/dist/client/api/resume.js +20 -4
  32. package/dist/client/api/state.d.ts +23 -0
  33. package/dist/client/api/state.js +29 -0
  34. package/dist/client/api/stop-provider.d.ts +11 -5
  35. package/dist/client/api/stop-provider.js +11 -5
  36. package/dist/client/api/suspend.d.ts +21 -3
  37. package/dist/client/api/suspend.js +21 -3
  38. package/dist/client/api/text-to-speech.d.ts +64 -6
  39. package/dist/client/api/text-to-speech.js +423 -47
  40. package/dist/client/api/transcribe.d.ts +29 -4
  41. package/dist/client/api/transcribe.js +86 -28
  42. package/dist/client/api/translate.d.ts +1 -0
  43. package/dist/client/api/translate.js +1 -0
  44. package/dist/client/rpc/bare-client.js +22 -1
  45. package/dist/client/rpc/expo-rpc-client.d.ts +1 -1
  46. package/dist/client/rpc/expo-rpc-client.js +96 -4
  47. package/dist/client/rpc/node-rpc-client.js +36 -0
  48. package/dist/examples/audio/mic-input.d.ts +9 -0
  49. package/dist/examples/audio/mic-input.js +111 -0
  50. package/dist/examples/completion-events.d.ts +18 -0
  51. package/dist/examples/completion-events.js +79 -0
  52. package/dist/examples/delegated-inference/composite.js +12 -18
  53. package/dist/examples/delegated-inference/consumer-profiled.js +4 -11
  54. package/dist/examples/delegated-inference/consumer.js +8 -13
  55. package/dist/examples/delegated-inference/provider.js +11 -16
  56. package/dist/examples/diffusion-flux2-klein-img2img.d.ts +2 -0
  57. package/dist/examples/diffusion-flux2-klein-img2img.js +60 -0
  58. package/dist/examples/diffusion-flux2-klein.js +1 -0
  59. package/dist/examples/diffusion-img2img.d.ts +2 -0
  60. package/dist/examples/diffusion-img2img.js +49 -0
  61. package/dist/examples/diffusion-txt2img.js +2 -1
  62. package/dist/examples/kv-cache-example.js +11 -12
  63. package/dist/examples/llamacpp-cache.d.ts +2 -0
  64. package/dist/examples/llamacpp-cache.js +107 -0
  65. package/dist/examples/llamacpp-dynamic-tools.d.ts +2 -0
  66. package/dist/examples/llamacpp-dynamic-tools.js +144 -0
  67. package/dist/examples/llamacpp-native-tools.js +2 -8
  68. package/dist/examples/llamacpp-structured-output.d.ts +2 -0
  69. package/dist/examples/llamacpp-structured-output.js +106 -0
  70. package/dist/examples/llamacpp-tools-pythonic.d.ts +2 -0
  71. package/dist/examples/llamacpp-tools-pythonic.js +69 -0
  72. package/dist/examples/plugins.js +4 -4
  73. package/dist/examples/suspend-resume.js +21 -4
  74. package/dist/examples/transcription/parakeet-microphone-record.js +6 -33
  75. package/dist/examples/transcription/whispercpp-filesystem-streaming.js +7 -5
  76. package/dist/examples/transcription/whispercpp-filesystem.js +12 -3
  77. package/dist/examples/transcription/whispercpp-microphone-record.js +6 -29
  78. package/dist/examples/translation/translation-stream.js +5 -5
  79. package/dist/examples/tts/llm-to-tts-streaming.d.ts +16 -0
  80. package/dist/examples/tts/llm-to-tts-streaming.js +143 -0
  81. package/dist/examples/tts/supertonic-multilingual.js +3 -3
  82. package/dist/examples/tts/supertonic.js +3 -3
  83. package/dist/examples/tts/utils.d.ts +11 -1
  84. package/dist/examples/tts/utils.js +70 -17
  85. package/dist/examples/voice-assistant/voice-assistant.d.ts +2 -0
  86. package/dist/examples/voice-assistant/voice-assistant.js +207 -0
  87. package/dist/expo/plugins/withMobileBundle.js +1 -1
  88. package/dist/index.d.ts +2 -2
  89. package/dist/index.js +2 -2
  90. package/dist/logging/logger.d.ts +11 -0
  91. package/dist/logging/logger.js +11 -0
  92. package/dist/logging/types.d.ts +18 -0
  93. package/dist/models/registry/models.d.ts +6620 -6185
  94. package/dist/models/registry/models.js +6296 -5318
  95. package/dist/models/update-models/codegen.js +84 -23
  96. package/dist/models/update-models/companions.d.ts +18 -0
  97. package/dist/models/update-models/companions.js +175 -0
  98. package/dist/models/update-models/naming.js +0 -25
  99. package/dist/models/update-models/registry.js +4 -2
  100. package/dist/models/update-models/types.d.ts +37 -9
  101. package/dist/profiling/index.d.ts +49 -0
  102. package/dist/profiling/index.js +49 -0
  103. package/dist/schemas/cancel.d.ts +6 -2
  104. package/dist/schemas/cancel.js +14 -7
  105. package/dist/schemas/common.d.ts +353 -271
  106. package/dist/schemas/common.js +26 -5
  107. package/dist/schemas/completion-event.d.ts +225 -0
  108. package/dist/schemas/completion-event.js +79 -0
  109. package/dist/schemas/completion-stream.d.ts +122 -31
  110. package/dist/schemas/completion-stream.js +137 -36
  111. package/dist/schemas/delegate.d.ts +0 -2
  112. package/dist/schemas/delegate.js +25 -6
  113. package/dist/schemas/download-asset.d.ts +5 -5
  114. package/dist/schemas/embed.js +21 -9
  115. package/dist/schemas/engine-addon-map.d.ts +11 -1
  116. package/dist/schemas/engine-addon-map.js +2 -2
  117. package/dist/schemas/get-loaded-model-info.d.ts +52 -0
  118. package/dist/schemas/get-loaded-model-info.js +44 -0
  119. package/dist/schemas/get-model-info.d.ts +2 -2
  120. package/dist/schemas/get-model-info.js +103 -32
  121. package/dist/schemas/heartbeat.d.ts +0 -1
  122. package/dist/schemas/index.d.ts +4 -1
  123. package/dist/schemas/index.js +4 -1
  124. package/dist/schemas/llamacpp-config.d.ts +14 -4
  125. package/dist/schemas/llamacpp-config.js +5 -0
  126. package/dist/schemas/load-model.d.ts +3233 -1260
  127. package/dist/schemas/load-model.js +23 -16
  128. package/dist/schemas/model-src-utils.d.ts +7 -6
  129. package/dist/schemas/model-src-utils.js +27 -1
  130. package/dist/schemas/model-types.d.ts +4 -4
  131. package/dist/schemas/ocr.d.ts +1 -1
  132. package/dist/schemas/plugin.d.ts +27 -3
  133. package/dist/schemas/plugin.js +27 -2
  134. package/dist/schemas/profiling.js +11 -3
  135. package/dist/schemas/provide.d.ts +1 -3
  136. package/dist/schemas/provide.js +0 -3
  137. package/dist/schemas/rag.d.ts +4 -4
  138. package/dist/schemas/registry.d.ts +10 -10
  139. package/dist/schemas/registry.js +36 -14
  140. package/dist/schemas/reload-config.d.ts +73 -7
  141. package/dist/schemas/sdcpp-config.d.ts +16 -8
  142. package/dist/schemas/sdcpp-config.js +118 -25
  143. package/dist/schemas/sdk-config.d.ts +116 -90
  144. package/dist/schemas/sdk-config.js +16 -0
  145. package/dist/schemas/sdk-errors-client.d.ts +3 -0
  146. package/dist/schemas/sdk-errors-client.js +16 -1
  147. package/dist/schemas/sdk-errors-server.d.ts +3 -0
  148. package/dist/schemas/sdk-errors-server.js +23 -0
  149. package/dist/schemas/state.d.ts +23 -0
  150. package/dist/schemas/state.js +14 -0
  151. package/dist/schemas/stop-provide.d.ts +0 -5
  152. package/dist/schemas/stop-provide.js +2 -6
  153. package/dist/schemas/text-to-speech.d.ts +93 -27
  154. package/dist/schemas/text-to-speech.js +27 -0
  155. package/dist/schemas/tools.d.ts +16 -0
  156. package/dist/schemas/tools.js +15 -0
  157. package/dist/schemas/transcription-config.d.ts +8 -8
  158. package/dist/schemas/transcription.d.ts +33 -0
  159. package/dist/schemas/transcription.js +9 -0
  160. package/dist/schemas/translate.js +59 -19
  161. package/dist/schemas/translation-config.d.ts +157 -133
  162. package/dist/schemas/translation-config.js +34 -11
  163. package/dist/server/bare/delegate-rpc-client.d.ts +1 -1
  164. package/dist/server/bare/delegate-rpc-client.js +131 -122
  165. package/dist/server/bare/hyperswarm.d.ts +2 -2
  166. package/dist/server/bare/hyperswarm.js +12 -7
  167. package/dist/server/bare/ops/cancel.js +7 -0
  168. package/dist/server/bare/ops/kv-cache-utils.d.ts +7 -10
  169. package/dist/server/bare/ops/kv-cache-utils.js +31 -40
  170. package/dist/server/bare/ops/load-model.js +0 -1
  171. package/dist/server/bare/ops/transcribe.d.ts +11 -4
  172. package/dist/server/bare/ops/transcribe.js +25 -4
  173. package/dist/server/bare/ops/translate.js +42 -4
  174. package/dist/server/bare/ops/unload-model.js +21 -19
  175. package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +1 -2
  176. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +13 -8
  177. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +257 -85
  178. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +101 -0
  179. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +135 -0
  180. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +79 -22
  181. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +57 -32
  182. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -16
  183. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +69 -44
  184. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +113 -94
  185. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +1 -1
  186. package/dist/server/bare/plugins/onnx-ocr/plugin.js +1 -2
  187. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.d.ts +7 -0
  188. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.js +116 -0
  189. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.d.ts +2 -3
  190. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.js +71 -9
  191. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +41 -13
  192. package/dist/server/bare/plugins/onnx-tts/plugin.js +48 -3
  193. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +15 -7
  194. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +5 -6
  195. package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +6 -0
  196. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +8 -5
  197. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +13 -13
  198. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +17 -1
  199. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +40 -17
  200. package/dist/server/bare/registry/config-registry.js +14 -3
  201. package/dist/server/bare/registry/model-registry.d.ts +8 -10
  202. package/dist/server/bare/registry/model-registry.js +17 -12
  203. package/dist/server/bare/registry/registry-client.js +79 -19
  204. package/dist/server/bare/runtime-lifecycle.d.ts +2 -1
  205. package/dist/server/bare/runtime-lifecycle.js +13 -2
  206. package/dist/server/bare/types/addon-responses.d.ts +8 -3
  207. package/dist/server/bare/utils/transcribe-metadata.d.ts +21 -0
  208. package/dist/server/bare/utils/transcribe-metadata.js +28 -0
  209. package/dist/server/bare/utils/tts-stats.d.ts +22 -0
  210. package/dist/server/bare/utils/tts-stats.js +10 -0
  211. package/dist/server/rpc/create-server.d.ts +4 -1
  212. package/dist/server/rpc/create-server.js +5 -1
  213. package/dist/server/rpc/delegate-transport.js +36 -29
  214. package/dist/server/rpc/handle-request.js +28 -3
  215. package/dist/server/rpc/handler-registry.js +7 -1
  216. package/dist/server/rpc/handler-utils.d.ts +5 -0
  217. package/dist/server/rpc/handler-utils.js +22 -0
  218. package/dist/server/rpc/handlers/cancel-delegated.js +3 -5
  219. package/dist/server/rpc/handlers/cancelHandler.js +4 -5
  220. package/dist/server/rpc/handlers/completion-stream-delegated.js +14 -5
  221. package/dist/server/rpc/handlers/delete-cache.js +8 -3
  222. package/dist/server/rpc/handlers/download-asset.js +3 -24
  223. package/dist/server/rpc/handlers/get-loaded-model-info.d.ts +3 -0
  224. package/dist/server/rpc/handlers/get-loaded-model-info.js +39 -0
  225. package/dist/server/rpc/handlers/get-model-info.js +93 -84
  226. package/dist/server/rpc/handlers/heartbeat-delegated.js +2 -2
  227. package/dist/server/rpc/handlers/index.d.ts +6 -0
  228. package/dist/server/rpc/handlers/index.js +6 -0
  229. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +35 -9
  230. package/dist/server/rpc/handlers/load-model/download-manager.js +142 -38
  231. package/dist/server/rpc/handlers/load-model/download-stats.d.ts +5 -4
  232. package/dist/server/rpc/handlers/load-model/download-stats.js +49 -8
  233. package/dist/server/rpc/handlers/load-model/handler.js +31 -50
  234. package/dist/server/rpc/handlers/load-model/http.d.ts +2 -2
  235. package/dist/server/rpc/handlers/load-model/http.js +97 -142
  236. package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +2 -2
  237. package/dist/server/rpc/handlers/load-model/hyperdrive.js +55 -74
  238. package/dist/server/rpc/handlers/load-model/index.d.ts +0 -1
  239. package/dist/server/rpc/handlers/load-model/index.js +0 -1
  240. package/dist/server/rpc/handlers/load-model/registry-client-options.d.ts +27 -0
  241. package/dist/server/rpc/handlers/load-model/registry-client-options.js +19 -0
  242. package/dist/server/rpc/handlers/load-model/registry-companion-set.d.ts +22 -0
  243. package/dist/server/rpc/handlers/load-model/registry-companion-set.js +208 -0
  244. package/dist/server/rpc/handlers/load-model/registry-download-utils.d.ts +24 -0
  245. package/dist/server/rpc/handlers/load-model/registry-download-utils.js +114 -0
  246. package/dist/server/rpc/handlers/load-model/registry.d.ts +2 -20
  247. package/dist/server/rpc/handlers/load-model/registry.js +109 -381
  248. package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +15 -0
  249. package/dist/server/rpc/handlers/load-model/resolve-session.js +61 -0
  250. package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -3
  251. package/dist/server/rpc/handlers/load-model/resolve.js +14 -23
  252. package/dist/server/rpc/handlers/load-model/types.d.ts +11 -4
  253. package/dist/server/rpc/handlers/load-model/types.js +28 -1
  254. package/dist/server/rpc/handlers/load-model-delegated.js +2 -4
  255. package/dist/server/rpc/handlers/plugin-dispatch.js +9 -5
  256. package/dist/server/rpc/handlers/plugin-invoke.js +1 -1
  257. package/dist/server/rpc/handlers/provideHandler/connection.js +13 -2
  258. package/dist/server/rpc/handlers/provideHandler/handler.js +42 -29
  259. package/dist/server/rpc/handlers/state.d.ts +3 -0
  260. package/dist/server/rpc/handlers/state.js +7 -0
  261. package/dist/server/rpc/handlers/stopProvideHandler.d.ts +2 -2
  262. package/dist/server/rpc/handlers/stopProvideHandler.js +12 -7
  263. package/dist/server/rpc/handlers/text-to-speech-stream.d.ts +3 -0
  264. package/dist/server/rpc/handlers/text-to-speech-stream.js +4 -0
  265. package/dist/server/rpc/handlers/unload-model-delegated.js +3 -3
  266. package/dist/server/rpc/profiling/operation-metrics.js +20 -0
  267. package/dist/server/rpc/rpc-utils.js +1 -1
  268. package/dist/server/rpc/transport-selector.d.ts +3 -0
  269. package/dist/server/rpc/transport-selector.js +18 -0
  270. package/dist/server/utils/cache/auto-history.d.ts +4 -0
  271. package/dist/server/utils/cache/auto-history.js +22 -0
  272. package/dist/server/utils/{cache.d.ts → cache/paths.d.ts} +22 -5
  273. package/dist/server/utils/{cache.js → cache/paths.js} +36 -20
  274. package/dist/server/utils/cache/types.d.ts +8 -0
  275. package/dist/server/utils/cache/types.js +1 -0
  276. package/dist/server/utils/checksum.d.ts +2 -2
  277. package/dist/server/utils/checksum.js +1 -1
  278. package/dist/server/utils/clear-storage.d.ts +5 -0
  279. package/dist/server/utils/clear-storage.js +17 -0
  280. package/dist/server/utils/completion-normalizer.d.ts +17 -0
  281. package/dist/server/utils/completion-normalizer.js +301 -0
  282. package/dist/server/utils/expand-gguf-shards.d.ts +3 -0
  283. package/dist/server/utils/expand-gguf-shards.js +22 -0
  284. package/dist/server/utils/formatting.js +1 -1
  285. package/dist/server/utils/index.d.ts +4 -2
  286. package/dist/server/utils/index.js +4 -2
  287. package/dist/server/utils/qvac-paths.d.ts +2 -0
  288. package/dist/server/utils/qvac-paths.js +5 -0
  289. package/dist/server/utils/response-format.d.ts +3 -0
  290. package/dist/server/utils/response-format.js +20 -0
  291. package/dist/server/utils/tool-integration.d.ts +15 -4
  292. package/dist/server/utils/tool-integration.js +21 -41
  293. package/dist/server/utils/tools/dialect.d.ts +8 -0
  294. package/dist/server/utils/tools/dialect.js +12 -0
  295. package/dist/server/utils/tools/index.d.ts +3 -0
  296. package/dist/server/utils/tools/index.js +2 -0
  297. package/dist/server/utils/tools/parser.d.ts +6 -0
  298. package/dist/server/utils/tools/parser.js +40 -0
  299. package/dist/server/utils/tools/parsers/hermes.d.ts +4 -0
  300. package/dist/server/utils/tools/parsers/hermes.js +100 -0
  301. package/dist/server/utils/tools/parsers/json.d.ts +6 -0
  302. package/dist/server/utils/tools/parsers/json.js +115 -0
  303. package/dist/server/utils/tools/parsers/pythonic.d.ts +4 -0
  304. package/dist/server/utils/tools/parsers/pythonic.js +267 -0
  305. package/dist/server/utils/tools/shared.d.ts +18 -0
  306. package/dist/server/utils/tools/shared.js +54 -0
  307. package/dist/server/utils/worker-lock.d.ts +3 -0
  308. package/dist/server/utils/worker-lock.js +67 -0
  309. package/dist/server/worker-core.d.ts +16 -1
  310. package/dist/server/worker-core.js +114 -14
  311. package/dist/utils/aggregate-events.d.ts +16 -0
  312. package/dist/utils/aggregate-events.js +52 -0
  313. package/dist/utils/cache-normalize.d.ts +10 -0
  314. package/dist/utils/cache-normalize.js +23 -0
  315. package/dist/utils/encoding.d.ts +8 -0
  316. package/dist/utils/encoding.js +13 -0
  317. package/dist/utils/errors-client.d.ts +12 -0
  318. package/dist/utils/errors-client.js +20 -0
  319. package/dist/utils/errors-server.d.ts +14 -0
  320. package/dist/utils/errors-server.js +31 -0
  321. package/dist/utils/load-model-validation.d.ts +7 -0
  322. package/dist/utils/load-model-validation.js +18 -0
  323. package/expo/plugins/patches/android-link.mjs +1 -1
  324. package/expo/plugins/patches/ios-link.mjs +1 -1
  325. package/package.json +14 -18
  326. package/dist/examples/translation/translation-opus.d.ts +0 -2
  327. package/dist/examples/translation/translation-opus.js +0 -33
  328. package/dist/server/bare/utils/loader-adapter.d.ts +0 -7
  329. package/dist/server/bare/utils/loader-adapter.js +0 -9
  330. package/dist/server/utils/model-path.d.ts +0 -5
  331. package/dist/server/utils/model-path.js +0 -7
  332. package/dist/server/utils/tool-parser.d.ts +0 -7
  333. package/dist/server/utils/tool-parser.js +0 -248
@@ -4,18 +4,17 @@ import Corestore from "corestore";
4
4
  import Hyperswarm, {} from "hyperswarm";
5
5
  import Hyperdrive from "hyperdrive";
6
6
  import {} from "bare-stream";
7
- import { AbortController } from "bare-abort-controller";
8
- import { getEnv } from "../../../env.js";
7
+ import { getQvacPath } from "../../../utils/qvac-paths.js";
9
8
  import { getModelsCacheDir, generateShortHash, detectShardedModel, getShardedModelCacheDir, getShardPath, checkShardCompleteness, measureChecksum, extractTensorsFromShards, calculatePercentage, } from "../../../utils/index.js";
10
9
  import { getModelBySrc } from "../../../../models/registry/index.js";
11
- import { getActiveDownload, registerDownload, unregisterDownload, createHyperdriveDownloadKey, shouldClearCache, clearClearCacheFlag, } from "./download-manager.js";
10
+ import { createHyperdriveDownloadKey, startOrJoinDownload, applyJoinedDownloadStats, } from "./download-manager.js";
12
11
  import { getSDKConfig } from "../../../bare/registry/config-registry.js";
13
12
  import { FileNotFoundError, ChecksumValidationFailedError, DownloadCancelledError, HyperdriveDownloadFailedError, ModelLoadFailedError, NoBlobFoundError, } from "../../../../utils/errors-server.js";
14
13
  import { getServerLogger } from "../../../../logging/index.js";
15
14
  import { registerSwarm, unregisterSwarm, registerCorestore, unregisterCorestore, } from "../../../bare/runtime-lifecycle.js";
16
15
  const logger = getServerLogger();
17
16
  function getCorestoreDir(hyperdriveKey) {
18
- return path.join(getEnv().HOME_DIR, ".qvac", "corestore", hyperdriveKey);
17
+ return getQvacPath("corestore", hyperdriveKey);
19
18
  }
20
19
  async function setupHyperdrive(hyperdriveKey, corestoreDir) {
21
20
  const corestore = new Corestore(corestoreDir);
@@ -185,7 +184,7 @@ async function validateCachedFile(modelPath, modelFileName, expectedSize, expect
185
184
  return null;
186
185
  }
187
186
  }
188
- async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, expectedChecksum, progressCallback, seed, signal, hooks) {
187
+ async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, expectedChecksum, progressCallback, seed, signal, hooks, shouldClearCache) {
189
188
  // Check if already aborted
190
189
  if (signal?.aborted) {
191
190
  throw new DownloadCancelledError();
@@ -231,8 +230,7 @@ async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdri
231
230
  }
232
231
  catch (error) {
233
232
  logger.error("❌ Error during hyperdrive download:", error instanceof Error ? error.message : String(error));
234
- // Preserve cancellation errors
235
- if (error instanceof Error && error.message === "Download cancelled") {
233
+ if (error instanceof DownloadCancelledError) {
236
234
  throw error;
237
235
  }
238
236
  throw new HyperdriveDownloadFailedError(`Download failed for ${modelFileName} from hyperdrive: ${hyperdriveKey}`, error);
@@ -247,16 +245,18 @@ async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdri
247
245
  }
248
246
  }
249
247
  // Only delete corestore and partial file if user explicitly requested clearCache
250
- if (signal?.aborted && shouldClearCache(downloadKey)) {
248
+ if (signal?.aborted && shouldClearCache?.()) {
251
249
  try {
252
250
  await fsPromises.unlink(modelPath);
253
251
  }
254
- catch {
255
- // no-op
252
+ catch (cleanupError) {
253
+ logger.debug("Failed to delete partial model file during cleanup", {
254
+ path: modelPath,
255
+ error: cleanupError,
256
+ });
256
257
  }
257
258
  await deleteCorestoreDirectory(corestoreDir);
258
259
  }
259
- clearClearCacheFlag(downloadKey);
260
260
  }
261
261
  }
262
262
  async function downloadAndValidateFile(drive, sourceFileName, targetFilePath, expectedSize, expectedChecksum, progressContext, signal, hooks) {
@@ -321,7 +321,7 @@ async function downloadAndValidateFile(drive, sourceFileName, targetFilePath, ex
321
321
  writeStream.on("finish", resolve);
322
322
  writeStream.on("error", reject);
323
323
  readStream.on("error", reject);
324
- signal?.addEventListener("abort", () => reject(new Error("Download cancelled")), { once: true });
324
+ signal?.addEventListener("abort", () => reject(new DownloadCancelledError()), { once: true });
325
325
  });
326
326
  blobs.core.off("download", progressHandler);
327
327
  // Validate file size
@@ -352,31 +352,7 @@ async function downloadAndValidateFile(drive, sourceFileName, targetFilePath, ex
352
352
  throw error;
353
353
  }
354
354
  }
355
- function createManagedDownload(downloadKey, hyperdriveKey, modelFileName, downloadFn, progressCallback) {
356
- const abortController = new AbortController();
357
- const downloadPromise = (async () => {
358
- try {
359
- return await downloadFn(abortController.signal);
360
- }
361
- finally {
362
- unregisterDownload(downloadKey);
363
- clearClearCacheFlag(downloadKey);
364
- }
365
- })();
366
- const downloadEntry = {
367
- key: downloadKey,
368
- promise: downloadPromise,
369
- abortController,
370
- startTime: Date.now(),
371
- type: "hyperdrive",
372
- hyperdriveKey,
373
- modelFileName,
374
- ...(progressCallback && { onProgress: progressCallback }),
375
- };
376
- registerDownload(downloadKey, downloadEntry);
377
- return downloadPromise;
378
- }
379
- async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileName, shardMetadata, progressCallback, seed, signal, hooks) {
355
+ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileName, shardMetadata, progressCallback, seed, signal, hooks, shouldClearCache) {
380
356
  if (signal?.aborted) {
381
357
  throw new DownloadCancelledError();
382
358
  }
@@ -389,10 +365,10 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
389
365
  const numberedShardCount = shardInfo.totalShards;
390
366
  logger.info(`Downloading sharded model with ${numberedShardCount} numbered shards + ${allFiles.length - numberedShardCount} companion files to ${shardDir}`);
391
367
  // Check which files need to be downloaded
392
- const invalidIndices = await checkShardCompleteness(hyperdriveKey, allFiles, shardMetadata, hooks ? (ms) => hooks.addChecksumValidationTimeMs(ms) : undefined);
368
+ const invalidIndices = await checkShardCompleteness(hyperdriveKey, allFiles, shardMetadata, hooks?.addChecksumValidationTimeMs ? (ms) => hooks.addChecksumValidationTimeMs(ms) : undefined);
393
369
  if (invalidIndices.length === 0) {
394
370
  logger.info(`✅ All ${allFiles.length} files already downloaded and validated`);
395
- hooks?.markCacheHit();
371
+ hooks?.markCacheHit?.();
396
372
  if (progressCallback) {
397
373
  const overallTotal = shardMetadata.reduce((sum, shard) => sum + shard.expectedSize, 0);
398
374
  const lastFile = allFiles[allFiles.length - 1];
@@ -416,7 +392,7 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
416
392
  return getShardPath(hyperdriveKey, allFiles[0]);
417
393
  }
418
394
  logger.info(`📥 Need to download ${invalidIndices.length} of ${allFiles.length} files`);
419
- hooks?.markCacheMiss();
395
+ hooks?.markCacheMiss?.();
420
396
  // Setup hyperdrive once for all shards
421
397
  const corestoreDir = getCorestoreDir(hyperdriveKey);
422
398
  const setup = await setupHyperdrive(hyperdriveKey, corestoreDir);
@@ -510,7 +486,7 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
510
486
  catch (error) {
511
487
  logger.error("❌ Error during sharded hyperdrive download:", error instanceof Error ? error.message : String(error));
512
488
  // Preserve cancellation errors
513
- if (error instanceof Error && error.message === "Download cancelled") {
489
+ if (error instanceof DownloadCancelledError) {
514
490
  throw error;
515
491
  }
516
492
  throw new HyperdriveDownloadFailedError(`Sharded download failed for ${firstShardFileName} from hyperdrive: ${hyperdriveKey}`, error);
@@ -525,57 +501,62 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
525
501
  }
526
502
  }
527
503
  // Only delete corestore and partial files if user explicitly requested clearCache
528
- const downloadKey = createHyperdriveDownloadKey(hyperdriveKey, firstShardFileName);
529
- if (signal?.aborted && shouldClearCache(downloadKey)) {
504
+ if (signal?.aborted && shouldClearCache?.()) {
530
505
  await deleteCorestoreDirectory(corestoreDir);
531
506
  }
532
- clearClearCacheFlag(downloadKey);
533
507
  }
534
508
  return getShardPath(hyperdriveKey, allFiles[0]);
535
509
  }
536
510
  export async function downloadModelFromHyperdrive(hyperdriveKey, modelFileName, seed, progressCallback, hooks, expectedChecksum) {
537
511
  const downloadKey = createHyperdriveDownloadKey(hyperdriveKey, modelFileName);
538
- // Check if already downloading
539
- const existing = getActiveDownload(downloadKey);
540
- if (existing) {
541
- hooks?.markCacheMiss();
542
- return existing.promise;
543
- }
512
+ hooks?.onDownloadKey?.(downloadKey);
544
513
  const shardInfo = detectShardedModel(modelFileName);
545
514
  const model = getModelBySrc(modelFileName, hyperdriveKey);
546
- if (shardInfo.isSharded && model?.shardMetadata) {
547
- return createManagedDownload(downloadKey, hyperdriveKey, modelFileName, (signal) => downloadShardedFilesToFilesystem(hyperdriveKey, modelFileName, model.shardMetadata, progressCallback, seed, signal, hooks), progressCallback);
548
- }
549
- // Non-sharded model download
550
- const corestoreDir = getCorestoreDir(hyperdriveKey);
551
- const cacheDir = getModelsCacheDir();
552
- const sourceHash = generateShortHash(`${hyperdriveKey}/${modelFileName}`);
553
- const modelPath = path.join(cacheDir, `${sourceHash}_${modelFileName}`);
554
- // First, check if we already have a valid cached file (only if we have model metadata)
555
- if (model) {
556
- const cachedPath = await validateCachedFile(modelPath, modelFileName, model.expectedSize, expectedChecksum || model.sha256Checksum, hooks);
557
- if (cachedPath) {
558
- hooks?.markCacheHit();
559
- if (progressCallback) {
560
- progressCallback({
515
+ const result = startOrJoinDownload(downloadKey, async (ctx) => {
516
+ if (shardInfo.isSharded && model?.shardMetadata) {
517
+ const hooksWithCacheHit = {
518
+ ...hooks,
519
+ markCacheHit: () => {
520
+ hooks?.markCacheHit?.();
521
+ ctx.setCacheHit(true);
522
+ },
523
+ markCacheMiss: () => {
524
+ hooks?.markCacheMiss?.();
525
+ ctx.setCacheHit(false);
526
+ },
527
+ };
528
+ return downloadShardedFilesToFilesystem(hyperdriveKey, modelFileName, model.shardMetadata, ctx.broadcastProgress, seed, ctx.signal, hooksWithCacheHit, ctx.shouldClearCache);
529
+ }
530
+ // Non-sharded model download
531
+ const corestoreDir = getCorestoreDir(hyperdriveKey);
532
+ const cacheDir = getModelsCacheDir();
533
+ const sourceHash = generateShortHash(`${hyperdriveKey}/${modelFileName}`);
534
+ const modelPath = path.join(cacheDir, `${sourceHash}_${modelFileName}`);
535
+ // First, check if we already have a valid cached file (only if we have model metadata)
536
+ if (model) {
537
+ const cachedPath = await validateCachedFile(modelPath, modelFileName, model.expectedSize, expectedChecksum || model.sha256Checksum, hooks);
538
+ if (cachedPath) {
539
+ hooks?.markCacheHit?.();
540
+ ctx.setCacheHit(true);
541
+ ctx.broadcastProgress({
561
542
  type: "modelProgress",
562
543
  downloaded: model.expectedSize,
563
544
  total: model.expectedSize,
564
545
  percentage: 100,
565
546
  downloadKey,
566
547
  });
548
+ // Delete any leftover corestore directory from previous runs (only when not seeding)
549
+ if (!seed) {
550
+ await deleteCorestoreDirectory(corestoreDir);
551
+ }
552
+ return cachedPath;
567
553
  }
568
- // Delete any leftover corestore directory from previous runs (only when not seeding)
569
- if (!seed) {
570
- await deleteCorestoreDirectory(corestoreDir);
571
- }
572
- return cachedPath;
573
554
  }
574
- }
575
- hooks?.markCacheMiss();
576
- return createManagedDownload(downloadKey, hyperdriveKey, modelFileName, async (signal) => {
555
+ hooks?.markCacheMiss?.();
556
+ ctx.setCacheHit(false);
577
557
  const checksumToValidate = expectedChecksum || model?.sha256Checksum || "";
578
- await downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, checksumToValidate, progressCallback, seed, signal, hooks);
558
+ await downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, checksumToValidate, ctx.broadcastProgress, seed, ctx.signal, hooks, ctx.shouldClearCache);
579
559
  return modelPath;
580
560
  }, progressCallback);
561
+ return applyJoinedDownloadStats(result, hooks);
581
562
  }
@@ -1,4 +1,3 @@
1
1
  export { handleLoadModel } from "./handler";
2
2
  export { resolveModelPath } from "./resolve";
3
- export { createCancelFunction } from "./download-manager";
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export { handleLoadModel } from "./handler.js";
2
2
  export { resolveModelPath } from "./resolve.js";
3
- export { createCancelFunction } from "./download-manager.js";
@@ -0,0 +1,27 @@
1
+ import type { QvacConfig } from "../../../../schemas/index";
2
+ export declare const DEFAULT_REGISTRY_STREAM_TIMEOUT_MS = 60000;
3
+ export interface RegistryClientDownloadOptions {
4
+ timeout: number;
5
+ outputFile: string;
6
+ maxRetries?: number;
7
+ onProgress?: (progress: {
8
+ downloaded: number;
9
+ total: number;
10
+ }) => void;
11
+ signal?: globalThis.AbortSignal;
12
+ }
13
+ /**
14
+ * Build the options passed to @qvac/registry-client download methods from the
15
+ * current SDK config. Pure helper (no bare-* imports) so the mapping can be
16
+ * unit-tested without standing up a real registry client.
17
+ */
18
+ export declare function buildRegistryClientOptions(params: {
19
+ sdkConfig: Pick<QvacConfig, "registryStreamTimeoutMs" | "registryDownloadMaxRetries">;
20
+ outputFile: string;
21
+ onProgress?: ((progress: {
22
+ downloaded: number;
23
+ total: number;
24
+ }) => void) | undefined;
25
+ signal?: globalThis.AbortSignal | undefined;
26
+ }): RegistryClientDownloadOptions;
27
+ //# sourceMappingURL=registry-client-options.d.ts.map
@@ -0,0 +1,19 @@
1
+ export const DEFAULT_REGISTRY_STREAM_TIMEOUT_MS = 60_000;
2
+ /**
3
+ * Build the options passed to @qvac/registry-client download methods from the
4
+ * current SDK config. Pure helper (no bare-* imports) so the mapping can be
5
+ * unit-tested without standing up a real registry client.
6
+ */
7
+ export function buildRegistryClientOptions(params) {
8
+ const { sdkConfig, outputFile, onProgress, signal } = params;
9
+ const timeout = sdkConfig.registryStreamTimeoutMs
10
+ ?? DEFAULT_REGISTRY_STREAM_TIMEOUT_MS;
11
+ const maxRetries = sdkConfig.registryDownloadMaxRetries;
12
+ return {
13
+ timeout,
14
+ outputFile,
15
+ ...(maxRetries !== undefined && { maxRetries }),
16
+ ...(onProgress && { onProgress }),
17
+ ...(signal && { signal: signal }),
18
+ };
19
+ }
@@ -0,0 +1,22 @@
1
+ import type { ModelProgressUpdate } from "../../../../schemas/index";
2
+ import type { RegistryItem } from "../../../../models/registry/index";
3
+ import type { AbortSignal } from "bare-abort-controller";
4
+ import type { DownloadHooks } from "./types";
5
+ type CompanionSetMetadata = NonNullable<RegistryItem["companionSet"]>;
6
+ export interface DownloadCompanionSetOptions {
7
+ companionSet: CompanionSetMetadata;
8
+ downloadKey: string;
9
+ progressCallback?: ((progress: ModelProgressUpdate) => void) | undefined;
10
+ signal?: AbortSignal | undefined;
11
+ hooks?: DownloadHooks | undefined;
12
+ shouldClearCache?: (() => boolean) | undefined;
13
+ }
14
+ /**
15
+ * Download a companion set from the registry, placing files directly
16
+ * into their canonical layout at `sets/<setKey>/<targetName>`.
17
+ *
18
+ * Returns the path to the primary file.
19
+ */
20
+ export declare function downloadCompanionSetFromRegistry(options: DownloadCompanionSetOptions): Promise<string>;
21
+ export {};
22
+ //# sourceMappingURL=registry-companion-set.d.ts.map
@@ -0,0 +1,208 @@
1
+ import { promises as fsPromises } from "bare-fs";
2
+ import { getModelsCacheDir, getCompanionSetPath, getCompanionSetCacheDir, getSingleFileCachePath, generateShortHash, calculatePercentage, } from "../../../utils/index.js";
3
+ import { measureChecksum } from "../../../utils/checksum.js";
4
+ import { validateAndJoinPath } from "../../../utils/path-security.js";
5
+ import { buildBlobBinding, downloadSingleFileFromRegistry, validateCachedFile, } from "./registry-download-utils.js";
6
+ import { DownloadCancelledError, RegistryDownloadFailedError, } from "../../../../utils/errors-server.js";
7
+ import { getServerLogger } from "../../../../logging/index.js";
8
+ const logger = getServerLogger();
9
+ /**
10
+ * Download a companion set from the registry, placing files directly
11
+ * into their canonical layout at `sets/<setKey>/<targetName>`.
12
+ *
13
+ * Returns the path to the primary file.
14
+ */
15
+ export async function downloadCompanionSetFromRegistry(options) {
16
+ const { companionSet, downloadKey, progressCallback, signal, hooks, shouldClearCache, } = options;
17
+ const { files, setKey, primaryKey } = companionSet;
18
+ validateCompanionSetMetadata(files, primaryKey);
19
+ const primaryEntry = files.find((f) => f.key === primaryKey);
20
+ const primaryRegistryPath = primaryEntry.registryPath;
21
+ if (isLegacyOnnxSet(files)) {
22
+ const legacyPath = await checkLegacyOnnxCache(primaryRegistryPath, files, hooks);
23
+ if (legacyPath) {
24
+ logger.info(`✅ Using legacy ONNX cache for companion set: ${legacyPath}`);
25
+ hooks?.markCacheHit?.();
26
+ emitFinalProgress(progressCallback, downloadKey, setKey, files);
27
+ return legacyPath;
28
+ }
29
+ }
30
+ // Legacy flat-cache compatibility for Bergamot-style companion sets.
31
+ // This is valid only for families whose runtime still works with explicit
32
+ // per-file absolute paths; it is not a generic rule for all companion sets.
33
+ if (!isLegacyOnnxSet(files)) {
34
+ const flatPath = await checkLegacyFlatCache(files, primaryKey, hooks);
35
+ if (flatPath) {
36
+ logger.info(`✅ Using legacy flat cache for companion set: ${flatPath}`);
37
+ hooks?.markCacheHit?.();
38
+ emitFinalProgress(progressCallback, downloadKey, setKey, files);
39
+ return flatPath;
40
+ }
41
+ }
42
+ // Check canonical companion set cache
43
+ const validatedFiles = new Set();
44
+ for (const file of files) {
45
+ const filePath = getCompanionSetPath(setKey, file.targetName);
46
+ const cached = await validateCachedFile(filePath, file.targetName, file.expectedSize, file.sha256Checksum, hooks);
47
+ if (cached) {
48
+ validatedFiles.add(file.key);
49
+ }
50
+ }
51
+ if (validatedFiles.size === files.length) {
52
+ logger.info(`✅ All companion set files cached`);
53
+ hooks?.markCacheHit?.();
54
+ emitFinalProgress(progressCallback, downloadKey, setKey, files);
55
+ return getCompanionSetPath(setKey, primaryEntry.targetName);
56
+ }
57
+ // Download missing files
58
+ hooks?.markCacheMiss?.();
59
+ const overallTotal = files.reduce((sum, f) => sum + f.expectedSize, 0);
60
+ let overallDownloaded = 0;
61
+ try {
62
+ for (let i = 0; i < files.length; i++) {
63
+ const file = files[i];
64
+ const filePath = getCompanionSetPath(setKey, file.targetName);
65
+ if (validatedFiles.has(file.key)) {
66
+ overallDownloaded += file.expectedSize;
67
+ continue;
68
+ }
69
+ const fileProgressCallback = progressCallback
70
+ ? (progress) => {
71
+ const currentOverall = overallDownloaded + progress.downloaded;
72
+ progressCallback({
73
+ ...progress,
74
+ downloadKey,
75
+ fileSetInfo: {
76
+ setKey,
77
+ currentFile: file.targetName,
78
+ fileIndex: i + 1,
79
+ totalFiles: files.length,
80
+ overallDownloaded: currentOverall,
81
+ overallTotal,
82
+ overallPercentage: calculatePercentage(currentOverall, overallTotal),
83
+ },
84
+ });
85
+ }
86
+ : undefined;
87
+ const blobBinding = file.blobCoreKey
88
+ ? buildBlobBinding(file)
89
+ : undefined;
90
+ await downloadSingleFileFromRegistry(file.registryPath, file.registrySource, filePath, file.targetName, downloadKey, file.expectedSize, file.sha256Checksum, fileProgressCallback, signal, blobBinding, hooks);
91
+ overallDownloaded += file.expectedSize;
92
+ }
93
+ }
94
+ catch (error) {
95
+ if (error instanceof DownloadCancelledError && shouldClearCache?.()) {
96
+ try {
97
+ await fsPromises.rm(getCompanionSetCacheDir(setKey), {
98
+ recursive: true,
99
+ force: true,
100
+ });
101
+ }
102
+ catch (cleanupError) {
103
+ logger.debug("Failed to delete companion set cache during cleanup", {
104
+ setKey,
105
+ error: cleanupError,
106
+ });
107
+ }
108
+ }
109
+ throw error;
110
+ }
111
+ emitFinalProgress(progressCallback, downloadKey, setKey, files);
112
+ return getCompanionSetPath(setKey, primaryEntry.targetName);
113
+ }
114
+ function emitFinalProgress(progressCallback, downloadKey, setKey, files) {
115
+ if (!progressCallback)
116
+ return;
117
+ const overallTotal = files.reduce((sum, f) => sum + f.expectedSize, 0);
118
+ const lastFile = files[files.length - 1];
119
+ progressCallback({
120
+ type: "modelProgress",
121
+ downloaded: overallTotal,
122
+ total: overallTotal,
123
+ percentage: 100,
124
+ downloadKey,
125
+ fileSetInfo: {
126
+ setKey,
127
+ currentFile: lastFile.targetName,
128
+ fileIndex: files.length,
129
+ totalFiles: files.length,
130
+ overallDownloaded: overallTotal,
131
+ overallTotal,
132
+ overallPercentage: 100,
133
+ },
134
+ });
135
+ }
136
+ function validateCompanionSetMetadata(files, primaryKey) {
137
+ if (!files.some((f) => f.key === primaryKey)) {
138
+ throw new RegistryDownloadFailedError(`Companion set missing primary file (key: ${primaryKey})`);
139
+ }
140
+ const targetNames = new Set();
141
+ for (const file of files) {
142
+ if (targetNames.has(file.targetName)) {
143
+ throw new RegistryDownloadFailedError(`Companion set has duplicate targetName "${file.targetName}"`);
144
+ }
145
+ targetNames.add(file.targetName);
146
+ }
147
+ }
148
+ function isLegacyOnnxSet(files) {
149
+ return files.some((f) => f.primary === true && f.targetName.endsWith(".onnx"));
150
+ }
151
+ /**
152
+ * Check if a complete legacy ONNX cache exists for a companion set.
153
+ * Read-only probe: does not create legacy cache directories.
154
+ */
155
+ async function checkLegacyOnnxCache(primaryRegistryPath, files, hooks) {
156
+ const cacheKey = generateShortHash(primaryRegistryPath);
157
+ let primaryPath = null;
158
+ for (const file of files) {
159
+ const filePath = getLegacyOnnxPath(cacheKey, file.targetName);
160
+ try {
161
+ const stats = await fsPromises.stat(filePath);
162
+ if (stats.size !== file.expectedSize)
163
+ return null;
164
+ if (file.sha256Checksum && file.sha256Checksum.length === 64) {
165
+ const checksum = await measureChecksum(filePath, hooks);
166
+ if (checksum !== file.sha256Checksum)
167
+ return null;
168
+ }
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ if (file.primary === true) {
174
+ primaryPath = filePath;
175
+ }
176
+ }
177
+ return primaryPath;
178
+ }
179
+ function getLegacyOnnxPath(cacheKey, filename) {
180
+ const baseCache = getModelsCacheDir();
181
+ return validateAndJoinPath(baseCache, "onnx", cacheKey, filename);
182
+ }
183
+ /**
184
+ * Check if all companion files exist in the flat single-file cache.
185
+ */
186
+ async function checkLegacyFlatCache(files, primaryKey, hooks) {
187
+ let primaryPath = null;
188
+ for (const file of files) {
189
+ const flatPath = getSingleFileCachePath(file.registryPath);
190
+ try {
191
+ const stats = await fsPromises.stat(flatPath);
192
+ if (stats.size !== file.expectedSize)
193
+ return null;
194
+ if (file.sha256Checksum && file.sha256Checksum.length === 64) {
195
+ const checksum = await measureChecksum(flatPath, hooks);
196
+ if (checksum !== file.sha256Checksum)
197
+ return null;
198
+ }
199
+ }
200
+ catch {
201
+ return null;
202
+ }
203
+ if (file.key === primaryKey) {
204
+ primaryPath = flatPath;
205
+ }
206
+ }
207
+ return primaryPath;
208
+ }
@@ -0,0 +1,24 @@
1
+ import type { ModelProgressUpdate } from "../../../../schemas/index";
2
+ import type { QVACBlobBinding } from "@qvac/registry-client";
3
+ import type { AbortSignal } from "bare-abort-controller";
4
+ import type { DownloadHooks } from "./types";
5
+ export { DEFAULT_REGISTRY_STREAM_TIMEOUT_MS, buildRegistryClientOptions, } from "./registry-client-options";
6
+ export type { RegistryClientDownloadOptions } from "./registry-client-options";
7
+ export declare function buildBlobBinding(meta: {
8
+ blobCoreKey: string;
9
+ blobBlockOffset: number;
10
+ blobBlockLength: number;
11
+ blobByteOffset: number;
12
+ expectedSize: number;
13
+ }): QVACBlobBinding;
14
+ /**
15
+ * Validate a cached file against expected size and checksum.
16
+ */
17
+ export declare function validateCachedFile(modelPath: string, modelFileName: string, expectedSize: number, expectedChecksum?: string, hooks?: DownloadHooks): Promise<string | null>;
18
+ /**
19
+ * Download a single file from the registry to filesystem.
20
+ * When blobBinding is provided, uses direct blob download (skips metadata sync).
21
+ * Otherwise falls back to metadata-based downloadModel.
22
+ */
23
+ export declare function downloadSingleFileFromRegistry(registryPath: string, registrySource: string, modelPath: string, modelFileName: string, downloadKey: string, expectedSize: number, expectedChecksum: string, progressCallback?: (progress: ModelProgressUpdate) => void, signal?: AbortSignal, blobBinding?: QVACBlobBinding, hooks?: DownloadHooks): Promise<void>;
24
+ //# sourceMappingURL=registry-download-utils.d.ts.map
@@ -0,0 +1,114 @@
1
+ import { promises as fsPromises } from "bare-fs";
2
+ import path from "bare-path";
3
+ import { measureChecksum, calculatePercentage, } from "../../../utils/index.js";
4
+ import { getRegistryClient } from "../../../bare/registry/registry-client.js";
5
+ import { getSDKConfig } from "../../../bare/registry/config-registry.js";
6
+ import { buildRegistryClientOptions } from "./registry-client-options.js";
7
+ import { ChecksumValidationFailedError, DownloadCancelledError, } from "../../../../utils/errors-server.js";
8
+ import { getServerLogger } from "../../../../logging/index.js";
9
+ const logger = getServerLogger();
10
+ export { DEFAULT_REGISTRY_STREAM_TIMEOUT_MS, buildRegistryClientOptions, } from "./registry-client-options.js";
11
+ export function buildBlobBinding(meta) {
12
+ return {
13
+ coreKey: meta.blobCoreKey,
14
+ blockOffset: meta.blobBlockOffset,
15
+ blockLength: meta.blobBlockLength,
16
+ byteOffset: meta.blobByteOffset,
17
+ byteLength: meta.expectedSize,
18
+ };
19
+ }
20
+ /**
21
+ * Validate a cached file against expected size and checksum.
22
+ */
23
+ export async function validateCachedFile(modelPath, modelFileName, expectedSize, expectedChecksum, hooks) {
24
+ try {
25
+ await fsPromises.access(modelPath);
26
+ const localStats = await fsPromises.stat(modelPath);
27
+ const localSize = localStats.size;
28
+ if (localSize === expectedSize) {
29
+ logger.info(`✅ Model cached with correct size: ${modelPath}`);
30
+ if (expectedChecksum && expectedChecksum.length === 64) {
31
+ const checksum = await measureChecksum(modelPath, hooks);
32
+ if (checksum !== expectedChecksum) {
33
+ throw new ChecksumValidationFailedError(`${modelFileName}. Expected: ${expectedChecksum}. Actual: ${checksum}. File may be corrupted`);
34
+ }
35
+ }
36
+ logger.info(`✅ Model already cached and validated: ${modelPath}`);
37
+ return modelPath;
38
+ }
39
+ logger.warn(`🗑️ Removing incomplete cached file (expected ${expectedSize}, got ${localSize}): ${modelPath}`);
40
+ await fsPromises.unlink(modelPath);
41
+ return null;
42
+ }
43
+ catch (error) {
44
+ if (error instanceof ChecksumValidationFailedError) {
45
+ logger.warn(`🗑️ Removing corrupted cached file: ${modelPath}`);
46
+ await fsPromises.unlink(modelPath).catch(() => { });
47
+ }
48
+ return null;
49
+ }
50
+ }
51
+ /**
52
+ * Download a single file from the registry to filesystem.
53
+ * When blobBinding is provided, uses direct blob download (skips metadata sync).
54
+ * Otherwise falls back to metadata-based downloadModel.
55
+ */
56
+ export async function downloadSingleFileFromRegistry(registryPath, registrySource, modelPath, modelFileName, downloadKey, expectedSize, expectedChecksum, progressCallback, signal, blobBinding, hooks) {
57
+ if (signal?.aborted) {
58
+ throw new DownloadCancelledError();
59
+ }
60
+ const client = await getRegistryClient();
61
+ const dir = path.dirname(modelPath);
62
+ await fsPromises.mkdir(dir, { recursive: true });
63
+ const onProgress = progressCallback
64
+ ? (progress) => {
65
+ const total = progress.total || expectedSize || progress.downloaded;
66
+ progressCallback({
67
+ type: "modelProgress",
68
+ downloaded: progress.downloaded,
69
+ total,
70
+ percentage: total > 0
71
+ ? calculatePercentage(progress.downloaded, total)
72
+ : 0,
73
+ downloadKey,
74
+ });
75
+ }
76
+ : undefined;
77
+ const clientOptions = buildRegistryClientOptions({
78
+ sdkConfig: getSDKConfig(),
79
+ outputFile: modelPath,
80
+ onProgress,
81
+ signal,
82
+ });
83
+ if (blobBinding) {
84
+ logger.info(`📥 Downloading blob directly: ${modelFileName}`);
85
+ await client.downloadBlob(blobBinding, clientOptions);
86
+ }
87
+ else {
88
+ logger.info(`📥 Downloading from registry: ${registryPath}`);
89
+ await client.downloadModel(registryPath, registrySource, clientOptions);
90
+ }
91
+ logger.info(`✅ Downloaded to ${modelPath}`);
92
+ const stats = await fsPromises.stat(modelPath);
93
+ if (expectedSize && stats.size !== expectedSize) {
94
+ await fsPromises.unlink(modelPath).catch(() => { });
95
+ throw new ChecksumValidationFailedError(`${modelFileName}. File size mismatch: expected ${expectedSize}, got ${stats.size}`);
96
+ }
97
+ if (expectedChecksum && expectedChecksum.length === 64) {
98
+ const checksum = await measureChecksum(modelPath, hooks);
99
+ if (checksum !== expectedChecksum) {
100
+ await fsPromises.unlink(modelPath);
101
+ throw new ChecksumValidationFailedError(`${modelFileName}. Expected: ${expectedChecksum}. Actual: ${checksum}`);
102
+ }
103
+ logger.info(`✅ Checksum validated for ${modelFileName}`);
104
+ }
105
+ if (progressCallback) {
106
+ progressCallback({
107
+ type: "modelProgress",
108
+ downloaded: stats.size,
109
+ total: stats.size,
110
+ percentage: 100,
111
+ downloadKey,
112
+ });
113
+ }
114
+ }