tempest-react-sdk 0.38.0 → 0.38.2

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.
@@ -1,2 +1,2 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("./exceptions.cjs"),n=require("./graph.cjs"),r=require("./metadata.cjs"),i=require("./providers.cjs");let a=require("onnxruntime-web");a=e.__toESM(a,1);async function o(e){try{let t=await fetch(e);return t.ok?new Uint8Array(await t.arrayBuffer()):e}catch{return e}}var s=class e{_session;providers;_metadata;constructor(e,t,n){this._session=e,this.providers=t,this._metadata=n}static async create(n,s={}){let c=i.resolveProviders(s.providers),l={...s.sessionOptions??{},executionProviders:c},u=s.readMetadata!==!1,d=typeof n==`string`&&u?await o(n):n,f;try{f=(typeof d==`string`||d instanceof Uint8Array,await a.InferenceSession.create(d,l))}catch(e){throw new t.ModelLoadError(`Failed to load ONNX model: ${e.message}`,{cause:e})}let p=u&&typeof d!=`string`?r.readModelMetadata(d):{};return new e(f,c,p)}get inputNames(){return this._session.inputNames}get inputName(){let e=this._session.inputNames[0];if(e===void 0)throw new t.InferenceError(`Model has no inputs.`);return e}get outputNames(){return this._session.outputNames}get inputShapes(){return n.declaredShapesFrom(this._session.inputMetadata)}get inputShape(){return this.inputShapes[0]??[]}get outputShapes(){return n.declaredShapesFrom(this._session.outputMetadata)}get outputShape(){return this.outputShapes[0]??[]}get metadata(){return this._metadata}async release(){await this._session.release().catch(()=>void 0)}get raw(){return this._session}async run(e){try{return await this._session.run(e)}catch(e){throw new t.InferenceError(`Inference failed: ${e.message}`,{cause:e})}}};exports.OrtSession=s;
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("./exceptions.cjs"),n=require("./graph.cjs"),r=require("./metadata.cjs"),i=require("./providers.cjs");let a=require("onnxruntime-web");a=e.__toESM(a,1);async function o(e){try{let t=await fetch(e);return t.ok?new Uint8Array(await t.arrayBuffer()):e}catch{return e}}var s=class e{_session;providers;_metadata;constructor(e,t,n){this._session=e,this.providers=t,this._metadata=n}static async create(n,s={}){let c=i.resolveProviders(s.providers),l={...s.sessionOptions??{},executionProviders:c},u=s.readMetadata!==!1,d=typeof n==`string`&&u?await o(n):n,f=u&&typeof d!=`string`?r.readModelMetadata(d):{},p;try{p=(typeof d==`string`||d instanceof Uint8Array,await a.InferenceSession.create(d,l))}catch(e){throw new t.ModelLoadError(`Failed to load ONNX model: ${e.message}`,{cause:e})}return new e(p,c,f)}get inputNames(){return this._session.inputNames}get inputName(){let e=this._session.inputNames[0];if(e===void 0)throw new t.InferenceError(`Model has no inputs.`);return e}get outputNames(){return this._session.outputNames}get inputShapes(){return n.declaredShapesFrom(this._session.inputMetadata)}get inputShape(){return this.inputShapes[0]??[]}get outputShapes(){return n.declaredShapesFrom(this._session.outputMetadata)}get outputShape(){return this.outputShapes[0]??[]}get metadata(){return this._metadata}async release(){await this._session.release().catch(()=>void 0)}get raw(){return this._session}async run(e){try{return await this._session.run(e)}catch(e){throw new t.InferenceError(`Inference failed: ${e.message}`,{cause:e})}}};exports.OrtSession=s;
2
2
  //# sourceMappingURL=session.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.cjs","names":[],"sources":["../../../src/vision/core/session.ts"],"sourcesContent":["/**\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 { 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) return url;\n return new Uint8Array(await response.arrayBuffer());\n } catch {\n return url;\n }\n}\n\nexport interface OrtSessionOptions {\n /** Execution providers in preference order. `undefined` uses {@link DEFAULT_PROVIDERS}. */\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 readonly readMetadata?: boolean;\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 public readonly providers: readonly string[],\n private readonly _metadata: Readonly<Record<string, string>>,\n ) {}\n\n /**\n * Load an ONNX model into an ORT inference session.\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 providers = resolveProviders(options.providers);\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\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 const metadata =\n wantsMetadata && typeof source !== \"string\" ? readModelMetadata(source) : {};\n return new OrtSession(session, providers, metadata);\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":"0NAyBA,eAAe,EAAW,EAA2C,CACjE,GAAI,CACA,IAAM,EAAW,MAAM,MAAM,CAAG,EAEhC,OADK,EAAS,GACP,IAAI,WAAW,MAAM,EAAS,YAAY,CAAC,EADzB,CAE7B,MAAQ,CACJ,OAAO,CACX,CACJ,CA2BA,IAAa,EAAb,MAAa,CAAW,CAEC,SACD,UACC,UAHrB,YACI,EACA,EACA,EACF,CAHmB,KAAA,SAAA,EACD,KAAA,UAAA,EACC,KAAA,UAAA,CAClB,CAUH,aAAa,OAAO,EAAoB,EAA6B,CAAC,EAAwB,CAC1F,IAAM,EAAY,EAAA,iBAAiB,EAAQ,SAAS,EAC9C,EAAsD,CACxD,GAAI,EAAQ,gBAAkB,CAAC,EAC/B,mBACI,CACR,EACM,EAAgB,EAAQ,eAAiB,GACzC,EAAS,OAAO,GAAU,UAAY,EAAgB,MAAM,EAAW,CAAK,EAAI,EAElF,EACJ,GAAI,CACA,AAKI,GALA,OAAO,GAAW,UAEX,aAAkB,WADf,MAAM,EAAW,iBAAiB,OAAO,EAAQ,CAAc,EASjF,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,8BAA+B,EAAc,UAAW,CAC7E,MAAO,CACX,CAAC,CACL,CAEA,IAAM,EACF,GAAiB,OAAO,GAAW,SAAW,EAAA,kBAAkB,CAAM,EAAI,CAAC,EAC/E,OAAO,IAAI,EAAW,EAAS,EAAW,CAAQ,CACtD,CAGA,IAAI,YAAgC,CAChC,OAAO,KAAK,SAAS,UACzB,CAGA,IAAI,WAAoB,CACpB,IAAM,EAAO,KAAK,SAAS,WAAW,GACtC,GAAI,IAAS,IAAA,GACT,MAAM,IAAI,EAAA,eAAe,sBAAsB,EAEnD,OAAO,CACX,CAGA,IAAI,aAAiC,CACjC,OAAO,KAAK,SAAS,WACzB,CASA,IAAI,aAAwC,CACxC,OAAO,EAAA,mBACH,KAAK,SAAS,aAElB,CACJ,CAOA,IAAI,YAA4B,CAC5B,OAAO,KAAK,YAAY,IAAM,CAAC,CACnC,CAQA,IAAI,cAAyC,CACzC,OAAO,EAAA,mBACH,KAAK,SAAS,cAElB,CACJ,CAOA,IAAI,aAA6B,CAC7B,OAAO,KAAK,aAAa,IAAM,CAAC,CACpC,CAUA,IAAI,UAA6C,CAC7C,OAAO,KAAK,SAChB,CAUA,MAAM,SAAyB,CAC3B,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,UAAY,IAAA,EAAS,CACvD,CAGA,IAAI,KAA4B,CAC5B,OAAO,KAAK,QAChB,CAQA,MAAM,IAAI,EAAwE,CAC9E,GAAI,CAEA,OAAO,MADc,KAAK,SAAS,IAAI,CAAK,CAEhD,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,qBAAsB,EAAc,UAAW,CAAE,MAAO,CAAI,CAAC,CAC1F,CACJ,CACJ"}
1
+ {"version":3,"file":"session.cjs","names":[],"sources":["../../../src/vision/core/session.ts"],"sourcesContent":["/**\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 { 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) return url;\n return new Uint8Array(await response.arrayBuffer());\n } catch {\n return url;\n }\n}\n\nexport interface OrtSessionOptions {\n /** Execution providers in preference order. `undefined` uses {@link DEFAULT_PROVIDERS}. */\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 * 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 public readonly providers: readonly string[],\n private readonly _metadata: Readonly<Record<string, 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 providers = resolveProviders(options.providers);\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);\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":"0NAyBA,eAAe,EAAW,EAA2C,CACjE,GAAI,CACA,IAAM,EAAW,MAAM,MAAM,CAAG,EAEhC,OADK,EAAS,GACP,IAAI,WAAW,MAAM,EAAS,YAAY,CAAC,EADzB,CAE7B,MAAQ,CACJ,OAAO,CACX,CACJ,CAkCA,IAAa,EAAb,MAAa,CAAW,CAEC,SACD,UACC,UAHrB,YACI,EACA,EACA,EACF,CAHmB,KAAA,SAAA,EACD,KAAA,UAAA,EACC,KAAA,UAAA,CAClB,CAoBH,aAAa,OAAO,EAAoB,EAA6B,CAAC,EAAwB,CAC1F,IAAM,EAAY,EAAA,iBAAiB,EAAQ,SAAS,EAC9C,EAAsD,CACxD,GAAI,EAAQ,gBAAkB,CAAC,EAC/B,mBACI,CACR,EACM,EAAgB,EAAQ,eAAiB,GACzC,EAAS,OAAO,GAAU,UAAY,EAAgB,MAAM,EAAW,CAAK,EAAI,EAChF,EACF,GAAiB,OAAO,GAAW,SAAW,EAAA,kBAAkB,CAAM,EAAI,CAAC,EAE3E,EACJ,GAAI,CACA,AAKI,GALA,OAAO,GAAW,UAEX,aAAkB,WADf,MAAM,EAAW,iBAAiB,OAAO,EAAQ,CAAc,EASjF,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,8BAA+B,EAAc,UAAW,CAC7E,MAAO,CACX,CAAC,CACL,CAEA,OAAO,IAAI,EAAW,EAAS,EAAW,CAAQ,CACtD,CAGA,IAAI,YAAgC,CAChC,OAAO,KAAK,SAAS,UACzB,CAGA,IAAI,WAAoB,CACpB,IAAM,EAAO,KAAK,SAAS,WAAW,GACtC,GAAI,IAAS,IAAA,GACT,MAAM,IAAI,EAAA,eAAe,sBAAsB,EAEnD,OAAO,CACX,CAGA,IAAI,aAAiC,CACjC,OAAO,KAAK,SAAS,WACzB,CASA,IAAI,aAAwC,CACxC,OAAO,EAAA,mBACH,KAAK,SAAS,aAElB,CACJ,CAOA,IAAI,YAA4B,CAC5B,OAAO,KAAK,YAAY,IAAM,CAAC,CACnC,CAQA,IAAI,cAAyC,CACzC,OAAO,EAAA,mBACH,KAAK,SAAS,cAElB,CACJ,CAOA,IAAI,aAA6B,CAC7B,OAAO,KAAK,aAAa,IAAM,CAAC,CACpC,CAUA,IAAI,UAA6C,CAC7C,OAAO,KAAK,SAChB,CAUA,MAAM,SAAyB,CAC3B,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,UAAY,IAAA,EAAS,CACvD,CAGA,IAAI,KAA4B,CAC5B,OAAO,KAAK,QAChB,CAQA,MAAM,IAAI,EAAwE,CAC9E,GAAI,CAEA,OAAO,MADc,KAAK,SAAS,IAAI,CAAK,CAEhD,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,qBAAsB,EAAc,UAAW,CAAE,MAAO,CAAI,CAAC,CAC1F,CACJ,CACJ"}
@@ -23,14 +23,13 @@ var s = class s {
23
23
  let c = i(n.providers), l = {
24
24
  ...n.sessionOptions ?? {},
25
25
  executionProviders: c
26
- }, u = n.readMetadata !== !1, d = typeof e == "string" && u ? await o(e) : e, f;
26
+ }, u = n.readMetadata !== !1, d = typeof e == "string" && u ? await o(e) : e, f = u && typeof d != "string" ? r(d) : {}, p;
27
27
  try {
28
- f = (typeof d == "string" || d instanceof Uint8Array, await a.InferenceSession.create(d, l));
28
+ p = (typeof d == "string" || d instanceof Uint8Array, await a.InferenceSession.create(d, l));
29
29
  } catch (e) {
30
30
  throw new t(`Failed to load ONNX model: ${e.message}`, { cause: e });
31
31
  }
32
- let p = u && typeof d != "string" ? r(d) : {};
33
- return new s(f, c, p);
32
+ return new s(p, c, f);
34
33
  }
35
34
  get inputNames() {
36
35
  return this._session.inputNames;
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","names":[],"sources":["../../../src/vision/core/session.ts"],"sourcesContent":["/**\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 { 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) return url;\n return new Uint8Array(await response.arrayBuffer());\n } catch {\n return url;\n }\n}\n\nexport interface OrtSessionOptions {\n /** Execution providers in preference order. `undefined` uses {@link DEFAULT_PROVIDERS}. */\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 readonly readMetadata?: boolean;\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 public readonly providers: readonly string[],\n private readonly _metadata: Readonly<Record<string, string>>,\n ) {}\n\n /**\n * Load an ONNX model into an ORT inference session.\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 providers = resolveProviders(options.providers);\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\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 const metadata =\n wantsMetadata && typeof source !== \"string\" ? readModelMetadata(source) : {};\n return new OrtSession(session, providers, metadata);\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":";;;;;;AAyBA,eAAe,EAAW,GAA2C;CACjE,IAAI;EACA,IAAM,IAAW,MAAM,MAAM,CAAG;EAEhC,OADK,EAAS,KACP,IAAI,WAAW,MAAM,EAAS,YAAY,CAAC,IADzB;CAE7B,QAAQ;EACJ,OAAO;CACX;AACJ;AA2BA,IAAa,IAAb,MAAa,EAAW;CAEC;CACD;CACC;CAHrB,YACI,GACA,GACA,GACF;EADmB,AAFA,KAAA,WAAA,GACD,KAAA,YAAA,GACC,KAAA,YAAA;CAClB;CAUH,aAAa,OAAO,GAAoB,IAA6B,CAAC,GAAwB;EAC1F,IAAM,IAAY,EAAiB,EAAQ,SAAS,GAC9C,IAAsD;GACxD,GAAI,EAAQ,kBAAkB,CAAC;GAC/B,oBACI;EACR,GACM,IAAgB,EAAQ,iBAAiB,IACzC,IAAS,OAAO,KAAU,YAAY,IAAgB,MAAM,EAAW,CAAK,IAAI,GAElF;EACJ,IAAI;GACA,AAKI,KALA,OAAO,KAAW,YAEX,aAAkB,YADf,MAAM,EAAW,iBAAiB,OAAO,GAAQ,CAAc;EASjF,SAAS,GAAK;GACV,MAAM,IAAI,EAAe,8BAA+B,EAAc,WAAW,EAC7E,OAAO,EACX,CAAC;EACL;EAEA,IAAM,IACF,KAAiB,OAAO,KAAW,WAAW,EAAkB,CAAM,IAAI,CAAC;EAC/E,OAAO,IAAI,EAAW,GAAS,GAAW,CAAQ;CACtD;CAGA,IAAI,aAAgC;EAChC,OAAO,KAAK,SAAS;CACzB;CAGA,IAAI,YAAoB;EACpB,IAAM,IAAO,KAAK,SAAS,WAAW;EACtC,IAAI,MAAS,KAAA,GACT,MAAM,IAAI,EAAe,sBAAsB;EAEnD,OAAO;CACX;CAGA,IAAI,cAAiC;EACjC,OAAO,KAAK,SAAS;CACzB;CASA,IAAI,cAAwC;EACxC,OAAO,EACH,KAAK,SAAS,aAElB;CACJ;CAOA,IAAI,aAA4B;EAC5B,OAAO,KAAK,YAAY,MAAM,CAAC;CACnC;CAQA,IAAI,eAAyC;EACzC,OAAO,EACH,KAAK,SAAS,cAElB;CACJ;CAOA,IAAI,cAA6B;EAC7B,OAAO,KAAK,aAAa,MAAM,CAAC;CACpC;CAUA,IAAI,WAA6C;EAC7C,OAAO,KAAK;CAChB;CAUA,MAAM,UAAyB;EAC3B,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,YAAY,KAAA,CAAS;CACvD;CAGA,IAAI,MAA4B;EAC5B,OAAO,KAAK;CAChB;CAQA,MAAM,IAAI,GAAwE;EAC9E,IAAI;GAEA,OAAO,MADc,KAAK,SAAS,IAAI,CAAK;EAEhD,SAAS,GAAK;GACV,MAAM,IAAI,EAAe,qBAAsB,EAAc,WAAW,EAAE,OAAO,EAAI,CAAC;EAC1F;CACJ;AACJ"}
1
+ {"version":3,"file":"session.js","names":[],"sources":["../../../src/vision/core/session.ts"],"sourcesContent":["/**\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 { 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) return url;\n return new Uint8Array(await response.arrayBuffer());\n } catch {\n return url;\n }\n}\n\nexport interface OrtSessionOptions {\n /** Execution providers in preference order. `undefined` uses {@link DEFAULT_PROVIDERS}. */\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 * 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 public readonly providers: readonly string[],\n private readonly _metadata: Readonly<Record<string, 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 providers = resolveProviders(options.providers);\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);\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":";;;;;;AAyBA,eAAe,EAAW,GAA2C;CACjE,IAAI;EACA,IAAM,IAAW,MAAM,MAAM,CAAG;EAEhC,OADK,EAAS,KACP,IAAI,WAAW,MAAM,EAAS,YAAY,CAAC,IADzB;CAE7B,QAAQ;EACJ,OAAO;CACX;AACJ;AAkCA,IAAa,IAAb,MAAa,EAAW;CAEC;CACD;CACC;CAHrB,YACI,GACA,GACA,GACF;EADmB,AAFA,KAAA,WAAA,GACD,KAAA,YAAA,GACC,KAAA,YAAA;CAClB;CAoBH,aAAa,OAAO,GAAoB,IAA6B,CAAC,GAAwB;EAC1F,IAAM,IAAY,EAAiB,EAAQ,SAAS,GAC9C,IAAsD;GACxD,GAAI,EAAQ,kBAAkB,CAAC;GAC/B,oBACI;EACR,GACM,IAAgB,EAAQ,iBAAiB,IACzC,IAAS,OAAO,KAAU,YAAY,IAAgB,MAAM,EAAW,CAAK,IAAI,GAChF,IACF,KAAiB,OAAO,KAAW,WAAW,EAAkB,CAAM,IAAI,CAAC,GAE3E;EACJ,IAAI;GACA,AAKI,KALA,OAAO,KAAW,YAEX,aAAkB,YADf,MAAM,EAAW,iBAAiB,OAAO,GAAQ,CAAc;EASjF,SAAS,GAAK;GACV,MAAM,IAAI,EAAe,8BAA+B,EAAc,WAAW,EAC7E,OAAO,EACX,CAAC;EACL;EAEA,OAAO,IAAI,EAAW,GAAS,GAAW,CAAQ;CACtD;CAGA,IAAI,aAAgC;EAChC,OAAO,KAAK,SAAS;CACzB;CAGA,IAAI,YAAoB;EACpB,IAAM,IAAO,KAAK,SAAS,WAAW;EACtC,IAAI,MAAS,KAAA,GACT,MAAM,IAAI,EAAe,sBAAsB;EAEnD,OAAO;CACX;CAGA,IAAI,cAAiC;EACjC,OAAO,KAAK,SAAS;CACzB;CASA,IAAI,cAAwC;EACxC,OAAO,EACH,KAAK,SAAS,aAElB;CACJ;CAOA,IAAI,aAA4B;EAC5B,OAAO,KAAK,YAAY,MAAM,CAAC;CACnC;CAQA,IAAI,eAAyC;EACzC,OAAO,EACH,KAAK,SAAS,cAElB;CACJ;CAOA,IAAI,cAA6B;EAC7B,OAAO,KAAK,aAAa,MAAM,CAAC;CACpC;CAUA,IAAI,WAA6C;EAC7C,OAAO,KAAK;CAChB;CAUA,MAAM,UAAyB;EAC3B,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,YAAY,KAAA,CAAS;CACvD;CAGA,IAAI,MAA4B;EAC5B,OAAO,KAAK;CAChB;CAQA,MAAM,IAAI,GAAwE;EAC9E,IAAI;GAEA,OAAO,MADc,KAAK,SAAS,IAAI,CAAK;EAEhD,SAAS,GAAK;GACV,MAAM,IAAI,EAAe,qBAAsB,EAAc,WAAW,EAAE,OAAO,EAAI,CAAC;EAC1F;CACJ;AACJ"}
@@ -1,2 +1,2 @@
1
- const e=require("./core/exceptions.cjs"),t=require("./types.cjs"),n=require("./core/timing.cjs"),r=require("./results.cjs"),i=require("./labels.cjs"),a=require("./core/graph.cjs"),o=require("./core/metadata.cjs"),s=require("./core/providers.cjs"),c=require("./core/session.cjs"),l=require("./io/image.cjs"),u=require("./preprocess/image.cjs"),d=require("./postprocess/classification.cjs"),f=require("./postprocess/detection.cjs"),p=require("./postprocess/segmentation.cjs"),m=require("./tasks/base.cjs"),h=require("./tasks/classifier.cjs"),g=require("./tasks/detector.cjs"),_=require("./tasks/segmenter.cjs");var v=`0.5.0`;exports.BoundingBox=t.BoundingBox,exports.Boxes=r.Boxes,exports.COCO_CLASSES=i.COCO_CLASSES,exports.ClassificationResults=r.ClassificationResults,exports.Classifier=h.Classifier,exports.DEFAULT_PROVIDERS=s.DEFAULT_PROVIDERS,exports.DetectionResults=r.DetectionResults,exports.Detector=g.Detector,exports.ImageLoadError=e.ImageLoadError,exports.InferenceError=e.InferenceError,exports.LabelMapError=e.LabelMapError,exports.Mask=t.Mask,exports.Masks=r.Masks,exports.ModelLoadError=e.ModelLoadError,exports.OrtSession=c.OrtSession,exports.OrtVisionError=e.OrtVisionError,exports.Probs=r.Probs,exports.ProviderNotAvailableError=e.ProviderNotAvailableError,exports.RGBImage=t.RGBImage,exports.SegmentationResults=r.SegmentationResults,exports.Segmenter=_.Segmenter,exports.SpeedTimer=n.SpeedTimer,exports.VERSION=v,exports.VisionTask=m.VisionTask,exports.batchedNms=f.batchedNms,exports.classificationNumClasses=a.classificationNumClasses,exports.declaredShapesFrom=a.declaredShapesFrom,exports.decodeYolo=f.decodeYolo,exports.decodeYoloAnchors=f.decodeYoloAnchors,exports.decodeYoloSeg=p.decodeYoloSeg,exports.decodeYoloV8=f.decodeYoloV8,exports.decodeYoloV8Anchors=f.decodeYoloV8Anchors,exports.decodeYoloV8Seg=p.decodeYoloV8Seg,exports.detectionNumClasses=a.detectionNumClasses,exports.fromCv2=u.fromCv2,exports.letterbox=u.letterbox,exports.loadImage=l.loadImage,exports.modelNames=o.modelNames,exports.nms=f.nms,exports.normalize=u.normalize,exports.readModelMetadata=o.readModelMetadata,exports.resize=u.resize,exports.resolveInputSize=a.resolveInputSize,exports.resolveLabels=i.resolveLabels,exports.resolveProviders=s.resolveProviders,exports.softmax=d.softmax,exports.spatialInputSize=a.spatialInputSize,exports.toCHW=u.toCHW,exports.toCv2=u.toCv2,exports.toFloat32=u.toFloat32,exports.toFloat32Tensor=u.toFloat32Tensor,exports.toTensor=u.toTensor,exports.topK=d.topK;
1
+ const e=require("./core/exceptions.cjs"),t=require("./types.cjs"),n=require("./core/timing.cjs"),r=require("./results.cjs"),i=require("./labels.cjs"),a=require("./core/graph.cjs"),o=require("./core/metadata.cjs"),s=require("./core/providers.cjs"),c=require("./core/session.cjs"),l=require("./io/image.cjs"),u=require("./preprocess/image.cjs"),d=require("./postprocess/classification.cjs"),f=require("./postprocess/detection.cjs"),p=require("./postprocess/segmentation.cjs"),m=require("./tasks/base.cjs"),h=require("./tasks/classifier.cjs"),g=require("./tasks/detector.cjs"),_=require("./tasks/segmenter.cjs");var v=`0.5.1`;exports.BoundingBox=t.BoundingBox,exports.Boxes=r.Boxes,exports.COCO_CLASSES=i.COCO_CLASSES,exports.ClassificationResults=r.ClassificationResults,exports.Classifier=h.Classifier,exports.DEFAULT_PROVIDERS=s.DEFAULT_PROVIDERS,exports.DetectionResults=r.DetectionResults,exports.Detector=g.Detector,exports.ImageLoadError=e.ImageLoadError,exports.InferenceError=e.InferenceError,exports.LabelMapError=e.LabelMapError,exports.Mask=t.Mask,exports.Masks=r.Masks,exports.ModelLoadError=e.ModelLoadError,exports.OrtSession=c.OrtSession,exports.OrtVisionError=e.OrtVisionError,exports.Probs=r.Probs,exports.ProviderNotAvailableError=e.ProviderNotAvailableError,exports.RGBImage=t.RGBImage,exports.SegmentationResults=r.SegmentationResults,exports.Segmenter=_.Segmenter,exports.SpeedTimer=n.SpeedTimer,exports.VERSION=v,exports.VisionTask=m.VisionTask,exports.batchedNms=f.batchedNms,exports.classificationNumClasses=a.classificationNumClasses,exports.declaredShapesFrom=a.declaredShapesFrom,exports.decodeYolo=f.decodeYolo,exports.decodeYoloAnchors=f.decodeYoloAnchors,exports.decodeYoloSeg=p.decodeYoloSeg,exports.decodeYoloV8=f.decodeYoloV8,exports.decodeYoloV8Anchors=f.decodeYoloV8Anchors,exports.decodeYoloV8Seg=p.decodeYoloV8Seg,exports.detectionNumClasses=a.detectionNumClasses,exports.fromCv2=u.fromCv2,exports.letterbox=u.letterbox,exports.loadImage=l.loadImage,exports.modelNames=o.modelNames,exports.nms=f.nms,exports.normalize=u.normalize,exports.readModelMetadata=o.readModelMetadata,exports.resize=u.resize,exports.resolveInputSize=a.resolveInputSize,exports.resolveLabels=i.resolveLabels,exports.resolveProviders=s.resolveProviders,exports.softmax=d.softmax,exports.spatialInputSize=a.spatialInputSize,exports.toCHW=u.toCHW,exports.toCv2=u.toCv2,exports.toFloat32=u.toFloat32,exports.toFloat32Tensor=u.toFloat32Tensor,exports.toTensor=u.toTensor,exports.topK=d.topK;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.5.0` (MIT, same\n * author) so it ships inside this SDK without an extra package install.\n * `onnxruntime-web` stays an optional peer dependency — install it (and ship\n * the matching `.wasm` files) only when you use this subpath.\n *\n * Do not hand-edit — regenerate with `npm run vendor:vision`.\n */\n\nexport {\n BoundingBox,\n Mask,\n RGBImage,\n type ClassProbability,\n type ClassificationResult,\n type DetectionResult,\n type SegmentationResult,\n} from \"./types\";\n\nexport {\n Boxes,\n ClassificationResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport { COCO_CLASSES, type LabelSpec, type ResolveLabelsOptions, resolveLabels } from \"./labels\";\n\nexport {\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport { type ModelSource, type OrtSessionOptions, OrtSession } from \"./core/session\";\nexport {\n type DeclaredDim,\n type DeclaredShape,\n type ResolveInputSizeOptions,\n classificationNumClasses,\n declaredShapesFrom,\n detectionNumClasses,\n resolveInputSize,\n spatialInputSize,\n} from \"./core/graph\";\nexport { modelNames, readModelMetadata } from \"./core/metadata\";\nexport { DEFAULT_PROVIDERS, resolveProviders } from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n type LetterboxResult,\n fromCv2,\n letterbox,\n normalize,\n resize,\n toCHW,\n toCv2,\n toFloat32,\n toFloat32Tensor,\n toTensor,\n} from \"./preprocess/image\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodeYoloV8AnchorsOptions,\n type DecodeYoloV8Options,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n decodeYoloV8,\n decodeYoloV8Anchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodeYoloV8SegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n decodeYoloV8Seg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectorHead,\n type DetectorOptions,\n type DetectorPredictOptions,\n Detector,\n} from \"./tasks/detector\";\nexport {\n type SegmenterHead,\n type SegmenterOptions,\n type SegmenterPredictOptions,\n Segmenter,\n} from \"./tasks/segmenter\";\n\nexport const VERSION: string = \"0.5.0\";\n"],"mappings":"imBAoHA,IAAa,EAAkB"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.5.1` (MIT, same\n * author) so it ships inside this SDK without an extra package install.\n * `onnxruntime-web` stays an optional peer dependency — install it (and ship\n * the matching `.wasm` files) only when you use this subpath.\n *\n * Do not hand-edit — regenerate with `npm run vendor:vision`.\n */\n\nexport {\n BoundingBox,\n Mask,\n RGBImage,\n type ClassProbability,\n type ClassificationResult,\n type DetectionResult,\n type SegmentationResult,\n} from \"./types\";\n\nexport {\n Boxes,\n ClassificationResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport { COCO_CLASSES, type LabelSpec, type ResolveLabelsOptions, resolveLabels } from \"./labels\";\n\nexport {\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport { type ModelSource, type OrtSessionOptions, OrtSession } from \"./core/session\";\nexport {\n type DeclaredDim,\n type DeclaredShape,\n type ResolveInputSizeOptions,\n classificationNumClasses,\n declaredShapesFrom,\n detectionNumClasses,\n resolveInputSize,\n spatialInputSize,\n} from \"./core/graph\";\nexport { modelNames, readModelMetadata } from \"./core/metadata\";\nexport { DEFAULT_PROVIDERS, resolveProviders } from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n type LetterboxResult,\n fromCv2,\n letterbox,\n normalize,\n resize,\n toCHW,\n toCv2,\n toFloat32,\n toFloat32Tensor,\n toTensor,\n} from \"./preprocess/image\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodeYoloV8AnchorsOptions,\n type DecodeYoloV8Options,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n decodeYoloV8,\n decodeYoloV8Anchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodeYoloV8SegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n decodeYoloV8Seg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectorHead,\n type DetectorOptions,\n type DetectorPredictOptions,\n Detector,\n} from \"./tasks/detector\";\nexport {\n type SegmenterHead,\n type SegmenterOptions,\n type SegmenterPredictOptions,\n Segmenter,\n} from \"./tasks/segmenter\";\n\nexport const VERSION: string = \"0.5.1\";\n"],"mappings":"imBAoHA,IAAa,EAAkB"}
@@ -17,7 +17,7 @@ import { Classifier as Y } from "./tasks/classifier.js";
17
17
  import { Detector as X } from "./tasks/detector.js";
18
18
  import { Segmenter as Z } from "./tasks/segmenter.js";
19
19
  //#region src/vision/index.ts
20
- var Q = "0.5.0";
20
+ var Q = "0.5.1";
21
21
  //#endregion
22
22
  export { o as BoundingBox, u as Boxes, g as COCO_CLASSES, d as ClassificationResults, Y as Classifier, T as DEFAULT_PROVIDERS, f as DetectionResults, X as Detector, e as ImageLoadError, t as InferenceError, n as LabelMapError, s as Mask, p as Masks, r as ModelLoadError, D as OrtSession, i as OrtVisionError, m as Probs, a as ProviderNotAvailableError, c as RGBImage, h as SegmentationResults, Z as Segmenter, l as SpeedTimer, Q as VERSION, J as VisionTask, B as batchedNms, v as classificationNumClasses, y as declaredShapesFrom, V as decodeYolo, H as decodeYoloAnchors, K as decodeYoloSeg, U as decodeYoloV8, W as decodeYoloV8Anchors, q as decodeYoloV8Seg, b as detectionNumClasses, k as fromCv2, A as letterbox, O as loadImage, C as modelNames, G as nms, j as normalize, w as readModelMetadata, M as resize, x as resolveInputSize, _ as resolveLabels, E as resolveProviders, R as softmax, S as spatialInputSize, N as toCHW, P as toCv2, F as toFloat32, I as toFloat32Tensor, L as toTensor, z as topK };
23
23
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.5.0` (MIT, same\n * author) so it ships inside this SDK without an extra package install.\n * `onnxruntime-web` stays an optional peer dependency — install it (and ship\n * the matching `.wasm` files) only when you use this subpath.\n *\n * Do not hand-edit — regenerate with `npm run vendor:vision`.\n */\n\nexport {\n BoundingBox,\n Mask,\n RGBImage,\n type ClassProbability,\n type ClassificationResult,\n type DetectionResult,\n type SegmentationResult,\n} from \"./types\";\n\nexport {\n Boxes,\n ClassificationResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport { COCO_CLASSES, type LabelSpec, type ResolveLabelsOptions, resolveLabels } from \"./labels\";\n\nexport {\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport { type ModelSource, type OrtSessionOptions, OrtSession } from \"./core/session\";\nexport {\n type DeclaredDim,\n type DeclaredShape,\n type ResolveInputSizeOptions,\n classificationNumClasses,\n declaredShapesFrom,\n detectionNumClasses,\n resolveInputSize,\n spatialInputSize,\n} from \"./core/graph\";\nexport { modelNames, readModelMetadata } from \"./core/metadata\";\nexport { DEFAULT_PROVIDERS, resolveProviders } from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n type LetterboxResult,\n fromCv2,\n letterbox,\n normalize,\n resize,\n toCHW,\n toCv2,\n toFloat32,\n toFloat32Tensor,\n toTensor,\n} from \"./preprocess/image\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodeYoloV8AnchorsOptions,\n type DecodeYoloV8Options,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n decodeYoloV8,\n decodeYoloV8Anchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodeYoloV8SegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n decodeYoloV8Seg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectorHead,\n type DetectorOptions,\n type DetectorPredictOptions,\n Detector,\n} from \"./tasks/detector\";\nexport {\n type SegmenterHead,\n type SegmenterOptions,\n type SegmenterPredictOptions,\n Segmenter,\n} from \"./tasks/segmenter\";\n\nexport const VERSION: string = \"0.5.0\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoHA,IAAa,IAAkB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.5.1` (MIT, same\n * author) so it ships inside this SDK without an extra package install.\n * `onnxruntime-web` stays an optional peer dependency — install it (and ship\n * the matching `.wasm` files) only when you use this subpath.\n *\n * Do not hand-edit — regenerate with `npm run vendor:vision`.\n */\n\nexport {\n BoundingBox,\n Mask,\n RGBImage,\n type ClassProbability,\n type ClassificationResult,\n type DetectionResult,\n type SegmentationResult,\n} from \"./types\";\n\nexport {\n Boxes,\n ClassificationResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport { COCO_CLASSES, type LabelSpec, type ResolveLabelsOptions, resolveLabels } from \"./labels\";\n\nexport {\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport { type ModelSource, type OrtSessionOptions, OrtSession } from \"./core/session\";\nexport {\n type DeclaredDim,\n type DeclaredShape,\n type ResolveInputSizeOptions,\n classificationNumClasses,\n declaredShapesFrom,\n detectionNumClasses,\n resolveInputSize,\n spatialInputSize,\n} from \"./core/graph\";\nexport { modelNames, readModelMetadata } from \"./core/metadata\";\nexport { DEFAULT_PROVIDERS, resolveProviders } from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n type LetterboxResult,\n fromCv2,\n letterbox,\n normalize,\n resize,\n toCHW,\n toCv2,\n toFloat32,\n toFloat32Tensor,\n toTensor,\n} from \"./preprocess/image\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodeYoloV8AnchorsOptions,\n type DecodeYoloV8Options,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n decodeYoloV8,\n decodeYoloV8Anchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodeYoloV8SegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n decodeYoloV8Seg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectorHead,\n type DetectorOptions,\n type DetectorPredictOptions,\n Detector,\n} from \"./tasks/detector\";\nexport {\n type SegmenterHead,\n type SegmenterOptions,\n type SegmenterPredictOptions,\n Segmenter,\n} from \"./tasks/segmenter\";\n\nexport const VERSION: string = \"0.5.1\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoHA,IAAa,IAAkB"}
@@ -1,2 +1,2 @@
1
- var e=256;function t(e){return e instanceof HTMLVideoElement?{width:e.videoWidth,height:e.videoHeight}:e instanceof HTMLCanvasElement?{width:e.width,height:e.height}:{width:e.naturalWidth||e.width,height:e.naturalHeight||e.height}}function n(e,n){let{width:r,height:i}=t(e);if(r===0||i===0)return 0;let a=Math.min(1,256/Math.max(r,i)),o=Math.max(1,Math.round(r*a)),s=Math.max(1,Math.round(i*a)),c=n??document.createElement(`canvas`);c.width=o,c.height=s;let l=c.getContext(`2d`,{willReadFrequently:!0});if(!l)return 0;l.drawImage(e,0,0,o,s);let u=l.getImageData(0,0,o,s).data,d=0,f=o*s;for(let e=0;e<u.length;e+=4)d+=.2126*u[e]+.7152*u[e+1]+.0722*u[e+2];return d/f}function r(e,t){return e>=t}var i=class extends Error{luminance;threshold;constructor(e,t){super(`Image is too dark to analyse. Capture again in a brighter environment.`),this.name=`LowLuminanceError`,this.luminance=e,this.threshold=t}};exports.LUMINANCE_SAMPLE_MAX_EDGE=e,exports.LowLuminanceError=i,exports.computeImageLuminance=n,exports.isLuminanceAcceptable=r;
1
+ var e=256;function t(e){return e instanceof HTMLVideoElement?{width:e.videoWidth,height:e.videoHeight}:e instanceof HTMLImageElement?{width:e.naturalWidth||e.width,height:e.naturalHeight||e.height}:{width:e.width,height:e.height}}function n(e,n){let{width:r,height:i}=t(e);if(r===0||i===0)return 0;let a=Math.min(1,256/Math.max(r,i)),o=Math.max(1,Math.round(r*a)),s=Math.max(1,Math.round(i*a)),c=n??document.createElement(`canvas`);c.width=o,c.height=s;let l=c.getContext(`2d`,{willReadFrequently:!0});if(!l)return 0;l.drawImage(e,0,0,o,s);let u=l.getImageData(0,0,o,s).data,d=0,f=o*s;for(let e=0;e<u.length;e+=4)d+=.2126*u[e]+.7152*u[e+1]+.0722*u[e+2];return d/f}function r(e,t){return e>=t}var i=class extends Error{luminance;threshold;constructor(e,t){super(`Image is too dark to analyse. Capture again in a brighter environment.`),this.name=`LowLuminanceError`,this.luminance=e,this.threshold=t}};exports.LUMINANCE_SAMPLE_MAX_EDGE=e,exports.LowLuminanceError=i,exports.computeImageLuminance=n,exports.isLuminanceAcceptable=r;
2
2
  //# sourceMappingURL=luminance.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"luminance.cjs","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * `<img>`, `<video>` or `<canvas>` so a UI can reject underexposed captures\n * before paying the cost of downstream inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/** Drawable source we can sample luminance from image, video, or canvas. */\nexport type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\n/** Natural pixel size of the source (`0`/`0` while it is still unloaded). */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLCanvasElement) {\n return { width: source.width, height: source.height };\n }\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded\n * `<img>`, `<video>` or `<canvas>`, scaled to `0..255`.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the image/video/canvas to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":"AAgBA,IAAa,EAA4B,IAMzC,SAAS,EAAW,EAA4D,CAO5E,OANI,aAAkB,iBACX,CAAE,MAAO,EAAO,WAAY,OAAQ,EAAO,WAAY,EAE9D,aAAkB,kBACX,CAAE,MAAO,EAAO,MAAO,OAAQ,EAAO,MAAO,EAEjD,CACH,MAAO,EAAO,cAAgB,EAAO,MACrC,OAAQ,EAAO,eAAiB,EAAO,MAC3C,CACJ,CAmBA,SAAgB,EACZ,EACA,EACM,CACN,GAAM,CAAE,MAAO,EAAM,OAAQ,GAAS,EAAW,CAAM,EACvD,GAAI,IAAS,GAAK,IAAS,EAAG,MAAO,GAErC,IAAM,EAAQ,KAAK,IAAI,EAAA,IAA+B,KAAK,IAAI,EAAM,CAAI,CAAC,EACpE,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EACxC,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EAExC,EAAS,GAAkB,SAAS,cAAc,QAAQ,EAChE,EAAO,MAAQ,EACf,EAAO,OAAS,EAChB,IAAM,EAAM,EAAO,WAAW,KAAM,CAAE,mBAAoB,EAAK,CAAC,EAChE,GAAI,CAAC,EAAK,MAAO,GACjB,EAAI,UAAU,EAAQ,EAAG,EAAG,EAAG,CAAC,EAEhC,IAAM,EAAO,EAAI,aAAa,EAAG,EAAG,EAAG,CAAC,CAAC,CAAC,KACtC,EAAM,EACJ,EAAa,EAAI,EACvB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,GAAK,EAClC,GAAO,MAAS,EAAK,GAAK,MAAS,EAAK,EAAI,GAAK,MAAS,EAAK,EAAI,GAEvE,OAAO,EAAM,CACjB,CAcA,SAAgB,EAAsB,EAAmB,EAA4B,CACjF,OAAO,GAAa,CACxB,CAOA,IAAa,EAAb,cAAuC,KAAM,CAEzC,UAEA,UAMA,YAAY,EAAmB,EAAmB,CAC9C,MAAM,wEAAwE,EAC9E,KAAK,KAAO,oBACZ,KAAK,UAAY,EACjB,KAAK,UAAY,CACrB,CACJ"}
1
+ {"version":3,"file":"luminance.cjs","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * frame (`<img>`, `<video>`, `<canvas>`, `ImageBitmap` or `OffscreenCanvas`) so\n * a UI can reject underexposed captures before paying the cost of downstream\n * inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/**\n * Drawable source we can sample luminance from.\n *\n * The list tracks what `CanvasRenderingContext2D.drawImage` accepts and we can\n * read a pixel size off, which is what the implementation actually needs.\n * `ImageBitmap` matters for the decode-downscaled path: `createImageBitmap(blob,\n * { resizeWidth })` is how a caller avoids materialising a full-resolution\n * phone photo, and the frame it hands back is the frame whose brightness has to\n * be checked.\n */\nexport type LuminanceSource =\n HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas;\n\n/**\n * Natural pixel size of the source (`0`/`0` while it is still unloaded).\n *\n * `ImageBitmap` and `OffscreenCanvas` both expose plain `width`/`height`, so\n * they fall through to the same branch as a canvas — but they are named\n * explicitly rather than left to the `naturalWidth || width` fallback, which\n * only reads as intentional for an `<img>`.\n */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLImageElement) {\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n }\n return { width: source.width, height: source.height };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded frame,\n * scaled to `0..255`. See {@link LuminanceSource} for what counts as one.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the decoded frame to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":"AAiBA,IAAa,EAA4B,IAuBzC,SAAS,EAAW,EAA4D,CAU5E,OATI,aAAkB,iBACX,CAAE,MAAO,EAAO,WAAY,OAAQ,EAAO,WAAY,EAE9D,aAAkB,iBACX,CACH,MAAO,EAAO,cAAgB,EAAO,MACrC,OAAQ,EAAO,eAAiB,EAAO,MAC3C,EAEG,CAAE,MAAO,EAAO,MAAO,OAAQ,EAAO,MAAO,CACxD,CAmBA,SAAgB,EACZ,EACA,EACM,CACN,GAAM,CAAE,MAAO,EAAM,OAAQ,GAAS,EAAW,CAAM,EACvD,GAAI,IAAS,GAAK,IAAS,EAAG,MAAO,GAErC,IAAM,EAAQ,KAAK,IAAI,EAAA,IAA+B,KAAK,IAAI,EAAM,CAAI,CAAC,EACpE,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EACxC,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EAExC,EAAS,GAAkB,SAAS,cAAc,QAAQ,EAChE,EAAO,MAAQ,EACf,EAAO,OAAS,EAChB,IAAM,EAAM,EAAO,WAAW,KAAM,CAAE,mBAAoB,EAAK,CAAC,EAChE,GAAI,CAAC,EAAK,MAAO,GACjB,EAAI,UAAU,EAAQ,EAAG,EAAG,EAAG,CAAC,EAEhC,IAAM,EAAO,EAAI,aAAa,EAAG,EAAG,EAAG,CAAC,CAAC,CAAC,KACtC,EAAM,EACJ,EAAa,EAAI,EACvB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,GAAK,EAClC,GAAO,MAAS,EAAK,GAAK,MAAS,EAAK,EAAI,GAAK,MAAS,EAAK,EAAI,GAEvE,OAAO,EAAM,CACjB,CAcA,SAAgB,EAAsB,EAAmB,EAA4B,CACjF,OAAO,GAAa,CACxB,CAOA,IAAa,EAAb,cAAuC,KAAM,CAEzC,UAEA,UAMA,YAAY,EAAmB,EAAmB,CAC9C,MAAM,wEAAwE,EAC9E,KAAK,KAAO,oBACZ,KAAK,UAAY,EACjB,KAAK,UAAY,CACrB,CACJ"}
@@ -4,12 +4,12 @@ function t(e) {
4
4
  return e instanceof HTMLVideoElement ? {
5
5
  width: e.videoWidth,
6
6
  height: e.videoHeight
7
- } : e instanceof HTMLCanvasElement ? {
8
- width: e.width,
9
- height: e.height
10
- } : {
7
+ } : e instanceof HTMLImageElement ? {
11
8
  width: e.naturalWidth || e.width,
12
9
  height: e.naturalHeight || e.height
10
+ } : {
11
+ width: e.width,
12
+ height: e.height
13
13
  };
14
14
  }
15
15
  function n(e, n) {
@@ -1 +1 @@
1
- {"version":3,"file":"luminance.js","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * `<img>`, `<video>` or `<canvas>` so a UI can reject underexposed captures\n * before paying the cost of downstream inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/** Drawable source we can sample luminance from image, video, or canvas. */\nexport type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\n/** Natural pixel size of the source (`0`/`0` while it is still unloaded). */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLCanvasElement) {\n return { width: source.width, height: source.height };\n }\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded\n * `<img>`, `<video>` or `<canvas>`, scaled to `0..255`.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the image/video/canvas to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":";AAgBA,IAAa,IAA4B;AAMzC,SAAS,EAAW,GAA4D;CAO5E,OANI,aAAkB,mBACX;EAAE,OAAO,EAAO;EAAY,QAAQ,EAAO;CAAY,IAE9D,aAAkB,oBACX;EAAE,OAAO,EAAO;EAAO,QAAQ,EAAO;CAAO,IAEjD;EACH,OAAO,EAAO,gBAAgB,EAAO;EACrC,QAAQ,EAAO,iBAAiB,EAAO;CAC3C;AACJ;AAmBA,SAAgB,EACZ,GACA,GACM;CACN,IAAM,EAAE,OAAO,GAAM,QAAQ,MAAS,EAAW,CAAM;CACvD,IAAI,MAAS,KAAK,MAAS,GAAG,OAAO;CAErC,IAAM,IAAQ,KAAK,IAAI,GAAA,MAA+B,KAAK,IAAI,GAAM,CAAI,CAAC,GACpE,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GACxC,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GAExC,IAAS,KAAkB,SAAS,cAAc,QAAQ;CAEhE,AADA,EAAO,QAAQ,GACf,EAAO,SAAS;CAChB,IAAM,IAAM,EAAO,WAAW,MAAM,EAAE,oBAAoB,GAAK,CAAC;CAChE,IAAI,CAAC,GAAK,OAAO;CACjB,EAAI,UAAU,GAAQ,GAAG,GAAG,GAAG,CAAC;CAEhC,IAAM,IAAO,EAAI,aAAa,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,MACtC,IAAM,GACJ,IAAa,IAAI;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,GAClC,KAAO,QAAS,EAAK,KAAK,QAAS,EAAK,IAAI,KAAK,QAAS,EAAK,IAAI;CAEvE,OAAO,IAAM;AACjB;AAcA,SAAgB,EAAsB,GAAmB,GAA4B;CACjF,OAAO,KAAa;AACxB;AAOA,IAAa,IAAb,cAAuC,MAAM;CAEzC;CAEA;CAMA,YAAY,GAAmB,GAAmB;EAI9C,AAHA,MAAM,wEAAwE,GAC9E,KAAK,OAAO,qBACZ,KAAK,YAAY,GACjB,KAAK,YAAY;CACrB;AACJ"}
1
+ {"version":3,"file":"luminance.js","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * frame (`<img>`, `<video>`, `<canvas>`, `ImageBitmap` or `OffscreenCanvas`) so\n * a UI can reject underexposed captures before paying the cost of downstream\n * inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/**\n * Drawable source we can sample luminance from.\n *\n * The list tracks what `CanvasRenderingContext2D.drawImage` accepts and we can\n * read a pixel size off, which is what the implementation actually needs.\n * `ImageBitmap` matters for the decode-downscaled path: `createImageBitmap(blob,\n * { resizeWidth })` is how a caller avoids materialising a full-resolution\n * phone photo, and the frame it hands back is the frame whose brightness has to\n * be checked.\n */\nexport type LuminanceSource =\n HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas;\n\n/**\n * Natural pixel size of the source (`0`/`0` while it is still unloaded).\n *\n * `ImageBitmap` and `OffscreenCanvas` both expose plain `width`/`height`, so\n * they fall through to the same branch as a canvas — but they are named\n * explicitly rather than left to the `naturalWidth || width` fallback, which\n * only reads as intentional for an `<img>`.\n */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLImageElement) {\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n }\n return { width: source.width, height: source.height };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded frame,\n * scaled to `0..255`. See {@link LuminanceSource} for what counts as one.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the decoded frame to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":";AAiBA,IAAa,IAA4B;AAuBzC,SAAS,EAAW,GAA4D;CAU5E,OATI,aAAkB,mBACX;EAAE,OAAO,EAAO;EAAY,QAAQ,EAAO;CAAY,IAE9D,aAAkB,mBACX;EACH,OAAO,EAAO,gBAAgB,EAAO;EACrC,QAAQ,EAAO,iBAAiB,EAAO;CAC3C,IAEG;EAAE,OAAO,EAAO;EAAO,QAAQ,EAAO;CAAO;AACxD;AAmBA,SAAgB,EACZ,GACA,GACM;CACN,IAAM,EAAE,OAAO,GAAM,QAAQ,MAAS,EAAW,CAAM;CACvD,IAAI,MAAS,KAAK,MAAS,GAAG,OAAO;CAErC,IAAM,IAAQ,KAAK,IAAI,GAAA,MAA+B,KAAK,IAAI,GAAM,CAAI,CAAC,GACpE,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GACxC,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GAExC,IAAS,KAAkB,SAAS,cAAc,QAAQ;CAEhE,AADA,EAAO,QAAQ,GACf,EAAO,SAAS;CAChB,IAAM,IAAM,EAAO,WAAW,MAAM,EAAE,oBAAoB,GAAK,CAAC;CAChE,IAAI,CAAC,GAAK,OAAO;CACjB,EAAI,UAAU,GAAQ,GAAG,GAAG,GAAG,CAAC;CAEhC,IAAM,IAAO,EAAI,aAAa,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,MACtC,IAAM,GACJ,IAAa,IAAI;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,GAClC,KAAO,QAAS,EAAK,KAAK,QAAS,EAAK,IAAI,KAAK,QAAS,EAAK,IAAI;CAEvE,OAAO,IAAM;AACjB;AAcA,SAAgB,EAAsB,GAAmB,GAA4B;CACjF,OAAO,KAAa;AACxB;AAOA,IAAa,IAAb,cAAuC,MAAM;CAEzC;CAEA;CAMA,YAAY,GAAmB,GAAmB;EAI9C,AAHA,MAAM,wEAAwE,GAC9E,KAAK,OAAO,qBACZ,KAAK,YAAY,GACjB,KAAK,YAAY;CACrB;AACJ"}
package/dist/vision.d.ts CHANGED
@@ -292,8 +292,8 @@ export declare interface ClassProbability {
292
292
  export declare const COCO_CLASSES: readonly string[];
293
293
 
294
294
  /**
295
- * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded
296
- * `<img>`, `<video>` or `<canvas>`, scaled to `0..255`.
295
+ * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded frame,
296
+ * scaled to `0..255`. See {@link LuminanceSource} for what counts as one.
297
297
  *
298
298
  * The source is downsampled so its longest edge is at most
299
299
  * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is
@@ -303,7 +303,7 @@ export declare const COCO_CLASSES: readonly string[];
303
303
  * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot
304
304
  * loop; when omitted a one-shot detached canvas is created.
305
305
  *
306
- * @param source - the image/video/canvas to sample.
306
+ * @param source - the decoded frame to sample.
307
307
  * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.
308
308
  * @returns The mean luminance in `0..255`, or `0` when the source is unloaded
309
309
  * (zero-sized) or a 2D context is unavailable.
@@ -761,8 +761,17 @@ export declare interface LetterboxResult {
761
761
  */
762
762
  export declare const LUMINANCE_SAMPLE_MAX_EDGE = 256;
763
763
 
764
- /** Drawable source we can sample luminance from — image, video, or canvas. */
765
- export declare type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;
764
+ /**
765
+ * Drawable source we can sample luminance from.
766
+ *
767
+ * The list tracks what `CanvasRenderingContext2D.drawImage` accepts and we can
768
+ * read a pixel size off, which is what the implementation actually needs.
769
+ * `ImageBitmap` matters for the decode-downscaled path: `createImageBitmap(blob,
770
+ * { resizeWidth })` is how a caller avoids materialising a full-resolution
771
+ * phone photo, and the frame it hands back is the frame whose brightness has to
772
+ * be checked.
773
+ */
774
+ export declare type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas;
766
775
 
767
776
  /**
768
777
  * Single-channel binary or grayscale mask, laid out row-major.
@@ -870,6 +879,16 @@ export declare interface LetterboxResult {
870
879
  /**
871
880
  * Load an ONNX model into an ORT inference session.
872
881
  *
882
+ * The metadata map is read **before** the session is built, and that order is
883
+ * load-bearing on memory-constrained devices. ORT copies the model into its
884
+ * WASM heap and then allocates the graph and the weights on top of that copy;
885
+ * a `readModelMetadata` call placed after `InferenceSession.create` keeps the
886
+ * JavaScript-side buffer reachable across the whole build, so a 5 MB model
887
+ * costs 5 MB of JS heap plus 5 MB of WASM heap plus the weights at the same
888
+ * instant. Reading first makes the buffer collectable as soon as ORT has copied
889
+ * it — on a phone that was the difference between a session and
890
+ * `Can't create a session. failed to allocate a buffer of size N`.
891
+ *
873
892
  * @param model Either a URL string, or a `Uint8Array`/`ArrayBuffer` containing the model bytes.
874
893
  * @param options Provider list, pass-through `SessionOptions`, and whether to
875
894
  * read the model's metadata map (see {@link OrtSessionOptions.readMetadata}).
@@ -952,6 +971,13 @@ export declare interface LetterboxResult {
952
971
  * of letting ORT fetch it. That is the same single download either way, and
953
972
  * it is what lets a task resolve its labels off the model. Set to `false` to
954
973
  * keep the URL path untouched and leave {@link OrtSession.metadata} empty.
974
+ *
975
+ * `false` is also the escape hatch when a device cannot afford the bytes: the
976
+ * fetched buffer is dropped before ORT builds the graph (see
977
+ * {@link OrtSession.create}), but ORT's own load path still keeps the model out
978
+ * of reach of anything the SDK holds. A session built this way resolves its
979
+ * input size from the graph as usual — only the class names are lost, so a
980
+ * caller taking this route has to pass `labels` itself.
955
981
  */
956
982
  readonly readMetadata?: boolean;
957
983
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tempest-react-sdk",
3
- "version": "0.38.0",
3
+ "version": "0.38.2",
4
4
  "description": "SDK público da Tempest com componentes, hooks e integrações para projetos React.",
5
5
  "type": "module",
6
6
  "license": "MIT",