@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
@@ -7,10 +7,11 @@ function createStatsCollector() {
7
7
  maxBytesDownloaded: 0,
8
8
  startTimeMs: nowMs(),
9
9
  cacheHit: undefined,
10
+ sharedTransfer: false,
10
11
  checksumValidationTimeMsTotal: 0,
11
12
  };
12
13
  }
13
- function createHooks(collector) {
14
+ function createStatsHooks(collector) {
14
15
  return {
15
16
  markCacheHit: () => {
16
17
  if (collector.cacheHit === undefined) {
@@ -21,6 +22,9 @@ function createHooks(collector) {
21
22
  markCacheMiss: () => {
22
23
  collector.cacheHit = false;
23
24
  },
25
+ markSharedTransfer: () => {
26
+ collector.sharedTransfer = true;
27
+ },
24
28
  addChecksumValidationTimeMs: (durationMs) => {
25
29
  collector.checksumValidationTimeMsTotal += durationMs;
26
30
  },
@@ -30,7 +34,7 @@ function wrapProgressCallback(collector, originalCallback) {
30
34
  return (progress) => {
31
35
  // Don't track bytes for cache hits (they're not real network transfer)
32
36
  if (collector.cacheHit !== true) {
33
- const downloaded = progress.onnxInfo?.overallDownloaded ??
37
+ const downloaded = progress.fileSetInfo?.overallDownloaded ??
34
38
  progress.shardInfo?.overallDownloaded ??
35
39
  progress.downloaded ??
36
40
  0;
@@ -43,6 +47,9 @@ function computeStats(collector) {
43
47
  const downloadTimeMs = nowMs() - collector.startTimeMs;
44
48
  const totalBytesDownloaded = collector.maxBytesDownloaded;
45
49
  const stats = {};
50
+ if (collector.sharedTransfer) {
51
+ stats.sharedTransfer = true;
52
+ }
46
53
  if (collector.cacheHit !== undefined) {
47
54
  stats.cacheHit = collector.cacheHit;
48
55
  }
@@ -52,6 +59,12 @@ function computeStats(collector) {
52
59
  if (collector.cacheHit === true) {
53
60
  return Object.keys(stats).length > 0 ? stats : undefined;
54
61
  }
62
+ if (collector.sharedTransfer) {
63
+ if (downloadTimeMs > 0) {
64
+ stats.downloadTimeMs = downloadTimeMs;
65
+ }
66
+ return Object.keys(stats).length > 0 ? stats : undefined;
67
+ }
55
68
  if (totalBytesDownloaded > 0) {
56
69
  stats.downloadTimeMs = downloadTimeMs;
57
70
  stats.totalBytesDownloaded = totalBytesDownloaded;
@@ -61,27 +74,55 @@ function computeStats(collector) {
61
74
  }
62
75
  return Object.keys(stats).length > 0 ? stats : undefined;
63
76
  }
64
- export async function downloadModelFromHttpWithStats(url, progressCallback) {
77
+ export async function downloadModelFromHttpWithStats(url, progressCallback, downloadHooks) {
65
78
  const collector = createStatsCollector();
66
- const hooks = createHooks(collector);
79
+ const hooks = { ...downloadHooks, ...createStatsHooks(collector) };
67
80
  const wrappedCallback = wrapProgressCallback(collector, progressCallback);
68
81
  const path = await downloadModelFromHttp(url, wrappedCallback, hooks);
69
82
  const stats = computeStats(collector);
70
83
  return stats ? { path, stats } : { path };
71
84
  }
72
- export async function downloadModelFromRegistryWithStats(registryPath, registrySource, progressCallback, expectedChecksum) {
85
+ export async function downloadModelFromRegistryWithStats(registryPath, registrySource, progressCallback, expectedChecksum, downloadHooks) {
73
86
  const collector = createStatsCollector();
74
- const hooks = createHooks(collector);
87
+ const hooks = { ...downloadHooks, ...createStatsHooks(collector) };
75
88
  const wrappedCallback = wrapProgressCallback(collector, progressCallback);
76
89
  const path = await downloadModelFromRegistry(registryPath, registrySource, wrappedCallback, expectedChecksum, hooks);
77
90
  const stats = computeStats(collector);
78
91
  return stats ? { path, stats } : { path };
79
92
  }
80
- export async function downloadModelFromHyperdriveWithStats(hyperdriveKey, modelFileName, seed, progressCallback) {
93
+ export async function downloadModelFromHyperdriveWithStats(hyperdriveKey, modelFileName, seed, progressCallback, downloadHooks) {
81
94
  const collector = createStatsCollector();
82
- const hooks = createHooks(collector);
95
+ const hooks = { ...downloadHooks, ...createStatsHooks(collector) };
83
96
  const wrappedCallback = wrapProgressCallback(collector, progressCallback);
84
97
  const path = await downloadModelFromHyperdrive(hyperdriveKey, modelFileName, seed, wrappedCallback, hooks);
85
98
  const stats = computeStats(collector);
86
99
  return stats ? { path, stats } : { path };
87
100
  }
101
+ export function mergeDownloadStats(results) {
102
+ const stats = results
103
+ .map((r) => r.downloadStats)
104
+ .filter((s) => s !== undefined);
105
+ if (stats.length === 0)
106
+ return undefined;
107
+ const downloadTimeMs = Math.max(...stats.map((s) => s.downloadTimeMs ?? 0));
108
+ const totalBytesDownloaded = stats.reduce((sum, s) => sum + (s.totalBytesDownloaded ?? 0), 0);
109
+ const checksumValidationTimeMs = stats.reduce((sum, s) => sum + (s.checksumValidationTimeMs ?? 0), 0);
110
+ const cacheHitValues = stats
111
+ .map((s) => s.cacheHit)
112
+ .filter((v) => v !== undefined);
113
+ const merged = {};
114
+ if (downloadTimeMs > 0)
115
+ merged.downloadTimeMs = downloadTimeMs;
116
+ if (totalBytesDownloaded > 0)
117
+ merged.totalBytesDownloaded = totalBytesDownloaded;
118
+ if (downloadTimeMs > 0 && totalBytesDownloaded > 0) {
119
+ merged.downloadSpeedBps = (totalBytesDownloaded * 1000) / downloadTimeMs;
120
+ }
121
+ if (checksumValidationTimeMs > 0)
122
+ merged.checksumValidationTimeMs = checksumValidationTimeMs;
123
+ if (cacheHitValues.length > 0)
124
+ merged.cacheHit = cacheHitValues.every(Boolean);
125
+ if (stats.some((s) => s.sharedTransfer))
126
+ merged.sharedTransfer = true;
127
+ return Object.keys(merged).length > 0 ? merged : undefined;
128
+ }
@@ -1,9 +1,10 @@
1
1
  import { normalizeModelType, PROFILING_KEY, OPERATION_EVENT_KEY, } from "../../../../schemas/index.js";
2
2
  import { loadModel } from "../../../bare/ops/load-model.js";
3
- import { resolveModelPath, resolveModelPathWithStats, } from "./resolve.js";
3
+ import { createResolveSession } from "./resolve-session.js";
4
4
  import { nowMs, generateProfileId } from "../../../../profiling/clock.js";
5
5
  import { getModelEntry, updateModelConfig, } from "../../../bare/registry/model-registry.js";
6
6
  import { generateShortHash, canonicalConfigString, transformConfigForReload, } from "../../../utils/index.js";
7
+ import { buildDownloadProfilingFields } from "./types.js";
7
8
  import { ConfigReloadNotSupportedError, ModelTypeMismatchError, ModelIsDelegatedError, ModelNotFoundError, ModelLoadFailedError, PluginLoadConfigValidationFailedError, PluginNotFoundError, } from "../../../../utils/errors-server.js";
8
9
  import { getServerLogger } from "../../../../logging/index.js";
9
10
  import { getPlugin } from "../../../plugins/index.js";
@@ -34,37 +35,39 @@ export async function handleLoadModel(request, progressCallback) {
34
35
  }
35
36
  resolvedModelConfig = parseResult.data;
36
37
  const totalLoadStart = profilingEnabled ? nowMs() : 0;
37
- let resolveResult;
38
+ const session = createResolveSession({
39
+ progressCallback,
40
+ seed,
41
+ profilingEnabled,
42
+ });
43
+ const primaryResolve = session.resolvePrimaryModelPath(modelSrc);
38
44
  let resolvedModelPath;
39
- if (profilingEnabled) {
40
- resolveResult = await resolveModelPathWithStats(modelSrc, progressCallback, seed);
41
- resolvedModelPath = resolveResult.path;
45
+ let pluginResolveResult;
46
+ try {
47
+ const pluginResolve = plugin.resolveConfig
48
+ ? Promise.resolve().then(() => plugin.resolveConfig(resolvedModelConfig, session.createResolveContext(modelSrc, canonicalModelType, modelName)))
49
+ : undefined;
50
+ [resolvedModelPath, pluginResolveResult] = pluginResolve
51
+ ? await Promise.all([primaryResolve, pluginResolve])
52
+ : [await primaryResolve, undefined];
42
53
  }
43
- else {
44
- resolvedModelPath = await resolveModelPath(modelSrc, progressCallback, seed);
45
- }
46
- let pluginArtifacts = {};
47
- if (plugin.resolveConfig) {
48
- const ctx = {
49
- resolveModelPath: (src) => resolveModelPath(src, progressCallback, seed),
50
- modelSrc,
51
- modelType: canonicalModelType,
52
- ...(modelName !== undefined && { modelName }),
53
- };
54
- const result = await plugin.resolveConfig(resolvedModelConfig, ctx);
55
- resolvedModelConfig = result.config;
56
- if (result.artifacts) {
57
- pluginArtifacts = result.artifacts;
58
- }
54
+ catch (error) {
55
+ session.cancelAll();
56
+ throw error;
59
57
  }
60
58
  const configStr = canonicalConfigString(request.modelConfig);
61
59
  const modelHashInput = `${request.modelType}:${modelSrc}:${configStr}`;
62
60
  const modelId = generateShortHash(modelHashInput);
61
+ let pluginArtifacts = {};
62
+ if (pluginResolveResult) {
63
+ resolvedModelConfig = pluginResolveResult.config;
64
+ if (pluginResolveResult.artifacts) {
65
+ pluginArtifacts = pluginResolveResult.artifacts;
66
+ }
67
+ }
63
68
  if ("modelPath" in pluginArtifacts) {
64
- logger.warn("Plugin returned 'modelPath' artifact which was overridden by core");
69
+ throw new ModelLoadFailedError("Plugin returned reserved key \"modelPath\" in artifacts; primary model resolution is core-owned");
65
70
  }
66
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
67
- const { modelPath: _, ...artifacts } = pluginArtifacts;
68
71
  if (!resolvedModelPath) {
69
72
  throw new ModelLoadFailedError("modelPath resolution failed");
70
73
  }
@@ -76,7 +79,7 @@ export async function handleLoadModel(request, progressCallback) {
76
79
  modelType: canonicalModelType,
77
80
  modelConfig: resolvedModelConfig,
78
81
  },
79
- artifacts: Object.keys(artifacts).length > 0 ? artifacts : undefined,
82
+ artifacts: Object.keys(pluginArtifacts).length > 0 ? pluginArtifacts : undefined,
80
83
  modelName,
81
84
  }, profilingEnabled ? { collectTiming: true } : undefined);
82
85
  const response = {
@@ -87,38 +90,16 @@ export async function handleLoadModel(request, progressCallback) {
87
90
  if (profilingEnabled) {
88
91
  const totalLoadTimeMs = nowMs() - totalLoadStart;
89
92
  const profileId = profilingMeta?.id ?? generateProfileId();
90
- const gauges = {
91
- totalLoadTime: totalLoadTimeMs,
92
- };
93
+ const resolveResult = session.getAggregateResult();
94
+ const { gauges, tags } = buildDownloadProfilingFields(resolveResult?.downloadStats, resolveResult?.sourceType);
95
+ gauges["totalLoadTime"] = totalLoadTimeMs;
93
96
  if (loadResult.timing?.modelInitializationTimeMs !== undefined) {
94
97
  gauges["modelInitializationTime"] =
95
98
  loadResult.timing.modelInitializationTimeMs;
96
99
  }
97
- if (resolveResult?.downloadStats) {
98
- const ds = resolveResult.downloadStats;
99
- if (ds.downloadTimeMs !== undefined) {
100
- gauges["downloadTime"] = ds.downloadTimeMs;
101
- }
102
- if (ds.totalBytesDownloaded !== undefined) {
103
- gauges["totalBytesDownloaded"] = ds.totalBytesDownloaded;
104
- }
105
- if (ds.downloadSpeedBps !== undefined) {
106
- gauges["downloadSpeedBps"] = ds.downloadSpeedBps;
107
- }
108
- if (ds.checksumValidationTimeMs !== undefined) {
109
- gauges["checksumValidationTime"] = ds.checksumValidationTimeMs;
110
- }
111
- }
112
- const tags = {};
113
100
  if (canonicalModelType) {
114
101
  tags["modelType"] = canonicalModelType;
115
102
  }
116
- if (resolveResult?.sourceType) {
117
- tags["sourceType"] = resolveResult.sourceType;
118
- }
119
- if (resolveResult?.downloadStats?.cacheHit !== undefined) {
120
- tags["cacheHit"] = resolveResult.downloadStats.cacheHit ? "true" : "false";
121
- }
122
103
  const operationEvent = {
123
104
  op: "loadModel",
124
105
  kind: "handler",
@@ -1,4 +1,4 @@
1
1
  import type { ModelProgressUpdate } from "../../../../schemas/index";
2
- import type { DownloadMetricsHooks } from "./types";
3
- export declare function downloadModelFromHttp(url: string, progressCallback?: (progress: ModelProgressUpdate) => void, hooks?: DownloadMetricsHooks): Promise<string>;
2
+ import type { DownloadHooks } from "./types";
3
+ export declare function downloadModelFromHttp(url: string, progressCallback?: (progress: ModelProgressUpdate) => void, hooks?: DownloadHooks): Promise<string>;
4
4
  //# sourceMappingURL=http.d.ts.map
@@ -2,11 +2,10 @@ import fs, { promises as fsPromises } from "bare-fs";
2
2
  import path from "bare-path";
3
3
  import { Readable } from "bare-stream";
4
4
  import fetch from "bare-fetch";
5
- import { AbortController } from "bare-abort-controller";
6
5
  import { withTimeout } from "../../../../utils/withTimeout.js";
7
6
  import { getModelsCacheDir, getShardedModelCacheDir, generateShortHash, detectShardedModel, parsePatternBasedShardUrl, extractTensorsFromShards, calculatePercentage, isArchiveUrl, sanitizePathComponent, extractAndValidateShardedArchive, validateShardedModelCache, checkAllShardsExist, generateShardFilenames, hasValidGGUFHeader, } from "../../../utils/index.js";
8
7
  import { getSDKConfig } from "../../../bare/registry/config-registry.js";
9
- import { getActiveDownload, registerDownload, unregisterDownload, createHttpDownloadKey, shouldClearCache, clearClearCacheFlag, } from "./download-manager.js";
8
+ import { createHttpDownloadKey, startOrJoinDownload, applyJoinedDownloadStats, } from "./download-manager.js";
10
9
  import { DownloadCancelledError, HTTPError, NoResponseBodyError, PartialDownloadOfflineError, ResponseBodyNotReadableError, } from "../../../../utils/errors-server.js";
11
10
  import { getServerLogger } from "../../../../logging/index.js";
12
11
  const logger = getServerLogger();
@@ -200,7 +199,7 @@ async function performHttpDownload(url, modelPath, downloadKey, progressCallback
200
199
  await new Promise((resolve, reject) => {
201
200
  // Handle abort signal
202
201
  const abortHandler = () => {
203
- const error = new Error("Download cancelled");
202
+ const error = new DownloadCancelledError();
204
203
  body.destroy();
205
204
  writeStream.destroy();
206
205
  reject(error);
@@ -324,51 +323,20 @@ export async function downloadModelFromHttp(url, progressCallback, hooks) {
324
323
  return downloadShardedModelFromHttp(url, progressCallback, hooks);
325
324
  }
326
325
  const downloadKey = createHttpDownloadKey(url);
327
- const existing = getActiveDownload(downloadKey);
328
- if (existing) {
329
- logger.info(`📥 Reusing existing download for: ${downloadKey}`);
330
- hooks?.markCacheMiss();
331
- return existing.promise;
332
- }
326
+ hooks?.onDownloadKey?.(downloadKey);
333
327
  const cacheDir = getModelsCacheDir();
334
328
  const sourceHash = generateShortHash(url);
335
329
  const modelPath = `${cacheDir}/${sourceHash}_${filename}`;
336
- // Create managed download with AbortController
337
- const abortController = new AbortController();
338
- const downloadPromise = (async () => {
330
+ const result = startOrJoinDownload(downloadKey, async (ctx) => {
339
331
  try {
340
332
  // Check if already cached
341
- const cachedPath = await validateCachedFile(modelPath, url, abortController.signal);
333
+ const cachedPath = await validateCachedFile(modelPath, url, ctx.signal);
342
334
  if (cachedPath) {
343
- hooks?.markCacheHit();
344
- if (progressCallback) {
345
- try {
346
- const stats = await fsPromises.stat(cachedPath);
347
- progressCallback({
348
- type: "modelProgress",
349
- downloaded: stats.size,
350
- total: stats.size,
351
- percentage: 100,
352
- downloadKey,
353
- });
354
- }
355
- catch (error) {
356
- logger.debug("Failed to get file stats for progress callback", {
357
- path: cachedPath,
358
- error,
359
- });
360
- }
361
- }
362
- return cachedPath;
363
- }
364
- // Download the file
365
- hooks?.markCacheMiss();
366
- await performHttpDownload(url, modelPath, downloadKey, progressCallback, abortController.signal);
367
- // Send final 100% progress update
368
- if (progressCallback) {
335
+ hooks?.markCacheHit?.();
336
+ ctx.setCacheHit(true);
369
337
  try {
370
- const stats = await fsPromises.stat(modelPath);
371
- progressCallback({
338
+ const stats = await fsPromises.stat(cachedPath);
339
+ ctx.broadcastProgress({
372
340
  type: "modelProgress",
373
341
  downloaded: stats.size,
374
342
  total: stats.size,
@@ -377,19 +345,40 @@ export async function downloadModelFromHttp(url, progressCallback, hooks) {
377
345
  });
378
346
  }
379
347
  catch (error) {
380
- logger.debug("Failed to get file stats for final progress update", {
381
- path: modelPath,
348
+ logger.debug("Failed to get file stats for progress callback", {
349
+ path: cachedPath,
382
350
  error,
383
351
  });
384
352
  }
353
+ return cachedPath;
354
+ }
355
+ // Download the file
356
+ hooks?.markCacheMiss?.();
357
+ ctx.setCacheHit(false);
358
+ await performHttpDownload(url, modelPath, downloadKey, ctx.broadcastProgress, ctx.signal);
359
+ try {
360
+ const stats = await fsPromises.stat(modelPath);
361
+ ctx.broadcastProgress({
362
+ type: "modelProgress",
363
+ downloaded: stats.size,
364
+ total: stats.size,
365
+ percentage: 100,
366
+ downloadKey,
367
+ });
368
+ }
369
+ catch (error) {
370
+ logger.debug("Failed to get file stats for final progress update", {
371
+ path: modelPath,
372
+ error,
373
+ });
385
374
  }
386
375
  return modelPath;
387
376
  }
388
377
  catch (error) {
389
378
  logger.error("❌ Error downloading model:", error instanceof Error ? error.message : String(error));
390
379
  // Check if we should delete the partial file (clearCache was requested)
391
- if (error instanceof Error && error.message === "Download cancelled") {
392
- if (shouldClearCache(downloadKey)) {
380
+ if (error instanceof DownloadCancelledError) {
381
+ if (ctx.shouldClearCache()) {
393
382
  logger.info("🗑️ Clearing cache - deleting partial file");
394
383
  try {
395
384
  await fsPromises.unlink(modelPath);
@@ -405,45 +394,22 @@ export async function downloadModelFromHttp(url, progressCallback, hooks) {
405
394
  else {
406
395
  logger.info("📥 Download paused - partial file preserved for resume");
407
396
  }
408
- clearClearCacheFlag(downloadKey);
409
397
  }
410
398
  const errorToThrow = error instanceof Error ? error : new Error(String(error));
411
399
  throw errorToThrow;
412
400
  }
413
- finally {
414
- // Cleanup from download manager
415
- unregisterDownload(downloadKey);
416
- }
417
- })();
418
- // Register download
419
- const downloadEntry = {
420
- key: downloadKey,
421
- promise: downloadPromise,
422
- abortController,
423
- startTime: Date.now(),
424
- type: "http",
425
- url,
426
- modelPath,
427
- ...(progressCallback && { onProgress: progressCallback }),
428
- };
429
- registerDownload(downloadKey, downloadEntry);
430
- return downloadPromise;
401
+ }, progressCallback);
402
+ return applyJoinedDownloadStats(result, hooks);
431
403
  }
432
404
  async function downloadShardedModelFromHttp(shardUrl, progressCallback, hooks) {
433
405
  const config = getSDKConfig();
434
406
  const concurrency = config.httpDownloadConcurrency ?? DEFAULT_CONCURRENCY;
435
407
  const { shardUrls: shardInfos, cacheKey } = parsePatternBasedShardUrl(shardUrl);
436
408
  const downloadKey = `http-sharded:${cacheKey}`;
409
+ hooks?.onDownloadKey?.(downloadKey);
437
410
  logger.info(`📥 HTTP sharded download: ${shardInfos.length} shards detected from ${shardUrl}`);
438
- const existing = getActiveDownload(downloadKey);
439
- if (existing) {
440
- logger.info(`📥 Reusing existing sharded download for: ${downloadKey}`);
441
- hooks?.markCacheMiss();
442
- return existing.promise;
443
- }
444
- const abortController = new AbortController();
445
411
  const shardDir = getShardedModelCacheDir(cacheKey);
446
- const downloadPromise = (async () => {
412
+ const result = startOrJoinDownload(downloadKey, async (ctx) => {
447
413
  try {
448
414
  const shardStates = await Promise.all(shardInfos.map(async (shard, index) => {
449
415
  const shardPath = path.join(shardDir, shard.filename);
@@ -451,7 +417,7 @@ async function downloadShardedModelFromHttp(shardUrl, progressCallback, hooks) {
451
417
  try {
452
418
  const response = await fetch(shard.url, {
453
419
  method: "HEAD",
454
- signal: abortController.signal,
420
+ signal: ctx.signal,
455
421
  });
456
422
  expectedSize = parseInt(response.headers.get("content-length") || "0");
457
423
  }
@@ -460,7 +426,6 @@ async function downloadShardedModelFromHttp(shardUrl, progressCallback, hooks) {
460
426
  url: shard.url,
461
427
  error,
462
428
  });
463
- // expectedSize remains 0, progress percentage will be 0
464
429
  }
465
430
  return {
466
431
  index,
@@ -474,7 +439,7 @@ async function downloadShardedModelFromHttp(shardUrl, progressCallback, hooks) {
474
439
  const overallTotal = shardStates.reduce((sum, s) => sum + s.expectedSize, 0);
475
440
  logger.info(`📏 Total size: ${overallTotal} bytes (${(overallTotal / 1024 / 1024).toFixed(2)} MB)`);
476
441
  const cacheChecks = await Promise.all(shardStates.map(async (state) => {
477
- const cached = await validateCachedFile(state.shardPath, state.shard.url, abortController.signal);
442
+ const cached = await validateCachedFile(state.shardPath, state.shard.url, ctx.signal);
478
443
  return { state, isCached: cached !== null };
479
444
  }));
480
445
  const shardsToDownload = cacheChecks
@@ -488,20 +453,22 @@ async function downloadShardedModelFromHttp(shardUrl, progressCallback, hooks) {
488
453
  }
489
454
  logger.info(`📥 ${shardsToDownload.length} of ${shardInfos.length} shards need downloading`);
490
455
  if (shardsToDownload.length === 0) {
491
- hooks?.markCacheHit();
456
+ hooks?.markCacheHit?.();
457
+ ctx.setCacheHit(true);
492
458
  }
493
459
  else {
494
- hooks?.markCacheMiss();
460
+ hooks?.markCacheMiss?.();
461
+ ctx.setCacheHit(false);
495
462
  }
496
- await downloadShardsWithConcurrency(shardsToDownload, shardStates, concurrency, abortController.signal, downloadKey, overallTotal, progressCallback);
463
+ await downloadShardsWithConcurrency(shardsToDownload, shardStates, concurrency, ctx.signal, downloadKey, overallTotal, ctx.broadcastProgress);
497
464
  logger.info(`✅ All ${shardInfos.length} shards downloaded successfully`);
498
465
  await extractTensorsFromShards(shardDir, shardInfos[0].filename);
499
466
  return path.join(shardDir, shardInfos[0].filename);
500
467
  }
501
468
  catch (error) {
502
469
  logger.error("❌ Error during sharded download:", error instanceof Error ? error.message : String(error));
503
- if (error instanceof Error && error.message === "Download cancelled") {
504
- if (shouldClearCache(downloadKey)) {
470
+ if (error instanceof DownloadCancelledError) {
471
+ if (ctx.shouldClearCache()) {
505
472
  logger.info("🗑️ Clearing cache - deleting partial shard files");
506
473
  try {
507
474
  await fsPromises.rm(shardDir, { recursive: true, force: true });
@@ -517,50 +484,33 @@ async function downloadShardedModelFromHttp(shardUrl, progressCallback, hooks) {
517
484
  }
518
485
  throw error;
519
486
  }
520
- finally {
521
- unregisterDownload(downloadKey);
522
- clearClearCacheFlag(downloadKey);
523
- }
524
- })();
525
- registerDownload(downloadKey, {
526
- key: downloadKey,
527
- promise: downloadPromise,
528
- abortController,
529
- startTime: Date.now(),
530
- type: "http",
531
- url: shardUrl,
532
- modelPath: shardDir,
533
- });
534
- return downloadPromise;
487
+ }, progressCallback);
488
+ return applyJoinedDownloadStats(result, hooks);
535
489
  }
536
490
  async function downloadShardedModelFromArchive(archiveUrl, progressCallback, hooks) {
537
491
  const filename = extractFilenameFromUrl(archiveUrl);
538
492
  const sourceHash = generateShortHash(archiveUrl);
539
493
  const downloadKey = `http-archive:${sourceHash}`;
494
+ hooks?.onDownloadKey?.(downloadKey);
540
495
  logger.info(`📦 HTTP archive download: ${filename}`);
541
- const existing = getActiveDownload(downloadKey);
542
- if (existing) {
543
- logger.info(`📥 Reusing existing archive download for: ${downloadKey}`);
544
- hooks?.markCacheMiss();
545
- return existing.promise;
546
- }
547
- const abortController = new AbortController();
548
496
  const extractDir = getShardedModelCacheDir(sourceHash);
549
497
  const archivePath = path.join(extractDir, `${sourceHash}_${filename}`);
550
- const downloadPromise = (async () => {
498
+ const result = startOrJoinDownload(downloadKey, async (ctx) => {
551
499
  try {
552
500
  await fsPromises.mkdir(extractDir, { recursive: true });
553
501
  const files = await fsPromises.readdir(extractDir);
554
502
  const shardedFile = files.find((f) => detectShardedModel(String(f)).isSharded);
555
503
  if (!shardedFile) {
556
- hooks?.markCacheMiss();
504
+ hooks?.markCacheMiss?.();
505
+ ctx.setCacheHit(false);
557
506
  return downloadAndExtractArchive();
558
507
  }
559
508
  const shardFilename = String(shardedFile);
560
509
  const allShardsExist = await checkAllShardsExist(extractDir, shardFilename);
561
510
  if (!allShardsExist) {
562
511
  logger.warn(`⚠️ Incomplete shards found, re-downloading archive`);
563
- hooks?.markCacheMiss();
512
+ hooks?.markCacheMiss?.();
513
+ ctx.setCacheHit(false);
564
514
  return downloadAndExtractArchive();
565
515
  }
566
516
  const shardFilenames = generateShardFilenames(shardFilename);
@@ -568,53 +518,67 @@ async function downloadShardedModelFromArchive(archiveUrl, progressCallback, hoo
568
518
  const isComplete = await validateShardedModelCache(extractDir, shardFilename);
569
519
  if (isComplete) {
570
520
  logger.info(`✅ Archive already extracted: ${extractDir}`);
571
- hooks?.markCacheHit();
572
- if (progressCallback) {
573
- progressCallback({
574
- type: "modelProgress",
575
- downloaded: 1,
576
- total: 1,
577
- percentage: 100,
578
- downloadKey,
579
- });
580
- }
521
+ hooks?.markCacheHit?.();
522
+ ctx.setCacheHit(true);
523
+ ctx.broadcastProgress({
524
+ type: "modelProgress",
525
+ downloaded: 1,
526
+ total: 1,
527
+ percentage: 100,
528
+ downloadKey,
529
+ });
581
530
  return firstShard;
582
531
  }
583
532
  logger.info(`📝 All shards present but tensors.txt missing, extracting tensors...`);
584
533
  try {
585
534
  await extractTensorsFromShards(extractDir, shardFilename);
586
535
  logger.info(`✅ Tensors extracted successfully`);
587
- hooks?.markCacheHit();
588
- if (progressCallback) {
589
- progressCallback({
590
- type: "modelProgress",
591
- downloaded: 1,
592
- total: 1,
593
- percentage: 100,
594
- downloadKey,
595
- });
596
- }
536
+ hooks?.markCacheHit?.();
537
+ ctx.setCacheHit(true);
538
+ ctx.broadcastProgress({
539
+ type: "modelProgress",
540
+ downloaded: 1,
541
+ total: 1,
542
+ percentage: 100,
543
+ downloadKey,
544
+ });
597
545
  return firstShard;
598
546
  }
599
547
  catch (error) {
600
548
  logger.warn(`Failed to extract tensors, will re-download archive`, {
601
549
  error,
602
550
  });
603
- hooks?.markCacheMiss();
551
+ hooks?.markCacheMiss?.();
552
+ ctx.setCacheHit(false);
604
553
  return downloadAndExtractArchive();
605
554
  }
606
555
  }
607
556
  catch (error) {
608
557
  logger.error("❌ Error downloading/extracting archive:", error);
558
+ if (error instanceof DownloadCancelledError) {
559
+ if (ctx.shouldClearCache()) {
560
+ logger.info("🗑️ Clearing cache - deleting archive extract directory");
561
+ try {
562
+ await fsPromises.rm(extractDir, {
563
+ recursive: true,
564
+ force: true,
565
+ });
566
+ logger.info(`✅ Deleted extract directory: ${extractDir}`);
567
+ }
568
+ catch (cleanupError) {
569
+ logger.debug("Failed to delete extract directory during cleanup", {
570
+ path: extractDir,
571
+ error: cleanupError,
572
+ });
573
+ }
574
+ }
575
+ }
609
576
  throw error;
610
577
  }
611
- finally {
612
- unregisterDownload(downloadKey);
613
- }
614
578
  async function downloadAndExtractArchive() {
615
- await performHttpDownload(archiveUrl, archivePath, downloadKey, progressCallback, abortController.signal);
579
+ await performHttpDownload(archiveUrl, archivePath, downloadKey, ctx.broadcastProgress, ctx.signal);
616
580
  logger.info(`✅ Archive downloaded, extracting to: ${extractDir}`);
617
- const firstShardPath = await extractAndValidateShardedArchive(archivePath, extractDir, abortController.signal);
581
+ const firstShardPath = await extractAndValidateShardedArchive(archivePath, extractDir, ctx.signal);
618
582
  try {
619
583
  await fsPromises.unlink(archivePath);
620
584
  logger.info(`🗑️ Cleaned up archive file: ${archivePath}`);
@@ -627,17 +591,8 @@ async function downloadShardedModelFromArchive(archiveUrl, progressCallback, hoo
627
591
  }
628
592
  return firstShardPath;
629
593
  }
630
- })();
631
- registerDownload(downloadKey, {
632
- key: downloadKey,
633
- promise: downloadPromise,
634
- abortController,
635
- startTime: Date.now(),
636
- type: "http",
637
- url: archiveUrl,
638
- modelPath: archivePath,
639
- });
640
- return downloadPromise;
594
+ }, progressCallback);
595
+ return applyJoinedDownloadStats(result, hooks);
641
596
  }
642
597
  async function downloadShardsWithConcurrency(shardsToDownload, allShards, concurrency, signal, downloadKey, overallTotal, progressCallback) {
643
598
  const queue = [...shardsToDownload];
@@ -1,5 +1,5 @@
1
1
  import type { ModelProgressUpdate } from "../../../../schemas/index";
2
- import type { DownloadMetricsHooks } from "./types";
2
+ import type { DownloadHooks } from "./types";
3
3
  export declare function deleteCorestoreDirectory(corestoreDir: string): Promise<void>;
4
- export declare function downloadModelFromHyperdrive(hyperdriveKey: string, modelFileName: string, seed?: boolean, progressCallback?: (progress: ModelProgressUpdate) => void, hooks?: DownloadMetricsHooks, expectedChecksum?: string): Promise<string>;
4
+ export declare function downloadModelFromHyperdrive(hyperdriveKey: string, modelFileName: string, seed?: boolean, progressCallback?: (progress: ModelProgressUpdate) => void, hooks?: DownloadHooks, expectedChecksum?: string): Promise<string>;
5
5
  //# sourceMappingURL=hyperdrive.d.ts.map