@plasius/gpu-model-runtime 0.1.1 → 0.2.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/README.md +76 -3
- package/dist/index.cjs +636 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -1
- package/dist/index.d.ts +118 -1
- package/dist/index.js +633 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/cache.ts","../src/fetch.ts","../src/runtime.ts"],"sourcesContent":["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","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"],"mappings":"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","names":["module"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/cache.ts","../src/fetch.ts","../src/runtime.ts","../src/model-residency.ts"],"sourcesContent":["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\nexport * from \"./model-residency.js\";\n","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","import type {\n ModelAssetRef,\n ModelLodLevel,\n} from \"@plasius/asset-contracts\";\n\nconst SHA256_PATTERN = /^[a-f0-9]{64}$/u;\nconst PARTITION_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/u;\n\n/** Hard CPU, GPU, and concurrent-load limits for one residency manager. */\nexport interface ModelResidencyBudget {\n readonly maxCpuBytes: number;\n readonly maxGpuBytes: number;\n readonly maxInFlightLoads: number;\n}\n\n/** Adapter request for one immutable model LOD or partition. */\nexport interface ModelLoadRequest {\n readonly assetRef: ModelAssetRef;\n readonly lod: ModelLodLevel;\n readonly partitionId?: string;\n readonly priority: number;\n readonly signal: AbortSignal;\n}\n\n/** Resource returned by a format-specific loader/upload adapter. */\nexport interface ModelLoadedResource<Resource> {\n readonly resource: Resource;\n readonly contentHash: string;\n readonly cpuBytes: number;\n readonly gpuBytes: number;\n readonly dispose: () => void | Promise<void>;\n}\n\n/** Options for acquiring a shared model resource. */\nexport interface AcquireModelOptions {\n readonly assetRef: ModelAssetRef;\n readonly lod: ModelLodLevel;\n readonly partitionId?: string;\n readonly priority: number;\n readonly estimatedCpuBytes: number;\n readonly estimatedGpuBytes: number;\n readonly signal?: AbortSignal;\n readonly pinned?: boolean;\n}\n\n/** Idempotent reference to one shared resident model resource. */\nexport interface ModelResidencyLease<Resource> {\n readonly key: string;\n readonly assetRef: ModelAssetRef;\n readonly lod: ModelLodLevel;\n readonly partitionId?: string;\n readonly resource: Resource;\n release(): void;\n setPriority(priority: number): void;\n setPinned(pinned: boolean): void;\n}\n\n/** Construction boundary for adapter-driven model loading. */\nexport interface ModelResidencyManagerOptions<Resource> {\n readonly budget: ModelResidencyBudget;\n readonly load: (\n request: ModelLoadRequest,\n ) => Promise<ModelLoadedResource<Resource>>;\n readonly loadTimeoutMs?: number;\n}\n\nexport type ModelResidencyErrorCode =\n | \"acquire-aborted\"\n | \"budget-exceeded\"\n | \"content-hash-mismatch\"\n | \"invalid-load-result\"\n | \"load-timeout\"\n | \"manager-closed\";\n\n/** Stable operational error returned by residency-specific failure paths. */\nexport class ModelResidencyError extends Error {\n readonly code: ModelResidencyErrorCode;\n\n constructor(code: ModelResidencyErrorCode, message: string) {\n super(message);\n this.name = \"ModelResidencyError\";\n this.code = code;\n }\n}\n\nexport interface ModelResidencyEntrySnapshot {\n readonly key: string;\n readonly state: \"queued\" | \"loading\" | \"resident\";\n readonly priority: number;\n readonly references: number;\n readonly pinned: boolean;\n readonly cpuBytes: number;\n readonly gpuBytes: number;\n}\n\n/** Immutable accounting and lifetime metrics for diagnostics. */\nexport interface ModelResidencySnapshot {\n readonly maxCpuBytes: number;\n readonly maxGpuBytes: number;\n readonly maxInFlightLoads: number;\n readonly cpuBytes: number;\n readonly gpuBytes: number;\n readonly reservedCpuBytes: number;\n readonly reservedGpuBytes: number;\n readonly residentCount: number;\n readonly pendingCount: number;\n readonly referenceCount: number;\n readonly pinnedCount: number;\n readonly inFlightLoads: number;\n readonly queuedLoads: number;\n readonly acquireCount: number;\n readonly cacheHits: number;\n readonly deduplicatedAcquires: number;\n readonly loadsStarted: number;\n readonly loadsCompleted: number;\n readonly loadsFailed: number;\n readonly loadsAborted: number;\n readonly loadsTimedOut: number;\n readonly evictions: number;\n readonly disposals: number;\n readonly disposalFailures: number;\n readonly residentKeys: readonly string[];\n readonly entries: readonly ModelResidencyEntrySnapshot[];\n}\n\ninterface AcquisitionWaiter<Resource> {\n readonly id: number;\n priority: number;\n pinned: boolean;\n readonly signal?: AbortSignal;\n readonly resolve: (lease: ModelResidencyLease<Resource>) => void;\n readonly reject: (reason: unknown) => void;\n onAbort?: () => void;\n}\n\ninterface LeaseRecord {\n readonly id: number;\n active: boolean;\n priority: number;\n pinned: boolean;\n}\n\ninterface ResidencyEntry<Resource> {\n readonly key: string;\n readonly assetRef: ModelAssetRef;\n readonly lod: ModelLodLevel;\n readonly partitionId?: string;\n readonly estimatedCpuBytes: number;\n readonly estimatedGpuBytes: number;\n readonly queueOrder: number;\n state: \"queued\" | \"loading\" | \"resident\";\n priority: number;\n retainedPriority: number;\n lastUsed: number;\n abandoned: boolean;\n loadSlotReleased: boolean;\n waiters: Map<number, AcquisitionWaiter<Resource>>;\n leases: Map<number, LeaseRecord>;\n controller?: AbortController;\n timeout?: ReturnType<typeof setTimeout>;\n loaded?: ModelLoadedResource<Resource>;\n loadTask?: Promise<void>;\n}\n\ninterface MutableMetrics {\n acquireCount: number;\n cacheHits: number;\n deduplicatedAcquires: number;\n loadsStarted: number;\n loadsCompleted: number;\n loadsFailed: number;\n loadsAborted: number;\n loadsTimedOut: number;\n evictions: number;\n disposals: number;\n disposalFailures: number;\n}\n\nfunction requireSafeNonNegativeInteger(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new RangeError(`${name} must be a non-negative safe integer`);\n }\n}\n\nfunction requirePositiveSafeInteger(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new RangeError(`${name} must be a positive safe integer`);\n }\n}\n\nfunction requirePriority(priority: number): void {\n if (!Number.isFinite(priority) || priority < 0) {\n throw new RangeError(\"priority must be a non-negative finite number\");\n }\n}\n\nfunction requireLod(lod: ModelLodLevel): void {\n if (!Number.isInteger(lod) || lod < 0 || lod > 3) {\n throw new RangeError(\"lod must be an integer from 0 to 3\");\n }\n}\n\n/** Build the canonical content-hash, LOD, and optional partition cache key. */\nexport function createModelResidencyKey(\n assetRef: ModelAssetRef,\n lod: ModelLodLevel,\n partitionId?: string,\n): string {\n if (!SHA256_PATTERN.test(assetRef.contentHash)) {\n throw new Error(\"ModelAssetRef.contentHash must be a lowercase SHA-256 value\");\n }\n requireLod(lod);\n if (partitionId !== undefined && !PARTITION_ID_PATTERN.test(partitionId)) {\n throw new Error(\"partitionId must be a bounded runtime token\");\n }\n return `${assetRef.contentHash}:lod${lod}:${partitionId ?? \"whole\"}`;\n}\n\nfunction closedError(): ModelResidencyError {\n return new ModelResidencyError(\n \"manager-closed\",\n \"The model residency manager is closed\",\n );\n}\n\nfunction abortedError(): ModelResidencyError {\n return new ModelResidencyError(\n \"acquire-aborted\",\n \"The model residency acquisition was aborted\",\n );\n}\n\nfunction signalIsAborted(signal?: AbortSignal): boolean {\n return signal?.aborted === true;\n}\n\n/**\n * Content-addressed model cache with bounded work, reference-counted leases,\n * deterministic eviction, and exact-once adapter disposal.\n */\nexport class ModelResidencyManager<Resource = unknown> {\n readonly #budget: ModelResidencyBudget;\n readonly #load: (\n request: ModelLoadRequest,\n ) => Promise<ModelLoadedResource<Resource>>;\n readonly #loadTimeoutMs?: number;\n readonly #entries = new Map<string, ResidencyEntry<Resource>>();\n readonly #loadTasks = new Set<Promise<void>>();\n readonly #disposalTasks = new Set<Promise<void>>();\n readonly #metrics: MutableMetrics = {\n acquireCount: 0,\n cacheHits: 0,\n deduplicatedAcquires: 0,\n loadsStarted: 0,\n loadsCompleted: 0,\n loadsFailed: 0,\n loadsAborted: 0,\n loadsTimedOut: 0,\n evictions: 0,\n disposals: 0,\n disposalFailures: 0,\n };\n #nextIdentity = 1;\n #clock = 1;\n #inFlightLoads = 0;\n #closed = false;\n #admissionTail: Promise<void> = Promise.resolve();\n #shutdownPromise?: Promise<void>;\n\n constructor(options: ModelResidencyManagerOptions<Resource>) {\n requirePositiveSafeInteger(\n options.budget.maxCpuBytes,\n \"budget.maxCpuBytes\",\n );\n requirePositiveSafeInteger(\n options.budget.maxGpuBytes,\n \"budget.maxGpuBytes\",\n );\n requirePositiveSafeInteger(\n options.budget.maxInFlightLoads,\n \"budget.maxInFlightLoads\",\n );\n if (options.loadTimeoutMs !== undefined) {\n requirePositiveSafeInteger(options.loadTimeoutMs, \"loadTimeoutMs\");\n }\n this.#budget = Object.freeze({ ...options.budget });\n this.#load = options.load;\n this.#loadTimeoutMs = options.loadTimeoutMs;\n }\n\n /** Acquire one shared resource lease, loading it at most once per cache key. */\n acquire(options: AcquireModelOptions): Promise<ModelResidencyLease<Resource>> {\n try {\n if (this.#closed) throw closedError();\n requirePriority(options.priority);\n requireSafeNonNegativeInteger(\n options.estimatedCpuBytes,\n \"estimatedCpuBytes\",\n );\n requireSafeNonNegativeInteger(\n options.estimatedGpuBytes,\n \"estimatedGpuBytes\",\n );\n const key = createModelResidencyKey(\n options.assetRef,\n options.lod,\n options.partitionId,\n );\n if (signalIsAborted(options.signal)) throw abortedError();\n this.#metrics.acquireCount += 1;\n\n const existing = this.#entries.get(key);\n if (existing !== undefined) return this.#acquireExisting(existing, options);\n return this.#scheduleAdmission(key, options);\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #acquireExisting(\n entry: ResidencyEntry<Resource>,\n options: AcquireModelOptions,\n ): Promise<ModelResidencyLease<Resource>> {\n this.#metrics.deduplicatedAcquires += 1;\n if (entry.state === \"resident\") {\n this.#metrics.cacheHits += 1;\n return Promise.resolve(\n this.#createLease(\n entry,\n options.priority,\n options.pinned ?? false,\n ),\n );\n }\n return this.#addWaiter(entry, options);\n }\n\n #scheduleAdmission(\n key: string,\n options: AcquireModelOptions,\n ): Promise<ModelResidencyLease<Resource>> {\n let resolveAcquisition!: (lease: ModelResidencyLease<Resource>) => void;\n let rejectAcquisition!: (reason: unknown) => void;\n const acquisition = new Promise<ModelResidencyLease<Resource>>(\n (resolve, reject) => {\n resolveAcquisition = resolve;\n rejectAcquisition = reject;\n },\n );\n const admission = this.#admissionTail.then(async () => {\n if (this.#closed) throw closedError();\n if (signalIsAborted(options.signal)) throw abortedError();\n const existing = this.#entries.get(key);\n if (existing !== undefined) {\n void this.#acquireExisting(existing, options).then(\n resolveAcquisition,\n rejectAcquisition,\n );\n return;\n }\n await this.#ensureCapacityForReservation(\n options.estimatedCpuBytes,\n options.estimatedGpuBytes,\n );\n if (this.#closed) throw closedError();\n if (signalIsAborted(options.signal)) throw abortedError();\n const entry: ResidencyEntry<Resource> = {\n key,\n assetRef: options.assetRef,\n lod: options.lod,\n ...(options.partitionId === undefined\n ? {}\n : { partitionId: options.partitionId }),\n estimatedCpuBytes: options.estimatedCpuBytes,\n estimatedGpuBytes: options.estimatedGpuBytes,\n queueOrder: this.#nextIdentity++,\n state: \"queued\",\n priority: options.priority,\n retainedPriority: options.priority,\n lastUsed: this.#clock++,\n abandoned: false,\n loadSlotReleased: true,\n waiters: new Map(),\n leases: new Map(),\n };\n this.#entries.set(key, entry);\n void this.#addWaiter(entry, options).then(\n resolveAcquisition,\n rejectAcquisition,\n );\n this.#pumpQueue();\n });\n this.#admissionTail = admission.catch(() => undefined);\n void admission.catch(rejectAcquisition);\n return acquisition;\n }\n\n /** Dispose every currently unreferenced, unpinned resident cache entry. */\n async evictUnused(): Promise<void> {\n const tasks: Promise<void>[] = [];\n for (const entry of this.#evictionCandidates()) {\n tasks.push(this.#evict(entry));\n }\n await Promise.all(tasks);\n }\n\n /** Wait until queued/loading work and its resulting disposal have settled. */\n async waitForIdle(): Promise<void> {\n await this.#admissionTail;\n do {\n this.#pumpQueue();\n const tasks = [...this.#loadTasks];\n if (tasks.length > 0) {\n await Promise.allSettled(tasks);\n }\n } while (this.#loadTasks.size > 0 || this.#queuedCount() > 0);\n await Promise.allSettled([...this.#disposalTasks]);\n }\n\n /** Abort pending work and dispose every resident or late-completing resource. */\n shutdown(): Promise<void> {\n if (this.#shutdownPromise !== undefined) return this.#shutdownPromise;\n this.#closed = true;\n const error = closedError();\n const disposalTasks: Promise<void>[] = [];\n for (const entry of [...this.#entries.values()]) {\n if (entry.state === \"resident\") {\n this.#entries.delete(entry.key);\n disposalTasks.push(this.#disposeEntry(entry));\n continue;\n }\n this.#rejectWaiters(entry, error);\n if (entry.state === \"queued\") {\n this.#entries.delete(entry.key);\n } else {\n this.#abandonLoadingEntry(entry, error, false);\n }\n }\n this.#shutdownPromise = (async () => {\n await Promise.allSettled(disposalTasks);\n await this.waitForIdle();\n await Promise.allSettled([...this.#disposalTasks]);\n })();\n return this.#shutdownPromise;\n }\n\n /** Return immutable byte, queue, cache, and lifetime metrics. */\n snapshot(): ModelResidencySnapshot {\n let cpuBytes = 0;\n let gpuBytes = 0;\n let reservedCpuBytes = 0;\n let reservedGpuBytes = 0;\n let referenceCount = 0;\n let pinnedCount = 0;\n let residentCount = 0;\n let pendingCount = 0;\n const entries: ModelResidencyEntrySnapshot[] = [];\n\n for (const entry of this.#entries.values()) {\n const pinned = [...entry.leases.values()].some(\n (lease) => lease.active && lease.pinned,\n );\n const references = [...entry.leases.values()].filter(\n (lease) => lease.active,\n ).length;\n referenceCount += references;\n if (pinned) pinnedCount += 1;\n if (entry.state === \"resident\") {\n residentCount += 1;\n cpuBytes += entry.loaded!.cpuBytes;\n gpuBytes += entry.loaded!.gpuBytes;\n } else {\n pendingCount += 1;\n reservedCpuBytes += entry.estimatedCpuBytes;\n reservedGpuBytes += entry.estimatedGpuBytes;\n }\n entries.push(\n Object.freeze({\n key: entry.key,\n state: entry.state,\n priority: entry.priority,\n references,\n pinned,\n cpuBytes:\n entry.state === \"resident\"\n ? entry.loaded!.cpuBytes\n : entry.estimatedCpuBytes,\n gpuBytes:\n entry.state === \"resident\"\n ? entry.loaded!.gpuBytes\n : entry.estimatedGpuBytes,\n }),\n );\n }\n entries.sort((left, right) => left.key.localeCompare(right.key));\n return Object.freeze({\n ...this.#budget,\n cpuBytes,\n gpuBytes,\n reservedCpuBytes,\n reservedGpuBytes,\n residentCount,\n pendingCount,\n referenceCount,\n pinnedCount,\n inFlightLoads: this.#inFlightLoads,\n queuedLoads: this.#queuedCount(),\n ...this.#metrics,\n residentKeys: Object.freeze(\n entries\n .filter((entry) => entry.state === \"resident\")\n .map((entry) => entry.key),\n ),\n entries: Object.freeze(entries),\n });\n }\n\n #addWaiter(\n entry: ResidencyEntry<Resource>,\n options: AcquireModelOptions,\n ): Promise<ModelResidencyLease<Resource>> {\n const id = this.#nextIdentity++;\n let resolvePromise!: (lease: ModelResidencyLease<Resource>) => void;\n let rejectPromise!: (reason: unknown) => void;\n const promise = new Promise<ModelResidencyLease<Resource>>(\n (resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n },\n );\n const waiter: AcquisitionWaiter<Resource> = {\n id,\n priority: options.priority,\n pinned: options.pinned ?? false,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n resolve: resolvePromise,\n reject: rejectPromise,\n };\n if (options.signal !== undefined) {\n waiter.onAbort = () => this.#abortWaiter(entry, waiter);\n options.signal.addEventListener(\"abort\", waiter.onAbort, { once: true });\n }\n entry.waiters.set(id, waiter);\n entry.retainedPriority = Math.max(entry.retainedPriority, options.priority);\n this.#recalculatePriority(entry);\n return promise;\n }\n\n #abortWaiter(\n entry: ResidencyEntry<Resource>,\n waiter: AcquisitionWaiter<Resource>,\n ): void {\n entry.waiters.delete(waiter.id);\n this.#detachWaiterSignal(waiter);\n waiter.reject(abortedError());\n this.#recalculatePriority(entry);\n if (entry.waiters.size > 0) return;\n if (entry.state === \"queued\") {\n this.#entries.delete(entry.key);\n this.#pumpQueue();\n return;\n }\n this.#abandonLoadingEntry(entry, abortedError(), true);\n }\n\n #createLease(\n entry: ResidencyEntry<Resource>,\n priority: number,\n pinned: boolean,\n ): ModelResidencyLease<Resource> {\n const id = this.#nextIdentity++;\n const record: LeaseRecord = {\n id,\n active: true,\n priority,\n pinned,\n };\n entry.leases.set(id, record);\n entry.retainedPriority = priority;\n entry.lastUsed = this.#clock++;\n this.#recalculatePriority(entry);\n const lease = {\n key: entry.key,\n assetRef: entry.assetRef,\n lod: entry.lod,\n ...(entry.partitionId === undefined\n ? {}\n : { partitionId: entry.partitionId }),\n resource: entry.loaded!.resource,\n release: () => {\n if (!record.active) return;\n record.active = false;\n entry.leases.delete(id);\n entry.lastUsed = this.#clock++;\n this.#recalculatePriority(entry);\n },\n setPriority: (nextPriority: number) => {\n if (!record.active || this.#entries.get(entry.key) !== entry) return;\n requirePriority(nextPriority);\n record.priority = nextPriority;\n entry.retainedPriority = nextPriority;\n entry.lastUsed = this.#clock++;\n this.#recalculatePriority(entry);\n },\n setPinned: (nextPinned: boolean) => {\n if (!record.active || this.#entries.get(entry.key) !== entry) return;\n record.pinned = nextPinned;\n },\n } satisfies ModelResidencyLease<Resource>;\n return Object.freeze(lease);\n }\n\n #recalculatePriority(entry: ResidencyEntry<Resource>): void {\n let priority = entry.retainedPriority;\n for (const waiter of entry.waiters.values()) {\n priority = Math.max(priority, waiter.priority);\n }\n for (const lease of entry.leases.values()) {\n priority = Math.max(priority, lease.priority);\n }\n entry.priority = priority;\n }\n\n #pumpQueue(): void {\n if (this.#closed) return;\n while (this.#inFlightLoads < this.#budget.maxInFlightLoads) {\n const candidate = [...this.#entries.values()]\n .filter(\n (entry) =>\n entry.state === \"queued\" &&\n !entry.abandoned &&\n entry.waiters.size > 0,\n )\n .sort(\n (left, right) =>\n right.priority - left.priority ||\n left.queueOrder - right.queueOrder,\n )[0];\n if (candidate === undefined) return;\n this.#startLoad(candidate);\n }\n }\n\n #startLoad(entry: ResidencyEntry<Resource>): void {\n entry.state = \"loading\";\n entry.loadSlotReleased = false;\n entry.controller = new AbortController();\n this.#inFlightLoads += 1;\n this.#metrics.loadsStarted += 1;\n if (this.#loadTimeoutMs !== undefined) {\n entry.timeout = setTimeout(() => {\n this.#metrics.loadsTimedOut += 1;\n this.#abandonLoadingEntry(\n entry,\n new ModelResidencyError(\n \"load-timeout\",\n `Model load exceeded ${this.#loadTimeoutMs} ms`,\n ),\n true,\n );\n }, this.#loadTimeoutMs);\n }\n\n let adapterPromise: Promise<ModelLoadedResource<Resource>>;\n try {\n adapterPromise = this.#load({\n assetRef: entry.assetRef,\n lod: entry.lod,\n ...(entry.partitionId === undefined\n ? {}\n : { partitionId: entry.partitionId }),\n priority: entry.priority,\n signal: entry.controller.signal,\n });\n } catch (error) {\n adapterPromise = Promise.reject(error);\n }\n const task = Promise.resolve(adapterPromise)\n .then((result) => this.#completeLoad(entry, result))\n .catch((error: unknown) => this.#failLoad(entry, error))\n .finally(() => {\n if (entry.timeout !== undefined) clearTimeout(entry.timeout);\n entry.timeout = undefined;\n entry.controller = undefined;\n this.#releaseLoadSlot(entry);\n entry.loadTask = undefined;\n });\n entry.loadTask = task;\n this.#loadTasks.add(task);\n }\n\n async #completeLoad(\n entry: ResidencyEntry<Resource>,\n result: ModelLoadedResource<Resource>,\n ): Promise<void> {\n if (entry.abandoned) {\n await this.#disposeLoaded(result);\n return;\n }\n\n try {\n this.#validateLoadedResource(entry, result);\n const evictions = this.#ensureCapacityForLoadedResult(entry, result);\n await Promise.all(evictions);\n } catch (error) {\n await this.#disposeLoaded(result);\n this.#entries.delete(entry.key);\n this.#rejectWaiters(entry, error);\n this.#metrics.loadsFailed += 1;\n return;\n }\n\n entry.state = \"resident\";\n entry.loaded = result;\n entry.lastUsed = this.#clock++;\n this.#metrics.loadsCompleted += 1;\n const waiters = [...entry.waiters.values()];\n entry.waiters.clear();\n for (const waiter of waiters) {\n this.#detachWaiterSignal(waiter);\n waiter.resolve(this.#createLease(entry, waiter.priority, waiter.pinned));\n }\n }\n\n #failLoad(entry: ResidencyEntry<Resource>, error: unknown): void {\n if (entry.abandoned) return;\n this.#entries.delete(entry.key);\n this.#metrics.loadsFailed += 1;\n this.#rejectWaiters(entry, error);\n }\n\n #abandonLoadingEntry(\n entry: ResidencyEntry<Resource>,\n error: ModelResidencyError,\n rejectWaiters: boolean,\n ): void {\n entry.abandoned = true;\n this.#metrics.loadsAborted += 1;\n if (entry.timeout !== undefined) clearTimeout(entry.timeout);\n entry.timeout = undefined;\n this.#entries.delete(entry.key);\n if (rejectWaiters) this.#rejectWaiters(entry, error);\n entry.controller?.abort(error);\n this.#releaseLoadSlot(entry);\n }\n\n #releaseLoadSlot(entry: ResidencyEntry<Resource>): void {\n if (entry.loadSlotReleased) return;\n entry.loadSlotReleased = true;\n this.#inFlightLoads -= 1;\n this.#loadTasks.delete(entry.loadTask!);\n this.#pumpQueue();\n }\n\n #rejectWaiters(entry: ResidencyEntry<Resource>, error: unknown): void {\n const waiters = [...entry.waiters.values()];\n entry.waiters.clear();\n for (const waiter of waiters) {\n this.#detachWaiterSignal(waiter);\n waiter.reject(error);\n }\n this.#recalculatePriority(entry);\n }\n\n #detachWaiterSignal(waiter: AcquisitionWaiter<Resource>): void {\n if (waiter.signal !== undefined && waiter.onAbort !== undefined) {\n waiter.signal.removeEventListener(\"abort\", waiter.onAbort);\n }\n waiter.onAbort = undefined;\n }\n\n #validateLoadedResource(\n entry: ResidencyEntry<Resource>,\n result: ModelLoadedResource<Resource>,\n ): void {\n if (result === null || typeof result !== \"object\") {\n throw new ModelResidencyError(\n \"invalid-load-result\",\n \"The model loader returned an invalid resource\",\n );\n }\n if (typeof result.dispose !== \"function\") {\n throw new ModelResidencyError(\n \"invalid-load-result\",\n \"The model loader must return a disposer\",\n );\n }\n requireSafeNonNegativeInteger(result.cpuBytes, \"loaded.cpuBytes\");\n requireSafeNonNegativeInteger(result.gpuBytes, \"loaded.gpuBytes\");\n if (result.contentHash !== entry.assetRef.contentHash) {\n throw new ModelResidencyError(\n \"content-hash-mismatch\",\n \"The loaded model content hash does not match its canonical reference\",\n );\n }\n }\n\n async #ensureCapacityForReservation(\n cpuBytes: number,\n gpuBytes: number,\n ): Promise<void> {\n if (\n cpuBytes > this.#budget.maxCpuBytes ||\n gpuBytes > this.#budget.maxGpuBytes\n ) {\n throw this.#budgetError();\n }\n let usage = this.#totalAccountedBytes();\n for (const candidate of this.#evictionCandidates()) {\n if (\n usage.cpu + cpuBytes <= this.#budget.maxCpuBytes &&\n usage.gpu + gpuBytes <= this.#budget.maxGpuBytes\n ) {\n return;\n }\n await this.#evict(candidate);\n usage = this.#totalAccountedBytes();\n }\n if (\n usage.cpu + cpuBytes > this.#budget.maxCpuBytes ||\n usage.gpu + gpuBytes > this.#budget.maxGpuBytes\n ) {\n throw this.#budgetError();\n }\n }\n\n #ensureCapacityForLoadedResult(\n loadingEntry: ResidencyEntry<Resource>,\n result: ModelLoadedResource<Resource>,\n ): Promise<void>[] {\n const usage = this.#totalAccountedBytes();\n usage.cpu += result.cpuBytes - loadingEntry.estimatedCpuBytes;\n usage.gpu += result.gpuBytes - loadingEntry.estimatedGpuBytes;\n const disposals: Promise<void>[] = [];\n for (const candidate of this.#evictionCandidates()) {\n if (\n usage.cpu <= this.#budget.maxCpuBytes &&\n usage.gpu <= this.#budget.maxGpuBytes\n ) {\n return disposals;\n }\n usage.cpu -= candidate.loaded!.cpuBytes;\n usage.gpu -= candidate.loaded!.gpuBytes;\n disposals.push(this.#evict(candidate));\n }\n if (\n usage.cpu > this.#budget.maxCpuBytes ||\n usage.gpu > this.#budget.maxGpuBytes\n ) {\n throw this.#budgetError();\n }\n return disposals;\n }\n\n #budgetError(): ModelResidencyError {\n return new ModelResidencyError(\n \"budget-exceeded\",\n \"Pinned, referenced, or pending models leave insufficient residency budget\",\n );\n }\n\n #totalAccountedBytes(): { cpu: number; gpu: number } {\n let cpu = 0;\n let gpu = 0;\n for (const entry of this.#entries.values()) {\n if (entry.state === \"resident\") {\n cpu += entry.loaded!.cpuBytes;\n gpu += entry.loaded!.gpuBytes;\n } else {\n cpu += entry.estimatedCpuBytes;\n gpu += entry.estimatedGpuBytes;\n }\n }\n return { cpu, gpu };\n }\n\n #evictionCandidates(): ResidencyEntry<Resource>[] {\n return [...this.#entries.values()]\n .filter(\n (entry) =>\n entry.state === \"resident\" &&\n entry.leases.size === 0,\n )\n .sort(\n (left, right) =>\n left.priority - right.priority ||\n left.lastUsed - right.lastUsed,\n );\n }\n\n #evict(entry: ResidencyEntry<Resource>): Promise<void> {\n this.#entries.delete(entry.key);\n this.#metrics.evictions += 1;\n return this.#disposeEntry(entry);\n }\n\n #disposeEntry(entry: ResidencyEntry<Resource>): Promise<void> {\n const result = entry.loaded!;\n entry.loaded = undefined;\n return this.#disposeLoaded(result);\n }\n\n #disposeLoaded(result: ModelLoadedResource<Resource>): Promise<void> {\n this.#metrics.disposals += 1;\n let disposal: Promise<void>;\n try {\n disposal = Promise.resolve(result.dispose());\n } catch (error) {\n disposal = Promise.reject(error);\n }\n const tracked = disposal\n .catch(() => {\n this.#metrics.disposalFailures += 1;\n })\n .finally(() => {\n this.#disposalTasks.delete(tracked);\n });\n this.#disposalTasks.add(tracked);\n return tracked;\n }\n\n #queuedCount(): number {\n let count = 0;\n for (const entry of this.#entries.values()) {\n if (entry.state === \"queued\") count += 1;\n }\n return count;\n }\n}\n"],"mappings":"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","names":["module"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ModelAssetRef, ModelLodLevel } from '@plasius/asset-contracts';
|
|
2
|
+
|
|
1
3
|
type ModelSourceKind = "file-path" | "url" | "blob-storage-url" | "blob" | "array-buffer" | "uint8-array" | "stream";
|
|
2
4
|
type ModelProvenance = Readonly<{
|
|
3
5
|
sourceId?: string;
|
|
@@ -264,6 +266,121 @@ declare class ModelRuntime {
|
|
|
264
266
|
private resolveSource;
|
|
265
267
|
}
|
|
266
268
|
|
|
269
|
+
/** Hard CPU, GPU, and concurrent-load limits for one residency manager. */
|
|
270
|
+
interface ModelResidencyBudget {
|
|
271
|
+
readonly maxCpuBytes: number;
|
|
272
|
+
readonly maxGpuBytes: number;
|
|
273
|
+
readonly maxInFlightLoads: number;
|
|
274
|
+
}
|
|
275
|
+
/** Adapter request for one immutable model LOD or partition. */
|
|
276
|
+
interface ModelLoadRequest {
|
|
277
|
+
readonly assetRef: ModelAssetRef;
|
|
278
|
+
readonly lod: ModelLodLevel;
|
|
279
|
+
readonly partitionId?: string;
|
|
280
|
+
readonly priority: number;
|
|
281
|
+
readonly signal: AbortSignal;
|
|
282
|
+
}
|
|
283
|
+
/** Resource returned by a format-specific loader/upload adapter. */
|
|
284
|
+
interface ModelLoadedResource<Resource> {
|
|
285
|
+
readonly resource: Resource;
|
|
286
|
+
readonly contentHash: string;
|
|
287
|
+
readonly cpuBytes: number;
|
|
288
|
+
readonly gpuBytes: number;
|
|
289
|
+
readonly dispose: () => void | Promise<void>;
|
|
290
|
+
}
|
|
291
|
+
/** Options for acquiring a shared model resource. */
|
|
292
|
+
interface AcquireModelOptions {
|
|
293
|
+
readonly assetRef: ModelAssetRef;
|
|
294
|
+
readonly lod: ModelLodLevel;
|
|
295
|
+
readonly partitionId?: string;
|
|
296
|
+
readonly priority: number;
|
|
297
|
+
readonly estimatedCpuBytes: number;
|
|
298
|
+
readonly estimatedGpuBytes: number;
|
|
299
|
+
readonly signal?: AbortSignal;
|
|
300
|
+
readonly pinned?: boolean;
|
|
301
|
+
}
|
|
302
|
+
/** Idempotent reference to one shared resident model resource. */
|
|
303
|
+
interface ModelResidencyLease<Resource> {
|
|
304
|
+
readonly key: string;
|
|
305
|
+
readonly assetRef: ModelAssetRef;
|
|
306
|
+
readonly lod: ModelLodLevel;
|
|
307
|
+
readonly partitionId?: string;
|
|
308
|
+
readonly resource: Resource;
|
|
309
|
+
release(): void;
|
|
310
|
+
setPriority(priority: number): void;
|
|
311
|
+
setPinned(pinned: boolean): void;
|
|
312
|
+
}
|
|
313
|
+
/** Construction boundary for adapter-driven model loading. */
|
|
314
|
+
interface ModelResidencyManagerOptions<Resource> {
|
|
315
|
+
readonly budget: ModelResidencyBudget;
|
|
316
|
+
readonly load: (request: ModelLoadRequest) => Promise<ModelLoadedResource<Resource>>;
|
|
317
|
+
readonly loadTimeoutMs?: number;
|
|
318
|
+
}
|
|
319
|
+
type ModelResidencyErrorCode = "acquire-aborted" | "budget-exceeded" | "content-hash-mismatch" | "invalid-load-result" | "load-timeout" | "manager-closed";
|
|
320
|
+
/** Stable operational error returned by residency-specific failure paths. */
|
|
321
|
+
declare class ModelResidencyError extends Error {
|
|
322
|
+
readonly code: ModelResidencyErrorCode;
|
|
323
|
+
constructor(code: ModelResidencyErrorCode, message: string);
|
|
324
|
+
}
|
|
325
|
+
interface ModelResidencyEntrySnapshot {
|
|
326
|
+
readonly key: string;
|
|
327
|
+
readonly state: "queued" | "loading" | "resident";
|
|
328
|
+
readonly priority: number;
|
|
329
|
+
readonly references: number;
|
|
330
|
+
readonly pinned: boolean;
|
|
331
|
+
readonly cpuBytes: number;
|
|
332
|
+
readonly gpuBytes: number;
|
|
333
|
+
}
|
|
334
|
+
/** Immutable accounting and lifetime metrics for diagnostics. */
|
|
335
|
+
interface ModelResidencySnapshot {
|
|
336
|
+
readonly maxCpuBytes: number;
|
|
337
|
+
readonly maxGpuBytes: number;
|
|
338
|
+
readonly maxInFlightLoads: number;
|
|
339
|
+
readonly cpuBytes: number;
|
|
340
|
+
readonly gpuBytes: number;
|
|
341
|
+
readonly reservedCpuBytes: number;
|
|
342
|
+
readonly reservedGpuBytes: number;
|
|
343
|
+
readonly residentCount: number;
|
|
344
|
+
readonly pendingCount: number;
|
|
345
|
+
readonly referenceCount: number;
|
|
346
|
+
readonly pinnedCount: number;
|
|
347
|
+
readonly inFlightLoads: number;
|
|
348
|
+
readonly queuedLoads: number;
|
|
349
|
+
readonly acquireCount: number;
|
|
350
|
+
readonly cacheHits: number;
|
|
351
|
+
readonly deduplicatedAcquires: number;
|
|
352
|
+
readonly loadsStarted: number;
|
|
353
|
+
readonly loadsCompleted: number;
|
|
354
|
+
readonly loadsFailed: number;
|
|
355
|
+
readonly loadsAborted: number;
|
|
356
|
+
readonly loadsTimedOut: number;
|
|
357
|
+
readonly evictions: number;
|
|
358
|
+
readonly disposals: number;
|
|
359
|
+
readonly disposalFailures: number;
|
|
360
|
+
readonly residentKeys: readonly string[];
|
|
361
|
+
readonly entries: readonly ModelResidencyEntrySnapshot[];
|
|
362
|
+
}
|
|
363
|
+
/** Build the canonical content-hash, LOD, and optional partition cache key. */
|
|
364
|
+
declare function createModelResidencyKey(assetRef: ModelAssetRef, lod: ModelLodLevel, partitionId?: string): string;
|
|
365
|
+
/**
|
|
366
|
+
* Content-addressed model cache with bounded work, reference-counted leases,
|
|
367
|
+
* deterministic eviction, and exact-once adapter disposal.
|
|
368
|
+
*/
|
|
369
|
+
declare class ModelResidencyManager<Resource = unknown> {
|
|
370
|
+
#private;
|
|
371
|
+
constructor(options: ModelResidencyManagerOptions<Resource>);
|
|
372
|
+
/** Acquire one shared resource lease, loading it at most once per cache key. */
|
|
373
|
+
acquire(options: AcquireModelOptions): Promise<ModelResidencyLease<Resource>>;
|
|
374
|
+
/** Dispose every currently unreferenced, unpinned resident cache entry. */
|
|
375
|
+
evictUnused(): Promise<void>;
|
|
376
|
+
/** Wait until queued/loading work and its resulting disposal have settled. */
|
|
377
|
+
waitForIdle(): Promise<void>;
|
|
378
|
+
/** Abort pending work and dispose every resident or late-completing resource. */
|
|
379
|
+
shutdown(): Promise<void>;
|
|
380
|
+
/** Return immutable byte, queue, cache, and lifetime metrics. */
|
|
381
|
+
snapshot(): ModelResidencySnapshot;
|
|
382
|
+
}
|
|
383
|
+
|
|
267
384
|
/** Package identity and rollout metadata for the runtime boundary. */
|
|
268
385
|
declare const packageName: "@plasius/gpu-model-runtime";
|
|
269
386
|
declare const packageBootstrap: Readonly<{
|
|
@@ -272,4 +389,4 @@ declare const packageBootstrap: Readonly<{
|
|
|
272
389
|
readonly status: "runtime";
|
|
273
390
|
}>;
|
|
274
391
|
|
|
275
|
-
export { type AdapterLoadContext, type AdapterLoadResult, type AdapterModule, type AdapterRegistration, AdapterRegistry, type BlobStorageUrlResolver, type FetchPolicy, type FetchedResource, type HashBytes, type LoadModelOptions, MemoryModelCache, type ModelAdapter, type ModelCache, type ModelLoadResult, type ModelPackage, type ModelProvenance, type ModelResourceInput, ModelRuntime, type ModelSource, type ModelSourceKind, PackageResourceResolver, type ReadFile, type ResolveResourceOptions, type ResolvedModelSource, type ResolvedResource, type ResourceReference, type ResourceResolver, type RuntimeDependencies, type RuntimeFetch, type Sleep, type SniffInput, type WorkerDispatcher, type WorkerLoadRequest, createModelCacheKey, defaultSleep, fetchResource, packageBootstrap, packageName, sha256Hex, verifyIntegrity };
|
|
392
|
+
export { type AcquireModelOptions, type AdapterLoadContext, type AdapterLoadResult, type AdapterModule, type AdapterRegistration, AdapterRegistry, type BlobStorageUrlResolver, type FetchPolicy, type FetchedResource, type HashBytes, type LoadModelOptions, MemoryModelCache, type ModelAdapter, type ModelCache, type ModelLoadRequest, type ModelLoadResult, type ModelLoadedResource, type ModelPackage, type ModelProvenance, type ModelResidencyBudget, type ModelResidencyEntrySnapshot, ModelResidencyError, type ModelResidencyErrorCode, type ModelResidencyLease, ModelResidencyManager, type ModelResidencyManagerOptions, type ModelResidencySnapshot, type ModelResourceInput, ModelRuntime, type ModelSource, type ModelSourceKind, PackageResourceResolver, type ReadFile, type ResolveResourceOptions, type ResolvedModelSource, type ResolvedResource, type ResourceReference, type ResourceResolver, type RuntimeDependencies, type RuntimeFetch, type Sleep, type SniffInput, type WorkerDispatcher, type WorkerLoadRequest, createModelCacheKey, createModelResidencyKey, defaultSleep, fetchResource, packageBootstrap, packageName, sha256Hex, verifyIntegrity };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ModelAssetRef, ModelLodLevel } from '@plasius/asset-contracts';
|
|
2
|
+
|
|
1
3
|
type ModelSourceKind = "file-path" | "url" | "blob-storage-url" | "blob" | "array-buffer" | "uint8-array" | "stream";
|
|
2
4
|
type ModelProvenance = Readonly<{
|
|
3
5
|
sourceId?: string;
|
|
@@ -264,6 +266,121 @@ declare class ModelRuntime {
|
|
|
264
266
|
private resolveSource;
|
|
265
267
|
}
|
|
266
268
|
|
|
269
|
+
/** Hard CPU, GPU, and concurrent-load limits for one residency manager. */
|
|
270
|
+
interface ModelResidencyBudget {
|
|
271
|
+
readonly maxCpuBytes: number;
|
|
272
|
+
readonly maxGpuBytes: number;
|
|
273
|
+
readonly maxInFlightLoads: number;
|
|
274
|
+
}
|
|
275
|
+
/** Adapter request for one immutable model LOD or partition. */
|
|
276
|
+
interface ModelLoadRequest {
|
|
277
|
+
readonly assetRef: ModelAssetRef;
|
|
278
|
+
readonly lod: ModelLodLevel;
|
|
279
|
+
readonly partitionId?: string;
|
|
280
|
+
readonly priority: number;
|
|
281
|
+
readonly signal: AbortSignal;
|
|
282
|
+
}
|
|
283
|
+
/** Resource returned by a format-specific loader/upload adapter. */
|
|
284
|
+
interface ModelLoadedResource<Resource> {
|
|
285
|
+
readonly resource: Resource;
|
|
286
|
+
readonly contentHash: string;
|
|
287
|
+
readonly cpuBytes: number;
|
|
288
|
+
readonly gpuBytes: number;
|
|
289
|
+
readonly dispose: () => void | Promise<void>;
|
|
290
|
+
}
|
|
291
|
+
/** Options for acquiring a shared model resource. */
|
|
292
|
+
interface AcquireModelOptions {
|
|
293
|
+
readonly assetRef: ModelAssetRef;
|
|
294
|
+
readonly lod: ModelLodLevel;
|
|
295
|
+
readonly partitionId?: string;
|
|
296
|
+
readonly priority: number;
|
|
297
|
+
readonly estimatedCpuBytes: number;
|
|
298
|
+
readonly estimatedGpuBytes: number;
|
|
299
|
+
readonly signal?: AbortSignal;
|
|
300
|
+
readonly pinned?: boolean;
|
|
301
|
+
}
|
|
302
|
+
/** Idempotent reference to one shared resident model resource. */
|
|
303
|
+
interface ModelResidencyLease<Resource> {
|
|
304
|
+
readonly key: string;
|
|
305
|
+
readonly assetRef: ModelAssetRef;
|
|
306
|
+
readonly lod: ModelLodLevel;
|
|
307
|
+
readonly partitionId?: string;
|
|
308
|
+
readonly resource: Resource;
|
|
309
|
+
release(): void;
|
|
310
|
+
setPriority(priority: number): void;
|
|
311
|
+
setPinned(pinned: boolean): void;
|
|
312
|
+
}
|
|
313
|
+
/** Construction boundary for adapter-driven model loading. */
|
|
314
|
+
interface ModelResidencyManagerOptions<Resource> {
|
|
315
|
+
readonly budget: ModelResidencyBudget;
|
|
316
|
+
readonly load: (request: ModelLoadRequest) => Promise<ModelLoadedResource<Resource>>;
|
|
317
|
+
readonly loadTimeoutMs?: number;
|
|
318
|
+
}
|
|
319
|
+
type ModelResidencyErrorCode = "acquire-aborted" | "budget-exceeded" | "content-hash-mismatch" | "invalid-load-result" | "load-timeout" | "manager-closed";
|
|
320
|
+
/** Stable operational error returned by residency-specific failure paths. */
|
|
321
|
+
declare class ModelResidencyError extends Error {
|
|
322
|
+
readonly code: ModelResidencyErrorCode;
|
|
323
|
+
constructor(code: ModelResidencyErrorCode, message: string);
|
|
324
|
+
}
|
|
325
|
+
interface ModelResidencyEntrySnapshot {
|
|
326
|
+
readonly key: string;
|
|
327
|
+
readonly state: "queued" | "loading" | "resident";
|
|
328
|
+
readonly priority: number;
|
|
329
|
+
readonly references: number;
|
|
330
|
+
readonly pinned: boolean;
|
|
331
|
+
readonly cpuBytes: number;
|
|
332
|
+
readonly gpuBytes: number;
|
|
333
|
+
}
|
|
334
|
+
/** Immutable accounting and lifetime metrics for diagnostics. */
|
|
335
|
+
interface ModelResidencySnapshot {
|
|
336
|
+
readonly maxCpuBytes: number;
|
|
337
|
+
readonly maxGpuBytes: number;
|
|
338
|
+
readonly maxInFlightLoads: number;
|
|
339
|
+
readonly cpuBytes: number;
|
|
340
|
+
readonly gpuBytes: number;
|
|
341
|
+
readonly reservedCpuBytes: number;
|
|
342
|
+
readonly reservedGpuBytes: number;
|
|
343
|
+
readonly residentCount: number;
|
|
344
|
+
readonly pendingCount: number;
|
|
345
|
+
readonly referenceCount: number;
|
|
346
|
+
readonly pinnedCount: number;
|
|
347
|
+
readonly inFlightLoads: number;
|
|
348
|
+
readonly queuedLoads: number;
|
|
349
|
+
readonly acquireCount: number;
|
|
350
|
+
readonly cacheHits: number;
|
|
351
|
+
readonly deduplicatedAcquires: number;
|
|
352
|
+
readonly loadsStarted: number;
|
|
353
|
+
readonly loadsCompleted: number;
|
|
354
|
+
readonly loadsFailed: number;
|
|
355
|
+
readonly loadsAborted: number;
|
|
356
|
+
readonly loadsTimedOut: number;
|
|
357
|
+
readonly evictions: number;
|
|
358
|
+
readonly disposals: number;
|
|
359
|
+
readonly disposalFailures: number;
|
|
360
|
+
readonly residentKeys: readonly string[];
|
|
361
|
+
readonly entries: readonly ModelResidencyEntrySnapshot[];
|
|
362
|
+
}
|
|
363
|
+
/** Build the canonical content-hash, LOD, and optional partition cache key. */
|
|
364
|
+
declare function createModelResidencyKey(assetRef: ModelAssetRef, lod: ModelLodLevel, partitionId?: string): string;
|
|
365
|
+
/**
|
|
366
|
+
* Content-addressed model cache with bounded work, reference-counted leases,
|
|
367
|
+
* deterministic eviction, and exact-once adapter disposal.
|
|
368
|
+
*/
|
|
369
|
+
declare class ModelResidencyManager<Resource = unknown> {
|
|
370
|
+
#private;
|
|
371
|
+
constructor(options: ModelResidencyManagerOptions<Resource>);
|
|
372
|
+
/** Acquire one shared resource lease, loading it at most once per cache key. */
|
|
373
|
+
acquire(options: AcquireModelOptions): Promise<ModelResidencyLease<Resource>>;
|
|
374
|
+
/** Dispose every currently unreferenced, unpinned resident cache entry. */
|
|
375
|
+
evictUnused(): Promise<void>;
|
|
376
|
+
/** Wait until queued/loading work and its resulting disposal have settled. */
|
|
377
|
+
waitForIdle(): Promise<void>;
|
|
378
|
+
/** Abort pending work and dispose every resident or late-completing resource. */
|
|
379
|
+
shutdown(): Promise<void>;
|
|
380
|
+
/** Return immutable byte, queue, cache, and lifetime metrics. */
|
|
381
|
+
snapshot(): ModelResidencySnapshot;
|
|
382
|
+
}
|
|
383
|
+
|
|
267
384
|
/** Package identity and rollout metadata for the runtime boundary. */
|
|
268
385
|
declare const packageName: "@plasius/gpu-model-runtime";
|
|
269
386
|
declare const packageBootstrap: Readonly<{
|
|
@@ -272,4 +389,4 @@ declare const packageBootstrap: Readonly<{
|
|
|
272
389
|
readonly status: "runtime";
|
|
273
390
|
}>;
|
|
274
391
|
|
|
275
|
-
export { type AdapterLoadContext, type AdapterLoadResult, type AdapterModule, type AdapterRegistration, AdapterRegistry, type BlobStorageUrlResolver, type FetchPolicy, type FetchedResource, type HashBytes, type LoadModelOptions, MemoryModelCache, type ModelAdapter, type ModelCache, type ModelLoadResult, type ModelPackage, type ModelProvenance, type ModelResourceInput, ModelRuntime, type ModelSource, type ModelSourceKind, PackageResourceResolver, type ReadFile, type ResolveResourceOptions, type ResolvedModelSource, type ResolvedResource, type ResourceReference, type ResourceResolver, type RuntimeDependencies, type RuntimeFetch, type Sleep, type SniffInput, type WorkerDispatcher, type WorkerLoadRequest, createModelCacheKey, defaultSleep, fetchResource, packageBootstrap, packageName, sha256Hex, verifyIntegrity };
|
|
392
|
+
export { type AcquireModelOptions, type AdapterLoadContext, type AdapterLoadResult, type AdapterModule, type AdapterRegistration, AdapterRegistry, type BlobStorageUrlResolver, type FetchPolicy, type FetchedResource, type HashBytes, type LoadModelOptions, MemoryModelCache, type ModelAdapter, type ModelCache, type ModelLoadRequest, type ModelLoadResult, type ModelLoadedResource, type ModelPackage, type ModelProvenance, type ModelResidencyBudget, type ModelResidencyEntrySnapshot, ModelResidencyError, type ModelResidencyErrorCode, type ModelResidencyLease, ModelResidencyManager, type ModelResidencyManagerOptions, type ModelResidencySnapshot, type ModelResourceInput, ModelRuntime, type ModelSource, type ModelSourceKind, PackageResourceResolver, type ReadFile, type ResolveResourceOptions, type ResolvedModelSource, type ResolvedResource, type ResourceReference, type ResourceResolver, type RuntimeDependencies, type RuntimeFetch, type Sleep, type SniffInput, type WorkerDispatcher, type WorkerLoadRequest, createModelCacheKey, createModelResidencyKey, defaultSleep, fetchResource, packageBootstrap, packageName, sha256Hex, verifyIntegrity };
|