{"version":3,"file":"session.cjs","names":[],"sources":["../../../src/vision/core/session.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Thin wrapper around `onnxruntime-web` `InferenceSession` with typed metadata.\n */\n\nimport type * as ort from \"onnxruntime-web\";\nimport * as ortRuntime from \"onnxruntime-web\";\n\nimport { InferenceError, ModelLoadError } from \"./exceptions\";\nimport { type DeclaredShape, declaredShapesFrom } from \"./graph\";\nimport { readModelMetadata } from \"./metadata\";\nimport { FALLBACK_PROVIDER, detectProviders, resolveProviders } from \"./providers\";\n\n/** Anything `InferenceSession.create` accepts. */\nexport type ModelSource = string | ArrayBufferLike | Uint8Array;\n\n/**\n * Fetch a model URL as bytes so its metadata can be read.\n *\n * Falls back to the URL itself when the fetch fails, letting ORT try its own\n * load path: losing the metadata map is a downgrade, but failing to load a model\n * that ORT could have fetched would be a regression.\n *\n * @param url Where the `.onnx` lives.\n * @returns The model bytes, or the original URL when they could not be fetched.\n */\nasync function fetchModel(url: string): Promise<Uint8Array | string> {\n    try {\n        const response = await fetch(url);\n        if (!response.ok) {\n            warnMetadataUnavailable(url, `HTTP ${response.status} ${response.statusText}`);\n            return url;\n        }\n        return new Uint8Array(await response.arrayBuffer());\n    } catch (err) {\n        warnMetadataUnavailable(url, (err as Error).message);\n        return url;\n    }\n}\n\n/**\n * Warn that a model's metadata could not be read, and say what that costs.\n *\n * The fallback itself is right — losing the metadata beats failing a load that\n * ORT could have completed on its own — but it used to be silent, and the\n * symptom it produces is remote from the cause: class names come back as\n * `class_0`, `class_1`, ... with nothing anywhere explaining why. Whoever hits\n * this needs to be told that passing `labels` is the way out.\n *\n * @param url The model URL that could not be fetched here.\n * @param reason What went wrong, as reported by `fetch`.\n */\nfunction warnMetadataUnavailable(url: string, reason: string): void {\n    console.warn(\n        `[@ort-vision-sdk/web] Could not fetch ${url} to read its metadata (${reason}). ` +\n            \"Letting ONNX Runtime load it instead: the model will work, but its baked-in \" +\n            \"class names are unavailable, so labels fall back to class_0, class_1, ... \" +\n            \"Pass `labels` explicitly to name them.\",\n    );\n}\n\nexport interface OrtSessionOptions {\n    /**\n     * Execution providers in preference order. `undefined` uses {@link DEFAULT_PROVIDERS}.\n     *\n     * Naming one explicitly also opts into a `console.warn` when this browser\n     * cannot offer it, instead of falling back in silence.\n     */\n    readonly providers?: readonly string[];\n    /** Optional ORT session options forwarded to `InferenceSession.create`. */\n    readonly sessionOptions?: ort.InferenceSession.SessionOptions;\n    /**\n     * Whether to read the model's custom metadata map (`names`, `task`, `imgsz`).\n     * Defaults to `true`.\n     *\n     * The runtime does not expose that map, so it is read from the file itself —\n     * which means a URL model is fetched here and handed to ORT as bytes instead\n     * of letting ORT fetch it. That is the same single download either way, and\n     * it is what lets a task resolve its labels off the model. Set to `false` to\n     * keep the URL path untouched and leave {@link OrtSession.metadata} empty.\n     *\n     * `false` is also the escape hatch when a device cannot afford the bytes: the\n     * fetched buffer is dropped before ORT builds the graph (see\n     * {@link OrtSession.create}), but ORT's own load path still keeps the model out\n     * of reach of anything the SDK holds. A session built this way resolves its\n     * input size from the graph as usual — only the class names are lost, so a\n     * caller taking this route has to pass `labels` itself.\n     */\n    readonly readMetadata?: boolean;\n}\n\n/**\n * Warn when a provider named explicitly by the caller is not going to run.\n *\n * Only explicit requests are worth a warning. The default list exists precisely\n * so that falling from `webgpu` to `wasm` is the expected outcome — but a caller\n * who wrote `providers: [\"webgpu\"]` and lands on WASM has a page several times\n * slower than intended and nothing in the console to explain it.\n *\n * @param requested Providers that were asked for.\n * @param effective Providers that survived capability detection.\n */\nfunction warnOnDroppedProviders(requested: readonly string[], effective: readonly string[]): void {\n    const dropped = requested.filter((provider) => !effective.includes(provider));\n    if (dropped.length === 0) {\n        return;\n    }\n    console.warn(\n        `This browser cannot offer the requested execution provider(s) ${JSON.stringify(dropped)}; ` +\n            `the session will run on ${JSON.stringify(effective)}. Inference still produces correct ` +\n            \"results, on the fallback provider.\",\n    );\n}\n\n/**\n * Wrap an ONNX Runtime Web `InferenceSession` with convenient metadata access.\n *\n * The wrapper exposes input/output names and the shapes the graph declares,\n * manages execution-provider selection, provides a typed {@link OrtSession.run}\n * method, and releases the native session through {@link OrtSession.release}.\n */\nexport class OrtSession {\n    private constructor(\n        private readonly _session: ort.InferenceSession,\n        /**\n         * Execution providers this session is expected to run on.\n         *\n         * The requested list narrowed to what this browser can actually offer — a\n         * `webgpu` entry survives only where an adapter exists. Best-effort: ORT-Web\n         * exposes no way to ask which provider a session ended up on, so an entry\n         * here means \"not ruled out\", not \"confirmed\". See\n         * {@link requestedProviders} for what was asked for.\n         *\n         * When nothing survives — a caller asking for `webgpu` alone on a device\n         * without it — this falls back to {@link FALLBACK_PROVIDER}, which ORT-Web\n         * can always run. Handing ORT the unsatisfiable list instead makes\n         * `InferenceSession.create` reject with \"no available backend found\", so the\n         * page gets no inference at all rather than the slow-but-working fallback\n         * the `console.warn` describes. Measured in a real Chromium, where\n         * `navigator.gpu` exists but yields no adapter.\n         */\n        public readonly providers: readonly string[],\n        private readonly _metadata: Readonly<Record<string, string>>,\n        /**\n         * Execution providers that were asked for, after defaults were applied.\n         *\n         * Kept separate because ORT-Web falls back silently: a page that asks for\n         * `webgpu` on a device without it runs on WASM and is told nothing.\n         */\n        public readonly requestedProviders: readonly string[],\n    ) {}\n\n    /**\n     * Load an ONNX model into an ORT inference session.\n     *\n     * The metadata map is read **before** the session is built, and that order is\n     * load-bearing on memory-constrained devices. ORT copies the model into its\n     * WASM heap and then allocates the graph and the weights on top of that copy;\n     * a `readModelMetadata` call placed after `InferenceSession.create` keeps the\n     * JavaScript-side buffer reachable across the whole build, so a 5 MB model\n     * costs 5 MB of JS heap plus 5 MB of WASM heap plus the weights at the same\n     * instant. Reading first makes the buffer collectable as soon as ORT has copied\n     * it — on a phone that was the difference between a session and\n     * `Can't create a session. failed to allocate a buffer of size N`.\n     *\n     * @param model Either a URL string, or a `Uint8Array`/`ArrayBuffer` containing the model bytes.\n     * @param options Provider list, pass-through `SessionOptions`, and whether to\n     *   read the model's metadata map (see {@link OrtSessionOptions.readMetadata}).\n     * @throws {@link ModelLoadError} if the model cannot be loaded.\n     */\n    static async create(model: ModelSource, options: OrtSessionOptions = {}): Promise<OrtSession> {\n        const requested = resolveProviders(options.providers);\n        const detected = await detectProviders(requested);\n        const providers = detected.length > 0 ? detected : [FALLBACK_PROVIDER];\n        if (options.providers !== undefined && options.providers.length > 0) {\n            warnOnDroppedProviders(requested, providers);\n        }\n        const sessionOptions: ort.InferenceSession.SessionOptions = {\n            ...(options.sessionOptions ?? {}),\n            executionProviders:\n                providers as ort.InferenceSession.SessionOptions[\"executionProviders\"],\n        };\n        const wantsMetadata = options.readMetadata !== false;\n        const source = typeof model === \"string\" && wantsMetadata ? await fetchModel(model) : model;\n        const metadata =\n            wantsMetadata && typeof source !== \"string\" ? readModelMetadata(source) : {};\n\n        let session: ort.InferenceSession;\n        try {\n            if (typeof source === \"string\") {\n                session = await ortRuntime.InferenceSession.create(source, sessionOptions);\n            } else if (source instanceof Uint8Array) {\n                session = await ortRuntime.InferenceSession.create(source, sessionOptions);\n            } else {\n                session = await ortRuntime.InferenceSession.create(\n                    source as ArrayBuffer,\n                    sessionOptions,\n                );\n            }\n        } catch (err) {\n            throw new ModelLoadError(`Failed to load ONNX model: ${(err as Error).message}`, {\n                cause: err,\n            });\n        }\n\n        return new OrtSession(session, providers, metadata, requested);\n    }\n\n    /** Names of the model's inputs, in declaration order. */\n    get inputNames(): readonly string[] {\n        return this._session.inputNames;\n    }\n\n    /** Name of the first (and usually only) input. */\n    get inputName(): string {\n        const name = this._session.inputNames[0];\n        if (name === undefined) {\n            throw new InferenceError(\"Model has no inputs.\");\n        }\n        return name;\n    }\n\n    /** Names of the model's outputs, in declaration order. */\n    get outputNames(): readonly string[] {\n        return this._session.outputNames;\n    }\n\n    /**\n     * Shapes the graph declares for its inputs, in declaration order.\n     *\n     * Dynamic (symbolic) axes appear as `null`. Empty shapes mean the runtime\n     * reported no metadata — either a non-tensor input, or an `onnxruntime-web`\n     * older than 1.21, which predates input metadata.\n     */\n    get inputShapes(): readonly DeclaredShape[] {\n        return declaredShapesFrom(\n            this._session.inputMetadata as\n                readonly ort.InferenceSession.ValueMetadata[] | undefined,\n        );\n    }\n\n    /**\n     * Shape the graph declares for its first input, dynamic axes as `null`.\n     *\n     * Empty when the runtime reports no metadata for it.\n     */\n    get inputShape(): DeclaredShape {\n        return this.inputShapes[0] ?? [];\n    }\n\n    /**\n     * Shapes the graph declares for its outputs, in declaration order.\n     *\n     * Dynamic (symbolic) axes appear as `null`. Reading them is how a task can\n     * tell how many classes a head emits without being told.\n     */\n    get outputShapes(): readonly DeclaredShape[] {\n        return declaredShapesFrom(\n            this._session.outputMetadata as\n                readonly ort.InferenceSession.ValueMetadata[] | undefined,\n        );\n    }\n\n    /**\n     * Shape the graph declares for its first output, dynamic axes as `null`.\n     *\n     * Empty when the runtime reports no metadata for it.\n     */\n    get outputShape(): DeclaredShape {\n        return this.outputShapes[0] ?? [];\n    }\n\n    /**\n     * The model's custom metadata map — `names`, `task`, `imgsz`, ... for an\n     * Ultralytics export.\n     *\n     * Read from the model's bytes at load time, since the runtime does not expose\n     * it. Empty when the session was created with `readMetadata: false`, from a\n     * URL that could not be fetched here, or from a model carrying no metadata.\n     */\n    get metadata(): Readonly<Record<string, string>> {\n        return this._metadata;\n    }\n\n    /**\n     * Release the native session and free its memory.\n     *\n     * Call it when a session is discarded while the page lives on — rebuilding a\n     * task at a different input size, swapping in a newer model. A failure from\n     * the runtime is ignored: a session being torn down has nothing left to fail\n     * at, and the caller is already moving on.\n     */\n    async release(): Promise<void> {\n        await this._session.release().catch(() => undefined);\n    }\n\n    /** The underlying `onnxruntime-web` session, for advanced use cases. */\n    get raw(): ort.InferenceSession {\n        return this._session;\n    }\n\n    /**\n     * Run inference and return all outputs.\n     *\n     * @param feeds Map of input name to `ort.Tensor`. Keys must match {@link inputNames}.\n     * @throws {@link InferenceError} if ORT raises any error during execution.\n     */\n    async run(feeds: Record<string, ort.Tensor>): Promise<Record<string, ort.Tensor>> {\n        try {\n            const result = await this._session.run(feeds);\n            return result as Record<string, ort.Tensor>;\n        } catch (err) {\n            throw new InferenceError(`Inference failed: ${(err as Error).message}`, { cause: err });\n        }\n    }\n}\n"],"mappings":"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"}