Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "interscript",
"version": "3.3.0",
"version": "4.0.0",
"description": "Interscript TypeScript runtime — interoperable script conversion",
"type": "module",
"main": "./dist/index.js",
Expand Down
29 changes: 0 additions & 29 deletions src/ml/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,35 +32,6 @@ export { registerModel, loadModel, registeredKinds, resetModels } from "./regist

export { createSession, detectBackend } from "./session/index.js"

/**
* @deprecated CDN-base override for the deprecated manifest-based
* provisioner. IMF models resolve through the GitHub Releases
* index instead.
*/
export { setModelBase, getModelBase } from "./provision/base.js"

/**
* @deprecated The manifest-based provisioner (loose .onnx + sidecars
* behind a version→URL manifest) is superseded by the IMF registry:
* `import { imf } from "interscript/ml"` → `imf.resolve("<model-id>")`
* (GitHub Releases index, sha256-verified zips). Kept for explicit-URL
* provisioning and inline-manifest (test/air-gapped) use; no manifest
* is published anymore.
*/
export {
loadManifest,
resolveManifestEntry,
artifactUrls,
sidecarFilenames,
setInlineManifest,
setManifestUrl,
type AssetVariant,
/** @deprecated — see the block comment above */
type Manifest,
/** @deprecated — see the block comment above */
type ManifestModelEntry,
} from "./provision/manifest.js"

/**
* The IMF v1 registry — models.yaml resolution over GitHub Releases
* (sha256-sidecar-verified). This is the canonical way to load models
Expand Down
21 changes: 0 additions & 21 deletions src/ml/provision/base.ts

This file was deleted.

91 changes: 15 additions & 76 deletions src/ml/provision/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,15 @@
* browsers); falls back to filesystem reads in Node when given a
* `file:` or relative URL.
*
* The manifest (version → URL mapping) lives in `./manifest.ts`.
* The base URL (CDN mirror override) lives in `./base.ts`.
*
* Adding a new provision source (e.g. IPFS, BitTorrent) = adding a
* new provisioner file. Existing code never changes (OCP).
* The manifest-based resolution layer was removed in 4.0.0: models
* resolve through the IMF registry (`imf`, GitHub Releases index,
* sha256-verified) or an explicit `url` on the ModelRef.
*/

import type { ModelArtifacts, ModelRef } from "../types.js"
import type { InferenceSession } from "../session/index.js"
import { createSession } from "../session/index.js"
import {
artifactUrls,
resolveManifestEntry,
sidecarFilenames,
type AssetFormat,
type AssetVariant,
} from "./manifest.js"
import type { AssetFormat, AssetVariant } from "./types.js"

export interface ProvisionedModel {
readonly session: InferenceSession
Expand Down Expand Up @@ -61,10 +53,9 @@ export interface ProvisionOptions {
}

/**
* Provision a model from the manifest. Resolves the task version,
* downloads the model file from the CDN (falls back to GitHub
* Releases), opens an inference session, and fetches sidecar
* artifacts (vocab, config, checksum) in parallel.
* Provision a model from an explicit URL. Downloads the model file,
* opens an inference session, and returns it with any artifacts the
* caller fetches separately.
*
* In Node, can read from the filesystem if `url` starts with `file:`
* or is a relative path.
Expand All @@ -73,35 +64,19 @@ export async function provisionModel(
ref: ModelRef,
opts: ProvisionOptions = {},
): Promise<ProvisionedModel> {
const variant = opts.variant ?? "q8"
const format = opts.format ?? "onnx"
const webgpu = opts.webgpu ?? true

const modelUrl = ref.url ?? (await resolveModelUrl(ref, variant, format))

const modelBuffer = await fetchBytesWithFallback(modelUrl)
if (!ref.url) {
throw new Error(
`No url on ModelRef kind=${ref.kind} id=${ref.id}. Load models via ` +
`\`import { imf } from "interscript/ml"\` and \`imf.resolve("${ref.id}")\` ` +
`(GitHub Releases index, sha256-verified), or pass an explicit \`url\` on the ModelRef.`,
)
}

const sidecars = await resolveSidecarUrls(ref, variant, format)
const modelBuffer = await fetchBytesWithFallback(ref.url)
const artifacts: Record<string, Uint8Array | string> = {}
await Promise.all(
sidecars.map(async ({ filename, url }) => {
try {
const bytes = await fetchBytesWithFallback(url)
if (
filename.endsWith(".json") ||
filename.endsWith(".yaml") ||
filename.endsWith(".yml") ||
filename.endsWith(".sha256")
) {
artifacts[filename] = new TextDecoder().decode(bytes)
} else {
artifacts[filename] = bytes
}
} catch {
// Sidecars are optional; missing ones are skipped.
}
}),
)

const sessionOpts: Record<string, unknown> = { webgpu }
if (format === "tflite") {
Expand All @@ -114,42 +89,6 @@ export async function provisionModel(
return { session, artifacts }
}

async function resolveModelUrl(
ref: ModelRef,
variant: AssetVariant,
format: AssetFormat,
): Promise<string> {
const entry = await resolveManifestEntry(ref.kind, ref.id)
if (!entry) {
throw new Error(
`No manifest entry for kind=${ref.kind} id=${ref.id}. The manifest-based ` +
`provisioner is deprecated; load models via \`import { imf } from "interscript/ml"\` ` +
`and \`imf.resolve("${ref.id}")\` (GitHub Releases index, sha256-verified), ` +
`or pass an explicit \`url\` on the ModelRef.`,
)
}
const { primary } = artifactUrls(entry, variant, format)
return primary
}

async function resolveSidecarUrls(
ref: ModelRef,
variant: AssetVariant,
format: AssetFormat,
): Promise<readonly { filename: string; url: string }[]> {
// If the caller provided an explicit URL, skip manifest-based sidecar
// resolution — they've taken control of provisioning.
if (ref.url) return []
const entry = await resolveManifestEntry(ref.kind, ref.id)
if (!entry) return []
const { primary, assetName } = artifactUrls(entry, variant, format)
const base = primary.slice(0, primary.lastIndexOf("/") + 1)
return sidecarFilenames(entry, variant, format).map((filename) => ({
filename,
url: `${base}${filename.startsWith(assetName) ? filename : filename}`,
}))
}

/**
* Fetch bytes from a URL. Tries the URL as-given; if it's the CDN
* primary and fails, the caller can supply a fallback URL via the
Expand Down
184 changes: 0 additions & 184 deletions src/ml/provision/manifest.ts

This file was deleted.

2 changes: 2 additions & 0 deletions src/ml/provision/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type AssetVariant = "fp32" | "q8" | "q4" | "fp16"
export type AssetFormat = "onnx" | "tflite"
Loading
Loading