66 * browsers); falls back to filesystem reads in Node when given a
77 * `file:` or relative URL.
88 *
9- * The manifest (version → URL mapping) lives in `./manifest.ts`.
10- * The base URL (CDN mirror override) lives in `./base.ts`.
11- *
12- * Adding a new provision source (e.g. IPFS, BitTorrent) = adding a
13- * new provisioner file. Existing code never changes (OCP).
9+ * The manifest-based resolution layer was removed in 4.0.0: models
10+ * resolve through the IMF registry (`imf`, GitHub Releases index,
11+ * sha256-verified) or an explicit `url` on the ModelRef.
1412 */
1513
1614import type { ModelArtifacts , ModelRef } from "../types.js"
1715import type { InferenceSession } from "../session/index.js"
1816import { createSession } from "../session/index.js"
19- import {
20- artifactUrls ,
21- resolveManifestEntry ,
22- sidecarFilenames ,
23- type AssetFormat ,
24- type AssetVariant ,
25- } from "./manifest.js"
17+ import type { AssetFormat , AssetVariant } from "./types.js"
2618
2719export interface ProvisionedModel {
2820 readonly session : InferenceSession
@@ -61,10 +53,9 @@ export interface ProvisionOptions {
6153}
6254
6355/**
64- * Provision a model from the manifest. Resolves the task version,
65- * downloads the model file from the CDN (falls back to GitHub
66- * Releases), opens an inference session, and fetches sidecar
67- * artifacts (vocab, config, checksum) in parallel.
56+ * Provision a model from an explicit URL. Downloads the model file,
57+ * opens an inference session, and returns it with any artifacts the
58+ * caller fetches separately.
6859 *
6960 * In Node, can read from the filesystem if `url` starts with `file:`
7061 * or is a relative path.
@@ -73,35 +64,19 @@ export async function provisionModel(
7364 ref : ModelRef ,
7465 opts : ProvisionOptions = { } ,
7566) : Promise < ProvisionedModel > {
76- const variant = opts . variant ?? "q8"
7767 const format = opts . format ?? "onnx"
7868 const webgpu = opts . webgpu ?? true
7969
80- const modelUrl = ref . url ?? ( await resolveModelUrl ( ref , variant , format ) )
81-
82- const modelBuffer = await fetchBytesWithFallback ( modelUrl )
70+ if ( ! ref . url ) {
71+ throw new Error (
72+ `No url on ModelRef kind=${ ref . kind } id=${ ref . id } . Load models via ` +
73+ `\`import { imf } from "interscript/ml"\` and \`imf.resolve("${ ref . id } ")\` ` +
74+ `(GitHub Releases index, sha256-verified), or pass an explicit \`url\` on the ModelRef.` ,
75+ )
76+ }
8377
84- const sidecars = await resolveSidecarUrls ( ref , variant , format )
78+ const modelBuffer = await fetchBytesWithFallback ( ref . url )
8579 const artifacts : Record < string , Uint8Array | string > = { }
86- await Promise . all (
87- sidecars . map ( async ( { filename, url } ) => {
88- try {
89- const bytes = await fetchBytesWithFallback ( url )
90- if (
91- filename . endsWith ( ".json" ) ||
92- filename . endsWith ( ".yaml" ) ||
93- filename . endsWith ( ".yml" ) ||
94- filename . endsWith ( ".sha256" )
95- ) {
96- artifacts [ filename ] = new TextDecoder ( ) . decode ( bytes )
97- } else {
98- artifacts [ filename ] = bytes
99- }
100- } catch {
101- // Sidecars are optional; missing ones are skipped.
102- }
103- } ) ,
104- )
10580
10681 const sessionOpts : Record < string , unknown > = { webgpu }
10782 if ( format === "tflite" ) {
@@ -114,42 +89,6 @@ export async function provisionModel(
11489 return { session, artifacts }
11590}
11691
117- async function resolveModelUrl (
118- ref : ModelRef ,
119- variant : AssetVariant ,
120- format : AssetFormat ,
121- ) : Promise < string > {
122- const entry = await resolveManifestEntry ( ref . kind , ref . id )
123- if ( ! entry ) {
124- throw new Error (
125- `No manifest entry for kind=${ ref . kind } id=${ ref . id } . The manifest-based ` +
126- `provisioner is deprecated; load models via \`import { imf } from "interscript/ml"\` ` +
127- `and \`imf.resolve("${ ref . id } ")\` (GitHub Releases index, sha256-verified), ` +
128- `or pass an explicit \`url\` on the ModelRef.` ,
129- )
130- }
131- const { primary } = artifactUrls ( entry , variant , format )
132- return primary
133- }
134-
135- async function resolveSidecarUrls (
136- ref : ModelRef ,
137- variant : AssetVariant ,
138- format : AssetFormat ,
139- ) : Promise < readonly { filename : string ; url : string } [ ] > {
140- // If the caller provided an explicit URL, skip manifest-based sidecar
141- // resolution — they've taken control of provisioning.
142- if ( ref . url ) return [ ]
143- const entry = await resolveManifestEntry ( ref . kind , ref . id )
144- if ( ! entry ) return [ ]
145- const { primary, assetName } = artifactUrls ( entry , variant , format )
146- const base = primary . slice ( 0 , primary . lastIndexOf ( "/" ) + 1 )
147- return sidecarFilenames ( entry , variant , format ) . map ( ( filename ) => ( {
148- filename,
149- url : `${ base } ${ filename . startsWith ( assetName ) ? filename : filename } ` ,
150- } ) )
151- }
152-
15392/**
15493 * Fetch bytes from a URL. Tries the URL as-given; if it's the CDN
15594 * primary and fails, the caller can supply a fallback URL via the
0 commit comments