@plasius/gpu-model-runtime 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,530 @@
1
+ // src/cache.ts
2
+ var MemoryModelCache = class {
3
+ entries = /* @__PURE__ */ new Map();
4
+ async get(key) {
5
+ return this.entries.get(key);
6
+ }
7
+ async set(key, value) {
8
+ this.entries.set(key, value);
9
+ }
10
+ async delete(key) {
11
+ return this.entries.delete(key);
12
+ }
13
+ async clear() {
14
+ this.entries.clear();
15
+ }
16
+ };
17
+ function stableValue(value) {
18
+ if (Array.isArray(value)) {
19
+ return value.map(stableValue);
20
+ }
21
+ if (value !== null && typeof value === "object") {
22
+ return Object.fromEntries(
23
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, stableValue(entry)])
24
+ );
25
+ }
26
+ return value;
27
+ }
28
+ function createModelCacheKey(contentHash, formatId, adapterOptions) {
29
+ return `${formatId}:${contentHash}:${JSON.stringify(stableValue(adapterOptions ?? null))}`;
30
+ }
31
+
32
+ // src/fetch.ts
33
+ var DEFAULT_POLICY = {
34
+ maxAttempts: 3,
35
+ baseDelayMs: 100,
36
+ maxDelayMs: 1e3,
37
+ timeoutMs: 3e4
38
+ };
39
+ var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
40
+ var NonRetryableResourceError = class extends Error {
41
+ };
42
+ function defaultSleep(milliseconds, signal) {
43
+ return new Promise((resolve, reject) => {
44
+ if (signal?.aborted) {
45
+ reject(createAbortError());
46
+ return;
47
+ }
48
+ const timer = setTimeout(resolve, milliseconds);
49
+ signal?.addEventListener("abort", () => {
50
+ clearTimeout(timer);
51
+ reject(createAbortError());
52
+ }, { once: true });
53
+ });
54
+ }
55
+ async function sha256Hex(bytes) {
56
+ if (!globalThis.crypto?.subtle) {
57
+ throw new Error("SHA-256 integrity checks require Web Crypto support or an injected hashBytes dependency");
58
+ }
59
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
60
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
61
+ }
62
+ async function fetchResource(url, options) {
63
+ const policy = { ...DEFAULT_POLICY, ...options.policy };
64
+ const headers = new Headers(options.headers);
65
+ if (options.resolveOptions?.range) {
66
+ const { start, end } = options.resolveOptions.range;
67
+ headers.set("Range", `bytes=${start}-${end ?? ""}`);
68
+ }
69
+ let lastError;
70
+ for (let attempt = 1; attempt <= policy.maxAttempts; attempt += 1) {
71
+ const controller = createRequestController(options.resolveOptions?.signal, policy.timeoutMs);
72
+ try {
73
+ const response = await options.fetch(url, {
74
+ headers,
75
+ signal: controller.signal
76
+ });
77
+ if (!response.ok) {
78
+ if (!RETRYABLE_STATUSES.has(response.status)) {
79
+ throw new NonRetryableResourceError(`Model resource request failed with HTTP ${response.status}`);
80
+ }
81
+ if (attempt === policy.maxAttempts) {
82
+ throw new NonRetryableResourceError(`Model resource request failed with HTTP ${response.status}`);
83
+ }
84
+ lastError = new Error(`Retryable model resource response: HTTP ${response.status}`);
85
+ await waitForRetry(options.sleep, attempt, policy, options.resolveOptions?.signal);
86
+ continue;
87
+ }
88
+ const bytes = new Uint8Array(await response.arrayBuffer());
89
+ await verifyIntegrity(bytes, options.integrity, options.hashBytes);
90
+ return {
91
+ bytes,
92
+ contentType: response.headers.get("content-type") ?? void 0,
93
+ rangeSupported: response.status === 206 || response.headers.get("accept-ranges")?.toLowerCase() === "bytes"
94
+ };
95
+ } catch (error) {
96
+ if (isAbortError(error) || options.resolveOptions?.signal?.aborted) {
97
+ throw createAbortError();
98
+ }
99
+ if (error instanceof NonRetryableResourceError) {
100
+ throw error;
101
+ }
102
+ lastError = error;
103
+ if (attempt === policy.maxAttempts) {
104
+ throw error;
105
+ }
106
+ await waitForRetry(options.sleep, attempt, policy, options.resolveOptions?.signal);
107
+ } finally {
108
+ controller.dispose();
109
+ }
110
+ }
111
+ throw lastError instanceof Error ? lastError : new Error("Model resource request failed");
112
+ }
113
+ async function verifyIntegrity(bytes, integrity, hashBytes) {
114
+ if (!integrity) {
115
+ return;
116
+ }
117
+ const expected = integrity.replace(/^sha256-/iu, "").toLowerCase();
118
+ const actualHex = (await hashBytes(bytes)).toLowerCase();
119
+ const actualBase64 = bytesToBase64(await digestBytes(bytes, hashBytes));
120
+ if (expected !== actualHex && expected !== actualBase64) {
121
+ throw new NonRetryableResourceError("Model resource integrity check failed");
122
+ }
123
+ }
124
+ async function digestBytes(bytes, hashBytes) {
125
+ if (globalThis.crypto?.subtle) {
126
+ return new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
127
+ }
128
+ const hex = await hashBytes(bytes);
129
+ if (!/^[0-9a-f]{64}$/iu.test(hex)) {
130
+ throw new Error("A base64 integrity check requires Web Crypto or a byte-level hash implementation");
131
+ }
132
+ return Uint8Array.from(hex.match(/.{2}/gu) ?? [], (pair) => Number.parseInt(pair, 16));
133
+ }
134
+ function bytesToBase64(bytes) {
135
+ let binary = "";
136
+ for (const byte of bytes) {
137
+ binary += String.fromCharCode(byte);
138
+ }
139
+ return btoa(binary);
140
+ }
141
+ async function waitForRetry(sleep, attempt, policy, signal) {
142
+ const delay = Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** (attempt - 1));
143
+ await sleep(delay, signal);
144
+ }
145
+ function createRequestController(signal, timeoutMs) {
146
+ const controller = new AbortController();
147
+ const onAbort = () => controller.abort();
148
+ signal?.addEventListener("abort", onAbort, { once: true });
149
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
150
+ return {
151
+ signal: controller.signal,
152
+ dispose: () => {
153
+ clearTimeout(timer);
154
+ signal?.removeEventListener("abort", onAbort);
155
+ }
156
+ };
157
+ }
158
+ function createAbortError() {
159
+ return new DOMException("The model load was aborted", "AbortError");
160
+ }
161
+ function isAbortError(error) {
162
+ return error instanceof DOMException && error.name === "AbortError";
163
+ }
164
+
165
+ // src/runtime.ts
166
+ var AdapterRegistry = class {
167
+ registrations = /* @__PURE__ */ new Map();
168
+ register(registration) {
169
+ if (this.registrations.has(registration.formatId)) {
170
+ throw new Error(`An adapter is already registered for format ${registration.formatId}`);
171
+ }
172
+ this.registrations.set(registration.formatId, registration);
173
+ return this;
174
+ }
175
+ async resolve(input, formatId) {
176
+ if (formatId) {
177
+ const registration = this.registrations.get(formatId);
178
+ if (!registration) {
179
+ throw new Error(`No model adapter is registered for format ${formatId}`);
180
+ }
181
+ return unwrapAdapter(await registration.load());
182
+ }
183
+ const candidates = [...this.registrations.values()].map((registration) => ({ registration, score: scoreRegistration(registration, input) })).filter(({ score }) => score > 0).sort((left, right) => right.score - left.score);
184
+ const selected = candidates[0]?.registration;
185
+ if (!selected) {
186
+ throw new Error("No model adapter matched the source content, MIME type, or extension");
187
+ }
188
+ return unwrapAdapter(await selected.load());
189
+ }
190
+ };
191
+ var PackageResourceResolver = class {
192
+ memoryResources;
193
+ baseUrl;
194
+ sourceKind;
195
+ fetch;
196
+ hashBytes;
197
+ sleep;
198
+ fetchPolicy;
199
+ headers;
200
+ blobStorageUrlResolver;
201
+ constructor(options) {
202
+ this.sourceKind = options.sourceKind;
203
+ this.baseUrl = options.package?.baseUrl ?? options.baseUrl;
204
+ this.memoryResources = options.package?.resources ?? {};
205
+ this.fetch = options.fetch;
206
+ this.hashBytes = options.hashBytes;
207
+ this.sleep = options.sleep;
208
+ this.fetchPolicy = options.fetchPolicy;
209
+ this.headers = options.headers;
210
+ this.blobStorageUrlResolver = options.blobStorageUrlResolver;
211
+ }
212
+ async resolve(reference, options = {}) {
213
+ const requested = typeof reference === "string" ? { path: reference } : reference;
214
+ const memoryKey = normalizePackagePath(requested.path);
215
+ const memoryResource = this.memoryResources[memoryKey] ?? this.memoryResources[`./${memoryKey}`];
216
+ if (memoryResource) {
217
+ const bytes = await toBytes(memoryResource.bytes);
218
+ await verifyResourceIntegrity(bytes, requested.integrity ?? memoryResource.integrity, this.hashBytes);
219
+ return {
220
+ path: memoryKey,
221
+ bytes,
222
+ contentType: requested.contentType ?? memoryResource.contentType,
223
+ contentHash: await this.hashBytes(bytes),
224
+ rangeSupported: false
225
+ };
226
+ }
227
+ const url = await this.resolveUrl(requested.path);
228
+ const result = await fetchResource(url, {
229
+ fetch: this.fetch,
230
+ hashBytes: this.hashBytes,
231
+ sleep: this.sleep,
232
+ headers: this.headers,
233
+ integrity: requested.integrity,
234
+ policy: this.fetchPolicy,
235
+ resolveOptions: options
236
+ });
237
+ return {
238
+ path: memoryKey,
239
+ bytes: result.bytes,
240
+ contentType: requested.contentType ?? result.contentType,
241
+ contentHash: await this.hashBytes(result.bytes),
242
+ rangeSupported: result.rangeSupported
243
+ };
244
+ }
245
+ async resolveUrl(reference) {
246
+ if (/^[a-z][a-z\d+.-]*:/iu.test(reference)) {
247
+ return ensureHttpUrl(reference);
248
+ }
249
+ if (!this.baseUrl) {
250
+ throw new Error(`Cannot resolve relative model resource ${reference} without a package base URL or memory resource`);
251
+ }
252
+ if (this.sourceKind === "blob-storage-url" && this.blobStorageUrlResolver) {
253
+ return this.blobStorageUrlResolver(this.baseUrl, reference);
254
+ }
255
+ return ensureHttpUrl(new URL(reference, this.baseUrl).href);
256
+ }
257
+ };
258
+ var ModelRuntime = class {
259
+ registry;
260
+ cache;
261
+ fetch;
262
+ readFile;
263
+ hashBytes;
264
+ sleep;
265
+ workerDispatcher;
266
+ blobStorageUrlResolver;
267
+ cacheKeys = /* @__PURE__ */ new Set();
268
+ constructor(options = {}) {
269
+ this.registry = options.registry ?? new AdapterRegistry();
270
+ this.cache = options.cache ?? new MemoryModelCache();
271
+ this.fetch = options.dependencies?.fetch ?? defaultFetch;
272
+ this.readFile = options.dependencies?.readFile;
273
+ this.hashBytes = options.dependencies?.hashBytes ?? sha256Hex;
274
+ this.sleep = options.dependencies?.sleep ?? defaultSleep;
275
+ this.workerDispatcher = options.workerDispatcher;
276
+ this.blobStorageUrlResolver = options.dependencies?.blobStorageUrlResolver;
277
+ }
278
+ get adapters() {
279
+ return this.registry;
280
+ }
281
+ async invalidate(contentHash) {
282
+ if (!contentHash) {
283
+ await this.cache.clear();
284
+ this.cacheKeys.clear();
285
+ return;
286
+ }
287
+ for (const key of this.cacheKeys) {
288
+ if (key.includes(`:${contentHash}:`)) {
289
+ await this.cache.delete(key);
290
+ this.cacheKeys.delete(key);
291
+ }
292
+ }
293
+ }
294
+ async loadModel(source, options = {}) {
295
+ const input = await this.resolveSource(source, options);
296
+ const adapter = await this.registry.resolve({
297
+ bytes: input.bytes,
298
+ contentType: input.contentType,
299
+ fileName: input.fileName,
300
+ sourceKind: source.kind
301
+ }, options.formatId);
302
+ const cacheKey = createModelCacheKey(input.contentHash, adapter.formatId, options.adapterOptions);
303
+ const useCache = options.useCache ?? true;
304
+ if (useCache) {
305
+ const cached = await this.cache.get(cacheKey);
306
+ if (cached) {
307
+ return { ...cached, fromCache: true };
308
+ }
309
+ }
310
+ const context = {
311
+ signal: options.signal ?? new AbortController().signal,
312
+ mode: options.mode ?? "strict",
313
+ execution: "main",
314
+ adapterOptions: options.adapterOptions ?? null
315
+ };
316
+ const adapterResult = await this.loadWithExecution(adapter, input, context, options);
317
+ const result = {
318
+ ...adapterResult,
319
+ contentHash: input.contentHash,
320
+ cacheKey,
321
+ fromCache: false,
322
+ contentType: input.contentType,
323
+ sourceKind: source.kind
324
+ };
325
+ if (useCache) {
326
+ await this.cache.set(cacheKey, result);
327
+ this.cacheKeys.add(cacheKey);
328
+ }
329
+ return result;
330
+ }
331
+ async loadWithExecution(adapter, input, context, options) {
332
+ const workerMode = options.worker?.mode ?? "auto";
333
+ const canUseWorker = workerMode !== "never" && Boolean(this.workerDispatcher) && Boolean(adapter.supportsWorker);
334
+ if (workerMode === "always" && !canUseWorker) {
335
+ throw new Error(`Adapter ${adapter.formatId} does not support the requested worker execution`);
336
+ }
337
+ if (canUseWorker && this.workerDispatcher) {
338
+ const workerRequest = {
339
+ formatId: adapter.formatId,
340
+ input,
341
+ context: { ...context, execution: "worker" }
342
+ };
343
+ return this.workerDispatcher.dispatch(workerRequest);
344
+ }
345
+ return adapter.load(input, context);
346
+ }
347
+ async resolveSource(source, options) {
348
+ const fileName = sourceFileName(source);
349
+ const baseUrl = "url" in source ? source.url : void 0;
350
+ const headers = "headers" in source ? source.headers : void 0;
351
+ let bytes;
352
+ let contentType = "mimeTypeHint" in source ? source.mimeTypeHint : void 0;
353
+ let rangeSupported = false;
354
+ if (source.kind === "file-path") {
355
+ if (!this.readFile) {
356
+ throw new Error("file-path sources require a readFile dependency");
357
+ }
358
+ bytes = await this.readFile(source.path, options.signal);
359
+ } else if (source.kind === "url" || source.kind === "blob-storage-url") {
360
+ const result = await fetchResource(ensureHttpUrl(source.url), {
361
+ fetch: this.fetch,
362
+ hashBytes: this.hashBytes,
363
+ sleep: this.sleep,
364
+ headers,
365
+ integrity: options.integrity,
366
+ policy: options.fetchPolicy,
367
+ resolveOptions: { signal: options.signal }
368
+ });
369
+ bytes = result.bytes;
370
+ contentType ??= result.contentType;
371
+ rangeSupported = result.rangeSupported;
372
+ } else {
373
+ bytes = await sourceToBytes(source);
374
+ }
375
+ const contentHash = await this.hashBytes(bytes);
376
+ const resourceResolver = new PackageResourceResolver({
377
+ sourceKind: source.kind,
378
+ baseUrl,
379
+ package: source.package,
380
+ fetch: this.fetch,
381
+ hashBytes: this.hashBytes,
382
+ sleep: this.sleep,
383
+ fetchPolicy: options.fetchPolicy,
384
+ headers,
385
+ blobStorageUrlResolver: this.blobStorageUrlResolver
386
+ });
387
+ return {
388
+ source,
389
+ bytes,
390
+ contentType,
391
+ fileName,
392
+ contentHash,
393
+ rangeSupported,
394
+ resourceResolver
395
+ };
396
+ }
397
+ };
398
+ function scoreRegistration(registration, input) {
399
+ const extension = input.fileName?.split(".").pop()?.toLowerCase();
400
+ const extensionScore = extension && registration.extensions?.some((item) => item.replace(/^\./u, "").toLowerCase() === extension) ? 2 : 0;
401
+ const mimeScore = input.contentType && registration.mimeTypes?.some((item) => item.toLowerCase() === input.contentType?.toLowerCase()) ? 3 : 0;
402
+ const sniffScore = registration.sniff?.(input) ?? 0;
403
+ const normalizedSniffScore = sniffScore === true ? 1 : sniffScore === false ? 0 : sniffScore;
404
+ return extensionScore + mimeScore + normalizedSniffScore;
405
+ }
406
+ function unwrapAdapter(module) {
407
+ return "default" in module ? module.default : module;
408
+ }
409
+ function normalizePackagePath(path) {
410
+ if (path.includes("\0")) {
411
+ throw new Error("Model resource paths cannot contain null bytes");
412
+ }
413
+ const segments = [];
414
+ for (const segment of path.replaceAll("\\", "/").split("/")) {
415
+ if (!segment || segment === ".") continue;
416
+ if (segment === "..") {
417
+ if (segments.length === 0) {
418
+ throw new Error(`Model resource path escapes its package: ${path}`);
419
+ }
420
+ segments.pop();
421
+ continue;
422
+ }
423
+ segments.push(segment);
424
+ }
425
+ return segments.join("/");
426
+ }
427
+ async function sourceToBytes(source) {
428
+ if (source.kind === "blob") {
429
+ return toBytes(source.blob);
430
+ }
431
+ if (source.kind === "array-buffer") {
432
+ return new Uint8Array(source.bytes);
433
+ }
434
+ if (source.kind === "uint8-array") {
435
+ return new Uint8Array(source.bytes);
436
+ }
437
+ const chunks = [];
438
+ if (Symbol.asyncIterator in Object(source.stream)) {
439
+ for await (const chunk of source.stream) {
440
+ chunks.push(new Uint8Array(chunk));
441
+ }
442
+ } else {
443
+ const reader = source.stream.getReader();
444
+ try {
445
+ while (true) {
446
+ const next = await reader.read();
447
+ if (next.done) break;
448
+ chunks.push(new Uint8Array(next.value));
449
+ }
450
+ } finally {
451
+ reader.releaseLock();
452
+ }
453
+ }
454
+ const length = chunks.reduce((total, chunk) => total + chunk.byteLength, 0);
455
+ const bytes = new Uint8Array(length);
456
+ let offset = 0;
457
+ for (const chunk of chunks) {
458
+ bytes.set(chunk, offset);
459
+ offset += chunk.byteLength;
460
+ }
461
+ return bytes;
462
+ }
463
+ async function toBytes(input) {
464
+ if (input instanceof Blob) {
465
+ return new Uint8Array(await input.arrayBuffer());
466
+ }
467
+ if (input instanceof Uint8Array) {
468
+ return new Uint8Array(input);
469
+ }
470
+ return new Uint8Array(input);
471
+ }
472
+ async function verifyResourceIntegrity(bytes, integrity, hashBytes) {
473
+ if (!integrity) return;
474
+ const expected = integrity.replace(/^sha256-/iu, "").toLowerCase();
475
+ const actual = (await hashBytes(bytes)).toLowerCase();
476
+ if (actual !== expected) {
477
+ throw new Error("Model resource integrity check failed");
478
+ }
479
+ }
480
+ var defaultFetch = (input, init) => {
481
+ if (!globalThis.fetch) {
482
+ throw new Error("URL sources require fetch or an injected fetch dependency");
483
+ }
484
+ return globalThis.fetch(input, init);
485
+ };
486
+ function sourceFileName(source) {
487
+ if ("fileNameHint" in source && source.fileNameHint) {
488
+ return source.fileNameHint;
489
+ }
490
+ if (source.kind === "file-path") {
491
+ return source.path.split(/[\\/]/u).pop();
492
+ }
493
+ if (source.kind === "url" || source.kind === "blob-storage-url") {
494
+ try {
495
+ return new URL(source.url).pathname.split("/").pop() || void 0;
496
+ } catch {
497
+ return void 0;
498
+ }
499
+ }
500
+ return void 0;
501
+ }
502
+ function ensureHttpUrl(value) {
503
+ const url = new URL(value);
504
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
505
+ throw new Error(`Unsupported model resource URL scheme: ${url.protocol}`);
506
+ }
507
+ return url.href;
508
+ }
509
+
510
+ // src/index.ts
511
+ var packageName = "@plasius/gpu-model-runtime";
512
+ var packageBootstrap = Object.freeze({
513
+ packageName,
514
+ featureFlag: "gpu.model.conversion.enabled",
515
+ status: "runtime"
516
+ });
517
+ export {
518
+ AdapterRegistry,
519
+ MemoryModelCache,
520
+ ModelRuntime,
521
+ PackageResourceResolver,
522
+ createModelCacheKey,
523
+ defaultSleep,
524
+ fetchResource,
525
+ packageBootstrap,
526
+ packageName,
527
+ sha256Hex,
528
+ verifyIntegrity
529
+ };
530
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cache.ts","../src/fetch.ts","../src/runtime.ts","../src/index.ts"],"sourcesContent":["import type { ModelCache } from \"./types.js\";\n\nexport class MemoryModelCache implements ModelCache {\n private readonly entries = new Map<string, unknown>();\n\n async get<T>(key: string): Promise<T | undefined> {\n return this.entries.get(key) as T | undefined;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.entries.set(key, value);\n }\n\n async delete(key: string): Promise<boolean> {\n return this.entries.delete(key);\n }\n\n async clear(): Promise<void> {\n this.entries.clear();\n }\n}\n\nfunction stableValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(stableValue);\n }\n\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, stableValue(entry)]),\n );\n }\n\n return value;\n}\n\nexport function createModelCacheKey(\n contentHash: string,\n formatId: string,\n adapterOptions: unknown,\n): string {\n return `${formatId}:${contentHash}:${JSON.stringify(stableValue(adapterOptions ?? null))}`;\n}\n","import type {\n FetchPolicy,\n HashBytes,\n RuntimeFetch,\n Sleep,\n ResolveResourceOptions,\n} from \"./types.js\";\n\nconst DEFAULT_POLICY: Required<FetchPolicy> = {\n maxAttempts: 3,\n baseDelayMs: 100,\n maxDelayMs: 1_000,\n timeoutMs: 30_000,\n};\n\nconst RETRYABLE_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);\n\nclass NonRetryableResourceError extends Error {}\n\nexport type FetchedResource = Readonly<{\n bytes: Uint8Array;\n contentType?: string;\n rangeSupported: boolean;\n}>;\n\nexport function defaultSleep(milliseconds: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(createAbortError());\n return;\n }\n\n const timer = setTimeout(resolve, milliseconds);\n signal?.addEventListener(\"abort\", () => {\n clearTimeout(timer);\n reject(createAbortError());\n }, { once: true });\n });\n}\n\nexport async function sha256Hex(bytes: Uint8Array): Promise<string> {\n if (!globalThis.crypto?.subtle) {\n throw new Error(\"SHA-256 integrity checks require Web Crypto support or an injected hashBytes dependency\");\n }\n\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes as BufferSource);\n return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport async function fetchResource(\n url: string,\n options: Readonly<{\n fetch: RuntimeFetch;\n hashBytes: HashBytes;\n sleep: Sleep;\n headers?: Readonly<Record<string, string>>;\n integrity?: string;\n policy?: FetchPolicy;\n resolveOptions?: ResolveResourceOptions;\n }>,\n): Promise<FetchedResource> {\n const policy = { ...DEFAULT_POLICY, ...options.policy };\n const headers = new Headers(options.headers);\n if (options.resolveOptions?.range) {\n const { start, end } = options.resolveOptions.range;\n headers.set(\"Range\", `bytes=${start}-${end ?? \"\"}`);\n }\n\n let lastError: unknown;\n for (let attempt = 1; attempt <= policy.maxAttempts; attempt += 1) {\n const controller = createRequestController(options.resolveOptions?.signal, policy.timeoutMs);\n\n try {\n const response = await options.fetch(url, {\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n if (!RETRYABLE_STATUSES.has(response.status)) {\n throw new NonRetryableResourceError(`Model resource request failed with HTTP ${response.status}`);\n }\n if (attempt === policy.maxAttempts) {\n throw new NonRetryableResourceError(`Model resource request failed with HTTP ${response.status}`);\n }\n lastError = new Error(`Retryable model resource response: HTTP ${response.status}`);\n await waitForRetry(options.sleep, attempt, policy, options.resolveOptions?.signal);\n continue;\n }\n\n const bytes = new Uint8Array(await response.arrayBuffer());\n await verifyIntegrity(bytes, options.integrity, options.hashBytes);\n return {\n bytes,\n contentType: response.headers.get(\"content-type\") ?? undefined,\n rangeSupported: response.status === 206 || response.headers.get(\"accept-ranges\")?.toLowerCase() === \"bytes\",\n };\n } catch (error) {\n if (isAbortError(error) || options.resolveOptions?.signal?.aborted) {\n throw createAbortError();\n }\n if (error instanceof NonRetryableResourceError) {\n throw error;\n }\n lastError = error;\n if (attempt === policy.maxAttempts) {\n throw error;\n }\n await waitForRetry(options.sleep, attempt, policy, options.resolveOptions?.signal);\n } finally {\n controller.dispose();\n }\n }\n\n throw lastError instanceof Error ? lastError : new Error(\"Model resource request failed\");\n}\n\nexport async function verifyIntegrity(bytes: Uint8Array, integrity: string | undefined, hashBytes: HashBytes): Promise<void> {\n if (!integrity) {\n return;\n }\n\n const expected = integrity.replace(/^sha256-/iu, \"\").toLowerCase();\n const actualHex = (await hashBytes(bytes)).toLowerCase();\n const actualBase64 = bytesToBase64(await digestBytes(bytes, hashBytes));\n if (expected !== actualHex && expected !== actualBase64) {\n throw new NonRetryableResourceError(\"Model resource integrity check failed\");\n }\n}\n\nasync function digestBytes(bytes: Uint8Array, hashBytes: HashBytes): Promise<Uint8Array> {\n if (globalThis.crypto?.subtle) {\n return new Uint8Array(await globalThis.crypto.subtle.digest(\"SHA-256\", bytes as BufferSource));\n }\n\n const hex = await hashBytes(bytes);\n if (!/^[0-9a-f]{64}$/iu.test(hex)) {\n throw new Error(\"A base64 integrity check requires Web Crypto or a byte-level hash implementation\");\n }\n return Uint8Array.from(hex.match(/.{2}/gu) ?? [], (pair) => Number.parseInt(pair, 16));\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\nasync function waitForRetry(sleep: Sleep, attempt: number, policy: Required<FetchPolicy>, signal?: AbortSignal): Promise<void> {\n const delay = Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** (attempt - 1));\n await sleep(delay, signal);\n}\n\nfunction createRequestController(signal: AbortSignal | undefined, timeoutMs: number): Readonly<{\n signal: AbortSignal;\n dispose: () => void;\n}> {\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onAbort);\n },\n };\n}\n\nfunction createAbortError(): Error {\n return new DOMException(\"The model load was aborted\", \"AbortError\");\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof DOMException && error.name === \"AbortError\";\n}\n","import { MemoryModelCache, createModelCacheKey } from \"./cache.js\";\nimport { defaultSleep, fetchResource, sha256Hex } from \"./fetch.js\";\nimport type {\n AdapterLoadResult,\n AdapterModule,\n AdapterRegistration,\n HashBytes,\n LoadModelOptions,\n ModelAdapter,\n ModelCache,\n ModelLoadResult,\n ModelPackage,\n ModelResourceInput,\n ModelSource,\n ModelSourceKind,\n ReadFile,\n ResolveResourceOptions,\n ResolvedModelSource,\n ResolvedResource,\n ResourceReference,\n ResourceResolver,\n RuntimeDependencies,\n RuntimeFetch,\n Sleep,\n SniffInput,\n WorkerDispatcher,\n WorkerLoadRequest,\n} from \"./types.js\";\n\nexport class AdapterRegistry {\n private readonly registrations = new Map<string, AdapterRegistration>();\n\n register<TCanonicalModel, TRendererReady>(registration: AdapterRegistration<TCanonicalModel, TRendererReady>): this {\n if (this.registrations.has(registration.formatId)) {\n throw new Error(`An adapter is already registered for format ${registration.formatId}`);\n }\n this.registrations.set(registration.formatId, registration as AdapterRegistration);\n return this;\n }\n\n async resolve<TCanonicalModel = unknown, TRendererReady = unknown>(\n input: SniffInput,\n formatId?: string,\n ): Promise<ModelAdapter<TCanonicalModel, TRendererReady>> {\n if (formatId) {\n const registration = this.registrations.get(formatId);\n if (!registration) {\n throw new Error(`No model adapter is registered for format ${formatId}`);\n }\n return unwrapAdapter(await registration.load()) as ModelAdapter<TCanonicalModel, TRendererReady>;\n }\n\n const candidates = [...this.registrations.values()]\n .map((registration) => ({ registration, score: scoreRegistration(registration, input) }))\n .filter(({ score }) => score > 0)\n .sort((left, right) => right.score - left.score);\n\n const selected = candidates[0]?.registration;\n if (!selected) {\n throw new Error(\"No model adapter matched the source content, MIME type, or extension\");\n }\n\n return unwrapAdapter(await selected.load()) as ModelAdapter<TCanonicalModel, TRendererReady>;\n }\n}\n\nexport class PackageResourceResolver implements ResourceResolver {\n private readonly memoryResources: Readonly<Record<string, ModelResourceInput>>;\n private readonly baseUrl?: string;\n private readonly sourceKind: ModelSourceKind;\n private readonly fetch: RuntimeFetch;\n private readonly hashBytes: HashBytes;\n private readonly sleep: Sleep;\n private readonly fetchPolicy: LoadModelOptions[\"fetchPolicy\"];\n private readonly headers?: Readonly<Record<string, string>>;\n private readonly blobStorageUrlResolver?: RuntimeDependencies[\"blobStorageUrlResolver\"];\n\n public constructor(options: Readonly<{\n sourceKind: ModelSourceKind;\n baseUrl?: string;\n package?: ModelPackage;\n fetch: RuntimeFetch;\n hashBytes: HashBytes;\n sleep: Sleep;\n fetchPolicy?: LoadModelOptions[\"fetchPolicy\"];\n headers?: Readonly<Record<string, string>>;\n blobStorageUrlResolver?: RuntimeDependencies[\"blobStorageUrlResolver\"];\n }>) {\n this.sourceKind = options.sourceKind;\n this.baseUrl = options.package?.baseUrl ?? options.baseUrl;\n this.memoryResources = options.package?.resources ?? {};\n this.fetch = options.fetch;\n this.hashBytes = options.hashBytes;\n this.sleep = options.sleep;\n this.fetchPolicy = options.fetchPolicy;\n this.headers = options.headers;\n this.blobStorageUrlResolver = options.blobStorageUrlResolver;\n }\n\n async resolve(reference: string | ResourceReference, options: ResolveResourceOptions = {}): Promise<ResolvedResource> {\n const requested = typeof reference === \"string\" ? { path: reference } : reference;\n const memoryKey = normalizePackagePath(requested.path);\n const memoryResource = this.memoryResources[memoryKey] ?? this.memoryResources[`./${memoryKey}`];\n if (memoryResource) {\n const bytes = await toBytes(memoryResource.bytes);\n await verifyResourceIntegrity(bytes, requested.integrity ?? memoryResource.integrity, this.hashBytes);\n return {\n path: memoryKey,\n bytes,\n contentType: requested.contentType ?? memoryResource.contentType,\n contentHash: await this.hashBytes(bytes),\n rangeSupported: false,\n };\n }\n\n const url = await this.resolveUrl(requested.path);\n const result = await fetchResource(url, {\n fetch: this.fetch,\n hashBytes: this.hashBytes,\n sleep: this.sleep,\n headers: this.headers,\n integrity: requested.integrity,\n policy: this.fetchPolicy,\n resolveOptions: options,\n });\n return {\n path: memoryKey,\n bytes: result.bytes,\n contentType: requested.contentType ?? result.contentType,\n contentHash: await this.hashBytes(result.bytes),\n rangeSupported: result.rangeSupported,\n };\n }\n\n private async resolveUrl(reference: string): Promise<string> {\n if (/^[a-z][a-z\\d+.-]*:/iu.test(reference)) {\n return ensureHttpUrl(reference);\n }\n if (!this.baseUrl) {\n throw new Error(`Cannot resolve relative model resource ${reference} without a package base URL or memory resource`);\n }\n if (this.sourceKind === \"blob-storage-url\" && this.blobStorageUrlResolver) {\n return this.blobStorageUrlResolver(this.baseUrl, reference);\n }\n return ensureHttpUrl(new URL(reference, this.baseUrl).href);\n }\n}\n\nexport class ModelRuntime {\n private readonly registry: AdapterRegistry;\n private readonly cache: ModelCache;\n private readonly fetch: RuntimeFetch;\n private readonly readFile?: ReadFile;\n private readonly hashBytes: HashBytes;\n private readonly sleep: Sleep;\n private readonly workerDispatcher?: WorkerDispatcher;\n private readonly blobStorageUrlResolver?: RuntimeDependencies[\"blobStorageUrlResolver\"];\n private readonly cacheKeys = new Set<string>();\n\n public constructor(options: Readonly<{\n registry?: AdapterRegistry;\n cache?: ModelCache;\n dependencies?: RuntimeDependencies;\n workerDispatcher?: WorkerDispatcher;\n }> = {}) {\n this.registry = options.registry ?? new AdapterRegistry();\n this.cache = options.cache ?? new MemoryModelCache();\n this.fetch = options.dependencies?.fetch ?? defaultFetch;\n this.readFile = options.dependencies?.readFile;\n this.hashBytes = options.dependencies?.hashBytes ?? sha256Hex;\n this.sleep = options.dependencies?.sleep ?? defaultSleep;\n this.workerDispatcher = options.workerDispatcher;\n this.blobStorageUrlResolver = options.dependencies?.blobStorageUrlResolver;\n }\n\n public get adapters(): AdapterRegistry {\n return this.registry;\n }\n\n public async invalidate(contentHash?: string): Promise<void> {\n if (!contentHash) {\n await this.cache.clear();\n this.cacheKeys.clear();\n return;\n }\n\n for (const key of this.cacheKeys) {\n if (key.includes(`:${contentHash}:`)) {\n await this.cache.delete(key);\n this.cacheKeys.delete(key);\n }\n }\n }\n\n public async loadModel<TCanonicalModel, TRendererReady = unknown>(\n source: ModelSource,\n options: LoadModelOptions = {},\n ): Promise<ModelLoadResult<TCanonicalModel, TRendererReady>> {\n const input = await this.resolveSource(source, options);\n const adapter = await this.registry.resolve<TCanonicalModel, TRendererReady>({\n bytes: input.bytes,\n contentType: input.contentType,\n fileName: input.fileName,\n sourceKind: source.kind,\n }, options.formatId);\n const cacheKey = createModelCacheKey(input.contentHash, adapter.formatId, options.adapterOptions);\n const useCache = options.useCache ?? true;\n if (useCache) {\n const cached = await this.cache.get<ModelLoadResult<TCanonicalModel, TRendererReady>>(cacheKey);\n if (cached) {\n return { ...cached, fromCache: true };\n }\n }\n\n const context = {\n signal: options.signal ?? new AbortController().signal,\n mode: options.mode ?? \"strict\",\n execution: \"main\" as const,\n adapterOptions: options.adapterOptions ?? null,\n };\n const adapterResult = await this.loadWithExecution<TCanonicalModel, TRendererReady>(adapter, input, context, options);\n const result: ModelLoadResult<TCanonicalModel, TRendererReady> = {\n ...adapterResult,\n contentHash: input.contentHash,\n cacheKey,\n fromCache: false,\n contentType: input.contentType,\n sourceKind: source.kind,\n };\n if (useCache) {\n await this.cache.set(cacheKey, result);\n this.cacheKeys.add(cacheKey);\n }\n return result;\n }\n\n private async loadWithExecution<TCanonicalModel, TRendererReady>(\n adapter: ModelAdapter<TCanonicalModel, TRendererReady>,\n input: ResolvedModelSource,\n context: Parameters<ModelAdapter<TCanonicalModel, TRendererReady>[\"load\"]>[1],\n options: LoadModelOptions,\n ): Promise<AdapterLoadResult<TCanonicalModel, TRendererReady>> {\n const workerMode = options.worker?.mode ?? \"auto\";\n const canUseWorker = workerMode !== \"never\" && Boolean(this.workerDispatcher) && Boolean(adapter.supportsWorker);\n if (workerMode === \"always\" && !canUseWorker) {\n throw new Error(`Adapter ${adapter.formatId} does not support the requested worker execution`);\n }\n if (canUseWorker && this.workerDispatcher) {\n const workerRequest: WorkerLoadRequest = {\n formatId: adapter.formatId,\n input,\n context: { ...context, execution: \"worker\" },\n };\n return this.workerDispatcher.dispatch<TCanonicalModel, TRendererReady>(workerRequest);\n }\n return adapter.load(input, context);\n }\n\n private async resolveSource(source: ModelSource, options: LoadModelOptions): Promise<ResolvedModelSource> {\n const fileName = sourceFileName(source);\n const baseUrl = \"url\" in source ? source.url : undefined;\n const headers = \"headers\" in source ? source.headers : undefined;\n let bytes: Uint8Array;\n let contentType: string | undefined = \"mimeTypeHint\" in source ? source.mimeTypeHint : undefined;\n let rangeSupported = false;\n\n if (source.kind === \"file-path\") {\n if (!this.readFile) {\n throw new Error(\"file-path sources require a readFile dependency\");\n }\n bytes = await this.readFile(source.path, options.signal);\n } else if (source.kind === \"url\" || source.kind === \"blob-storage-url\") {\n const result = await fetchResource(ensureHttpUrl(source.url), {\n fetch: this.fetch,\n hashBytes: this.hashBytes,\n sleep: this.sleep,\n headers,\n integrity: options.integrity,\n policy: options.fetchPolicy,\n resolveOptions: { signal: options.signal },\n });\n bytes = result.bytes;\n contentType ??= result.contentType;\n rangeSupported = result.rangeSupported;\n } else {\n bytes = await sourceToBytes(source);\n }\n\n const contentHash = await this.hashBytes(bytes);\n const resourceResolver = new PackageResourceResolver({\n sourceKind: source.kind,\n baseUrl,\n package: source.package,\n fetch: this.fetch,\n hashBytes: this.hashBytes,\n sleep: this.sleep,\n fetchPolicy: options.fetchPolicy,\n headers,\n blobStorageUrlResolver: this.blobStorageUrlResolver,\n });\n return {\n source,\n bytes,\n contentType,\n fileName,\n contentHash,\n rangeSupported,\n resourceResolver,\n };\n }\n}\n\nfunction scoreRegistration(registration: AdapterRegistration, input: SniffInput): number {\n const extension = input.fileName?.split(\".\").pop()?.toLowerCase();\n const extensionScore = extension && registration.extensions?.some((item) => item.replace(/^\\./u, \"\").toLowerCase() === extension) ? 2 : 0;\n const mimeScore = input.contentType && registration.mimeTypes?.some((item) => item.toLowerCase() === input.contentType?.toLowerCase()) ? 3 : 0;\n const sniffScore = registration.sniff?.(input) ?? 0;\n const normalizedSniffScore = sniffScore === true ? 1 : sniffScore === false ? 0 : sniffScore;\n return extensionScore + mimeScore + normalizedSniffScore;\n}\n\nfunction unwrapAdapter<TCanonicalModel, TRendererReady>(module: AdapterModule<TCanonicalModel, TRendererReady>): ModelAdapter<TCanonicalModel, TRendererReady> {\n return \"default\" in module ? module.default : module;\n}\n\nfunction normalizePackagePath(path: string): string {\n if (path.includes(\"\\0\")) {\n throw new Error(\"Model resource paths cannot contain null bytes\");\n }\n const segments: string[] = [];\n for (const segment of path.replaceAll(\"\\\\\", \"/\").split(\"/\")) {\n if (!segment || segment === \".\") continue;\n if (segment === \"..\") {\n if (segments.length === 0) {\n throw new Error(`Model resource path escapes its package: ${path}`);\n }\n segments.pop();\n continue;\n }\n segments.push(segment);\n }\n return segments.join(\"/\");\n}\n\nasync function sourceToBytes(source: Exclude<ModelSource, { kind: \"file-path\" | \"url\" | \"blob-storage-url\" }>): Promise<Uint8Array> {\n if (source.kind === \"blob\") {\n return toBytes(source.blob);\n }\n if (source.kind === \"array-buffer\") {\n return new Uint8Array(source.bytes);\n }\n if (source.kind === \"uint8-array\") {\n return new Uint8Array(source.bytes);\n }\n\n const chunks: Uint8Array[] = [];\n if (Symbol.asyncIterator in Object(source.stream)) {\n for await (const chunk of source.stream as AsyncIterable<Uint8Array>) {\n chunks.push(new Uint8Array(chunk));\n }\n } else {\n const reader = (source.stream as ReadableStream<Uint8Array>).getReader();\n try {\n while (true) {\n const next = await reader.read();\n if (next.done) break;\n chunks.push(new Uint8Array(next.value));\n }\n } finally {\n reader.releaseLock();\n }\n }\n const length = chunks.reduce((total, chunk) => total + chunk.byteLength, 0);\n const bytes = new Uint8Array(length);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n}\n\nasync function toBytes(input: ArrayBuffer | Blob | Uint8Array): Promise<Uint8Array> {\n if (input instanceof Blob) {\n return new Uint8Array(await input.arrayBuffer());\n }\n if (input instanceof Uint8Array) {\n return new Uint8Array(input);\n }\n return new Uint8Array(input);\n}\n\nasync function verifyResourceIntegrity(bytes: Uint8Array, integrity: string | undefined, hashBytes: HashBytes): Promise<void> {\n if (!integrity) return;\n const expected = integrity.replace(/^sha256-/iu, \"\").toLowerCase();\n const actual = (await hashBytes(bytes)).toLowerCase();\n if (actual !== expected) {\n throw new Error(\"Model resource integrity check failed\");\n }\n}\n\nconst defaultFetch: RuntimeFetch = (input, init) => {\n if (!globalThis.fetch) {\n throw new Error(\"URL sources require fetch or an injected fetch dependency\");\n }\n return globalThis.fetch(input, init);\n};\n\nfunction sourceFileName(source: ModelSource): string | undefined {\n if (\"fileNameHint\" in source && source.fileNameHint) {\n return source.fileNameHint;\n }\n if (source.kind === \"file-path\") {\n return source.path.split(/[\\\\/]/u).pop();\n }\n if (source.kind === \"url\" || source.kind === \"blob-storage-url\") {\n try {\n return new URL(source.url).pathname.split(\"/\").pop() || undefined;\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\nfunction ensureHttpUrl(value: string): string {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(`Unsupported model resource URL scheme: ${url.protocol}`);\n }\n return url.href;\n}\n","export * from \"./cache.js\";\nexport * from \"./fetch.js\";\nexport * from \"./runtime.js\";\nexport * from \"./types.js\";\n\n/** Package identity and rollout metadata for the runtime boundary. */\nexport const packageName = \"@plasius/gpu-model-runtime\" as const;\n\nexport const packageBootstrap = Object.freeze({\n packageName,\n featureFlag: \"gpu.model.conversion.enabled\",\n status: \"runtime\",\n} as const);\n"],"mappings":"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","names":[]}