@qvac/sdk 0.7.1 → 0.8.1

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 (257) hide show
  1. package/NOTICE +73 -10
  2. package/README.md +4 -4
  3. package/bare-imports.json +9 -0
  4. package/dist/client/api/cancel.d.ts +9 -0
  5. package/dist/client/api/cancel.js +9 -0
  6. package/dist/client/api/completion-stream.d.ts +2 -1
  7. package/dist/client/api/completion-stream.js +2 -1
  8. package/dist/client/api/download-asset.d.ts +3 -2
  9. package/dist/client/api/download-asset.js +4 -3
  10. package/dist/client/api/embed.d.ts +5 -2
  11. package/dist/client/api/embed.js +2 -2
  12. package/dist/client/api/get-model-info.d.ts +1 -1
  13. package/dist/client/api/heartbeat.d.ts +30 -0
  14. package/dist/client/api/heartbeat.js +38 -0
  15. package/dist/client/api/index.d.ts +1 -1
  16. package/dist/client/api/index.js +1 -1
  17. package/dist/client/api/invoke-plugin.d.ts +3 -2
  18. package/dist/client/api/invoke-plugin.js +4 -4
  19. package/dist/client/api/load-model.d.ts +12 -10
  20. package/dist/client/api/load-model.js +3 -3
  21. package/dist/client/api/rag.d.ts +10 -10
  22. package/dist/client/api/rag.js +21 -21
  23. package/dist/client/api/text-to-speech.d.ts +2 -2
  24. package/dist/client/api/text-to-speech.js +3 -3
  25. package/dist/client/api/transcribe.d.ts +5 -3
  26. package/dist/client/api/transcribe.js +6 -4
  27. package/dist/client/api/translate.d.ts +2 -2
  28. package/dist/client/api/translate.js +3 -3
  29. package/dist/client/rpc/node-rpc-client.d.ts +2 -7
  30. package/dist/client/rpc/node-rpc-client.js +2 -39
  31. package/dist/client/rpc/profiling/index.d.ts +2 -0
  32. package/dist/client/rpc/profiling/index.js +1 -0
  33. package/dist/client/rpc/profiling/profiler.d.ts +27 -0
  34. package/dist/client/rpc/profiling/profiler.js +139 -0
  35. package/dist/client/rpc/rpc-client.d.ts +2 -2
  36. package/dist/client/rpc/rpc-client.js +174 -12
  37. package/dist/examples/delegated-inference/consumer-profiled.d.ts +2 -0
  38. package/dist/examples/delegated-inference/consumer-profiled.js +67 -0
  39. package/dist/examples/embed-p2p.d.ts +2 -0
  40. package/dist/examples/llamacpp-multimodal.js +1 -1
  41. package/dist/examples/llamacpp-p2p.d.ts +2 -0
  42. package/dist/examples/parallel-download.js +45 -13
  43. package/dist/examples/profiling/basic.d.ts +2 -0
  44. package/dist/examples/profiling/basic.js +71 -0
  45. package/dist/examples/profiling/per-call.d.ts +2 -0
  46. package/dist/examples/profiling/per-call.js +30 -0
  47. package/dist/examples/seed-p2p.d.ts +2 -0
  48. package/dist/examples/transcription/parakeet-ctc-filesystem.d.ts +2 -0
  49. package/dist/examples/transcription/parakeet-ctc-filesystem.js +40 -0
  50. package/dist/examples/transcription/parakeet-microphone-record.d.ts +2 -0
  51. package/dist/examples/transcription/parakeet-microphone-record.js +95 -0
  52. package/dist/examples/transcription/parakeet-sortformer.d.ts +2 -0
  53. package/dist/examples/transcription/parakeet-sortformer.js +115 -0
  54. package/dist/examples/transcription/parakeet-tdt-filesystem.d.ts +2 -0
  55. package/dist/examples/transcription/parakeet-tdt-filesystem.js +44 -0
  56. package/dist/examples/translation/translation-bergamot-pivot.d.ts +2 -0
  57. package/dist/examples/translation/translation-bergamot-pivot.js +73 -0
  58. package/dist/examples/translation/translation-llm-afriquegemma.d.ts +2 -0
  59. package/dist/examples/translation/translation-llm-afriquegemma.js +39 -0
  60. package/dist/index.d.ts +4 -2
  61. package/dist/index.js +3 -1
  62. package/dist/logging/index.d.ts +1 -1
  63. package/dist/logging/index.js +1 -1
  64. package/dist/logging/namespaces.d.ts +3 -9
  65. package/dist/logging/namespaces.js +2 -8
  66. package/dist/logging/registry.js +15 -1
  67. package/dist/models/registry/models.d.ts +1671 -310
  68. package/dist/models/registry/models.js +2116 -710
  69. package/dist/models/update-models/codegen.js +2 -2
  70. package/dist/models/update-models/history.d.ts +11 -0
  71. package/dist/models/update-models/history.js +24 -5
  72. package/dist/models/update-models/index.js +17 -16
  73. package/dist/models/update-models/naming.js +56 -0
  74. package/dist/profiling/aggregator.d.ts +15 -0
  75. package/dist/profiling/aggregator.js +100 -0
  76. package/dist/profiling/clock.d.ts +12 -0
  77. package/dist/profiling/clock.js +51 -0
  78. package/dist/profiling/controller.d.ts +33 -0
  79. package/dist/profiling/controller.js +123 -0
  80. package/dist/profiling/envelope.d.ts +10 -0
  81. package/dist/profiling/envelope.js +36 -0
  82. package/dist/profiling/events.d.ts +20 -0
  83. package/dist/profiling/events.js +37 -0
  84. package/dist/profiling/exporters.d.ts +10 -0
  85. package/dist/profiling/exporters.js +236 -0
  86. package/dist/profiling/index.d.ts +36 -0
  87. package/dist/profiling/index.js +31 -0
  88. package/dist/profiling/ring-buffer.d.ts +19 -0
  89. package/dist/profiling/ring-buffer.js +83 -0
  90. package/dist/profiling/types.d.ts +47 -0
  91. package/dist/profiling/types.js +1 -0
  92. package/dist/schemas/cancel.d.ts +12 -0
  93. package/dist/schemas/cancel.js +2 -0
  94. package/dist/schemas/common.d.ts +1927 -135
  95. package/dist/schemas/common.js +6 -3
  96. package/dist/schemas/completion-stream.d.ts +31 -0
  97. package/dist/schemas/completion-stream.js +13 -0
  98. package/dist/schemas/delegate.d.ts +8 -0
  99. package/dist/schemas/delegate.js +5 -2
  100. package/dist/schemas/download-asset.d.ts +14 -3
  101. package/dist/schemas/download-asset.js +3 -1
  102. package/dist/schemas/engine-addon-map.js +9 -6
  103. package/dist/schemas/get-model-info.d.ts +2 -0
  104. package/dist/schemas/get-model-info.js +1 -0
  105. package/dist/schemas/heartbeat.d.ts +17 -0
  106. package/dist/schemas/heartbeat.js +10 -0
  107. package/dist/schemas/index.d.ts +3 -2
  108. package/dist/schemas/index.js +3 -2
  109. package/dist/schemas/llamacpp-config.d.ts +140 -14
  110. package/dist/schemas/llamacpp-config.js +11 -7
  111. package/dist/schemas/load-model.d.ts +9762 -2515
  112. package/dist/schemas/load-model.js +142 -182
  113. package/dist/schemas/model-src-utils.d.ts +10 -2
  114. package/dist/schemas/model-types.d.ts +19 -1
  115. package/dist/schemas/model-types.js +11 -0
  116. package/dist/schemas/ocr.d.ts +37 -0
  117. package/dist/schemas/ocr.js +5 -0
  118. package/dist/schemas/plugin.d.ts +51 -5
  119. package/dist/schemas/plugin.js +26 -0
  120. package/dist/schemas/profiling.d.ts +105 -0
  121. package/dist/schemas/profiling.js +66 -0
  122. package/dist/schemas/registry.d.ts +18 -0
  123. package/dist/schemas/registry.js +2 -0
  124. package/dist/schemas/reload-config.d.ts +126 -6
  125. package/dist/schemas/reload-config.js +1 -1
  126. package/dist/schemas/sdk-config.d.ts +2280 -24
  127. package/dist/schemas/sdk-config.js +6 -1
  128. package/dist/schemas/sdk-errors-client.d.ts +1 -0
  129. package/dist/schemas/sdk-errors-client.js +7 -0
  130. package/dist/schemas/sdk-errors-server.d.ts +3 -0
  131. package/dist/schemas/sdk-errors-server.js +15 -0
  132. package/dist/schemas/text-to-speech.d.ts +90 -68
  133. package/dist/schemas/text-to-speech.js +16 -33
  134. package/dist/schemas/transcription-config.d.ts +383 -0
  135. package/dist/schemas/{whispercpp-config.js → transcription-config.js} +29 -1
  136. package/dist/schemas/translation-config.d.ts +463 -8
  137. package/dist/schemas/translation-config.js +35 -2
  138. package/dist/server/bare/delegate-rpc-client.js +52 -11
  139. package/dist/server/bare/ops/load-model.d.ts +7 -1
  140. package/dist/server/bare/ops/load-model.js +41 -42
  141. package/dist/server/bare/ops/transcribe.d.ts +3 -0
  142. package/dist/server/bare/ops/transcribe.js +75 -0
  143. package/dist/server/bare/ops/translate.d.ts +2 -0
  144. package/dist/server/bare/ops/translate.js +12 -4
  145. package/dist/server/bare/plugins/index.d.ts +1 -0
  146. package/dist/server/bare/plugins/index.js +1 -0
  147. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +2 -1
  148. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +8 -6
  149. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +108 -3
  150. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +19 -6
  151. package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +32 -2
  152. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +31 -17
  153. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +325 -3
  154. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +117 -13
  155. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +50 -2
  156. package/dist/server/bare/plugins/onnx-ocr/plugin.js +46 -5
  157. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +351 -4
  158. package/dist/server/bare/plugins/onnx-tts/plugin.js +81 -61
  159. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +317 -0
  160. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +154 -0
  161. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +209 -3
  162. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +21 -9
  163. package/dist/server/bare/rag-hyperdb/rag-workspace-manager.js +2 -2
  164. package/dist/server/bare/registry/model-config-utils.js +3 -1
  165. package/dist/server/bare/registry/model-registry.d.ts +2 -0
  166. package/dist/server/bare/registry/model-registry.js +2 -1
  167. package/dist/server/bare/utils/audio-input.d.ts +10 -0
  168. package/dist/server/bare/utils/audio-input.js +33 -0
  169. package/dist/server/error-handlers.d.ts +3 -2
  170. package/dist/server/error-handlers.js +11 -8
  171. package/dist/server/plugins/registry.js +5 -1
  172. package/dist/server/rpc/delegate-transport.d.ts +11 -3
  173. package/dist/server/rpc/delegate-transport.js +214 -38
  174. package/dist/server/rpc/delegate-utils.d.ts +2 -0
  175. package/dist/server/rpc/delegate-utils.js +5 -0
  176. package/dist/server/rpc/handle-request.js +43 -4
  177. package/dist/server/rpc/handler-registry.js +33 -4
  178. package/dist/server/rpc/handler-utils.d.ts +5 -4
  179. package/dist/server/rpc/handler-utils.js +114 -31
  180. package/dist/server/rpc/handlers/cancel-delegated.d.ts +4 -0
  181. package/dist/server/rpc/handlers/cancel-delegated.js +71 -0
  182. package/dist/server/rpc/handlers/completion-stream-delegated.d.ts +3 -1
  183. package/dist/server/rpc/handlers/completion-stream-delegated.js +13 -4
  184. package/dist/server/rpc/handlers/download-asset.js +55 -3
  185. package/dist/server/rpc/handlers/heartbeat-delegated.d.ts +4 -0
  186. package/dist/server/rpc/handlers/heartbeat-delegated.js +32 -0
  187. package/dist/server/rpc/handlers/heartbeat.d.ts +3 -0
  188. package/dist/server/rpc/handlers/heartbeat.js +3 -0
  189. package/dist/server/rpc/handlers/index.d.ts +2 -2
  190. package/dist/server/rpc/handlers/index.js +2 -2
  191. package/dist/server/rpc/handlers/load-model/download-stats.d.ts +6 -0
  192. package/dist/server/rpc/handlers/load-model/download-stats.js +87 -0
  193. package/dist/server/rpc/handlers/load-model/handler.js +108 -123
  194. package/dist/server/rpc/handlers/load-model/http.d.ts +2 -1
  195. package/dist/server/rpc/handlers/load-model/http.js +21 -5
  196. package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +2 -1
  197. package/dist/server/rpc/handlers/load-model/hyperdrive.js +19 -14
  198. package/dist/server/rpc/handlers/load-model/registry.d.ts +2 -1
  199. package/dist/server/rpc/handlers/load-model/registry.js +113 -136
  200. package/dist/server/rpc/handlers/load-model/resolve.d.ts +2 -0
  201. package/dist/server/rpc/handlers/load-model/resolve.js +55 -22
  202. package/dist/server/rpc/handlers/load-model/types.d.ts +29 -0
  203. package/dist/server/rpc/handlers/load-model/types.js +1 -0
  204. package/dist/server/rpc/handlers/load-model-delegated.d.ts +5 -1
  205. package/dist/server/rpc/handlers/load-model-delegated.js +41 -11
  206. package/dist/server/rpc/handlers/plugin-dispatch.js +15 -10
  207. package/dist/server/rpc/handlers/plugin-invoke.js +56 -51
  208. package/dist/server/rpc/handlers/rag.js +24 -0
  209. package/dist/server/rpc/handlers/unload-model-delegated.d.ts +3 -0
  210. package/dist/server/rpc/handlers/unload-model-delegated.js +32 -0
  211. package/dist/server/rpc/profiling/context.d.ts +18 -0
  212. package/dist/server/rpc/profiling/context.js +38 -0
  213. package/dist/server/rpc/profiling/delegation-profiler.d.ts +32 -0
  214. package/dist/server/rpc/profiling/delegation-profiler.js +154 -0
  215. package/dist/server/rpc/profiling/index.d.ts +5 -0
  216. package/dist/server/rpc/profiling/index.js +4 -0
  217. package/dist/server/rpc/profiling/operation-metrics.d.ts +25 -0
  218. package/dist/server/rpc/profiling/operation-metrics.js +199 -0
  219. package/dist/server/rpc/profiling/operation-wrappers.d.ts +18 -0
  220. package/dist/server/rpc/profiling/operation-wrappers.js +124 -0
  221. package/dist/server/rpc/profiling/profiler.d.ts +13 -0
  222. package/dist/server/rpc/profiling/profiler.js +97 -0
  223. package/dist/server/utils/cache.d.ts +2 -1
  224. package/dist/server/utils/cache.js +5 -1
  225. package/dist/server/utils/checksum.d.ts +2 -0
  226. package/dist/server/utils/checksum.js +7 -0
  227. package/dist/server/utils/formatting.d.ts +6 -0
  228. package/dist/server/utils/formatting.js +35 -0
  229. package/dist/server/worker.js +2 -1
  230. package/dist/utils/errors-client.d.ts +3 -0
  231. package/dist/utils/errors-client.js +6 -0
  232. package/dist/utils/errors-server.d.ts +9 -0
  233. package/dist/utils/errors-server.js +15 -0
  234. package/dist/utils/global-singleton.d.ts +2 -0
  235. package/dist/utils/global-singleton.js +10 -0
  236. package/package.json +22 -18
  237. package/dist/client/api/ping.d.ts +0 -11
  238. package/dist/client/api/ping.js +0 -19
  239. package/dist/examples/embed-hyperdrive.d.ts +0 -2
  240. package/dist/examples/llamacpp-hyperdrive.d.ts +0 -2
  241. package/dist/examples/seed-hyperdrive.d.ts +0 -2
  242. package/dist/schemas/ping.d.ts +0 -11
  243. package/dist/schemas/ping.js +0 -8
  244. package/dist/schemas/whispercpp-config.d.ts +0 -70
  245. package/dist/server/bare/plugins/whispercpp-transcription/ops/transcribe-stream.d.ts +0 -3
  246. package/dist/server/bare/plugins/whispercpp-transcription/ops/transcribe-stream.js +0 -81
  247. package/dist/server/rpc/handlers/ping.d.ts +0 -3
  248. package/dist/server/rpc/handlers/ping.js +0 -3
  249. /package/dist/examples/{embed-hyperdrive.js → embed-p2p.js} +0 -0
  250. /package/dist/examples/{llamacpp-hyperdrive.js → llamacpp-p2p.js} +0 -0
  251. /package/dist/examples/{seed-hyperdrive.js → seed-p2p.js} +0 -0
  252. /package/dist/examples/{whispercpp-filesystem.d.ts → transcription/whispercpp-filesystem.d.ts} +0 -0
  253. /package/dist/examples/{whispercpp-filesystem.js → transcription/whispercpp-filesystem.js} +0 -0
  254. /package/dist/examples/{whispercpp-microphone-record.d.ts → transcription/whispercpp-microphone-record.d.ts} +0 -0
  255. /package/dist/examples/{whispercpp-microphone-record.js → transcription/whispercpp-microphone-record.js} +0 -0
  256. /package/dist/examples/{whispercpp-prompt.d.ts → transcription/whispercpp-prompt.d.ts} +0 -0
  257. /package/dist/examples/{whispercpp-prompt.js → transcription/whispercpp-prompt.js} +0 -0
@@ -1,10 +1,9 @@
1
- import fs, { promises as fsPromises } from "bare-fs";
1
+ import { promises as fsPromises } from "bare-fs";
2
2
  import path from "bare-path";
3
- import {} from "bare-stream";
4
3
  import { AbortController } from "bare-abort-controller";
5
- import { getModelsCacheDir, generateShortHash, detectShardedModel, getShardedModelCacheDir, getShardPath, getOnnxModelPath, calculateFileChecksum, extractTensorsFromShards, calculatePercentage, } from "../../../utils/index.js";
4
+ import { getModelsCacheDir, generateShortHash, detectShardedModel, getShardedModelCacheDir, getShardPath, getOnnxModelPath, measureChecksum, extractTensorsFromShards, calculatePercentage, } from "../../../utils/index.js";
6
5
  import { getModelByPath } from "../../../../models/registry/index.js";
7
- import { getRegistryClient, closeRegistryClient, } from "../../../bare/registry/registry-client.js";
6
+ import { getRegistryClient } from "../../../bare/registry/registry-client.js";
8
7
  import { getActiveDownload, registerDownload, unregisterDownload, createRegistryDownloadKey, clearClearCacheFlag, } from "./download-manager.js";
9
8
  import { ChecksumValidationFailedError, DownloadCancelledError, ModelNotFoundError, RegistryDownloadFailedError, } from "../../../../utils/errors-server.js";
10
9
  import { getServerLogger } from "../../../../logging/index.js";
@@ -22,7 +21,7 @@ function buildBlobBinding(meta) {
22
21
  /**
23
22
  * Validate a cached file against expected size and checksum.
24
23
  */
25
- async function validateCachedFile(modelPath, modelFileName, expectedSize, expectedChecksum) {
24
+ async function validateCachedFile(modelPath, modelFileName, expectedSize, expectedChecksum, hooks) {
26
25
  try {
27
26
  await fsPromises.access(modelPath);
28
27
  const localStats = await fsPromises.stat(modelPath);
@@ -31,7 +30,7 @@ async function validateCachedFile(modelPath, modelFileName, expectedSize, expect
31
30
  logger.info(`✅ Model cached with correct size: ${modelPath}`);
32
31
  // Validate checksum if provided
33
32
  if (expectedChecksum && expectedChecksum.length === 64) {
34
- const checksum = await calculateFileChecksum(modelPath);
33
+ const checksum = await measureChecksum(modelPath, hooks);
35
34
  if (checksum !== expectedChecksum) {
36
35
  throw new ChecksumValidationFailedError(`${modelFileName}. Expected: ${expectedChecksum}. Actual: ${checksum}. File may be corrupted`);
37
36
  }
@@ -59,89 +58,65 @@ async function validateCachedFile(modelPath, modelFileName, expectedSize, expect
59
58
  * When blobBinding is provided, uses direct blob download (skips metadata sync).
60
59
  * Otherwise falls back to metadata-based downloadModel.
61
60
  */
62
- async function downloadSingleFileFromRegistry(registryPath, registrySource, modelPath, modelFileName, downloadKey, expectedSize, expectedChecksum, progressCallback, signal, blobBinding) {
61
+ async function downloadSingleFileFromRegistry(registryPath, registrySource, modelPath, modelFileName, downloadKey, expectedSize, expectedChecksum, progressCallback, signal, blobBinding, hooks) {
63
62
  if (signal?.aborted) {
64
63
  throw new DownloadCancelledError();
65
64
  }
66
65
  const client = await getRegistryClient();
67
- try {
68
- let readStream;
69
- if (blobBinding) {
70
- logger.info(`📥 Downloading blob directly: ${modelFileName}`);
71
- const result = await client.downloadBlob(blobBinding, { timeout: REGISTRY_STREAM_TIMEOUT_MS });
72
- if (!("stream" in result.artifact)) {
73
- throw new RegistryDownloadFailedError(`No stream returned for blob ${modelFileName}`);
74
- }
75
- readStream = result.artifact.stream;
76
- }
77
- else {
78
- logger.info(`📥 Downloading from registry: ${registryPath}`);
79
- const result = await client.downloadModel(registryPath, registrySource, {
80
- timeout: REGISTRY_STREAM_TIMEOUT_MS,
81
- });
82
- if (!("stream" in result.artifact)) {
83
- throw new RegistryDownloadFailedError(`No stream returned for ${registryPath}`);
84
- }
85
- readStream = result.artifact.stream;
86
- }
87
- const dir = path.dirname(modelPath);
88
- await fsPromises.mkdir(dir, { recursive: true });
89
- const writeStream = fs.createWriteStream(modelPath);
90
- // Track progress
91
- let downloadedBytes = 0;
92
- readStream.on("data", (chunk) => {
93
- const buffer = chunk;
94
- downloadedBytes += buffer.length;
95
- if (progressCallback) {
96
- progressCallback({
97
- type: "modelProgress",
98
- downloaded: downloadedBytes,
99
- total: expectedSize || downloadedBytes,
100
- percentage: expectedSize
101
- ? calculatePercentage(downloadedBytes, expectedSize)
102
- : 0,
103
- downloadKey,
104
- });
105
- }
106
- });
107
- // Pipe stream to file
108
- readStream.pipe(writeStream);
109
- // Wait for download to complete
110
- await new Promise((resolve, reject) => {
111
- writeStream.on("finish", resolve);
112
- writeStream.on("error", reject);
113
- readStream.on("error", reject);
114
- signal?.addEventListener("abort", () => reject(new Error("Download cancelled")), { once: true });
115
- });
116
- logger.info(`✅ Downloaded to ${modelPath}`);
117
- // Validate file size
118
- const stats = await fsPromises.stat(modelPath);
119
- if (expectedSize && stats.size !== expectedSize) {
120
- await fsPromises.unlink(modelPath).catch(() => { });
121
- throw new ChecksumValidationFailedError(`${modelFileName}. File size mismatch: expected ${expectedSize}, got ${stats.size}`);
122
- }
123
- // Validate checksum
124
- if (expectedChecksum && expectedChecksum.length === 64) {
125
- const checksum = await calculateFileChecksum(modelPath);
126
- if (checksum !== expectedChecksum) {
127
- await fsPromises.unlink(modelPath);
128
- throw new ChecksumValidationFailedError(`${modelFileName}. Expected: ${expectedChecksum}. Actual: ${checksum}`);
129
- }
130
- logger.info(`✅ Checksum validated for ${modelFileName}`);
131
- }
132
- // Send final 100% progress
133
- if (progressCallback) {
66
+ const dir = path.dirname(modelPath);
67
+ await fsPromises.mkdir(dir, { recursive: true });
68
+ // Adapt registry client's core.on("download") progress to SDK ModelProgressUpdate.
69
+ // This reports network-layer bytes, decoupled from disk I/O backpressure.
70
+ const onProgress = progressCallback
71
+ ? (progress) => {
72
+ const total = progress.total || expectedSize || progress.downloaded;
134
73
  progressCallback({
135
74
  type: "modelProgress",
136
- downloaded: stats.size,
137
- total: stats.size,
138
- percentage: 100,
75
+ downloaded: progress.downloaded,
76
+ total,
77
+ percentage: total > 0
78
+ ? calculatePercentage(progress.downloaded, total)
79
+ : 0,
139
80
  downloadKey,
140
81
  });
141
82
  }
83
+ : undefined;
84
+ const clientOptions = {
85
+ timeout: REGISTRY_STREAM_TIMEOUT_MS,
86
+ outputFile: modelPath,
87
+ ...(onProgress && { onProgress }),
88
+ ...(signal && { signal: signal }),
89
+ };
90
+ if (blobBinding) {
91
+ logger.info(`📥 Downloading blob directly: ${modelFileName}`);
92
+ await client.downloadBlob(blobBinding, clientOptions);
93
+ }
94
+ else {
95
+ logger.info(`📥 Downloading from registry: ${registryPath}`);
96
+ await client.downloadModel(registryPath, registrySource, clientOptions);
97
+ }
98
+ logger.info(`✅ Downloaded to ${modelPath}`);
99
+ const stats = await fsPromises.stat(modelPath);
100
+ if (expectedSize && stats.size !== expectedSize) {
101
+ await fsPromises.unlink(modelPath).catch(() => { });
102
+ throw new ChecksumValidationFailedError(`${modelFileName}. File size mismatch: expected ${expectedSize}, got ${stats.size}`);
103
+ }
104
+ if (expectedChecksum && expectedChecksum.length === 64) {
105
+ const checksum = await measureChecksum(modelPath, hooks);
106
+ if (checksum !== expectedChecksum) {
107
+ await fsPromises.unlink(modelPath);
108
+ throw new ChecksumValidationFailedError(`${modelFileName}. Expected: ${expectedChecksum}. Actual: ${checksum}`);
109
+ }
110
+ logger.info(`✅ Checksum validated for ${modelFileName}`);
142
111
  }
143
- finally {
144
- await closeRegistryClient();
112
+ if (progressCallback) {
113
+ progressCallback({
114
+ type: "modelProgress",
115
+ downloaded: stats.size,
116
+ total: stats.size,
117
+ percentage: 100,
118
+ downloadKey,
119
+ });
145
120
  }
146
121
  }
147
122
  /**
@@ -149,53 +124,44 @@ async function downloadSingleFileFromRegistry(registryPath, registrySource, mode
149
124
  */
150
125
  async function findModelShards(registryPath) {
151
126
  const client = await getRegistryClient();
152
- try {
153
- // Extract the base path without the shard suffix
154
- const shardInfo = detectShardedModel(registryPath.split("/").pop() || "");
155
- if (!shardInfo.isSharded) {
156
- throw new Error(`Not a sharded model path: ${registryPath}`);
157
- }
158
- // Get path prefix by removing the shard suffix
159
- const pathPrefix = registryPath.replace(/-\d{5}-of-\d{5}\./, ".");
160
- const basePath = pathPrefix.substring(0, pathPrefix.lastIndexOf("."));
161
- logger.info(`🔍 Finding shards with prefix: ${basePath}`);
162
- // Use indexed path range query instead of fetching all models
163
- const shards = await client.findModels({
164
- gte: { path: basePath },
165
- lte: { path: basePath + "\uffff" },
166
- });
167
- // Sort shards by shard number
168
- const sortedShards = shards
169
- .filter((s) => {
170
- const info = detectShardedModel(s.path.split("/").pop() || "");
171
- return info.isSharded;
172
- })
173
- .sort((a, b) => {
174
- const aInfo = detectShardedModel(a.path.split("/").pop() || "");
175
- const bInfo = detectShardedModel(b.path.split("/").pop() || "");
176
- return (aInfo.currentShard || 0) - (bInfo.currentShard || 0);
177
- })
178
- .map((s) => ({
179
- path: s.path,
180
- source: s.source,
181
- size: s.blobBinding?.byteLength || 0,
182
- checksum: s.blobBinding?.["sha256"] ||
183
- s.sha256 ||
184
- "",
185
- }));
186
- logger.info(`📦 Found ${sortedShards.length} shards`);
187
- return sortedShards;
188
- }
189
- finally {
190
- await closeRegistryClient();
127
+ const shardInfo = detectShardedModel(registryPath.split("/").pop() || "");
128
+ if (!shardInfo.isSharded) {
129
+ throw new Error(`Not a sharded model path: ${registryPath}`);
191
130
  }
131
+ const pathPrefix = registryPath.replace(/-\d{5}-of-\d{5}\./, ".");
132
+ const basePath = pathPrefix.substring(0, pathPrefix.lastIndexOf("."));
133
+ logger.info(`🔍 Finding shards with prefix: ${basePath}`);
134
+ const shards = await client.findModels({
135
+ gte: { path: basePath },
136
+ lte: { path: basePath + "\uffff" },
137
+ });
138
+ const sortedShards = shards
139
+ .filter((s) => {
140
+ const info = detectShardedModel(s.path.split("/").pop() || "");
141
+ return info.isSharded;
142
+ })
143
+ .sort((a, b) => {
144
+ const aInfo = detectShardedModel(a.path.split("/").pop() || "");
145
+ const bInfo = detectShardedModel(b.path.split("/").pop() || "");
146
+ return (aInfo.currentShard || 0) - (bInfo.currentShard || 0);
147
+ })
148
+ .map((s) => ({
149
+ path: s.path,
150
+ source: s.source,
151
+ size: s.blobBinding?.byteLength || 0,
152
+ checksum: s.blobBinding?.["sha256"] ||
153
+ s.sha256 ||
154
+ "",
155
+ }));
156
+ logger.info(`📦 Found ${sortedShards.length} shards`);
157
+ return sortedShards;
192
158
  }
193
159
  /**
194
160
  * Download sharded model files from registry.
195
161
  * When localShardMetadata is provided, uses pre-computed metadata + blob direct download
196
162
  * instead of querying the registry for shard info.
197
163
  */
198
- async function downloadShardedFilesFromRegistry(registryPath, registrySource, cacheKey, progressCallback, signal, localShardMetadata) {
164
+ async function downloadShardedFilesFromRegistry(registryPath, registrySource, cacheKey, progressCallback, signal, localShardMetadata, hooks) {
199
165
  if (signal?.aborted) {
200
166
  throw new DownloadCancelledError();
201
167
  }
@@ -242,7 +208,7 @@ async function downloadShardedFilesFromRegistry(registryPath, registrySource, ca
242
208
  }
243
209
  const shard = shards[i];
244
210
  const shardPath = getShardPath(cacheKey, shard.filename);
245
- const cachedPath = await validateCachedFile(shardPath, shard.filename, shard.size, shard.checksum);
211
+ const cachedPath = await validateCachedFile(shardPath, shard.filename, shard.size, shard.checksum, hooks);
246
212
  if (cachedPath) {
247
213
  logger.debug(`✅ Shard ${i + 1}/${shards.length} already cached`);
248
214
  overallDownloaded += shard.size;
@@ -283,7 +249,7 @@ async function downloadShardedFilesFromRegistry(registryPath, registrySource, ca
283
249
  });
284
250
  }
285
251
  : undefined;
286
- await downloadSingleFileFromRegistry(shard.path, shard.source, shardPath, shard.filename, downloadKey, shard.size, shard.checksum, shardProgressCallback, signal, shard.blobBinding);
252
+ await downloadSingleFileFromRegistry(shard.path, shard.source, shardPath, shard.filename, downloadKey, shard.size, shard.checksum, shardProgressCallback, signal, shard.blobBinding, hooks);
287
253
  overallDownloaded += shard.size;
288
254
  logger.info(`✅ Shard ${i + 1}/${shards.length} downloaded`);
289
255
  }
@@ -324,7 +290,7 @@ function findOnnxCompanionDataFile(registryPath) {
324
290
  * Both files are placed in the same directory to satisfy ONNX Runtime requirements.
325
291
  * When blob bindings are provided, uses direct blob download (skips metadata sync).
326
292
  */
327
- async function downloadOnnxWithDataFromRegistry(registryPath, registrySource, companionDataFile, cacheKey, progressCallback, signal, mainBlobBinding, dataBlobBinding) {
293
+ async function downloadOnnxWithDataFromRegistry(registryPath, registrySource, companionDataFile, cacheKey, progressCallback, signal, mainBlobBinding, dataBlobBinding, hooks) {
328
294
  if (signal?.aborted) {
329
295
  throw new DownloadCancelledError();
330
296
  }
@@ -342,7 +308,7 @@ async function downloadOnnxWithDataFromRegistry(registryPath, registrySource, co
342
308
  const overallTotal = mainExpectedSize + dataExpectedSize;
343
309
  let overallDownloaded = 0;
344
310
  // Check if main file already cached
345
- const cachedMainPath = await validateCachedFile(mainPath, mainFilename, mainExpectedSize, mainChecksum);
311
+ const cachedMainPath = await validateCachedFile(mainPath, mainFilename, mainExpectedSize, mainChecksum, hooks);
346
312
  if (cachedMainPath) {
347
313
  logger.info(`✅ Main ONNX file already cached: ${mainFilename}`);
348
314
  overallDownloaded += mainExpectedSize;
@@ -366,12 +332,12 @@ async function downloadOnnxWithDataFromRegistry(registryPath, registrySource, co
366
332
  });
367
333
  }
368
334
  : undefined;
369
- await downloadSingleFileFromRegistry(registryPath, registrySource, mainPath, mainFilename, downloadKey, mainExpectedSize, mainChecksum, mainProgressCallback, signal, mainBlobBinding);
335
+ await downloadSingleFileFromRegistry(registryPath, registrySource, mainPath, mainFilename, downloadKey, mainExpectedSize, mainChecksum, mainProgressCallback, signal, mainBlobBinding, hooks);
370
336
  overallDownloaded += mainExpectedSize;
371
337
  logger.info(`✅ Main ONNX file downloaded: ${mainFilename}`);
372
338
  }
373
339
  // Check if data file already cached
374
- const cachedDataPath = await validateCachedFile(dataPath, dataFilename, dataExpectedSize, dataChecksum);
340
+ const cachedDataPath = await validateCachedFile(dataPath, dataFilename, dataExpectedSize, dataChecksum, hooks);
375
341
  if (cachedDataPath) {
376
342
  logger.info(`✅ ONNX data file already cached: ${dataFilename}`);
377
343
  overallDownloaded = overallTotal;
@@ -395,7 +361,7 @@ async function downloadOnnxWithDataFromRegistry(registryPath, registrySource, co
395
361
  });
396
362
  }
397
363
  : undefined;
398
- await downloadSingleFileFromRegistry(companionDataFile.registryPath, companionDataFile.registrySource, dataPath, dataFilename, downloadKey, dataExpectedSize, dataChecksum, dataProgressCallback, signal, dataBlobBinding);
364
+ await downloadSingleFileFromRegistry(companionDataFile.registryPath, companionDataFile.registrySource, dataPath, dataFilename, downloadKey, dataExpectedSize, dataChecksum, dataProgressCallback, signal, dataBlobBinding, hooks);
399
365
  logger.info(`✅ ONNX data file downloaded: ${dataFilename}`);
400
366
  }
401
367
  // Send final 100% progress
@@ -451,12 +417,13 @@ function createManagedDownload(downloadKey, registryPath, downloadFn, progressCa
451
417
  * skips the registry metadata sync entirely. Falls back to metadata-based
452
418
  * download for unknown models.
453
419
  */
454
- export async function downloadModelFromRegistry(registryPath, registrySource, progressCallback, expectedChecksum) {
420
+ export async function downloadModelFromRegistry(registryPath, registrySource, progressCallback, expectedChecksum, hooks) {
455
421
  const downloadKey = createRegistryDownloadKey(registryPath);
456
422
  // Check if already downloading
457
423
  const existing = getActiveDownload(downloadKey);
458
424
  if (existing) {
459
425
  logger.info(`📥 Reusing existing download for: ${downloadKey}`);
426
+ hooks?.markCacheMiss();
460
427
  return existing.promise;
461
428
  }
462
429
  const filename = registryPath.split("/").pop() || registryPath;
@@ -471,7 +438,7 @@ export async function downloadModelFromRegistry(registryPath, registrySource, pr
471
438
  let allCached = true;
472
439
  for (const shard of localShardMeta) {
473
440
  const shardPath = getShardPath(cacheKey, shard.filename);
474
- const cached = await validateCachedFile(shardPath, shard.filename, shard.expectedSize, shard.sha256Checksum);
441
+ const cached = await validateCachedFile(shardPath, shard.filename, shard.expectedSize, shard.sha256Checksum, hooks);
475
442
  if (!cached) {
476
443
  allCached = false;
477
444
  break;
@@ -480,6 +447,7 @@ export async function downloadModelFromRegistry(registryPath, registrySource, pr
480
447
  if (allCached) {
481
448
  const firstShardFilename = localShardMeta[0].filename;
482
449
  logger.info(`✅ All ${localShardMeta.length} shards cached`);
450
+ hooks?.markCacheHit();
483
451
  if (progressCallback) {
484
452
  const overallTotal = localShardMeta.reduce((sum, s) => sum + s.expectedSize, 0);
485
453
  progressCallback({
@@ -501,7 +469,8 @@ export async function downloadModelFromRegistry(registryPath, registrySource, pr
501
469
  return getShardPath(cacheKey, firstShardFilename);
502
470
  }
503
471
  }
504
- return createManagedDownload(downloadKey, registryPath, (signal) => downloadShardedFilesFromRegistry(registryPath, registrySource, cacheKey, progressCallback, signal, localShardMeta), progressCallback);
472
+ hooks?.markCacheMiss();
473
+ return createManagedDownload(downloadKey, registryPath, (signal) => downloadShardedFilesFromRegistry(registryPath, registrySource, cacheKey, progressCallback, signal, localShardMeta, hooks), progressCallback);
505
474
  }
506
475
  // Check for ONNX with companion data file
507
476
  const companionDataFile = findOnnxCompanionDataFile(registryPath);
@@ -512,10 +481,11 @@ export async function downloadModelFromRegistry(registryPath, registrySource, pr
512
481
  const dataFilename = companionDataFile.registryPath.split("/").pop() || "";
513
482
  const mainPath = getOnnxModelPath(cacheKey, mainFilename);
514
483
  const dataPath = getOnnxModelPath(cacheKey, dataFilename);
515
- const mainCached = await validateCachedFile(mainPath, mainFilename, modelMetadata?.expectedSize || 0, modelMetadata?.sha256Checksum);
516
- const dataCached = await validateCachedFile(dataPath, dataFilename, companionDataFile.expectedSize, companionDataFile.sha256Checksum);
484
+ const mainCached = await validateCachedFile(mainPath, mainFilename, modelMetadata?.expectedSize || 0, modelMetadata?.sha256Checksum, hooks);
485
+ const dataCached = await validateCachedFile(dataPath, dataFilename, companionDataFile.expectedSize, companionDataFile.sha256Checksum, hooks);
517
486
  if (mainCached && dataCached) {
518
487
  logger.info(`✅ ONNX model and data file both cached`);
488
+ hooks?.markCacheHit();
519
489
  if (progressCallback) {
520
490
  const total = (modelMetadata?.expectedSize || 0) + companionDataFile.expectedSize;
521
491
  progressCallback({
@@ -536,11 +506,14 @@ export async function downloadModelFromRegistry(registryPath, registrySource, pr
536
506
  }
537
507
  return mainCached;
538
508
  }
539
- const mainBlobBinding = modelMetadata ? buildBlobBinding(modelMetadata) : undefined;
509
+ const mainBlobBinding = modelMetadata
510
+ ? buildBlobBinding(modelMetadata)
511
+ : undefined;
540
512
  const dataBlobBinding = companionDataFile.blobCoreKey
541
513
  ? buildBlobBinding(companionDataFile)
542
514
  : undefined;
543
- return createManagedDownload(downloadKey, registryPath, (signal) => downloadOnnxWithDataFromRegistry(registryPath, registrySource, companionDataFile, cacheKey, progressCallback, signal, mainBlobBinding, dataBlobBinding), progressCallback);
515
+ hooks?.markCacheMiss();
516
+ return createManagedDownload(downloadKey, registryPath, (signal) => downloadOnnxWithDataFromRegistry(registryPath, registrySource, companionDataFile, cacheKey, progressCallback, signal, mainBlobBinding, dataBlobBinding, hooks), progressCallback);
544
517
  }
545
518
  // Single file download
546
519
  const cacheDir = getModelsCacheDir();
@@ -549,9 +522,10 @@ export async function downloadModelFromRegistry(registryPath, registrySource, pr
549
522
  // Check if already cached
550
523
  const expectedSize = modelMetadata?.expectedSize || 0;
551
524
  const checksum = expectedChecksum || modelMetadata?.sha256Checksum || "";
552
- const cachedPath = await validateCachedFile(modelPath, filename, expectedSize, checksum);
525
+ const cachedPath = await validateCachedFile(modelPath, filename, expectedSize, checksum, hooks);
553
526
  if (cachedPath) {
554
527
  logger.info(`✅ Using cached model: ${cachedPath}`);
528
+ hooks?.markCacheHit();
555
529
  if (progressCallback) {
556
530
  progressCallback({
557
531
  type: "modelProgress",
@@ -563,9 +537,12 @@ export async function downloadModelFromRegistry(registryPath, registrySource, pr
563
537
  }
564
538
  return cachedPath;
565
539
  }
566
- const blobBinding = modelMetadata ? buildBlobBinding(modelMetadata) : undefined;
540
+ const blobBinding = modelMetadata
541
+ ? buildBlobBinding(modelMetadata)
542
+ : undefined;
543
+ hooks?.markCacheMiss();
567
544
  return createManagedDownload(downloadKey, registryPath, async (signal) => {
568
- await downloadSingleFileFromRegistry(registryPath, registrySource, modelPath, filename, downloadKey, expectedSize, checksum, progressCallback, signal, blobBinding);
545
+ await downloadSingleFileFromRegistry(registryPath, registrySource, modelPath, filename, downloadKey, expectedSize, checksum, progressCallback, signal, blobBinding, hooks);
569
546
  return modelPath;
570
547
  }, progressCallback);
571
548
  }
@@ -1,3 +1,5 @@
1
1
  import { type ModelProgressUpdate } from "../../../../schemas/index";
2
+ import type { ResolveResult } from "./types";
2
3
  export declare function resolveModelPath(modelSrc: unknown, progressCallback?: (progress: ModelProgressUpdate) => void, seed?: boolean): Promise<string>;
4
+ export declare function resolveModelPathWithStats(modelSrc: unknown, progressCallback?: (progress: ModelProgressUpdate) => void, seed?: boolean): Promise<ResolveResult>;
3
5
  //# sourceMappingURL=resolve.d.ts.map
@@ -6,9 +6,11 @@ import path from "bare-path";
6
6
  import { downloadModelFromHttp } from "./http.js";
7
7
  import { downloadModelFromHyperdrive } from "./hyperdrive.js";
8
8
  import { downloadModelFromRegistry } from "./registry.js";
9
+ import { downloadModelFromHttpWithStats, downloadModelFromHyperdriveWithStats, downloadModelFromRegistryWithStats, } from "./download-stats.js";
9
10
  import { ModelLoadFailedError, ModelNotFoundError, SeedingNotSupportedError, } from "../../../../utils/errors-server.js";
10
11
  import { validateAndJoinPath } from "../../../utils/path-security.js";
11
12
  import { getServerLogger } from "../../../../logging/index.js";
13
+ import { modelInputToSrcSchema } from "../../../../schemas/index.js";
12
14
  const logger = getServerLogger();
13
15
  function isArchivePath(filePath) {
14
16
  const filename = path.basename(filePath).toLowerCase();
@@ -61,10 +63,34 @@ async function resolveLocalOrCachedFile(modelIdOrPath) {
61
63
  }
62
64
  }
63
65
  }
64
- import { modelInputToSrcSchema } from "../../../../schemas/index.js";
65
- export async function resolveModelPath(modelSrc, progressCallback, seed) {
66
- // Extract src and validate using Zod schema transform
66
+ function selectDownloaders(mode) {
67
+ if (mode === "stats") {
68
+ return {
69
+ http: downloadModelFromHttpWithStats,
70
+ registry: downloadModelFromRegistryWithStats,
71
+ hyperdrive: downloadModelFromHyperdriveWithStats,
72
+ };
73
+ }
74
+ return {
75
+ http: downloadModelFromHttp,
76
+ registry: downloadModelFromRegistry,
77
+ hyperdrive: downloadModelFromHyperdrive,
78
+ };
79
+ }
80
+ function isDownloadResult(value) {
81
+ return value !== null && typeof value === "object" && "path" in value;
82
+ }
83
+ function buildResult(pathOrResult, sourceType) {
84
+ if (isDownloadResult(pathOrResult)) {
85
+ return pathOrResult.stats
86
+ ? { path: pathOrResult.path, sourceType, downloadStats: pathOrResult.stats }
87
+ : { path: pathOrResult.path, sourceType };
88
+ }
89
+ return { path: pathOrResult, sourceType };
90
+ }
91
+ async function resolveModelPathCore(modelSrc, progressCallback, seed, mode) {
67
92
  const srcString = modelInputToSrcSchema.parse(modelSrc);
93
+ const downloaders = selectDownloaders(mode);
68
94
  // Parse hyperdrive URLs if present
69
95
  let hyperdriveKey;
70
96
  let actualModelSrc = srcString;
@@ -73,50 +99,57 @@ export async function resolveModelPath(modelSrc, progressCallback, seed) {
73
99
  hyperdriveKey = key;
74
100
  actualModelSrc = pathValue;
75
101
  }
76
- // Handle registry:// URLs
102
+ // Registry source
77
103
  if (srcString.startsWith("registry://")) {
78
104
  const { registryPath, registrySource } = registryUrlSchema.parse(srcString);
79
105
  logger.info(`Loading from registry: ${registryPath}`);
80
106
  // Look up model metadata for checksum validation
81
107
  const modelMetadata = getModelByPath(registryPath);
82
108
  const expectedChecksum = modelMetadata?.sha256Checksum;
83
- const actualPath = await downloadModelFromRegistry(registryPath, registrySource, progressCallback, expectedChecksum);
84
- logger.info(`Loaded Model to ${actualPath}`);
85
- return actualPath;
109
+ const result = await downloaders.registry(registryPath, registrySource, progressCallback, expectedChecksum);
110
+ logger.info(`Loaded Model to ${isDownloadResult(result) ? result.path : result}`);
111
+ return buildResult(result, "registry");
86
112
  }
87
- let actualPath;
88
113
  // Validate seeding is only used with hyperdrive models
89
114
  if (seed && !hyperdriveKey) {
90
115
  throw new SeedingNotSupportedError();
91
116
  }
92
- // Check if it's an HTTP/HTTPS URL
117
+ // HTTP source
93
118
  if (actualModelSrc.startsWith("http://") ||
94
119
  actualModelSrc.startsWith("https://")) {
95
120
  logger.info(`Loading from HTTP URL: ${actualModelSrc}`);
96
- actualPath = await downloadModelFromHttp(actualModelSrc, progressCallback);
97
- logger.info(`Loaded Model to ${actualPath}`);
121
+ const result = await downloaders.http(actualModelSrc, progressCallback);
122
+ logger.info(`Loaded Model to ${isDownloadResult(result) ? result.path : result}`);
123
+ return buildResult(result, "http");
98
124
  }
99
- else if (hyperdriveKey) {
100
- // Direct hyperdrive loading
125
+ // Hyperdrive source
126
+ if (hyperdriveKey) {
101
127
  logger.info(`Loading from hyperdrive: ${hyperdriveKey}`);
102
- actualPath = await downloadModelFromHyperdrive(hyperdriveKey, actualModelSrc, seed, progressCallback);
128
+ const result = await downloaders.hyperdrive(hyperdriveKey, actualModelSrc, seed, progressCallback);
129
+ return buildResult(result, "hyperdrive");
103
130
  }
104
- else if (actualModelSrc.includes("/") || actualModelSrc.includes("\\")) {
105
- // Handle file paths (absolute or relative with slashes)
106
- // Check if it's a local archive file
131
+ // Filesystem source (local files, cached files)
132
+ let resolvedPath;
133
+ if (actualModelSrc.includes("/") || actualModelSrc.includes("\\")) {
107
134
  if (isArchivePath(actualModelSrc)) {
108
135
  logger.info(`Extracting local archive: ${actualModelSrc}`);
109
136
  const archiveHash = generateShortHash(actualModelSrc);
110
137
  const extractDir = getShardedModelCacheDir(archiveHash);
111
- actualPath = await extractAndValidateShardedArchive(actualModelSrc, extractDir);
138
+ resolvedPath = await extractAndValidateShardedArchive(actualModelSrc, extractDir);
112
139
  }
113
140
  else {
114
- actualPath = actualModelSrc;
141
+ resolvedPath = actualModelSrc;
115
142
  }
116
143
  }
117
144
  else {
118
- // Handle local files and cached files
119
- actualPath = await resolveLocalOrCachedFile(actualModelSrc);
145
+ resolvedPath = await resolveLocalOrCachedFile(actualModelSrc);
120
146
  }
121
- return actualPath;
147
+ return { path: resolvedPath, sourceType: "filesystem" };
148
+ }
149
+ export async function resolveModelPath(modelSrc, progressCallback, seed) {
150
+ const result = await resolveModelPathCore(modelSrc, progressCallback, seed, "base");
151
+ return result.path;
152
+ }
153
+ export async function resolveModelPathWithStats(modelSrc, progressCallback, seed) {
154
+ return resolveModelPathCore(modelSrc, progressCallback, seed, "stats");
122
155
  }
@@ -0,0 +1,29 @@
1
+ import type { SourceType } from "../../../../schemas/index";
2
+ export interface DownloadStats {
3
+ downloadTimeMs?: number;
4
+ totalBytesDownloaded?: number;
5
+ downloadSpeedBps?: number;
6
+ checksumValidationTimeMs?: number;
7
+ cacheHit?: boolean;
8
+ }
9
+ export interface ResolveResult {
10
+ path: string;
11
+ sourceType: SourceType;
12
+ downloadStats?: DownloadStats;
13
+ }
14
+ export interface DownloadResult {
15
+ path: string;
16
+ stats?: DownloadStats;
17
+ }
18
+ export interface DownloadMetricsHooks {
19
+ markCacheHit: () => void;
20
+ markCacheMiss: () => void;
21
+ addChecksumValidationTimeMs: (durationMs: number) => void;
22
+ }
23
+ export interface LoadModelProfilingMeta {
24
+ sourceType?: string;
25
+ downloadStats?: DownloadStats;
26
+ modelInitializationTimeMs?: number;
27
+ totalLoadTimeMs?: number;
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,7 @@
1
1
  import type { LoadModelSrcRequest, LoadModelResponse, ModelProgressUpdate } from "../../../schemas/index";
2
- export declare function handleLoadModelDelegated(request: LoadModelSrcRequest, progressCallback?: (update: ModelProgressUpdate) => void): Promise<LoadModelResponse>;
2
+ import type { DelegatedHandlerOptions } from "../profiling/index";
3
+ export interface HandleLoadModelDelegatedOptions extends DelegatedHandlerOptions {
4
+ progressCallback?: (update: ModelProgressUpdate) => void;
5
+ }
6
+ export declare function handleLoadModelDelegated(request: LoadModelSrcRequest, options?: HandleLoadModelDelegatedOptions): Promise<LoadModelResponse>;
3
7
  //# sourceMappingURL=load-model-delegated.d.ts.map