@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
|
@@ -4,18 +4,17 @@ import Corestore from "corestore";
|
|
|
4
4
|
import Hyperswarm, {} from "hyperswarm";
|
|
5
5
|
import Hyperdrive from "hyperdrive";
|
|
6
6
|
import {} from "bare-stream";
|
|
7
|
-
import {
|
|
8
|
-
import { getEnv } from "../../../env.js";
|
|
7
|
+
import { getQvacPath } from "../../../utils/qvac-paths.js";
|
|
9
8
|
import { getModelsCacheDir, generateShortHash, detectShardedModel, getShardedModelCacheDir, getShardPath, checkShardCompleteness, measureChecksum, extractTensorsFromShards, calculatePercentage, } from "../../../utils/index.js";
|
|
10
9
|
import { getModelBySrc } from "../../../../models/registry/index.js";
|
|
11
|
-
import {
|
|
10
|
+
import { createHyperdriveDownloadKey, startOrJoinDownload, applyJoinedDownloadStats, } from "./download-manager.js";
|
|
12
11
|
import { getSDKConfig } from "../../../bare/registry/config-registry.js";
|
|
13
12
|
import { FileNotFoundError, ChecksumValidationFailedError, DownloadCancelledError, HyperdriveDownloadFailedError, ModelLoadFailedError, NoBlobFoundError, } from "../../../../utils/errors-server.js";
|
|
14
13
|
import { getServerLogger } from "../../../../logging/index.js";
|
|
15
14
|
import { registerSwarm, unregisterSwarm, registerCorestore, unregisterCorestore, } from "../../../bare/runtime-lifecycle.js";
|
|
16
15
|
const logger = getServerLogger();
|
|
17
16
|
function getCorestoreDir(hyperdriveKey) {
|
|
18
|
-
return
|
|
17
|
+
return getQvacPath("corestore", hyperdriveKey);
|
|
19
18
|
}
|
|
20
19
|
async function setupHyperdrive(hyperdriveKey, corestoreDir) {
|
|
21
20
|
const corestore = new Corestore(corestoreDir);
|
|
@@ -185,7 +184,7 @@ async function validateCachedFile(modelPath, modelFileName, expectedSize, expect
|
|
|
185
184
|
return null;
|
|
186
185
|
}
|
|
187
186
|
}
|
|
188
|
-
async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, expectedChecksum, progressCallback, seed, signal, hooks) {
|
|
187
|
+
async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, expectedChecksum, progressCallback, seed, signal, hooks, shouldClearCache) {
|
|
189
188
|
// Check if already aborted
|
|
190
189
|
if (signal?.aborted) {
|
|
191
190
|
throw new DownloadCancelledError();
|
|
@@ -231,8 +230,7 @@ async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdri
|
|
|
231
230
|
}
|
|
232
231
|
catch (error) {
|
|
233
232
|
logger.error("❌ Error during hyperdrive download:", error instanceof Error ? error.message : String(error));
|
|
234
|
-
|
|
235
|
-
if (error instanceof Error && error.message === "Download cancelled") {
|
|
233
|
+
if (error instanceof DownloadCancelledError) {
|
|
236
234
|
throw error;
|
|
237
235
|
}
|
|
238
236
|
throw new HyperdriveDownloadFailedError(`Download failed for ${modelFileName} from hyperdrive: ${hyperdriveKey}`, error);
|
|
@@ -247,16 +245,18 @@ async function downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdri
|
|
|
247
245
|
}
|
|
248
246
|
}
|
|
249
247
|
// Only delete corestore and partial file if user explicitly requested clearCache
|
|
250
|
-
if (signal?.aborted && shouldClearCache(
|
|
248
|
+
if (signal?.aborted && shouldClearCache?.()) {
|
|
251
249
|
try {
|
|
252
250
|
await fsPromises.unlink(modelPath);
|
|
253
251
|
}
|
|
254
|
-
catch {
|
|
255
|
-
|
|
252
|
+
catch (cleanupError) {
|
|
253
|
+
logger.debug("Failed to delete partial model file during cleanup", {
|
|
254
|
+
path: modelPath,
|
|
255
|
+
error: cleanupError,
|
|
256
|
+
});
|
|
256
257
|
}
|
|
257
258
|
await deleteCorestoreDirectory(corestoreDir);
|
|
258
259
|
}
|
|
259
|
-
clearClearCacheFlag(downloadKey);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
async function downloadAndValidateFile(drive, sourceFileName, targetFilePath, expectedSize, expectedChecksum, progressContext, signal, hooks) {
|
|
@@ -321,7 +321,7 @@ async function downloadAndValidateFile(drive, sourceFileName, targetFilePath, ex
|
|
|
321
321
|
writeStream.on("finish", resolve);
|
|
322
322
|
writeStream.on("error", reject);
|
|
323
323
|
readStream.on("error", reject);
|
|
324
|
-
signal?.addEventListener("abort", () => reject(new
|
|
324
|
+
signal?.addEventListener("abort", () => reject(new DownloadCancelledError()), { once: true });
|
|
325
325
|
});
|
|
326
326
|
blobs.core.off("download", progressHandler);
|
|
327
327
|
// Validate file size
|
|
@@ -352,31 +352,7 @@ async function downloadAndValidateFile(drive, sourceFileName, targetFilePath, ex
|
|
|
352
352
|
throw error;
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
|
-
function
|
|
356
|
-
const abortController = new AbortController();
|
|
357
|
-
const downloadPromise = (async () => {
|
|
358
|
-
try {
|
|
359
|
-
return await downloadFn(abortController.signal);
|
|
360
|
-
}
|
|
361
|
-
finally {
|
|
362
|
-
unregisterDownload(downloadKey);
|
|
363
|
-
clearClearCacheFlag(downloadKey);
|
|
364
|
-
}
|
|
365
|
-
})();
|
|
366
|
-
const downloadEntry = {
|
|
367
|
-
key: downloadKey,
|
|
368
|
-
promise: downloadPromise,
|
|
369
|
-
abortController,
|
|
370
|
-
startTime: Date.now(),
|
|
371
|
-
type: "hyperdrive",
|
|
372
|
-
hyperdriveKey,
|
|
373
|
-
modelFileName,
|
|
374
|
-
...(progressCallback && { onProgress: progressCallback }),
|
|
375
|
-
};
|
|
376
|
-
registerDownload(downloadKey, downloadEntry);
|
|
377
|
-
return downloadPromise;
|
|
378
|
-
}
|
|
379
|
-
async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileName, shardMetadata, progressCallback, seed, signal, hooks) {
|
|
355
|
+
async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileName, shardMetadata, progressCallback, seed, signal, hooks, shouldClearCache) {
|
|
380
356
|
if (signal?.aborted) {
|
|
381
357
|
throw new DownloadCancelledError();
|
|
382
358
|
}
|
|
@@ -389,10 +365,10 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
|
|
|
389
365
|
const numberedShardCount = shardInfo.totalShards;
|
|
390
366
|
logger.info(`Downloading sharded model with ${numberedShardCount} numbered shards + ${allFiles.length - numberedShardCount} companion files to ${shardDir}`);
|
|
391
367
|
// Check which files need to be downloaded
|
|
392
|
-
const invalidIndices = await checkShardCompleteness(hyperdriveKey, allFiles, shardMetadata, hooks ? (ms) => hooks.addChecksumValidationTimeMs(ms) : undefined);
|
|
368
|
+
const invalidIndices = await checkShardCompleteness(hyperdriveKey, allFiles, shardMetadata, hooks?.addChecksumValidationTimeMs ? (ms) => hooks.addChecksumValidationTimeMs(ms) : undefined);
|
|
393
369
|
if (invalidIndices.length === 0) {
|
|
394
370
|
logger.info(`✅ All ${allFiles.length} files already downloaded and validated`);
|
|
395
|
-
hooks?.markCacheHit();
|
|
371
|
+
hooks?.markCacheHit?.();
|
|
396
372
|
if (progressCallback) {
|
|
397
373
|
const overallTotal = shardMetadata.reduce((sum, shard) => sum + shard.expectedSize, 0);
|
|
398
374
|
const lastFile = allFiles[allFiles.length - 1];
|
|
@@ -416,7 +392,7 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
|
|
|
416
392
|
return getShardPath(hyperdriveKey, allFiles[0]);
|
|
417
393
|
}
|
|
418
394
|
logger.info(`📥 Need to download ${invalidIndices.length} of ${allFiles.length} files`);
|
|
419
|
-
hooks?.markCacheMiss();
|
|
395
|
+
hooks?.markCacheMiss?.();
|
|
420
396
|
// Setup hyperdrive once for all shards
|
|
421
397
|
const corestoreDir = getCorestoreDir(hyperdriveKey);
|
|
422
398
|
const setup = await setupHyperdrive(hyperdriveKey, corestoreDir);
|
|
@@ -510,7 +486,7 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
|
|
|
510
486
|
catch (error) {
|
|
511
487
|
logger.error("❌ Error during sharded hyperdrive download:", error instanceof Error ? error.message : String(error));
|
|
512
488
|
// Preserve cancellation errors
|
|
513
|
-
if (error instanceof
|
|
489
|
+
if (error instanceof DownloadCancelledError) {
|
|
514
490
|
throw error;
|
|
515
491
|
}
|
|
516
492
|
throw new HyperdriveDownloadFailedError(`Sharded download failed for ${firstShardFileName} from hyperdrive: ${hyperdriveKey}`, error);
|
|
@@ -525,57 +501,62 @@ async function downloadShardedFilesToFilesystem(hyperdriveKey, firstShardFileNam
|
|
|
525
501
|
}
|
|
526
502
|
}
|
|
527
503
|
// Only delete corestore and partial files if user explicitly requested clearCache
|
|
528
|
-
|
|
529
|
-
if (signal?.aborted && shouldClearCache(downloadKey)) {
|
|
504
|
+
if (signal?.aborted && shouldClearCache?.()) {
|
|
530
505
|
await deleteCorestoreDirectory(corestoreDir);
|
|
531
506
|
}
|
|
532
|
-
clearClearCacheFlag(downloadKey);
|
|
533
507
|
}
|
|
534
508
|
return getShardPath(hyperdriveKey, allFiles[0]);
|
|
535
509
|
}
|
|
536
510
|
export async function downloadModelFromHyperdrive(hyperdriveKey, modelFileName, seed, progressCallback, hooks, expectedChecksum) {
|
|
537
511
|
const downloadKey = createHyperdriveDownloadKey(hyperdriveKey, modelFileName);
|
|
538
|
-
|
|
539
|
-
const existing = getActiveDownload(downloadKey);
|
|
540
|
-
if (existing) {
|
|
541
|
-
hooks?.markCacheMiss();
|
|
542
|
-
return existing.promise;
|
|
543
|
-
}
|
|
512
|
+
hooks?.onDownloadKey?.(downloadKey);
|
|
544
513
|
const shardInfo = detectShardedModel(modelFileName);
|
|
545
514
|
const model = getModelBySrc(modelFileName, hyperdriveKey);
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
515
|
+
const result = startOrJoinDownload(downloadKey, async (ctx) => {
|
|
516
|
+
if (shardInfo.isSharded && model?.shardMetadata) {
|
|
517
|
+
const hooksWithCacheHit = {
|
|
518
|
+
...hooks,
|
|
519
|
+
markCacheHit: () => {
|
|
520
|
+
hooks?.markCacheHit?.();
|
|
521
|
+
ctx.setCacheHit(true);
|
|
522
|
+
},
|
|
523
|
+
markCacheMiss: () => {
|
|
524
|
+
hooks?.markCacheMiss?.();
|
|
525
|
+
ctx.setCacheHit(false);
|
|
526
|
+
},
|
|
527
|
+
};
|
|
528
|
+
return downloadShardedFilesToFilesystem(hyperdriveKey, modelFileName, model.shardMetadata, ctx.broadcastProgress, seed, ctx.signal, hooksWithCacheHit, ctx.shouldClearCache);
|
|
529
|
+
}
|
|
530
|
+
// Non-sharded model download
|
|
531
|
+
const corestoreDir = getCorestoreDir(hyperdriveKey);
|
|
532
|
+
const cacheDir = getModelsCacheDir();
|
|
533
|
+
const sourceHash = generateShortHash(`${hyperdriveKey}/${modelFileName}`);
|
|
534
|
+
const modelPath = path.join(cacheDir, `${sourceHash}_${modelFileName}`);
|
|
535
|
+
// First, check if we already have a valid cached file (only if we have model metadata)
|
|
536
|
+
if (model) {
|
|
537
|
+
const cachedPath = await validateCachedFile(modelPath, modelFileName, model.expectedSize, expectedChecksum || model.sha256Checksum, hooks);
|
|
538
|
+
if (cachedPath) {
|
|
539
|
+
hooks?.markCacheHit?.();
|
|
540
|
+
ctx.setCacheHit(true);
|
|
541
|
+
ctx.broadcastProgress({
|
|
561
542
|
type: "modelProgress",
|
|
562
543
|
downloaded: model.expectedSize,
|
|
563
544
|
total: model.expectedSize,
|
|
564
545
|
percentage: 100,
|
|
565
546
|
downloadKey,
|
|
566
547
|
});
|
|
548
|
+
// Delete any leftover corestore directory from previous runs (only when not seeding)
|
|
549
|
+
if (!seed) {
|
|
550
|
+
await deleteCorestoreDirectory(corestoreDir);
|
|
551
|
+
}
|
|
552
|
+
return cachedPath;
|
|
567
553
|
}
|
|
568
|
-
// Delete any leftover corestore directory from previous runs (only when not seeding)
|
|
569
|
-
if (!seed) {
|
|
570
|
-
await deleteCorestoreDirectory(corestoreDir);
|
|
571
|
-
}
|
|
572
|
-
return cachedPath;
|
|
573
554
|
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
return createManagedDownload(downloadKey, hyperdriveKey, modelFileName, async (signal) => {
|
|
555
|
+
hooks?.markCacheMiss?.();
|
|
556
|
+
ctx.setCacheHit(false);
|
|
577
557
|
const checksumToValidate = expectedChecksum || model?.sha256Checksum || "";
|
|
578
|
-
await downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, checksumToValidate,
|
|
558
|
+
await downloadSingleFileToFilesystem(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, checksumToValidate, ctx.broadcastProgress, seed, ctx.signal, hooks, ctx.shouldClearCache);
|
|
579
559
|
return modelPath;
|
|
580
560
|
}, progressCallback);
|
|
561
|
+
return applyJoinedDownloadStats(result, hooks);
|
|
581
562
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { QvacConfig } from "../../../../schemas/index";
|
|
2
|
+
export declare const DEFAULT_REGISTRY_STREAM_TIMEOUT_MS = 60000;
|
|
3
|
+
export interface RegistryClientDownloadOptions {
|
|
4
|
+
timeout: number;
|
|
5
|
+
outputFile: string;
|
|
6
|
+
maxRetries?: number;
|
|
7
|
+
onProgress?: (progress: {
|
|
8
|
+
downloaded: number;
|
|
9
|
+
total: number;
|
|
10
|
+
}) => void;
|
|
11
|
+
signal?: globalThis.AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build the options passed to @qvac/registry-client download methods from the
|
|
15
|
+
* current SDK config. Pure helper (no bare-* imports) so the mapping can be
|
|
16
|
+
* unit-tested without standing up a real registry client.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildRegistryClientOptions(params: {
|
|
19
|
+
sdkConfig: Pick<QvacConfig, "registryStreamTimeoutMs" | "registryDownloadMaxRetries">;
|
|
20
|
+
outputFile: string;
|
|
21
|
+
onProgress?: ((progress: {
|
|
22
|
+
downloaded: number;
|
|
23
|
+
total: number;
|
|
24
|
+
}) => void) | undefined;
|
|
25
|
+
signal?: globalThis.AbortSignal | undefined;
|
|
26
|
+
}): RegistryClientDownloadOptions;
|
|
27
|
+
//# sourceMappingURL=registry-client-options.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const DEFAULT_REGISTRY_STREAM_TIMEOUT_MS = 60_000;
|
|
2
|
+
/**
|
|
3
|
+
* Build the options passed to @qvac/registry-client download methods from the
|
|
4
|
+
* current SDK config. Pure helper (no bare-* imports) so the mapping can be
|
|
5
|
+
* unit-tested without standing up a real registry client.
|
|
6
|
+
*/
|
|
7
|
+
export function buildRegistryClientOptions(params) {
|
|
8
|
+
const { sdkConfig, outputFile, onProgress, signal } = params;
|
|
9
|
+
const timeout = sdkConfig.registryStreamTimeoutMs
|
|
10
|
+
?? DEFAULT_REGISTRY_STREAM_TIMEOUT_MS;
|
|
11
|
+
const maxRetries = sdkConfig.registryDownloadMaxRetries;
|
|
12
|
+
return {
|
|
13
|
+
timeout,
|
|
14
|
+
outputFile,
|
|
15
|
+
...(maxRetries !== undefined && { maxRetries }),
|
|
16
|
+
...(onProgress && { onProgress }),
|
|
17
|
+
...(signal && { signal: signal }),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ModelProgressUpdate } from "../../../../schemas/index";
|
|
2
|
+
import type { RegistryItem } from "../../../../models/registry/index";
|
|
3
|
+
import type { AbortSignal } from "bare-abort-controller";
|
|
4
|
+
import type { DownloadHooks } from "./types";
|
|
5
|
+
type CompanionSetMetadata = NonNullable<RegistryItem["companionSet"]>;
|
|
6
|
+
export interface DownloadCompanionSetOptions {
|
|
7
|
+
companionSet: CompanionSetMetadata;
|
|
8
|
+
downloadKey: string;
|
|
9
|
+
progressCallback?: ((progress: ModelProgressUpdate) => void) | undefined;
|
|
10
|
+
signal?: AbortSignal | undefined;
|
|
11
|
+
hooks?: DownloadHooks | undefined;
|
|
12
|
+
shouldClearCache?: (() => boolean) | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Download a companion set from the registry, placing files directly
|
|
16
|
+
* into their canonical layout at `sets/<setKey>/<targetName>`.
|
|
17
|
+
*
|
|
18
|
+
* Returns the path to the primary file.
|
|
19
|
+
*/
|
|
20
|
+
export declare function downloadCompanionSetFromRegistry(options: DownloadCompanionSetOptions): Promise<string>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=registry-companion-set.d.ts.map
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { promises as fsPromises } from "bare-fs";
|
|
2
|
+
import { getModelsCacheDir, getCompanionSetPath, getCompanionSetCacheDir, getSingleFileCachePath, generateShortHash, calculatePercentage, } from "../../../utils/index.js";
|
|
3
|
+
import { measureChecksum } from "../../../utils/checksum.js";
|
|
4
|
+
import { validateAndJoinPath } from "../../../utils/path-security.js";
|
|
5
|
+
import { buildBlobBinding, downloadSingleFileFromRegistry, validateCachedFile, } from "./registry-download-utils.js";
|
|
6
|
+
import { DownloadCancelledError, RegistryDownloadFailedError, } from "../../../../utils/errors-server.js";
|
|
7
|
+
import { getServerLogger } from "../../../../logging/index.js";
|
|
8
|
+
const logger = getServerLogger();
|
|
9
|
+
/**
|
|
10
|
+
* Download a companion set from the registry, placing files directly
|
|
11
|
+
* into their canonical layout at `sets/<setKey>/<targetName>`.
|
|
12
|
+
*
|
|
13
|
+
* Returns the path to the primary file.
|
|
14
|
+
*/
|
|
15
|
+
export async function downloadCompanionSetFromRegistry(options) {
|
|
16
|
+
const { companionSet, downloadKey, progressCallback, signal, hooks, shouldClearCache, } = options;
|
|
17
|
+
const { files, setKey, primaryKey } = companionSet;
|
|
18
|
+
validateCompanionSetMetadata(files, primaryKey);
|
|
19
|
+
const primaryEntry = files.find((f) => f.key === primaryKey);
|
|
20
|
+
const primaryRegistryPath = primaryEntry.registryPath;
|
|
21
|
+
if (isLegacyOnnxSet(files)) {
|
|
22
|
+
const legacyPath = await checkLegacyOnnxCache(primaryRegistryPath, files, hooks);
|
|
23
|
+
if (legacyPath) {
|
|
24
|
+
logger.info(`✅ Using legacy ONNX cache for companion set: ${legacyPath}`);
|
|
25
|
+
hooks?.markCacheHit?.();
|
|
26
|
+
emitFinalProgress(progressCallback, downloadKey, setKey, files);
|
|
27
|
+
return legacyPath;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Legacy flat-cache compatibility for Bergamot-style companion sets.
|
|
31
|
+
// This is valid only for families whose runtime still works with explicit
|
|
32
|
+
// per-file absolute paths; it is not a generic rule for all companion sets.
|
|
33
|
+
if (!isLegacyOnnxSet(files)) {
|
|
34
|
+
const flatPath = await checkLegacyFlatCache(files, primaryKey, hooks);
|
|
35
|
+
if (flatPath) {
|
|
36
|
+
logger.info(`✅ Using legacy flat cache for companion set: ${flatPath}`);
|
|
37
|
+
hooks?.markCacheHit?.();
|
|
38
|
+
emitFinalProgress(progressCallback, downloadKey, setKey, files);
|
|
39
|
+
return flatPath;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Check canonical companion set cache
|
|
43
|
+
const validatedFiles = new Set();
|
|
44
|
+
for (const file of files) {
|
|
45
|
+
const filePath = getCompanionSetPath(setKey, file.targetName);
|
|
46
|
+
const cached = await validateCachedFile(filePath, file.targetName, file.expectedSize, file.sha256Checksum, hooks);
|
|
47
|
+
if (cached) {
|
|
48
|
+
validatedFiles.add(file.key);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (validatedFiles.size === files.length) {
|
|
52
|
+
logger.info(`✅ All companion set files cached`);
|
|
53
|
+
hooks?.markCacheHit?.();
|
|
54
|
+
emitFinalProgress(progressCallback, downloadKey, setKey, files);
|
|
55
|
+
return getCompanionSetPath(setKey, primaryEntry.targetName);
|
|
56
|
+
}
|
|
57
|
+
// Download missing files
|
|
58
|
+
hooks?.markCacheMiss?.();
|
|
59
|
+
const overallTotal = files.reduce((sum, f) => sum + f.expectedSize, 0);
|
|
60
|
+
let overallDownloaded = 0;
|
|
61
|
+
try {
|
|
62
|
+
for (let i = 0; i < files.length; i++) {
|
|
63
|
+
const file = files[i];
|
|
64
|
+
const filePath = getCompanionSetPath(setKey, file.targetName);
|
|
65
|
+
if (validatedFiles.has(file.key)) {
|
|
66
|
+
overallDownloaded += file.expectedSize;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const fileProgressCallback = progressCallback
|
|
70
|
+
? (progress) => {
|
|
71
|
+
const currentOverall = overallDownloaded + progress.downloaded;
|
|
72
|
+
progressCallback({
|
|
73
|
+
...progress,
|
|
74
|
+
downloadKey,
|
|
75
|
+
fileSetInfo: {
|
|
76
|
+
setKey,
|
|
77
|
+
currentFile: file.targetName,
|
|
78
|
+
fileIndex: i + 1,
|
|
79
|
+
totalFiles: files.length,
|
|
80
|
+
overallDownloaded: currentOverall,
|
|
81
|
+
overallTotal,
|
|
82
|
+
overallPercentage: calculatePercentage(currentOverall, overallTotal),
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
: undefined;
|
|
87
|
+
const blobBinding = file.blobCoreKey
|
|
88
|
+
? buildBlobBinding(file)
|
|
89
|
+
: undefined;
|
|
90
|
+
await downloadSingleFileFromRegistry(file.registryPath, file.registrySource, filePath, file.targetName, downloadKey, file.expectedSize, file.sha256Checksum, fileProgressCallback, signal, blobBinding, hooks);
|
|
91
|
+
overallDownloaded += file.expectedSize;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof DownloadCancelledError && shouldClearCache?.()) {
|
|
96
|
+
try {
|
|
97
|
+
await fsPromises.rm(getCompanionSetCacheDir(setKey), {
|
|
98
|
+
recursive: true,
|
|
99
|
+
force: true,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (cleanupError) {
|
|
103
|
+
logger.debug("Failed to delete companion set cache during cleanup", {
|
|
104
|
+
setKey,
|
|
105
|
+
error: cleanupError,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
emitFinalProgress(progressCallback, downloadKey, setKey, files);
|
|
112
|
+
return getCompanionSetPath(setKey, primaryEntry.targetName);
|
|
113
|
+
}
|
|
114
|
+
function emitFinalProgress(progressCallback, downloadKey, setKey, files) {
|
|
115
|
+
if (!progressCallback)
|
|
116
|
+
return;
|
|
117
|
+
const overallTotal = files.reduce((sum, f) => sum + f.expectedSize, 0);
|
|
118
|
+
const lastFile = files[files.length - 1];
|
|
119
|
+
progressCallback({
|
|
120
|
+
type: "modelProgress",
|
|
121
|
+
downloaded: overallTotal,
|
|
122
|
+
total: overallTotal,
|
|
123
|
+
percentage: 100,
|
|
124
|
+
downloadKey,
|
|
125
|
+
fileSetInfo: {
|
|
126
|
+
setKey,
|
|
127
|
+
currentFile: lastFile.targetName,
|
|
128
|
+
fileIndex: files.length,
|
|
129
|
+
totalFiles: files.length,
|
|
130
|
+
overallDownloaded: overallTotal,
|
|
131
|
+
overallTotal,
|
|
132
|
+
overallPercentage: 100,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function validateCompanionSetMetadata(files, primaryKey) {
|
|
137
|
+
if (!files.some((f) => f.key === primaryKey)) {
|
|
138
|
+
throw new RegistryDownloadFailedError(`Companion set missing primary file (key: ${primaryKey})`);
|
|
139
|
+
}
|
|
140
|
+
const targetNames = new Set();
|
|
141
|
+
for (const file of files) {
|
|
142
|
+
if (targetNames.has(file.targetName)) {
|
|
143
|
+
throw new RegistryDownloadFailedError(`Companion set has duplicate targetName "${file.targetName}"`);
|
|
144
|
+
}
|
|
145
|
+
targetNames.add(file.targetName);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function isLegacyOnnxSet(files) {
|
|
149
|
+
return files.some((f) => f.primary === true && f.targetName.endsWith(".onnx"));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Check if a complete legacy ONNX cache exists for a companion set.
|
|
153
|
+
* Read-only probe: does not create legacy cache directories.
|
|
154
|
+
*/
|
|
155
|
+
async function checkLegacyOnnxCache(primaryRegistryPath, files, hooks) {
|
|
156
|
+
const cacheKey = generateShortHash(primaryRegistryPath);
|
|
157
|
+
let primaryPath = null;
|
|
158
|
+
for (const file of files) {
|
|
159
|
+
const filePath = getLegacyOnnxPath(cacheKey, file.targetName);
|
|
160
|
+
try {
|
|
161
|
+
const stats = await fsPromises.stat(filePath);
|
|
162
|
+
if (stats.size !== file.expectedSize)
|
|
163
|
+
return null;
|
|
164
|
+
if (file.sha256Checksum && file.sha256Checksum.length === 64) {
|
|
165
|
+
const checksum = await measureChecksum(filePath, hooks);
|
|
166
|
+
if (checksum !== file.sha256Checksum)
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
if (file.primary === true) {
|
|
174
|
+
primaryPath = filePath;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return primaryPath;
|
|
178
|
+
}
|
|
179
|
+
function getLegacyOnnxPath(cacheKey, filename) {
|
|
180
|
+
const baseCache = getModelsCacheDir();
|
|
181
|
+
return validateAndJoinPath(baseCache, "onnx", cacheKey, filename);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Check if all companion files exist in the flat single-file cache.
|
|
185
|
+
*/
|
|
186
|
+
async function checkLegacyFlatCache(files, primaryKey, hooks) {
|
|
187
|
+
let primaryPath = null;
|
|
188
|
+
for (const file of files) {
|
|
189
|
+
const flatPath = getSingleFileCachePath(file.registryPath);
|
|
190
|
+
try {
|
|
191
|
+
const stats = await fsPromises.stat(flatPath);
|
|
192
|
+
if (stats.size !== file.expectedSize)
|
|
193
|
+
return null;
|
|
194
|
+
if (file.sha256Checksum && file.sha256Checksum.length === 64) {
|
|
195
|
+
const checksum = await measureChecksum(flatPath, hooks);
|
|
196
|
+
if (checksum !== file.sha256Checksum)
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
if (file.key === primaryKey) {
|
|
204
|
+
primaryPath = flatPath;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return primaryPath;
|
|
208
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ModelProgressUpdate } from "../../../../schemas/index";
|
|
2
|
+
import type { QVACBlobBinding } from "@qvac/registry-client";
|
|
3
|
+
import type { AbortSignal } from "bare-abort-controller";
|
|
4
|
+
import type { DownloadHooks } from "./types";
|
|
5
|
+
export { DEFAULT_REGISTRY_STREAM_TIMEOUT_MS, buildRegistryClientOptions, } from "./registry-client-options";
|
|
6
|
+
export type { RegistryClientDownloadOptions } from "./registry-client-options";
|
|
7
|
+
export declare function buildBlobBinding(meta: {
|
|
8
|
+
blobCoreKey: string;
|
|
9
|
+
blobBlockOffset: number;
|
|
10
|
+
blobBlockLength: number;
|
|
11
|
+
blobByteOffset: number;
|
|
12
|
+
expectedSize: number;
|
|
13
|
+
}): QVACBlobBinding;
|
|
14
|
+
/**
|
|
15
|
+
* Validate a cached file against expected size and checksum.
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateCachedFile(modelPath: string, modelFileName: string, expectedSize: number, expectedChecksum?: string, hooks?: DownloadHooks): Promise<string | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Download a single file from the registry to filesystem.
|
|
20
|
+
* When blobBinding is provided, uses direct blob download (skips metadata sync).
|
|
21
|
+
* Otherwise falls back to metadata-based downloadModel.
|
|
22
|
+
*/
|
|
23
|
+
export declare function downloadSingleFileFromRegistry(registryPath: string, registrySource: string, modelPath: string, modelFileName: string, downloadKey: string, expectedSize: number, expectedChecksum: string, progressCallback?: (progress: ModelProgressUpdate) => void, signal?: AbortSignal, blobBinding?: QVACBlobBinding, hooks?: DownloadHooks): Promise<void>;
|
|
24
|
+
//# sourceMappingURL=registry-download-utils.d.ts.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { promises as fsPromises } from "bare-fs";
|
|
2
|
+
import path from "bare-path";
|
|
3
|
+
import { measureChecksum, calculatePercentage, } from "../../../utils/index.js";
|
|
4
|
+
import { getRegistryClient } from "../../../bare/registry/registry-client.js";
|
|
5
|
+
import { getSDKConfig } from "../../../bare/registry/config-registry.js";
|
|
6
|
+
import { buildRegistryClientOptions } from "./registry-client-options.js";
|
|
7
|
+
import { ChecksumValidationFailedError, DownloadCancelledError, } from "../../../../utils/errors-server.js";
|
|
8
|
+
import { getServerLogger } from "../../../../logging/index.js";
|
|
9
|
+
const logger = getServerLogger();
|
|
10
|
+
export { DEFAULT_REGISTRY_STREAM_TIMEOUT_MS, buildRegistryClientOptions, } from "./registry-client-options.js";
|
|
11
|
+
export function buildBlobBinding(meta) {
|
|
12
|
+
return {
|
|
13
|
+
coreKey: meta.blobCoreKey,
|
|
14
|
+
blockOffset: meta.blobBlockOffset,
|
|
15
|
+
blockLength: meta.blobBlockLength,
|
|
16
|
+
byteOffset: meta.blobByteOffset,
|
|
17
|
+
byteLength: meta.expectedSize,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate a cached file against expected size and checksum.
|
|
22
|
+
*/
|
|
23
|
+
export async function validateCachedFile(modelPath, modelFileName, expectedSize, expectedChecksum, hooks) {
|
|
24
|
+
try {
|
|
25
|
+
await fsPromises.access(modelPath);
|
|
26
|
+
const localStats = await fsPromises.stat(modelPath);
|
|
27
|
+
const localSize = localStats.size;
|
|
28
|
+
if (localSize === expectedSize) {
|
|
29
|
+
logger.info(`✅ Model cached with correct size: ${modelPath}`);
|
|
30
|
+
if (expectedChecksum && expectedChecksum.length === 64) {
|
|
31
|
+
const checksum = await measureChecksum(modelPath, hooks);
|
|
32
|
+
if (checksum !== expectedChecksum) {
|
|
33
|
+
throw new ChecksumValidationFailedError(`${modelFileName}. Expected: ${expectedChecksum}. Actual: ${checksum}. File may be corrupted`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
logger.info(`✅ Model already cached and validated: ${modelPath}`);
|
|
37
|
+
return modelPath;
|
|
38
|
+
}
|
|
39
|
+
logger.warn(`🗑️ Removing incomplete cached file (expected ${expectedSize}, got ${localSize}): ${modelPath}`);
|
|
40
|
+
await fsPromises.unlink(modelPath);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error instanceof ChecksumValidationFailedError) {
|
|
45
|
+
logger.warn(`🗑️ Removing corrupted cached file: ${modelPath}`);
|
|
46
|
+
await fsPromises.unlink(modelPath).catch(() => { });
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Download a single file from the registry to filesystem.
|
|
53
|
+
* When blobBinding is provided, uses direct blob download (skips metadata sync).
|
|
54
|
+
* Otherwise falls back to metadata-based downloadModel.
|
|
55
|
+
*/
|
|
56
|
+
export async function downloadSingleFileFromRegistry(registryPath, registrySource, modelPath, modelFileName, downloadKey, expectedSize, expectedChecksum, progressCallback, signal, blobBinding, hooks) {
|
|
57
|
+
if (signal?.aborted) {
|
|
58
|
+
throw new DownloadCancelledError();
|
|
59
|
+
}
|
|
60
|
+
const client = await getRegistryClient();
|
|
61
|
+
const dir = path.dirname(modelPath);
|
|
62
|
+
await fsPromises.mkdir(dir, { recursive: true });
|
|
63
|
+
const onProgress = progressCallback
|
|
64
|
+
? (progress) => {
|
|
65
|
+
const total = progress.total || expectedSize || progress.downloaded;
|
|
66
|
+
progressCallback({
|
|
67
|
+
type: "modelProgress",
|
|
68
|
+
downloaded: progress.downloaded,
|
|
69
|
+
total,
|
|
70
|
+
percentage: total > 0
|
|
71
|
+
? calculatePercentage(progress.downloaded, total)
|
|
72
|
+
: 0,
|
|
73
|
+
downloadKey,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
: undefined;
|
|
77
|
+
const clientOptions = buildRegistryClientOptions({
|
|
78
|
+
sdkConfig: getSDKConfig(),
|
|
79
|
+
outputFile: modelPath,
|
|
80
|
+
onProgress,
|
|
81
|
+
signal,
|
|
82
|
+
});
|
|
83
|
+
if (blobBinding) {
|
|
84
|
+
logger.info(`📥 Downloading blob directly: ${modelFileName}`);
|
|
85
|
+
await client.downloadBlob(blobBinding, clientOptions);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
logger.info(`📥 Downloading from registry: ${registryPath}`);
|
|
89
|
+
await client.downloadModel(registryPath, registrySource, clientOptions);
|
|
90
|
+
}
|
|
91
|
+
logger.info(`✅ Downloaded to ${modelPath}`);
|
|
92
|
+
const stats = await fsPromises.stat(modelPath);
|
|
93
|
+
if (expectedSize && stats.size !== expectedSize) {
|
|
94
|
+
await fsPromises.unlink(modelPath).catch(() => { });
|
|
95
|
+
throw new ChecksumValidationFailedError(`${modelFileName}. File size mismatch: expected ${expectedSize}, got ${stats.size}`);
|
|
96
|
+
}
|
|
97
|
+
if (expectedChecksum && expectedChecksum.length === 64) {
|
|
98
|
+
const checksum = await measureChecksum(modelPath, hooks);
|
|
99
|
+
if (checksum !== expectedChecksum) {
|
|
100
|
+
await fsPromises.unlink(modelPath);
|
|
101
|
+
throw new ChecksumValidationFailedError(`${modelFileName}. Expected: ${expectedChecksum}. Actual: ${checksum}`);
|
|
102
|
+
}
|
|
103
|
+
logger.info(`✅ Checksum validated for ${modelFileName}`);
|
|
104
|
+
}
|
|
105
|
+
if (progressCallback) {
|
|
106
|
+
progressCallback({
|
|
107
|
+
type: "modelProgress",
|
|
108
|
+
downloaded: stats.size,
|
|
109
|
+
total: stats.size,
|
|
110
|
+
percentage: 100,
|
|
111
|
+
downloadKey,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|