From d9ee3ede0810912933a7a17362d2a66ef6ebb886 Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Fri, 28 Aug 2026 06:30:26 +0800 Subject: [PATCH] =?UTF-8?q?deprecate:=20manifest-based=20provisioner=20?= =?UTF-8?q?=E2=80=94=20IMF=20registry=20is=20the=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No manifest has ever been published (the @interscript/models package was never released; the CDN manifest.json URL 404s — with a doubled path segment in the default URL). Both failure paths now direct users to imf.resolve (GitHub Releases index, sha256-verified). Public manifest APIs get @deprecated annotations; explicit-URL and inline-manifest (test/air-gapped) use is unchanged. --- package.json | 2 +- src/ml/index.ts | 15 +++++++++++++++ src/ml/provision/index.ts | 6 ++++-- src/ml/provision/manifest.ts | 24 ++++++++++++++---------- test/ml/provision.test.ts | 21 +++++++++++++++++++++ 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 7be7734..a7a453e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interscript", - "version": "3.2.0", + "version": "3.3.0", "description": "Interscript TypeScript runtime — interoperable script conversion", "type": "module", "main": "./dist/index.js", diff --git a/src/ml/index.ts b/src/ml/index.ts index 658b7c6..f252748 100644 --- a/src/ml/index.ts +++ b/src/ml/index.ts @@ -32,8 +32,21 @@ 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("")` + * (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, @@ -42,7 +55,9 @@ export { setInlineManifest, setManifestUrl, type AssetVariant, + /** @deprecated — see the block comment above */ type Manifest, + /** @deprecated — see the block comment above */ type ManifestModelEntry, } from "./provision/manifest.js" diff --git a/src/ml/provision/index.ts b/src/ml/provision/index.ts index b13d3a3..42cc38b 100644 --- a/src/ml/provision/index.ts +++ b/src/ml/provision/index.ts @@ -122,8 +122,10 @@ async function resolveModelUrl( const entry = await resolveManifestEntry(ref.kind, ref.id) if (!entry) { throw new Error( - `No manifest entry for kind=${ref.kind} id=${ref.id}. ` + - `Pass an explicit \`url\` on the ModelRef or pin a task version in the manifest.`, + `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) diff --git a/src/ml/provision/manifest.ts b/src/ml/provision/manifest.ts index 700ccba..45f6aaf 100644 --- a/src/ml/provision/manifest.ts +++ b/src/ml/provision/manifest.ts @@ -1,19 +1,18 @@ /** - * Manifest-driven model resolution. + * Manifest-driven model resolution. DEPRECATED — superseded by the IMF + * registry (`src/ml/imf/`, published at `imf` from "interscript/ml"): + * models.yaml on GitHub Releases with sha256 sidecar verification. * - * The source of truth for "what model version is current" lives in - * the `@interscript/models` npm package (a tiny JSON manifest kept - * in lockstep with GH Releases in `interscript/ml-models`). + * No manifest is published anymore (the `@interscript/models` npm + * package was never released; the CDN manifest.json URL is dead). + * This module remains for explicit-URL provisioning and + * inline-manifest (test / air-gapped) use. * * Resolution order for the manifest itself: * 1. Programmatically injected via `setManifestUrl()` or * `setInlineManifest()` (tests, air-gapped envs). - * 2. The `@interscript/models` package, when installed. - * 3. A remote JSON URL on the CDN (`manifest.json` next to the + * 2. A remote JSON URL on the CDN (`manifest.json` next to the * release assets). - * - * See `ml-models/TODO.distribution/04-npm-packages.md` for the - * full MECE breakdown of who owns what. */ import { getModelBase } from "./base.js" @@ -99,7 +98,12 @@ export async function loadManifest(): Promise { const url = manifestUrlOverride ?? defaultManifestUrl() const res = await fetch(url) if (!res.ok) { - throw new Error(`Failed to load model manifest from ${url}: ${res.status} ${res.statusText}`) + throw new Error( + `Failed to load model manifest from ${url}: ${res.status} ${res.statusText}. ` + + `The manifest-based provisioner is deprecated and no manifest is published; ` + + `load models via \`import { imf } from "interscript/ml"\` and \`imf.resolve("")\` ` + + `(GitHub Releases index, sha256-verified), or pass an explicit \`url\` on the ModelRef.`, + ) } const json = (await res.json()) as Manifest cachedManifest = json diff --git a/test/ml/provision.test.ts b/test/ml/provision.test.ts index 6ef8a22..2b817d9 100644 --- a/test/ml/provision.test.ts +++ b/test/ml/provision.test.ts @@ -15,6 +15,7 @@ import { type Manifest, type ManifestModelEntry, } from "../../src/ml/provision/manifest.js" +import { provisionModel } from "../../src/ml/provision/index.js" const SAMPLE_ENTRY: ManifestModelEntry = { status: "stable", @@ -115,4 +116,24 @@ describe("manifest provisioner", () => { expect(() => artifactUrls(malformed)).toThrow(/task name/) }) }) + + describe("manifest-less resolution errors point at the IMF registry", () => { + it("rejects with imf guidance when no manifest is published and no url given", async () => { + setInlineManifest(null) + try { + await expect(provisionModel({ kind: "secryst", id: "unresolved" })).rejects.toThrow( + /imf\.resolve\(/, + ) + } finally { + setInlineManifest(SAMPLE_MANIFEST) + } + }) + + it("rejects with imf guidance when the manifest has no matching entry", async () => { + setInlineManifest(SAMPLE_MANIFEST) // has no entry for this id + await expect(provisionModel({ kind: "secryst", id: "unresolved" })).rejects.toThrow( + /imf\.resolve\(/, + ) + }) + }) })