@qvac/sdk 0.9.1 → 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.
- package/NOTICE +15 -68
- package/dist/client/api/cancel.d.ts +1 -1
- package/dist/client/api/cancel.js +1 -1
- package/dist/client/api/completion-stream.d.ts +51 -12
- package/dist/client/api/completion-stream.js +129 -56
- package/dist/client/api/delete-cache.d.ts +1 -0
- package/dist/client/api/delete-cache.js +1 -0
- package/dist/client/api/diffusion.d.ts +17 -2
- package/dist/client/api/diffusion.js +21 -4
- package/dist/client/api/embed.d.ts +4 -0
- package/dist/client/api/finetune.d.ts +21 -0
- package/dist/client/api/get-loaded-model-info.d.ts +25 -0
- package/dist/client/api/get-loaded-model-info.js +36 -0
- package/dist/client/api/get-model-info.d.ts +9 -1
- package/dist/client/api/get-model-info.js +8 -0
- package/dist/client/api/heartbeat.d.ts +2 -2
- package/dist/client/api/heartbeat.js +2 -2
- package/dist/client/api/index.d.ts +3 -1
- package/dist/client/api/index.js +3 -1
- package/dist/client/api/invoke-plugin.d.ts +16 -0
- package/dist/client/api/invoke-plugin.js +16 -0
- package/dist/client/api/load-model.d.ts +36 -3
- package/dist/client/api/load-model.js +31 -10
- package/dist/client/api/provide.d.ts +11 -5
- package/dist/client/api/provide.js +11 -6
- package/dist/client/api/rag.d.ts +9 -0
- package/dist/client/api/rag.js +9 -0
- package/dist/client/api/registry.d.ts +26 -0
- package/dist/client/api/registry.js +26 -0
- package/dist/client/api/resume.d.ts +20 -4
- package/dist/client/api/resume.js +20 -4
- package/dist/client/api/state.d.ts +23 -0
- package/dist/client/api/state.js +29 -0
- package/dist/client/api/stop-provider.d.ts +11 -5
- package/dist/client/api/stop-provider.js +11 -5
- package/dist/client/api/suspend.d.ts +21 -3
- package/dist/client/api/suspend.js +21 -3
- package/dist/client/api/text-to-speech.d.ts +64 -6
- package/dist/client/api/text-to-speech.js +423 -47
- package/dist/client/api/transcribe.d.ts +29 -4
- package/dist/client/api/transcribe.js +86 -28
- package/dist/client/api/translate.d.ts +1 -0
- package/dist/client/api/translate.js +1 -0
- package/dist/client/rpc/bare-client.js +22 -1
- package/dist/client/rpc/expo-rpc-client.d.ts +1 -1
- package/dist/client/rpc/expo-rpc-client.js +96 -4
- package/dist/client/rpc/node-rpc-client.js +36 -0
- package/dist/examples/audio/mic-input.d.ts +9 -0
- package/dist/examples/audio/mic-input.js +111 -0
- package/dist/examples/completion-events.d.ts +18 -0
- package/dist/examples/completion-events.js +79 -0
- package/dist/examples/delegated-inference/composite.js +12 -18
- package/dist/examples/delegated-inference/consumer-profiled.js +4 -11
- package/dist/examples/delegated-inference/consumer.js +8 -13
- package/dist/examples/delegated-inference/provider.js +11 -16
- package/dist/examples/diffusion-flux2-klein-img2img.d.ts +2 -0
- package/dist/examples/diffusion-flux2-klein-img2img.js +60 -0
- package/dist/examples/diffusion-flux2-klein.js +1 -0
- package/dist/examples/diffusion-img2img.d.ts +2 -0
- package/dist/examples/diffusion-img2img.js +49 -0
- package/dist/examples/diffusion-txt2img.js +2 -1
- package/dist/examples/kv-cache-example.js +11 -12
- package/dist/examples/llamacpp-cache.d.ts +2 -0
- package/dist/examples/llamacpp-cache.js +107 -0
- package/dist/examples/llamacpp-dynamic-tools.d.ts +2 -0
- package/dist/examples/llamacpp-dynamic-tools.js +144 -0
- package/dist/examples/llamacpp-native-tools.js +2 -8
- package/dist/examples/llamacpp-structured-output.d.ts +2 -0
- package/dist/examples/llamacpp-structured-output.js +106 -0
- package/dist/examples/llamacpp-tools-pythonic.d.ts +2 -0
- package/dist/examples/llamacpp-tools-pythonic.js +69 -0
- package/dist/examples/plugins.js +4 -4
- package/dist/examples/suspend-resume.js +21 -4
- package/dist/examples/transcription/parakeet-microphone-record.js +6 -33
- package/dist/examples/transcription/whispercpp-filesystem-streaming.js +7 -5
- package/dist/examples/transcription/whispercpp-filesystem.js +12 -3
- package/dist/examples/transcription/whispercpp-microphone-record.js +6 -29
- package/dist/examples/translation/translation-stream.js +5 -5
- package/dist/examples/tts/llm-to-tts-streaming.d.ts +16 -0
- package/dist/examples/tts/llm-to-tts-streaming.js +143 -0
- package/dist/examples/tts/supertonic-multilingual.js +3 -3
- package/dist/examples/tts/supertonic.js +3 -3
- package/dist/examples/tts/utils.d.ts +11 -1
- package/dist/examples/tts/utils.js +70 -17
- package/dist/examples/voice-assistant/voice-assistant.d.ts +2 -0
- package/dist/examples/voice-assistant/voice-assistant.js +207 -0
- package/dist/expo/plugins/withMobileBundle.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/logging/logger.d.ts +11 -0
- package/dist/logging/logger.js +11 -0
- package/dist/logging/types.d.ts +18 -0
- package/dist/models/registry/models.d.ts +6620 -6185
- package/dist/models/registry/models.js +6296 -5318
- package/dist/models/update-models/codegen.js +84 -23
- package/dist/models/update-models/companions.d.ts +18 -0
- package/dist/models/update-models/companions.js +175 -0
- package/dist/models/update-models/naming.js +0 -25
- package/dist/models/update-models/registry.js +4 -2
- package/dist/models/update-models/types.d.ts +37 -9
- package/dist/profiling/index.d.ts +49 -0
- package/dist/profiling/index.js +49 -0
- package/dist/schemas/cancel.d.ts +6 -2
- package/dist/schemas/cancel.js +14 -7
- package/dist/schemas/common.d.ts +361 -279
- package/dist/schemas/common.js +26 -5
- package/dist/schemas/completion-event.d.ts +225 -0
- package/dist/schemas/completion-event.js +79 -0
- package/dist/schemas/completion-stream.d.ts +122 -31
- package/dist/schemas/completion-stream.js +137 -36
- package/dist/schemas/delegate.d.ts +0 -2
- package/dist/schemas/delegate.js +25 -6
- package/dist/schemas/download-asset.d.ts +5 -5
- package/dist/schemas/embed.js +21 -9
- package/dist/schemas/engine-addon-map.d.ts +11 -1
- package/dist/schemas/engine-addon-map.js +2 -2
- package/dist/schemas/finetune.d.ts +16 -16
- package/dist/schemas/finetune.js +8 -8
- package/dist/schemas/get-loaded-model-info.d.ts +52 -0
- package/dist/schemas/get-loaded-model-info.js +44 -0
- package/dist/schemas/get-model-info.d.ts +2 -2
- package/dist/schemas/get-model-info.js +103 -32
- package/dist/schemas/heartbeat.d.ts +0 -1
- package/dist/schemas/index.d.ts +4 -1
- package/dist/schemas/index.js +4 -1
- package/dist/schemas/llamacpp-config.d.ts +14 -4
- package/dist/schemas/llamacpp-config.js +5 -0
- package/dist/schemas/load-model.d.ts +3233 -1260
- package/dist/schemas/load-model.js +23 -16
- package/dist/schemas/model-src-utils.d.ts +7 -6
- package/dist/schemas/model-src-utils.js +27 -1
- package/dist/schemas/model-types.d.ts +4 -4
- package/dist/schemas/ocr.d.ts +1 -1
- package/dist/schemas/plugin.d.ts +27 -3
- package/dist/schemas/plugin.js +27 -2
- package/dist/schemas/profiling.js +11 -3
- package/dist/schemas/provide.d.ts +1 -3
- package/dist/schemas/provide.js +0 -3
- package/dist/schemas/rag.d.ts +4 -4
- package/dist/schemas/registry.d.ts +10 -10
- package/dist/schemas/registry.js +36 -14
- package/dist/schemas/reload-config.d.ts +73 -7
- package/dist/schemas/sdcpp-config.d.ts +16 -8
- package/dist/schemas/sdcpp-config.js +118 -25
- package/dist/schemas/sdk-config.d.ts +116 -90
- package/dist/schemas/sdk-config.js +16 -0
- package/dist/schemas/sdk-errors-client.d.ts +3 -0
- package/dist/schemas/sdk-errors-client.js +16 -1
- package/dist/schemas/sdk-errors-server.d.ts +3 -0
- package/dist/schemas/sdk-errors-server.js +23 -0
- package/dist/schemas/state.d.ts +23 -0
- package/dist/schemas/state.js +14 -0
- package/dist/schemas/stop-provide.d.ts +0 -5
- package/dist/schemas/stop-provide.js +2 -6
- package/dist/schemas/text-to-speech.d.ts +93 -27
- package/dist/schemas/text-to-speech.js +27 -0
- package/dist/schemas/tools.d.ts +16 -0
- package/dist/schemas/tools.js +15 -0
- package/dist/schemas/transcription-config.d.ts +8 -8
- package/dist/schemas/transcription.d.ts +33 -0
- package/dist/schemas/transcription.js +9 -0
- package/dist/schemas/translate.js +59 -19
- package/dist/schemas/translation-config.d.ts +157 -133
- package/dist/schemas/translation-config.js +34 -11
- package/dist/server/bare/delegate-rpc-client.d.ts +1 -1
- package/dist/server/bare/delegate-rpc-client.js +131 -122
- package/dist/server/bare/hyperswarm.d.ts +2 -2
- package/dist/server/bare/hyperswarm.js +12 -7
- package/dist/server/bare/ops/cancel.js +7 -0
- package/dist/server/bare/ops/kv-cache-utils.d.ts +7 -10
- package/dist/server/bare/ops/kv-cache-utils.js +31 -40
- package/dist/server/bare/ops/load-model.js +0 -1
- package/dist/server/bare/ops/transcribe.d.ts +11 -4
- package/dist/server/bare/ops/transcribe.js +25 -4
- package/dist/server/bare/ops/translate.js +42 -4
- package/dist/server/bare/ops/unload-model.js +21 -19
- package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +1 -2
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +13 -8
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +257 -85
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +101 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +135 -0
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +83 -26
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +57 -32
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -16
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +69 -44
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +113 -94
- package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +1 -1
- package/dist/server/bare/plugins/onnx-ocr/plugin.js +1 -2
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.d.ts +7 -0
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.js +116 -0
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.d.ts +2 -3
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.js +71 -9
- package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +41 -13
- package/dist/server/bare/plugins/onnx-tts/plugin.js +48 -3
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +15 -7
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +5 -6
- package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +6 -0
- package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +8 -5
- package/dist/server/bare/plugins/sdcpp-generation/plugin.js +13 -13
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +17 -1
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +40 -17
- package/dist/server/bare/registry/config-registry.js +14 -3
- package/dist/server/bare/registry/model-registry.d.ts +8 -10
- package/dist/server/bare/registry/model-registry.js +17 -12
- package/dist/server/bare/registry/registry-client.js +79 -19
- package/dist/server/bare/runtime-lifecycle.d.ts +2 -1
- package/dist/server/bare/runtime-lifecycle.js +13 -2
- package/dist/server/bare/types/addon-responses.d.ts +8 -3
- package/dist/server/bare/utils/transcribe-metadata.d.ts +21 -0
- package/dist/server/bare/utils/transcribe-metadata.js +28 -0
- package/dist/server/bare/utils/tts-stats.d.ts +22 -0
- package/dist/server/bare/utils/tts-stats.js +10 -0
- package/dist/server/rpc/create-server.d.ts +4 -1
- package/dist/server/rpc/create-server.js +5 -1
- package/dist/server/rpc/delegate-transport.js +36 -29
- package/dist/server/rpc/handle-request.js +28 -3
- package/dist/server/rpc/handler-registry.js +7 -1
- package/dist/server/rpc/handler-utils.d.ts +5 -0
- package/dist/server/rpc/handler-utils.js +22 -0
- package/dist/server/rpc/handlers/cancel-delegated.js +3 -5
- package/dist/server/rpc/handlers/cancelHandler.js +4 -5
- package/dist/server/rpc/handlers/completion-stream-delegated.js +14 -5
- package/dist/server/rpc/handlers/delete-cache.js +8 -3
- package/dist/server/rpc/handlers/download-asset.js +3 -24
- package/dist/server/rpc/handlers/get-loaded-model-info.d.ts +3 -0
- package/dist/server/rpc/handlers/get-loaded-model-info.js +39 -0
- package/dist/server/rpc/handlers/get-model-info.js +93 -84
- package/dist/server/rpc/handlers/heartbeat-delegated.js +2 -2
- package/dist/server/rpc/handlers/index.d.ts +6 -0
- package/dist/server/rpc/handlers/index.js +6 -0
- package/dist/server/rpc/handlers/load-model/download-manager.d.ts +35 -9
- package/dist/server/rpc/handlers/load-model/download-manager.js +142 -38
- package/dist/server/rpc/handlers/load-model/download-stats.d.ts +5 -4
- package/dist/server/rpc/handlers/load-model/download-stats.js +49 -8
- package/dist/server/rpc/handlers/load-model/handler.js +31 -50
- package/dist/server/rpc/handlers/load-model/http.d.ts +2 -2
- package/dist/server/rpc/handlers/load-model/http.js +97 -142
- package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +2 -2
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +55 -74
- package/dist/server/rpc/handlers/load-model/index.d.ts +0 -1
- package/dist/server/rpc/handlers/load-model/index.js +0 -1
- package/dist/server/rpc/handlers/load-model/registry-client-options.d.ts +27 -0
- package/dist/server/rpc/handlers/load-model/registry-client-options.js +19 -0
- package/dist/server/rpc/handlers/load-model/registry-companion-set.d.ts +22 -0
- package/dist/server/rpc/handlers/load-model/registry-companion-set.js +208 -0
- package/dist/server/rpc/handlers/load-model/registry-download-utils.d.ts +24 -0
- package/dist/server/rpc/handlers/load-model/registry-download-utils.js +114 -0
- package/dist/server/rpc/handlers/load-model/registry.d.ts +2 -20
- package/dist/server/rpc/handlers/load-model/registry.js +109 -381
- package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +15 -0
- package/dist/server/rpc/handlers/load-model/resolve-session.js +61 -0
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -3
- package/dist/server/rpc/handlers/load-model/resolve.js +14 -23
- package/dist/server/rpc/handlers/load-model/types.d.ts +11 -4
- package/dist/server/rpc/handlers/load-model/types.js +28 -1
- package/dist/server/rpc/handlers/load-model-delegated.js +2 -4
- package/dist/server/rpc/handlers/plugin-dispatch.js +9 -5
- package/dist/server/rpc/handlers/plugin-invoke.js +1 -1
- package/dist/server/rpc/handlers/provideHandler/connection.js +13 -2
- package/dist/server/rpc/handlers/provideHandler/handler.js +42 -29
- package/dist/server/rpc/handlers/state.d.ts +3 -0
- package/dist/server/rpc/handlers/state.js +7 -0
- package/dist/server/rpc/handlers/stopProvideHandler.d.ts +2 -2
- package/dist/server/rpc/handlers/stopProvideHandler.js +12 -7
- package/dist/server/rpc/handlers/text-to-speech-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/text-to-speech-stream.js +4 -0
- package/dist/server/rpc/handlers/unload-model-delegated.js +3 -3
- package/dist/server/rpc/profiling/operation-metrics.js +20 -0
- package/dist/server/rpc/rpc-utils.js +1 -1
- package/dist/server/rpc/transport-selector.d.ts +3 -0
- package/dist/server/rpc/transport-selector.js +18 -0
- package/dist/server/utils/cache/auto-history.d.ts +4 -0
- package/dist/server/utils/cache/auto-history.js +22 -0
- package/dist/server/utils/{cache.d.ts → cache/paths.d.ts} +22 -5
- package/dist/server/utils/{cache.js → cache/paths.js} +36 -20
- package/dist/server/utils/cache/types.d.ts +8 -0
- package/dist/server/utils/cache/types.js +1 -0
- package/dist/server/utils/checksum.d.ts +2 -2
- package/dist/server/utils/checksum.js +1 -1
- package/dist/server/utils/clear-storage.d.ts +5 -0
- package/dist/server/utils/clear-storage.js +17 -0
- package/dist/server/utils/completion-normalizer.d.ts +17 -0
- package/dist/server/utils/completion-normalizer.js +301 -0
- package/dist/server/utils/expand-gguf-shards.d.ts +3 -0
- package/dist/server/utils/expand-gguf-shards.js +22 -0
- package/dist/server/utils/formatting.js +1 -1
- package/dist/server/utils/index.d.ts +4 -2
- package/dist/server/utils/index.js +4 -2
- package/dist/server/utils/qvac-paths.d.ts +2 -0
- package/dist/server/utils/qvac-paths.js +5 -0
- package/dist/server/utils/response-format.d.ts +3 -0
- package/dist/server/utils/response-format.js +20 -0
- package/dist/server/utils/tool-integration.d.ts +15 -4
- package/dist/server/utils/tool-integration.js +21 -41
- package/dist/server/utils/tools/dialect.d.ts +8 -0
- package/dist/server/utils/tools/dialect.js +12 -0
- package/dist/server/utils/tools/index.d.ts +3 -0
- package/dist/server/utils/tools/index.js +2 -0
- package/dist/server/utils/tools/parser.d.ts +6 -0
- package/dist/server/utils/tools/parser.js +40 -0
- package/dist/server/utils/tools/parsers/hermes.d.ts +4 -0
- package/dist/server/utils/tools/parsers/hermes.js +100 -0
- package/dist/server/utils/tools/parsers/json.d.ts +6 -0
- package/dist/server/utils/tools/parsers/json.js +115 -0
- package/dist/server/utils/tools/parsers/pythonic.d.ts +4 -0
- package/dist/server/utils/tools/parsers/pythonic.js +267 -0
- package/dist/server/utils/tools/shared.d.ts +18 -0
- package/dist/server/utils/tools/shared.js +54 -0
- package/dist/server/utils/worker-lock.d.ts +3 -0
- package/dist/server/utils/worker-lock.js +67 -0
- package/dist/server/worker-core.d.ts +16 -1
- package/dist/server/worker-core.js +114 -14
- package/dist/utils/aggregate-events.d.ts +16 -0
- package/dist/utils/aggregate-events.js +52 -0
- package/dist/utils/cache-normalize.d.ts +10 -0
- package/dist/utils/cache-normalize.js +23 -0
- package/dist/utils/encoding.d.ts +8 -0
- package/dist/utils/encoding.js +13 -0
- package/dist/utils/errors-client.d.ts +12 -0
- package/dist/utils/errors-client.js +20 -0
- package/dist/utils/errors-server.d.ts +14 -0
- package/dist/utils/errors-server.js +31 -0
- package/dist/utils/load-model-validation.d.ts +7 -0
- package/dist/utils/load-model-validation.js +18 -0
- package/expo/plugins/patches/android-link.mjs +1 -1
- package/expo/plugins/patches/ios-link.mjs +1 -1
- package/package.json +15 -19
- package/dist/examples/translation/translation-opus.d.ts +0 -2
- package/dist/examples/translation/translation-opus.js +0 -33
- package/dist/server/bare/utils/loader-adapter.d.ts +0 -7
- package/dist/server/bare/utils/loader-adapter.js +0 -9
- package/dist/server/utils/model-path.d.ts +0 -5
- package/dist/server/utils/model-path.js +0 -7
- package/dist/server/utils/tool-parser.d.ts +0 -7
- 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
|
|
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.
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 {
|
|
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
|
-
|
|
38
|
+
const session = createResolveSession({
|
|
39
|
+
progressCallback,
|
|
40
|
+
seed,
|
|
41
|
+
profilingEnabled,
|
|
42
|
+
});
|
|
43
|
+
const primaryResolve = session.resolvePrimaryModelPath(modelSrc);
|
|
38
44
|
let resolvedModelPath;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
91
|
-
|
|
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 {
|
|
3
|
-
export declare function downloadModelFromHttp(url: string, progressCallback?: (progress: ModelProgressUpdate) => void, hooks?:
|
|
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 {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
333
|
+
const cachedPath = await validateCachedFile(modelPath, url, ctx.signal);
|
|
342
334
|
if (cachedPath) {
|
|
343
|
-
hooks?.markCacheHit();
|
|
344
|
-
|
|
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(
|
|
371
|
-
|
|
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
|
|
381
|
-
path:
|
|
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
|
|
392
|
-
if (shouldClearCache(
|
|
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
|
-
|
|
414
|
-
|
|
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
|
|
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:
|
|
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,
|
|
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,
|
|
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
|
|
504
|
-
if (shouldClearCache(
|
|
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
|
-
|
|
521
|
-
|
|
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
|
|
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
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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 {
|
|
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?:
|
|
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
|