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