@guidekit/vanilla 0.1.0-beta.2 → 0.1.0-beta.3
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.
- package/dist/index.global.js +12 -12
- package/dist/index.global.js.map +1 -1
- package/package.json +2 -2
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/backend-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/backend.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/version.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/env-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/env.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-conversion-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-factory-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-impl-type-mapping.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-utils-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/trace.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/inference-session-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/inference-session.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-conversion.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-factory.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/onnx-model.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/onnx-value.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/index.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils-env.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils-import.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-factory.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/run-options.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/session-options.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-common.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils-load-file.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-core-impl.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/proxy-wrapper.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/session-handler-inference.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/backend-wasm.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/index.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/version.ts","../../vad/src/index.ts","../src/index.ts","../../core/src/bus/index.ts","../../core/src/resources/index.ts","../../core/src/dom/index.ts","../../core/src/context/index.ts","../../core/src/errors/index.ts","../../core/src/llm/openai-adapter.ts","../../core/src/llm/index.ts","../../core/src/llm/tool-executor.ts","../../core/src/connectivity/index.ts","../../core/src/navigation/index.ts","../../core/src/voice/websocket-manager.ts","../../core/src/voice/deepgram-stt.ts","../../core/src/voice/elevenlabs-stt.ts","../../core/src/voice/elevenlabs-tts.ts","../../core/src/voice/web-speech-stt.ts","../../core/src/voice/web-speech-tts.ts","../../core/src/voice/index.ts","../../core/src/visual/index.ts","../../core/src/awareness/index.ts","../../core/src/awareness/proactive.ts","../../core/src/llm/rate-limiter.ts","../../core/src/i18n/index.ts","../../core/src/auth/token-manager.ts","../../core/src/core.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Backend } from './backend.js';\nimport { InferenceSession } from './inference-session.js';\n\ninterface BackendInfo {\n backend: Backend;\n priority: number;\n\n initPromise?: Promise<void>;\n initialized?: boolean;\n aborted?: boolean;\n error?: string;\n}\n\nconst backends: Map<string, BackendInfo> = new Map();\nconst backendsSortedByPriority: string[] = [];\n\n/**\n * Register a backend.\n *\n * @param name - the name as a key to lookup as an execution provider.\n * @param backend - the backend object.\n * @param priority - an integer indicating the priority of the backend. Higher number means higher priority. if priority\n * < 0, it will be considered as a 'beta' version and will not be used as a fallback backend by default.\n *\n * @ignore\n */\nexport const registerBackend = (name: string, backend: Backend, priority: number): void => {\n if (backend && typeof backend.init === 'function' && typeof backend.createInferenceSessionHandler === 'function') {\n const currentBackend = backends.get(name);\n if (currentBackend === undefined) {\n backends.set(name, { backend, priority });\n } else if (currentBackend.priority > priority) {\n // same name is already registered with a higher priority. skip registeration.\n return;\n } else if (currentBackend.priority === priority) {\n if (currentBackend.backend !== backend) {\n throw new Error(`cannot register backend \"${name}\" using priority ${priority}`);\n }\n }\n\n if (priority >= 0) {\n const i = backendsSortedByPriority.indexOf(name);\n if (i !== -1) {\n backendsSortedByPriority.splice(i, 1);\n }\n\n for (let i = 0; i < backendsSortedByPriority.length; i++) {\n if (backends.get(backendsSortedByPriority[i])!.priority <= priority) {\n backendsSortedByPriority.splice(i, 0, name);\n return;\n }\n }\n backendsSortedByPriority.push(name);\n }\n return;\n }\n\n throw new TypeError('not a valid backend');\n};\n\n/**\n * Try to resolve and initialize a backend.\n *\n * @param backendName - the name of the backend.\n * @returns the backend instance if resolved and initialized successfully, or an error message if failed.\n */\nconst tryResolveAndInitializeBackend = async (backendName: string): Promise<Backend | string> => {\n const backendInfo = backends.get(backendName);\n if (!backendInfo) {\n return 'backend not found.';\n }\n\n if (backendInfo.initialized) {\n return backendInfo.backend;\n } else if (backendInfo.aborted) {\n return backendInfo.error!;\n } else {\n const isInitializing = !!backendInfo.initPromise;\n try {\n if (!isInitializing) {\n backendInfo.initPromise = backendInfo.backend.init(backendName);\n }\n await backendInfo.initPromise;\n backendInfo.initialized = true;\n return backendInfo.backend;\n } catch (e) {\n if (!isInitializing) {\n backendInfo.error = `${e}`;\n backendInfo.aborted = true;\n }\n return backendInfo.error!;\n } finally {\n delete backendInfo.initPromise;\n }\n }\n};\n\n/**\n * Resolve execution providers from the specific session options.\n *\n * @param options - the session options object.\n * @returns a promise that resolves to a tuple of an initialized backend instance and a session options object with\n * filtered EP list.\n *\n * @ignore\n */\nexport const resolveBackendAndExecutionProviders = async (\n options: InferenceSession.SessionOptions,\n): Promise<[backend: Backend, options: InferenceSession.SessionOptions]> => {\n // extract backend hints from session options\n const eps = options.executionProviders || [];\n const backendHints = eps.map((i) => (typeof i === 'string' ? i : i.name));\n const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints;\n\n // try to resolve and initialize all requested backends\n let backend: Backend | undefined;\n const errors = [];\n const availableBackendNames = new Set<string>();\n for (const backendName of backendNames) {\n const resolveResult = await tryResolveAndInitializeBackend(backendName);\n if (typeof resolveResult === 'string') {\n errors.push({ name: backendName, err: resolveResult });\n } else {\n if (!backend) {\n backend = resolveResult;\n }\n if (backend === resolveResult) {\n availableBackendNames.add(backendName);\n }\n }\n }\n\n // if no backend is available, throw error.\n if (!backend) {\n throw new Error(`no available backend found. ERR: ${errors.map((e) => `[${e.name}] ${e.err}`).join(', ')}`);\n }\n\n // for each explicitly requested backend, if it's not available, output warning message.\n for (const { name, err } of errors) {\n if (backendHints.includes(name)) {\n // eslint-disable-next-line no-console\n console.warn(\n `removing requested execution provider \"${name}\" from session options because it is not available: ${err}`,\n );\n }\n }\n\n const filteredEps = eps.filter((i) => availableBackendNames.has(typeof i === 'string' ? i : i.name));\n\n return [\n backend,\n new Proxy(options, {\n get: (target, prop) => {\n if (prop === 'executionProviders') {\n return filteredEps;\n }\n return Reflect.get(target, prop);\n },\n }),\n ];\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession } from './inference-session.js';\nimport { OnnxValue } from './onnx-value.js';\n\n/**\n * @ignore\n */\nexport declare namespace SessionHandler {\n type FeedsType = { [name: string]: OnnxValue };\n type FetchesType = { [name: string]: OnnxValue | null };\n type ReturnType = { [name: string]: OnnxValue };\n}\n\n/**\n * Represents shared SessionHandler functionality\n *\n * @ignore\n */\ninterface SessionHandler {\n dispose(): Promise<void>;\n\n readonly inputNames: readonly string[];\n readonly outputNames: readonly string[];\n\n readonly inputMetadata: readonly InferenceSession.ValueMetadata[];\n readonly outputMetadata: readonly InferenceSession.ValueMetadata[];\n}\n\n/**\n * Represent a handler instance of an inference session.\n *\n * @ignore\n */\nexport interface InferenceSessionHandler extends SessionHandler {\n startProfiling(): void;\n endProfiling(): void;\n\n run(\n feeds: SessionHandler.FeedsType,\n fetches: SessionHandler.FetchesType,\n options: InferenceSession.RunOptions,\n ): Promise<SessionHandler.ReturnType>;\n}\n\n/**\n * Represent a backend that provides implementation of model inferencing.\n *\n * @ignore\n */\nexport interface Backend {\n /**\n * Initialize the backend asynchronously. Should throw when failed.\n */\n init(backendName: string): Promise<void>;\n\n createInferenceSessionHandler(\n uriOrBuffer: string | Uint8Array,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler>;\n}\n\nexport { registerBackend } from './backend-impl.js';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// This file is generated by /js/scripts/update-version.ts\n// Do not modify file content manually.\n\nexport const version = '1.24.2';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Env } from './env.js';\nimport { version } from './version.js';\n\ntype LogLevelType = Env['logLevel'];\n\nlet logLevelValue: Required<LogLevelType> = 'warning';\n\nexport const env: Env = {\n wasm: {} as Env.WebAssemblyFlags,\n webgl: {} as Env.WebGLFlags,\n webgpu: {} as Env.WebGpuFlags,\n versions: { common: version },\n\n set logLevel(value: LogLevelType) {\n if (value === undefined) {\n return;\n }\n if (typeof value !== 'string' || ['verbose', 'info', 'warning', 'error', 'fatal'].indexOf(value) === -1) {\n throw new Error(`Unsupported logging level: ${value}`);\n }\n logLevelValue = value;\n },\n get logLevel(): Required<LogLevelType> {\n return logLevelValue;\n },\n};\n\n// set property 'logLevel' so that they can be correctly transferred to worker by `postMessage()`.\nObject.defineProperty(env, 'logLevel', { enumerable: true });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env as envImpl } from './env-impl.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\nexport declare namespace Env {\n export type WasmPathPrefix = string;\n export interface WasmFilePaths {\n /**\n * Specify the override path for the main .wasm file.\n *\n * This path should be an absolute path.\n *\n * If not modified, the filename of the .wasm file is:\n * - `ort-wasm-simd-threaded.wasm` for default build\n * - `ort-wasm-simd-threaded.jsep.wasm` for JSEP build (with WebGPU and WebNN)\n * - `ort-wasm-simd-threaded.asyncify.wasm` for WebGPU build with Asyncify (with WebNN)\n * - `ort-wasm-simd-threaded.jspi.wasm` for WebGPU build with JSPI support (with WebNN)\n */\n wasm?: URL | string;\n /**\n * Specify the override path for the main .mjs file.\n *\n * This path should be an absolute path.\n *\n * If not modified, the filename of the .mjs file is:\n * - `ort-wasm-simd-threaded.mjs` for default build\n * - `ort-wasm-simd-threaded.jsep.mjs` for JSEP build (with WebGPU and WebNN)\n * - `ort-wasm-simd-threaded.asyncify.mjs` for WebGPU build with Asyncify (with WebNN)\n * - `ort-wasm-simd-threaded.jspi.mjs` for WebGPU build with JSPI support (with WebNN)\n */\n mjs?: URL | string;\n }\n export type WasmPrefixOrFilePaths = WasmPathPrefix | WasmFilePaths;\n export interface WebAssemblyFlags {\n /**\n * set or get number of thread(s). If omitted or set to 0, number of thread(s) will be determined by system. If set\n * to 1, no worker thread will be spawned.\n *\n * This setting is available only when WebAssembly multithread feature is available in current context.\n *\n * @defaultValue `0`\n */\n numThreads?: number;\n\n /**\n * set a value indicating whether to enable SIMD.\n *\n * ONNX Runtime will perform feature detection based on the value of this property. Specifically, when the value is\n * set to:\n * - `undefined`, `true` or `\"fixed\"`: will check availability of Fixed-width SIMD.\n * - `\"relaxed\"`: will check availability of Relaxed SIMD.\n * - `false`: will not perform SIMD feature checking.\n *\n * Setting this property does not make ONNX Runtime to switch to the corresponding runtime automatically. User need\n * to set `wasmPaths` or `wasmBinary` property to load the corresponding runtime.\n *\n * This setting is available only when WebAssembly SIMD feature is available in current context.\n *\n * @defaultValue `true`\n */\n simd?: boolean | 'fixed' | 'relaxed';\n\n /**\n * set or get a boolean value indicating whether to enable trace.\n *\n * @defaultValue `false`\n *\n * @deprecated Use `env.trace` instead. If `env.trace` is set, this property will be ignored.\n */\n trace?: boolean;\n\n /**\n * Set or get a number specifying the timeout for initialization of WebAssembly backend, in milliseconds. A zero\n * value indicates no timeout is set.\n *\n * @defaultValue `0`\n */\n initTimeout?: number;\n\n /**\n * Set a custom URL prefix to the .wasm/.mjs files, or an object of overrides for both .wasm/.mjs file. The override\n * path should be an absolute path.\n */\n wasmPaths?: WasmPrefixOrFilePaths;\n\n /**\n * Set a custom buffer which contains the WebAssembly binary. If this property is set, the `wasmPaths` property will\n * be ignored.\n */\n wasmBinary?: ArrayBufferLike | Uint8Array;\n\n /**\n * Set or get a boolean value indicating whether to proxy the execution of main thread to a worker thread.\n *\n * @defaultValue `false`\n */\n proxy?: boolean;\n }\n\n export interface WebGLFlags {\n /**\n * Set or get the WebGL Context ID (webgl or webgl2).\n *\n * @defaultValue `'webgl2'`\n */\n contextId?: 'webgl' | 'webgl2';\n /**\n * Get the WebGL rendering context.\n */\n readonly context: WebGLRenderingContext;\n /**\n * Set or get the maximum batch size for matmul. 0 means to disable batching.\n *\n * @deprecated\n */\n matmulMaxBatchSize?: number;\n /**\n * Set or get the texture cache mode.\n *\n * @defaultValue `'full'`\n */\n textureCacheMode?: 'initializerOnly' | 'full';\n /**\n * Set or get the packed texture mode\n *\n * @defaultValue `false`\n */\n pack?: boolean;\n /**\n * Set or get whether enable async download.\n *\n * @defaultValue `false`\n */\n async?: boolean;\n }\n\n export interface WebGpuProfilingDataV1TensorMetadata {\n dims: readonly number[];\n dataType: string;\n }\n export interface WebGpuProfilingDataV1 {\n version: 1;\n inputsMetadata: readonly WebGpuProfilingDataV1TensorMetadata[];\n outputsMetadata: readonly WebGpuProfilingDataV1TensorMetadata[];\n kernelId: number;\n kernelType: string;\n kernelName: string;\n programName: string;\n startTime: number;\n endTime: number;\n }\n\n export type WebGpuProfilingData = WebGpuProfilingDataV1;\n\n export interface WebGpuFlags {\n /**\n * Set or get the profiling mode.\n *\n * @deprecated Use `env.webgpu.profiling.mode` instead. If `env.webgpu.profiling.mode` is set, this property will be\n * ignored.\n */\n profilingMode?: 'off' | 'default';\n /**\n * Set or get the profiling configuration.\n */\n profiling: {\n /**\n * Set or get the profiling mode.\n *\n * @defaultValue `'off'`\n */\n mode?: 'off' | 'default';\n\n /**\n * Set or get a callback function when a profiling data is received. If not set, the profiling data will be\n * printed to console.\n */\n ondata?: (data: WebGpuProfilingData) => void;\n };\n /**\n * Set or get the power preference.\n *\n * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n * used as options for `navigator.gpu.requestAdapter()`.\n *\n * See {@link https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions} for more details.\n *\n * @defaultValue `undefined`\n *\n * @deprecated Create your own GPUAdapter, use it to create a GPUDevice instance and set {@link device} property if\n * you want to use a specific power preference.\n */\n powerPreference?: 'low-power' | 'high-performance';\n /**\n * Set or get the force fallback adapter flag.\n *\n * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n * used as options for `navigator.gpu.requestAdapter()`.\n *\n * See {@link https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions} for more details.\n *\n * @defaultValue `undefined`\n *\n * @deprecated Create your own GPUAdapter, use it to create a GPUDevice instance and set {@link device} property if\n * you want to use a specific fallback option.\n */\n forceFallbackAdapter?: boolean;\n /**\n * Set or get the adapter for WebGPU.\n *\n * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n * used as the GPU adapter for the underlying WebGPU backend to create GPU device.\n *\n * If this property is not set, it will be available to get after the first WebGPU inference session is created. The\n * value will be the GPU adapter that created by the underlying WebGPU backend.\n *\n * When use with TypeScript, the type of this property is `GPUAdapter` defined in \"@webgpu/types\".\n *\n * @deprecated It is no longer recommended to use this property. The latest WebGPU spec adds `GPUDevice.adapterInfo`\n * (https://www.w3.org/TR/webgpu/#dom-gpudevice-adapterinfo), which allows to get the adapter information from the\n * device. When it's available, there is no need to set/get the {@link adapter} property.\n */\n adapter: TryGetGlobalType<'GPUAdapter'>;\n /**\n * Set or get the GPU device for WebGPU.\n *\n * There are 3 valid scenarios of accessing this property:\n * - Set a value before the first WebGPU inference session is created. The value will be used by the WebGPU backend\n * to perform calculations. If the value is not a `GPUDevice` object, an error will be thrown.\n * - Get the value before the first WebGPU inference session is created. This will try to create a new GPUDevice\n * instance. Returns a `Promise` that resolves to a `GPUDevice` object.\n * - Get the value after the first WebGPU inference session is created. Returns a resolved `Promise` to the\n * `GPUDevice` object used by the WebGPU backend.\n */\n get device(): Promise<TryGetGlobalType<'GPUDevice'>>;\n set device(value: TryGetGlobalType<'GPUDevice'>);\n /**\n * Set or get whether validate input content.\n *\n * @defaultValue `false`\n */\n validateInputContent?: boolean;\n }\n}\n\nexport interface Env {\n /**\n * set the severity level for logging.\n *\n * @defaultValue `'warning'`\n */\n logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal';\n\n /**\n * Indicate whether run in debug mode.\n *\n * @defaultValue `false`\n */\n debug?: boolean;\n\n /**\n * set or get a boolean value indicating whether to enable trace.\n *\n * @defaultValue `false`\n */\n trace?: boolean;\n\n /**\n * Get version of the current package.\n */\n readonly versions: {\n readonly common: string;\n readonly web?: string;\n readonly node?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n readonly 'react-native'?: string;\n };\n\n /**\n * Represent a set of flags for WebAssembly\n */\n readonly wasm: Env.WebAssemblyFlags;\n\n /**\n * Represent a set of flags for WebGL\n */\n readonly webgl: Env.WebGLFlags;\n\n /**\n * Represent a set of flags for WebGPU\n */\n readonly webgpu: Env.WebGpuFlags;\n\n [name: string]: unknown;\n}\n\n/**\n * Represent a set of flags as a global singleton.\n */\nexport const env: Env = envImpl;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js';\nimport { Tensor } from './tensor.js';\n\n/**\n * implementation of Tensor.toDataURL()\n */\nexport const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions): string => {\n const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : new OffscreenCanvas(1, 1);\n canvas.width = tensor.dims[3];\n canvas.height = tensor.dims[2];\n const pixels2DContext = canvas.getContext('2d') as\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D\n | null;\n\n if (pixels2DContext != null) {\n // Default values for height and width & format\n let width: number;\n let height: number;\n if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') {\n width = tensor.dims[2];\n height = tensor.dims[3];\n } else {\n // Default layout is NCWH\n width = tensor.dims[3];\n height = tensor.dims[2];\n }\n\n const inputformat = options?.format !== undefined ? options.format : 'RGB';\n\n const norm = options?.norm;\n let normMean: [number, number, number, number];\n let normBias: [number, number, number, number];\n if (norm === undefined || norm.mean === undefined) {\n normMean = [255, 255, 255, 255];\n } else {\n if (typeof norm.mean === 'number') {\n normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n } else {\n normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 0];\n if (norm.mean[3] !== undefined) {\n normMean[3] = norm.mean[3];\n }\n }\n }\n if (norm === undefined || norm.bias === undefined) {\n normBias = [0, 0, 0, 0];\n } else {\n if (typeof norm.bias === 'number') {\n normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n } else {\n normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0];\n if (norm.bias[3] !== undefined) {\n normBias[3] = norm.bias[3];\n }\n }\n }\n\n const stride = height * width;\n // Default pointer assignments\n let rTensorPointer = 0,\n gTensorPointer = stride,\n bTensorPointer = stride * 2,\n aTensorPointer = -1;\n\n // Updating the pointer assignments based on the input image format\n if (inputformat === 'RGBA') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n aTensorPointer = stride * 3;\n } else if (inputformat === 'RGB') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n } else if (inputformat === 'RBG') {\n rTensorPointer = 0;\n bTensorPointer = stride;\n gTensorPointer = stride * 2;\n }\n\n for (let i = 0; i < height; i++) {\n for (let j = 0; j < width; j++) {\n const R = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value\n const G = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value\n const B = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value\n const A = aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value\n\n pixels2DContext.fillStyle = 'rgba(' + R + ',' + G + ',' + B + ',' + A + ')';\n pixels2DContext.fillRect(j, i, 1, 1);\n }\n }\n if ('toDataURL' in canvas) {\n return canvas.toDataURL();\n } else {\n throw new Error('toDataURL is not supported');\n }\n } else {\n throw new Error('Can not access image data');\n }\n};\n\n/**\n * implementation of Tensor.toImageData()\n */\nexport const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOptions): ImageData => {\n const pixels2DContext =\n typeof document !== 'undefined'\n ? document.createElement('canvas').getContext('2d')\n : (new OffscreenCanvas(1, 1).getContext('2d') as OffscreenCanvasRenderingContext2D);\n let image: ImageData;\n if (pixels2DContext != null) {\n // Default values for height and width & format\n let width: number;\n let height: number;\n let channels: number;\n if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') {\n width = tensor.dims[2];\n height = tensor.dims[1];\n channels = tensor.dims[3];\n } else {\n // Default layout is NCWH\n width = tensor.dims[3];\n height = tensor.dims[2];\n channels = tensor.dims[1];\n }\n const inputformat = options !== undefined ? (options.format !== undefined ? options.format : 'RGB') : 'RGB';\n\n const norm = options?.norm;\n let normMean: [number, number, number, number];\n let normBias: [number, number, number, number];\n if (norm === undefined || norm.mean === undefined) {\n normMean = [255, 255, 255, 255];\n } else {\n if (typeof norm.mean === 'number') {\n normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n } else {\n normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 255];\n if (norm.mean[3] !== undefined) {\n normMean[3] = norm.mean[3];\n }\n }\n }\n if (norm === undefined || norm.bias === undefined) {\n normBias = [0, 0, 0, 0];\n } else {\n if (typeof norm.bias === 'number') {\n normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n } else {\n normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0];\n if (norm.bias[3] !== undefined) {\n normBias[3] = norm.bias[3];\n }\n }\n }\n\n const stride = height * width;\n if (options !== undefined) {\n if (\n (options.format !== undefined && channels === 4 && options.format !== 'RGBA') ||\n (channels === 3 && options.format !== 'RGB' && options.format !== 'BGR')\n ) {\n throw new Error(\"Tensor format doesn't match input tensor dims\");\n }\n }\n\n // Default pointer assignments\n const step = 4;\n let rImagePointer = 0,\n gImagePointer = 1,\n bImagePointer = 2,\n aImagePointer = 3;\n let rTensorPointer = 0,\n gTensorPointer = stride,\n bTensorPointer = stride * 2,\n aTensorPointer = -1;\n\n // Updating the pointer assignments based on the input image format\n if (inputformat === 'RGBA') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n aTensorPointer = stride * 3;\n } else if (inputformat === 'RGB') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n } else if (inputformat === 'RBG') {\n rTensorPointer = 0;\n bTensorPointer = stride;\n gTensorPointer = stride * 2;\n }\n\n image = pixels2DContext.createImageData(width, height);\n\n for (\n let i = 0;\n i < height * width;\n rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++\n ) {\n image.data[rImagePointer] = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value\n image.data[gImagePointer] = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value\n image.data[bImagePointer] = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value\n image.data[aImagePointer] =\n aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value\n }\n } else {\n throw new Error('Can not access image data');\n }\n return image;\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n OptionsDimensions,\n OptionsFormat,\n OptionsNormalizationParameters,\n OptionsTensorFormat,\n OptionsTensorLayout,\n TensorFromGpuBufferOptions,\n TensorFromImageBitmapOptions,\n TensorFromImageDataOptions,\n TensorFromImageElementOptions,\n TensorFromMLTensorOptions,\n TensorFromTextureOptions,\n TensorFromUrlOptions,\n} from './tensor-factory.js';\nimport { Tensor } from './tensor-impl.js';\nimport { Tensor as TensorInterface } from './tensor.js';\n\ninterface BufferToTensorOptions\n extends OptionsDimensions,\n OptionsTensorLayout,\n OptionsNormalizationParameters,\n OptionsFormat,\n OptionsTensorFormat {}\n\n/**\n * Create a new tensor object from image object\n *\n * @param buffer - Extracted image buffer data - assuming RGBA format\n * @param imageFormat - input image configuration - required configurations height, width, format\n * @param tensorFormat - output tensor configuration - Default is RGB format\n */\nexport const bufferToTensor = (buffer: Uint8ClampedArray | undefined, options: BufferToTensorOptions): Tensor => {\n if (buffer === undefined) {\n throw new Error('Image buffer must be defined');\n }\n if (options.height === undefined || options.width === undefined) {\n throw new Error('Image height and width must be defined');\n }\n if (options.tensorLayout === 'NHWC') {\n throw new Error('NHWC Tensor layout is not supported yet');\n }\n\n const { height, width } = options;\n\n const norm = options.norm ?? { mean: 255, bias: 0 };\n let normMean: [number, number, number, number];\n let normBias: [number, number, number, number];\n\n if (typeof norm.mean === 'number') {\n normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n } else {\n normMean = [norm.mean![0], norm.mean![1], norm.mean![2], norm.mean![3] ?? 255];\n }\n\n if (typeof norm.bias === 'number') {\n normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n } else {\n normBias = [norm.bias![0], norm.bias![1], norm.bias![2], norm.bias![3] ?? 0];\n }\n\n const inputformat = options.format !== undefined ? options.format : 'RGBA';\n // default value is RGBA since imagedata and HTMLImageElement uses it\n\n const outputformat =\n options.tensorFormat !== undefined ? (options.tensorFormat !== undefined ? options.tensorFormat : 'RGB') : 'RGB';\n const stride = height * width;\n const float32Data = outputformat === 'RGBA' ? new Float32Array(stride * 4) : new Float32Array(stride * 3);\n\n // Default pointer assignments\n let step = 4,\n rImagePointer = 0,\n gImagePointer = 1,\n bImagePointer = 2,\n aImagePointer = 3;\n let rTensorPointer = 0,\n gTensorPointer = stride,\n bTensorPointer = stride * 2,\n aTensorPointer = -1;\n\n // Updating the pointer assignments based on the input image format\n if (inputformat === 'RGB') {\n step = 3;\n rImagePointer = 0;\n gImagePointer = 1;\n bImagePointer = 2;\n aImagePointer = -1;\n }\n\n // Updating the pointer assignments based on the output tensor format\n if (outputformat === 'RGBA') {\n aTensorPointer = stride * 3;\n } else if (outputformat === 'RBG') {\n rTensorPointer = 0;\n bTensorPointer = stride;\n gTensorPointer = stride * 2;\n } else if (outputformat === 'BGR') {\n bTensorPointer = 0;\n gTensorPointer = stride;\n rTensorPointer = stride * 2;\n }\n\n for (\n let i = 0;\n i < stride;\n i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step\n ) {\n float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias[0]) / normMean[0];\n float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias[1]) / normMean[1];\n float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias[2]) / normMean[2];\n if (aTensorPointer !== -1 && aImagePointer !== -1) {\n float32Data[aTensorPointer++] = (buffer[aImagePointer] + normBias[3]) / normMean[3];\n }\n }\n\n // Float32Array -> ort.Tensor\n const outputTensor =\n outputformat === 'RGBA'\n ? new Tensor('float32', float32Data, [1, 4, height, width])\n : new Tensor('float32', float32Data, [1, 3, height, width]);\n return outputTensor;\n};\n\n/**\n * implementation of Tensor.fromImage().\n */\nexport const tensorFromImage = async (\n image: ImageData | HTMLImageElement | ImageBitmap | string,\n options?:\n | TensorFromImageDataOptions\n | TensorFromImageElementOptions\n | TensorFromImageBitmapOptions\n | TensorFromUrlOptions,\n): Promise<Tensor> => {\n // checking the type of image object\n const isHTMLImageEle = typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement;\n const isImageDataEle = typeof ImageData !== 'undefined' && image instanceof ImageData;\n const isImageBitmap = typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap;\n const isString = typeof image === 'string';\n\n let data: Uint8ClampedArray | undefined;\n let bufferToTensorOptions: BufferToTensorOptions = options ?? {};\n\n const createCanvas = () => {\n if (typeof document !== 'undefined') {\n return document.createElement('canvas');\n } else if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(1, 1);\n } else {\n throw new Error('Canvas is not supported');\n }\n };\n const createCanvasContext = (canvas: HTMLCanvasElement | OffscreenCanvas) => {\n if (typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement) {\n return canvas.getContext('2d');\n } else if (canvas instanceof OffscreenCanvas) {\n return canvas.getContext('2d') as OffscreenCanvasRenderingContext2D;\n } else {\n return null;\n }\n };\n // filling and checking image configuration options\n if (isHTMLImageEle) {\n // HTMLImageElement - image object - format is RGBA by default\n const canvas = createCanvas();\n canvas.width = image.width;\n canvas.height = image.height;\n const pixels2DContext = createCanvasContext(canvas);\n\n if (pixels2DContext != null) {\n let height = image.height;\n let width = image.width;\n if (options !== undefined && options.resizedHeight !== undefined && options.resizedWidth !== undefined) {\n height = options.resizedHeight;\n width = options.resizedWidth;\n }\n\n if (options !== undefined) {\n bufferToTensorOptions = options;\n if (options.tensorFormat !== undefined) {\n throw new Error('Image input config format must be RGBA for HTMLImageElement');\n } else {\n bufferToTensorOptions.tensorFormat = 'RGBA';\n }\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n } else {\n bufferToTensorOptions.tensorFormat = 'RGBA';\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n }\n\n pixels2DContext.drawImage(image, 0, 0);\n data = pixels2DContext.getImageData(0, 0, width, height).data;\n } else {\n throw new Error('Can not access image data');\n }\n } else if (isImageDataEle) {\n let height: number;\n let width: number;\n\n if (options !== undefined && options.resizedWidth !== undefined && options.resizedHeight !== undefined) {\n height = options.resizedHeight;\n width = options.resizedWidth;\n } else {\n height = image.height;\n width = image.width;\n }\n\n if (options !== undefined) {\n bufferToTensorOptions = options;\n }\n bufferToTensorOptions.format = 'RGBA';\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n\n if (options !== undefined) {\n const tempCanvas = createCanvas();\n\n tempCanvas.width = width;\n tempCanvas.height = height;\n\n const pixels2DContext = createCanvasContext(tempCanvas);\n\n if (pixels2DContext != null) {\n pixels2DContext.putImageData(image, 0, 0);\n data = pixels2DContext.getImageData(0, 0, width, height).data;\n } else {\n throw new Error('Can not access image data');\n }\n } else {\n data = image.data;\n }\n } else if (isImageBitmap) {\n // ImageBitmap - image object - format must be provided by user\n if (options === undefined) {\n throw new Error('Please provide image config with format for Imagebitmap');\n }\n\n const canvas = createCanvas();\n canvas.width = image.width;\n canvas.height = image.height;\n const pixels2DContext = createCanvasContext(canvas);\n\n if (pixels2DContext != null) {\n const height = image.height;\n const width = image.width;\n pixels2DContext.drawImage(image, 0, 0, width, height);\n data = pixels2DContext.getImageData(0, 0, width, height).data;\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n return bufferToTensor(data, bufferToTensorOptions);\n } else {\n throw new Error('Can not access image data');\n }\n } else if (isString) {\n return new Promise((resolve, reject) => {\n const canvas = createCanvas();\n const context = createCanvasContext(canvas);\n if (!image || !context) {\n return reject();\n }\n const newImage = new Image();\n newImage.crossOrigin = 'Anonymous';\n newImage.src = image;\n newImage.onload = () => {\n canvas.width = newImage.width;\n canvas.height = newImage.height;\n context.drawImage(newImage, 0, 0, canvas.width, canvas.height);\n const img = context.getImageData(0, 0, canvas.width, canvas.height);\n\n bufferToTensorOptions.height = canvas.height;\n bufferToTensorOptions.width = canvas.width;\n resolve(bufferToTensor(img.data, bufferToTensorOptions));\n };\n });\n } else {\n throw new Error('Input data provided is not supported - aborted tensor creation');\n }\n\n if (data !== undefined) {\n return bufferToTensor(data, bufferToTensorOptions);\n } else {\n throw new Error('Input data provided is not supported - aborted tensor creation');\n }\n};\n\n/**\n * implementation of Tensor.fromTexture().\n */\nexport const tensorFromTexture = <T extends TensorInterface.TextureDataTypes>(\n texture: TensorInterface.TextureType,\n options: TensorFromTextureOptions<T>,\n): Tensor => {\n const { width, height, download, dispose } = options;\n // Always assume RGBAF32. TODO: support different texture format\n const dims = [1, height, width, 4];\n return new Tensor({ location: 'texture', type: 'float32', texture, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromGpuBuffer().\n */\nexport const tensorFromGpuBuffer = <T extends TensorInterface.GpuBufferDataTypes>(\n gpuBuffer: TensorInterface.GpuBufferType,\n options: TensorFromGpuBufferOptions<T>,\n): Tensor => {\n const { dataType, dims, download, dispose } = options;\n return new Tensor({ location: 'gpu-buffer', type: dataType ?? 'float32', gpuBuffer, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromMLTensor().\n */\nexport const tensorFromMLTensor = <T extends TensorInterface.MLTensorDataTypes>(\n mlTensor: TensorInterface.MLTensorType,\n options: TensorFromMLTensorOptions<T>,\n): Tensor => {\n const { dataType, dims, download, dispose } = options;\n return new Tensor({ location: 'ml-tensor', type: dataType ?? 'float32', mlTensor, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromPinnedBuffer().\n */\nexport const tensorFromPinnedBuffer = <T extends TensorInterface.CpuPinnedDataTypes>(\n type: T,\n buffer: TensorInterface.DataTypeMap[T],\n dims?: readonly number[],\n): Tensor => new Tensor({ location: 'cpu-pinned', type, data: buffer, dims: dims ?? [buffer.length] });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from './tensor.js';\n\nexport type SupportedTypedArrayConstructors =\n | Float32ArrayConstructor\n | Uint8ArrayConstructor\n | Int8ArrayConstructor\n | Uint16ArrayConstructor\n | Int16ArrayConstructor\n | Int32ArrayConstructor\n | BigInt64ArrayConstructor\n | Uint8ArrayConstructor\n | Float64ArrayConstructor\n | Uint32ArrayConstructor\n | BigUint64ArrayConstructor;\nexport type SupportedTypedArray = InstanceType<SupportedTypedArrayConstructors>;\n\n// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.\nexport const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map<string, SupportedTypedArrayConstructors>([\n ['float32', Float32Array],\n ['uint8', Uint8Array],\n ['int8', Int8Array],\n ['uint16', Uint16Array],\n ['int16', Int16Array],\n ['int32', Int32Array],\n ['bool', Uint8Array],\n ['float64', Float64Array],\n ['uint32', Uint32Array],\n ['int4', Uint8Array],\n ['uint4', Uint8Array],\n]);\n\n// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.\nexport const NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = new Map<SupportedTypedArrayConstructors, Tensor.Type>([\n [Float32Array, 'float32'],\n [Uint8Array, 'uint8'],\n [Int8Array, 'int8'],\n [Uint16Array, 'uint16'],\n [Int16Array, 'int16'],\n [Int32Array, 'int32'],\n [Float64Array, 'float64'],\n [Uint32Array, 'uint32'],\n]);\n\n// the following code allows delaying execution of BigInt/Float16Array checking. This allows lazy initialization for\n// NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP and NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, which allows BigInt/Float16Array\n// polyfill if available.\nlet isTypedArrayChecked = false;\nexport const checkTypedArray = () => {\n if (!isTypedArrayChecked) {\n isTypedArrayChecked = true;\n const isBigInt64ArrayAvailable = typeof BigInt64Array !== 'undefined' && BigInt64Array.from;\n const isBigUint64ArrayAvailable = typeof BigUint64Array !== 'undefined' && BigUint64Array.from;\n\n // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any\n const Float16Array = (globalThis as any).Float16Array;\n const isFloat16ArrayAvailable = typeof Float16Array !== 'undefined' && Float16Array.from;\n\n if (isBigInt64ArrayAvailable) {\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('int64', BigInt64Array);\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigInt64Array, 'int64');\n }\n if (isBigUint64ArrayAvailable) {\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('uint64', BigUint64Array);\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigUint64Array, 'uint64');\n }\n if (isFloat16ArrayAvailable) {\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('float16', Float16Array);\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(Float16Array, 'float16');\n } else {\n // if Float16Array is not available, use 'Uint16Array' to store the data.\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('float16', Uint16Array);\n }\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n CpuPinnedConstructorParameters,\n GpuBufferConstructorParameters,\n MLTensorConstructorParameters,\n TextureConstructorParameters,\n} from './tensor-factory.js';\nimport { Tensor } from './tensor-impl.js';\n\n/**\n * calculate size from dims.\n *\n * @param dims the dims array. May be an illegal input.\n */\nexport const calculateSize = (dims: readonly unknown[]): number => {\n let size = 1;\n for (let i = 0; i < dims.length; i++) {\n const dim = dims[i];\n if (typeof dim !== 'number' || !Number.isSafeInteger(dim)) {\n throw new TypeError(`dims[${i}] must be an integer, got: ${dim}`);\n }\n if (dim < 0) {\n throw new RangeError(`dims[${i}] must be a non-negative integer, got: ${dim}`);\n }\n size *= dim;\n }\n return size;\n};\n\n/**\n * implementation of Tensor.reshape()\n */\nexport const tensorReshape = (tensor: Tensor, dims: readonly number[]): Tensor => {\n switch (tensor.location) {\n case 'cpu':\n return new Tensor(tensor.type, tensor.data, dims);\n case 'cpu-pinned':\n return new Tensor({\n location: 'cpu-pinned',\n data: tensor.data as CpuPinnedConstructorParameters['data'],\n type: tensor.type as CpuPinnedConstructorParameters['type'],\n dims,\n });\n case 'texture':\n return new Tensor({\n location: 'texture',\n texture: tensor.texture,\n type: tensor.type as TextureConstructorParameters['type'],\n dims,\n });\n case 'gpu-buffer':\n return new Tensor({\n location: 'gpu-buffer',\n gpuBuffer: tensor.gpuBuffer,\n type: tensor.type as GpuBufferConstructorParameters['type'],\n dims,\n });\n case 'ml-tensor':\n return new Tensor({\n location: 'ml-tensor',\n mlTensor: tensor.mlTensor,\n type: tensor.type as MLTensorConstructorParameters['type'],\n dims,\n });\n default:\n throw new Error(`tensorReshape: tensor location ${tensor.location} is not supported`);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { tensorToDataURL, tensorToImageData } from './tensor-conversion-impl.js';\nimport { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js';\nimport {\n tensorFromGpuBuffer,\n tensorFromImage,\n tensorFromMLTensor,\n tensorFromPinnedBuffer,\n tensorFromTexture,\n} from './tensor-factory-impl.js';\nimport {\n CpuPinnedConstructorParameters,\n GpuBufferConstructorParameters,\n MLTensorConstructorParameters,\n TensorFromGpuBufferOptions,\n TensorFromImageBitmapOptions,\n TensorFromImageDataOptions,\n TensorFromImageElementOptions,\n TensorFromMLTensorOptions,\n TensorFromTextureOptions,\n TensorFromUrlOptions,\n TextureConstructorParameters,\n} from './tensor-factory.js';\nimport {\n checkTypedArray,\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP,\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP,\n SupportedTypedArray,\n SupportedTypedArrayConstructors,\n} from './tensor-impl-type-mapping.js';\nimport { calculateSize, tensorReshape } from './tensor-utils-impl.js';\nimport { Tensor as TensorInterface } from './tensor.js';\n\n// type aliases for those exported from Tensor interface\n\ntype TensorType = TensorInterface.Type;\ntype TensorDataType = TensorInterface.DataType;\ntype TensorDataLocation = TensorInterface.DataLocation;\ntype TensorTextureType = TensorInterface.TextureType;\ntype TensorGpuBufferType = TensorInterface.GpuBufferType;\ntype TensorMLTensorType = TensorInterface.MLTensorType;\n\n/**\n * the implementation of Tensor interface.\n *\n * @ignore\n */\nexport class Tensor implements TensorInterface {\n // #region constructors\n\n /**\n * Construct a new CPU tensor object from the given type, data and dims.\n */\n constructor(\n type: TensorType,\n data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly number[] | readonly boolean[],\n dims?: readonly number[],\n );\n /**\n * Construct a new CPU tensor object from the given data and dims. Type is inferred from data.\n */\n constructor(\n data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly boolean[],\n dims?: readonly number[],\n );\n /**\n * Construct a new tensor object from the pinned CPU data with the given type and dims.\n *\n * Tensor's location will be set to 'cpu-pinned'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: CpuPinnedConstructorParameters);\n /**\n * Construct a new tensor object from the WebGL texture with the given type and dims.\n *\n * Tensor's location will be set to 'texture'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: TextureConstructorParameters);\n /**\n * Construct a new tensor object from the WebGPU buffer with the given type and dims.\n *\n * Tensor's location will be set to 'gpu-buffer'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: GpuBufferConstructorParameters);\n\n /**\n * Construct a new tensor object from the WebNN MLTensor with the given type and dims.\n *\n * Tensor's location will be set to 'ml-tensor'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: MLTensorConstructorParameters);\n\n /**\n * implementation.\n */\n constructor(\n arg0:\n | TensorType\n | TensorDataType\n | Uint8ClampedArray\n | readonly string[]\n | readonly boolean[]\n | CpuPinnedConstructorParameters\n | TextureConstructorParameters\n | GpuBufferConstructorParameters\n | MLTensorConstructorParameters,\n arg1?: TensorDataType | Uint8ClampedArray | readonly number[] | readonly string[] | readonly boolean[],\n arg2?: readonly number[],\n ) {\n // perform one-time check for BigInt/Float16Array support\n checkTypedArray();\n\n let type: TensorType;\n let dims: readonly number[];\n\n if (typeof arg0 === 'object' && 'location' in arg0) {\n //\n // constructing tensor from specific location\n //\n this.dataLocation = arg0.location;\n type = arg0.type;\n dims = arg0.dims;\n switch (arg0.location) {\n case 'cpu-pinned': {\n const expectedTypedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(type);\n if (!expectedTypedArrayConstructor) {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from pinned buffer`);\n }\n if (!(arg0.data instanceof expectedTypedArrayConstructor)) {\n throw new TypeError(`buffer should be of type ${expectedTypedArrayConstructor.name}`);\n }\n this.cpuData = arg0.data;\n break;\n }\n case 'texture': {\n if (type !== 'float32') {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from texture`);\n }\n this.gpuTextureData = arg0.texture;\n this.downloader = arg0.download;\n this.disposer = arg0.dispose;\n break;\n }\n case 'gpu-buffer': {\n if (\n type !== 'float32' &&\n type !== 'float16' &&\n type !== 'int32' &&\n type !== 'int64' &&\n type !== 'uint32' &&\n type !== 'uint8' &&\n type !== 'bool' &&\n type !== 'uint4' &&\n type !== 'int4'\n ) {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from gpu buffer`);\n }\n this.gpuBufferData = arg0.gpuBuffer;\n this.downloader = arg0.download;\n this.disposer = arg0.dispose;\n break;\n }\n case 'ml-tensor': {\n if (\n type !== 'float32' &&\n type !== 'float16' &&\n type !== 'int32' &&\n type !== 'int64' &&\n type !== 'uint32' &&\n type !== 'uint64' &&\n type !== 'int8' &&\n type !== 'uint8' &&\n type !== 'bool' &&\n type !== 'uint4' &&\n type !== 'int4'\n ) {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from MLTensor`);\n }\n this.mlTensorData = arg0.mlTensor;\n this.downloader = arg0.download;\n this.disposer = arg0.dispose;\n break;\n }\n default:\n throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`);\n }\n } else {\n //\n // constructing tensor of location 'cpu'\n //\n let data: TensorDataType;\n let maybeDims: typeof arg1 | typeof arg2;\n // check whether arg0 is type or data\n if (typeof arg0 === 'string') {\n //\n // Override: constructor(type, data, ...)\n //\n type = arg0;\n maybeDims = arg2;\n if (arg0 === 'string') {\n // string tensor\n if (!Array.isArray(arg1)) {\n throw new TypeError(\"A string tensor's data must be a string array.\");\n }\n // we don't check whether every element in the array is string; this is too slow. we assume it's correct and\n // error will be populated at inference\n data = arg1;\n } else {\n // numeric tensor\n const typedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(arg0);\n if (typedArrayConstructor === undefined) {\n throw new TypeError(`Unsupported tensor type: ${arg0}.`);\n }\n if (Array.isArray(arg1)) {\n if ((arg0 === 'float16' && typedArrayConstructor === Uint16Array) || arg0 === 'uint4' || arg0 === 'int4') {\n // - 'float16':\n // When no Float16Array polyfill is used, we cannot create 'float16' tensor from number array.\n //\n // Throw error here because when user try to use number array as data,\n // e.g. new Tensor('float16', [1, 2, 3, 4], dims)), it will actually call\n // Uint16Array.from(arg1) which generates wrong data.\n //\n // - 'uint4' and 'int4':\n // Uint8Array.from(arg1) will generate wrong data for 'uint4' and 'int4' tensor.\n //\n throw new TypeError(\n `Creating a ${arg0} tensor from number array is not supported. Please use ${typedArrayConstructor.name} as data.`,\n );\n } else if (arg0 === 'uint64' || arg0 === 'int64') {\n // use 'as any' here because:\n // 1. TypeScript's check on type of 'Array.isArray()' does not work with readonly arrays.\n // see https://github.com/microsoft/TypeScript/issues/17002\n // 2. TypeScript's check on union type of '(BigInt64ArrayConstructor|BigUint64ArrayConstructor).from()'\n // does not accept parameter mapFn.\n // 3. parameters of 'SupportedTypedArrayConstructors.from()' does not match the requirement of the union\n // type.\n\n // assume 'arg1' is of type \"readonly number[]|readonly bigint[]\" here.\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = (typedArrayConstructor as any).from(arg1, BigInt);\n } else {\n // assume 'arg1' is of type \"readonly number[]\" here.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = (typedArrayConstructor as any).from(arg1);\n }\n } else if (arg1 instanceof typedArrayConstructor) {\n data = arg1;\n } else if (arg1 instanceof Uint8ClampedArray) {\n if (arg0 === 'uint8') {\n data = Uint8Array.from(arg1);\n } else {\n throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`);\n }\n } else if (arg0 === 'float16' && arg1 instanceof Uint16Array && typedArrayConstructor !== Uint16Array) {\n // when Float16Array is available and data is of type Uint16Array.\n // We allow Uint16Array to be passed in as data for 'float16' tensor until Float16Array is generally\n // supported in JavaScript environment.\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = new (globalThis as any).Float16Array(arg1.buffer, arg1.byteOffset, arg1.length);\n } else {\n throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`);\n }\n }\n } else {\n //\n // Override: constructor(data, ...)\n //\n maybeDims = arg1;\n if (Array.isArray(arg0)) {\n // only boolean[] and string[] is supported\n if (arg0.length === 0) {\n throw new TypeError('Tensor type cannot be inferred from an empty array.');\n }\n const firstElementType = typeof arg0[0];\n if (firstElementType === 'string') {\n type = 'string';\n data = arg0;\n } else if (firstElementType === 'boolean') {\n type = 'bool';\n // 'arg0' is of type 'boolean[]'. Uint8Array.from(boolean[]) actually works, but typescript thinks this is\n // wrong type. We use 'as any' to make it happy.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = Uint8Array.from(arg0 as any[]);\n } else {\n throw new TypeError(`Invalid element type of data array: ${firstElementType}.`);\n }\n } else if (arg0 instanceof Uint8ClampedArray) {\n type = 'uint8';\n data = Uint8Array.from(arg0);\n } else {\n // get tensor type from TypedArray\n const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get(\n arg0.constructor as SupportedTypedArrayConstructors,\n );\n if (mappedType === undefined) {\n throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`);\n }\n type = mappedType;\n data = arg0 as SupportedTypedArray;\n }\n }\n\n // type and data is processed, now processing dims\n if (maybeDims === undefined) {\n // assume 1-D tensor if dims omitted\n maybeDims = [data.length];\n } else if (!Array.isArray(maybeDims)) {\n throw new TypeError(\"A tensor's dims must be a number array\");\n }\n dims = maybeDims as readonly number[];\n\n this.cpuData = data;\n this.dataLocation = 'cpu';\n }\n\n // perform check on dims\n const size = calculateSize(dims);\n // if data is on CPU, check whether data length matches tensor size\n if (this.cpuData && size !== this.cpuData.length) {\n if ((type === 'uint4' || type === 'int4') && Math.ceil(size / 2) === this.cpuData.length) {\n // for (u)int4, the data length is half of the tensor size. So we check this special case when size is odd.\n } else {\n throw new Error(`Tensor's size(${size}) does not match data length(${this.cpuData.length}).`);\n }\n }\n\n this.type = type;\n this.dims = dims;\n this.size = size;\n }\n // #endregion\n\n // #region factory\n static async fromImage(\n image: ImageData | HTMLImageElement | ImageBitmap | string,\n options?:\n | TensorFromImageDataOptions\n | TensorFromImageElementOptions\n | TensorFromImageBitmapOptions\n | TensorFromUrlOptions,\n ): Promise<TensorInterface> {\n return tensorFromImage(image, options);\n }\n\n static fromTexture<T extends TensorInterface.TextureDataTypes>(\n texture: TensorTextureType,\n options: TensorFromTextureOptions<T>,\n ): TensorInterface {\n return tensorFromTexture(texture, options);\n }\n\n static fromGpuBuffer<T extends TensorInterface.GpuBufferDataTypes>(\n gpuBuffer: TensorGpuBufferType,\n options: TensorFromGpuBufferOptions<T>,\n ): TensorInterface {\n return tensorFromGpuBuffer(gpuBuffer, options);\n }\n\n static fromMLTensor<T extends TensorInterface.MLTensorDataTypes>(\n mlTensor: TensorMLTensorType,\n options: TensorFromMLTensorOptions<T>,\n ): TensorInterface {\n return tensorFromMLTensor(mlTensor, options);\n }\n\n static fromPinnedBuffer<T extends TensorInterface.CpuPinnedDataTypes>(\n type: T,\n buffer: TensorInterface.DataTypeMap[T],\n dims?: readonly number[],\n ): Tensor {\n return tensorFromPinnedBuffer(type, buffer, dims);\n }\n\n // #endregion\n\n // #region conversions\n toDataURL(options?: TensorToDataUrlOptions): string {\n return tensorToDataURL(this, options);\n }\n\n toImageData(options?: TensorToImageDataOptions): ImageData {\n return tensorToImageData(this, options);\n }\n // #endregion\n\n // #region public fields\n readonly dims: readonly number[];\n readonly type: TensorType;\n readonly size: number;\n // #endregion\n\n // #region private fields\n\n /**\n * stores the location of the data.\n */\n private dataLocation: TensorDataLocation;\n\n /**\n * stores the data on CPU, if location is 'cpu' or 'cpu-pinned'. otherwise empty.\n */\n private cpuData?: TensorDataType;\n\n /**\n * stores the underlying texture when location is 'texture'. otherwise empty.\n */\n private gpuTextureData?: TensorTextureType;\n\n /**\n * stores the underlying GPU buffer when location is 'gpu-buffer'. otherwise empty.\n */\n private gpuBufferData?: TensorGpuBufferType;\n\n /**\n * stores the underlying WebNN MLTensor when location is 'ml-tensor'. otherwise empty.\n */\n private mlTensorData?: TensorMLTensorType;\n\n /**\n * stores an optional downloader function to download data from GPU to CPU.\n */\n private downloader?(): Promise<TensorDataType>;\n\n /**\n * a flag indicating whether the data is being downloaded from GPU to CPU.\n */\n private isDownloading?: boolean;\n\n /**\n * stores an optional disposer function to dispose the underlying data.\n */\n private disposer?(): void;\n // #endregion\n\n // #region properties\n get data(): TensorDataType {\n this.ensureValid();\n if (!this.cpuData) {\n throw new Error(\n 'The data is not on CPU. Use `getData()` to download GPU data to CPU, ' +\n 'or use `texture` or `gpuBuffer` property to access the GPU data directly.',\n );\n }\n return this.cpuData;\n }\n\n get location(): TensorDataLocation {\n return this.dataLocation;\n }\n\n get texture(): TensorTextureType {\n this.ensureValid();\n if (!this.gpuTextureData) {\n throw new Error('The data is not stored as a WebGL texture.');\n }\n return this.gpuTextureData;\n }\n\n get gpuBuffer(): TensorGpuBufferType {\n this.ensureValid();\n if (!this.gpuBufferData) {\n throw new Error('The data is not stored as a WebGPU buffer.');\n }\n return this.gpuBufferData;\n }\n\n get mlTensor(): TensorMLTensorType {\n this.ensureValid();\n if (!this.mlTensorData) {\n throw new Error('The data is not stored as a WebNN MLTensor.');\n }\n return this.mlTensorData;\n }\n // #endregion\n\n // #region methods\n\n async getData(releaseData?: boolean): Promise<TensorDataType> {\n this.ensureValid();\n switch (this.dataLocation) {\n case 'cpu':\n case 'cpu-pinned':\n return this.data;\n case 'texture':\n case 'gpu-buffer':\n case 'ml-tensor': {\n if (!this.downloader) {\n throw new Error('The current tensor is not created with a specified data downloader.');\n }\n if (this.isDownloading) {\n throw new Error('The current tensor is being downloaded.');\n }\n try {\n this.isDownloading = true;\n const data = await this.downloader();\n this.downloader = undefined;\n this.dataLocation = 'cpu';\n this.cpuData = data;\n\n if (releaseData && this.disposer) {\n this.disposer();\n this.disposer = undefined;\n }\n\n return data;\n } finally {\n this.isDownloading = false;\n }\n }\n default:\n throw new Error(`cannot get data from location: ${this.dataLocation}`);\n }\n }\n\n dispose(): void {\n if (this.isDownloading) {\n throw new Error('The current tensor is being downloaded.');\n }\n\n if (this.disposer) {\n this.disposer();\n this.disposer = undefined;\n }\n this.cpuData = undefined;\n this.gpuTextureData = undefined;\n this.gpuBufferData = undefined;\n this.mlTensorData = undefined;\n this.downloader = undefined;\n this.isDownloading = undefined;\n\n this.dataLocation = 'none';\n }\n\n // #endregion\n\n // #region tensor utilities\n private ensureValid(): void {\n if (this.dataLocation === 'none') {\n throw new Error('The tensor is disposed.');\n }\n }\n\n reshape(dims: readonly number[]): TensorInterface {\n this.ensureValid();\n if (this.downloader || this.disposer) {\n throw new Error('Cannot reshape a tensor that owns GPU resource.');\n }\n return tensorReshape(this, dims);\n }\n // #endregion\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { TensorFactory } from './tensor-factory.js';\nimport { Tensor as TensorImpl } from './tensor-impl.js';\nimport { TypedTensorUtils } from './tensor-utils.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\n/* eslint-disable @typescript-eslint/no-redeclare */\n\n/**\n * represent a basic tensor with specified dimensions and data type.\n */\ninterface TypedTensorBase<T extends Tensor.Type> {\n /**\n * Get the dimensions of the tensor.\n */\n readonly dims: readonly number[];\n /**\n * Get the data type of the tensor.\n */\n readonly type: T;\n /**\n * Get the buffer data of the tensor.\n *\n * If the data is not on CPU (eg. it's in the form of WebGL texture or WebGPU buffer), throw error.\n */\n readonly data: Tensor.DataTypeMap[T];\n /**\n * Get the location of the data.\n */\n readonly location: Tensor.DataLocation;\n /**\n * Get the WebGL texture that holds the tensor data.\n *\n * If the data is not on GPU as WebGL texture, throw error.\n */\n readonly texture: Tensor.TextureType;\n /**\n * Get the WebGPU buffer that holds the tensor data.\n *\n * If the data is not on GPU as WebGPU buffer, throw error.\n */\n readonly gpuBuffer: Tensor.GpuBufferType;\n\n /**\n * Get the WebNN MLTensor that holds the tensor data.\n *\n * If the data is not in a WebNN MLTensor, throw error.\n */\n readonly mlTensor: Tensor.MLTensorType;\n\n /**\n * Get the buffer data of the tensor.\n *\n * If the data is on CPU, returns the data immediately.\n * If the data is on GPU, downloads the data and returns the promise.\n *\n * @param releaseData - whether release the data on GPU. Ignore if data is already on CPU.\n */\n getData(releaseData?: boolean): Promise<Tensor.DataTypeMap[T]>;\n\n /**\n * Dispose the tensor data.\n *\n * If the data is on CPU, remove its internal reference to the underlying data.\n * If the data is on GPU, release the data on GPU.\n *\n * After calling this function, the tensor is considered no longer valid. Its location will be set to 'none'.\n */\n dispose(): void;\n}\n\nexport declare namespace Tensor {\n interface DataTypeMap {\n float32: Float32Array;\n uint8: Uint8Array;\n int8: Int8Array;\n uint16: Uint16Array;\n int16: Int16Array;\n int32: Int32Array;\n int64: BigInt64Array;\n string: string[];\n bool: Uint8Array;\n float16: Uint16Array; // Keep using Uint16Array until we have a concrete solution for float 16.\n float64: Float64Array;\n uint32: Uint32Array;\n uint64: BigUint64Array;\n // complex64: never;\n // complex128: never;\n // bfloat16: never;\n uint4: Uint8Array;\n int4: Int8Array;\n }\n\n interface ElementTypeMap {\n float32: number;\n uint8: number;\n int8: number;\n uint16: number;\n int16: number;\n int32: number;\n int64: bigint;\n string: string;\n bool: boolean;\n float16: number; // Keep using Uint16Array until we have a concrete solution for float 16.\n float64: number;\n uint32: number;\n uint64: bigint;\n // complex64: never;\n // complex128: never;\n // bfloat16: never;\n uint4: number;\n int4: number;\n }\n\n type DataType = DataTypeMap[Type];\n type ElementType = ElementTypeMap[Type];\n\n /**\n * supported data types for constructing a tensor from a pinned CPU buffer\n */\n export type CpuPinnedDataTypes = Exclude<Tensor.Type, 'string'>;\n\n /**\n * type alias for WebGL texture\n */\n export type TextureType = WebGLTexture;\n\n /**\n * supported data types for constructing a tensor from a WebGL texture\n */\n export type TextureDataTypes = 'float32';\n\n type GpuBufferTypeFallback = { size: number; mapState: 'unmapped' | 'pending' | 'mapped' };\n /**\n * type alias for WebGPU buffer\n */\n export type GpuBufferType = TryGetGlobalType<'GPUBuffer', GpuBufferTypeFallback>;\n\n type MLTensorTypeFallback = { destroy(): void };\n /**\n * type alias for WebNN MLTensor\n *\n * The specification for WebNN's MLTensor is currently in flux.\n */\n export type MLTensorType = TryGetGlobalType<'MLTensor', MLTensorTypeFallback>;\n\n /**\n * supported data types for constructing a tensor from a WebGPU buffer\n */\n export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'bool';\n\n /**\n * supported data types for constructing a tensor from a WebNN MLTensor\n */\n export type MLTensorDataTypes =\n | 'float32'\n | 'float16'\n | 'int8'\n | 'uint8'\n | 'int32'\n | 'uint32'\n | 'int64'\n | 'uint64'\n | 'bool'\n | 'uint4'\n | 'int4';\n\n /**\n * represent where the tensor data is stored\n */\n export type DataLocation = 'none' | 'cpu' | 'cpu-pinned' | 'texture' | 'gpu-buffer' | 'ml-tensor';\n\n /**\n * represent the data type of a tensor\n */\n export type Type = keyof DataTypeMap;\n}\n\n/**\n * Represent multi-dimensional arrays to feed to or fetch from model inferencing.\n */\nexport interface TypedTensor<T extends Tensor.Type> extends TypedTensorBase<T>, TypedTensorUtils<T> {}\n/**\n * Represent multi-dimensional arrays to feed to or fetch from model inferencing.\n */\nexport interface Tensor extends TypedTensorBase<Tensor.Type>, TypedTensorUtils<Tensor.Type> {}\n\n/**\n * type TensorConstructor defines the constructors of 'Tensor' to create CPU tensor instances.\n */\nexport interface TensorConstructor extends TensorFactory {\n // #region CPU tensor - specify element type\n /**\n * Construct a new string tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (\n type: 'string',\n data: Tensor.DataTypeMap['string'] | readonly string[],\n dims?: readonly number[],\n ): TypedTensor<'string'>;\n\n /**\n * Construct a new bool tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (\n type: 'bool',\n data: Tensor.DataTypeMap['bool'] | readonly boolean[],\n dims?: readonly number[],\n ): TypedTensor<'bool'>;\n\n /**\n * Construct a new uint8 tensor object from a Uint8ClampedArray, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n /**\n * Construct a new 64-bit integer typed tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new <T extends 'uint64' | 'int64'>(\n type: T,\n data: Tensor.DataTypeMap[T] | readonly bigint[] | readonly number[],\n dims?: readonly number[],\n ): TypedTensor<T>;\n\n /**\n * Construct a new numeric tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new <T extends Exclude<Tensor.Type, 'string' | 'bool' | 'uint64' | 'int64'>>(\n type: T,\n data: Tensor.DataTypeMap[T] | readonly number[],\n dims?: readonly number[],\n ): TypedTensor<T>;\n // #endregion\n\n // #region CPU tensor - infer element types\n\n /**\n * Construct a new float32 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Float32Array, dims?: readonly number[]): TypedTensor<'float32'>;\n\n /**\n * Construct a new int8 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Int8Array, dims?: readonly number[]): TypedTensor<'int8'>;\n\n /**\n * Construct a new uint8 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n /**\n * Construct a new uint8 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n /**\n * Construct a new uint16 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint16Array, dims?: readonly number[]): TypedTensor<'uint16'>;\n\n /**\n * Construct a new int16 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Int16Array, dims?: readonly number[]): TypedTensor<'int16'>;\n\n /**\n * Construct a new int32 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Int32Array, dims?: readonly number[]): TypedTensor<'int32'>;\n\n /**\n * Construct a new int64 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: BigInt64Array, dims?: readonly number[]): TypedTensor<'int64'>;\n\n /**\n * Construct a new string tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: readonly string[], dims?: readonly number[]): TypedTensor<'string'>;\n\n /**\n * Construct a new bool tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>;\n\n /**\n * Construct a new float64 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Float64Array, dims?: readonly number[]): TypedTensor<'float64'>;\n\n /**\n * Construct a new uint32 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint32Array, dims?: readonly number[]): TypedTensor<'uint32'>;\n\n /**\n * Construct a new uint64 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: BigUint64Array, dims?: readonly number[]): TypedTensor<'uint64'>;\n\n // #endregion\n\n // #region CPU tensor - fall back to non-generic tensor type declaration\n\n /**\n * Construct a new tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (\n type: Tensor.Type,\n data: Tensor.DataType | readonly number[] | readonly string[] | readonly bigint[] | readonly boolean[],\n dims?: readonly number[],\n ): Tensor;\n\n /**\n * Construct a new tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Tensor.DataType, dims?: readonly number[]): Tensor;\n // #endregion\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const Tensor = TensorImpl as TensorConstructor;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env } from './env-impl.js';\n\n/**\n * @ignore\n */\nexport const TRACE = (deviceType: string, label: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n // eslint-disable-next-line no-console\n console.timeStamp(`${deviceType}::ORT::${label}`);\n};\n\nconst TRACE_FUNC = (msg: string, extraMsg?: string) => {\n const stack = new Error().stack?.split(/\\r\\n|\\r|\\n/g) || [];\n let hasTraceFunc = false;\n for (let i = 0; i < stack.length; i++) {\n if (hasTraceFunc && !stack[i].includes('TRACE_FUNC')) {\n let label = `FUNC_${msg}::${stack[i].trim().split(' ')[1]}`;\n if (extraMsg) {\n label += `::${extraMsg}`;\n }\n TRACE('CPU', label);\n return;\n }\n if (stack[i].includes('TRACE_FUNC')) {\n hasTraceFunc = true;\n }\n }\n};\n\n/**\n * @ignore\n */\nexport const TRACE_FUNC_BEGIN = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n TRACE_FUNC('BEGIN', extraMsg);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_FUNC_END = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n TRACE_FUNC('END', extraMsg);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_EVENT_BEGIN = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n // eslint-disable-next-line no-console\n console.time(`ORT::${extraMsg}`);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_EVENT_END = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n // eslint-disable-next-line no-console\n console.timeEnd(`ORT::${extraMsg}`);\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { resolveBackendAndExecutionProviders } from './backend-impl.js';\nimport { InferenceSessionHandler } from './backend.js';\nimport { InferenceSession as InferenceSessionInterface } from './inference-session.js';\nimport { OnnxValue } from './onnx-value.js';\nimport { Tensor } from './tensor.js';\nimport { TRACE_FUNC_BEGIN, TRACE_FUNC_END, TRACE_EVENT_BEGIN, TRACE_EVENT_END } from './trace.js';\n\ntype SessionOptions = InferenceSessionInterface.SessionOptions;\ntype RunOptions = InferenceSessionInterface.RunOptions;\ntype FeedsType = InferenceSessionInterface.FeedsType;\ntype FetchesType = InferenceSessionInterface.FetchesType;\ntype ReturnType = InferenceSessionInterface.ReturnType;\n\nexport class InferenceSession implements InferenceSessionInterface {\n private constructor(handler: InferenceSessionHandler) {\n this.handler = handler;\n }\n run(feeds: FeedsType, options?: RunOptions): Promise<ReturnType>;\n run(feeds: FeedsType, fetches: FetchesType, options?: RunOptions): Promise<ReturnType>;\n async run(feeds: FeedsType, arg1?: FetchesType | RunOptions, arg2?: RunOptions): Promise<ReturnType> {\n TRACE_FUNC_BEGIN();\n TRACE_EVENT_BEGIN('InferenceSession.run');\n const fetches: { [name: string]: OnnxValue | null } = {};\n let options: RunOptions = {};\n // check inputs\n if (typeof feeds !== 'object' || feeds === null || feeds instanceof Tensor || Array.isArray(feeds)) {\n throw new TypeError(\n \"'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.\",\n );\n }\n\n let isFetchesEmpty = true;\n // determine which override is being used\n if (typeof arg1 === 'object') {\n if (arg1 === null) {\n throw new TypeError('Unexpected argument[1]: cannot be null.');\n }\n if (arg1 instanceof Tensor) {\n throw new TypeError(\"'fetches' cannot be a Tensor\");\n }\n\n if (Array.isArray(arg1)) {\n if (arg1.length === 0) {\n throw new TypeError(\"'fetches' cannot be an empty array.\");\n }\n isFetchesEmpty = false;\n // output names\n for (const name of arg1) {\n if (typeof name !== 'string') {\n throw new TypeError(\"'fetches' must be a string array or an object.\");\n }\n if (this.outputNames.indexOf(name) === -1) {\n throw new RangeError(`'fetches' contains invalid output name: ${name}.`);\n }\n fetches[name] = null;\n }\n\n if (typeof arg2 === 'object' && arg2 !== null) {\n options = arg2;\n } else if (typeof arg2 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else {\n // decide whether arg1 is fetches or options\n // if any output name is present and its value is valid OnnxValue, we consider it fetches\n let isFetches = false;\n const arg1Keys = Object.getOwnPropertyNames(arg1);\n for (const name of this.outputNames) {\n if (arg1Keys.indexOf(name) !== -1) {\n const v = (arg1 as InferenceSessionInterface.NullableOnnxValueMapType)[name];\n if (v === null || v instanceof Tensor) {\n isFetches = true;\n isFetchesEmpty = false;\n fetches[name] = v;\n }\n }\n }\n\n if (isFetches) {\n if (typeof arg2 === 'object' && arg2 !== null) {\n options = arg2;\n } else if (typeof arg2 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else {\n options = arg1 as RunOptions;\n }\n }\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"Unexpected argument[1]: must be 'fetches' or 'options'.\");\n }\n\n // check if all inputs are in feed\n for (const name of this.inputNames) {\n if (typeof feeds[name] === 'undefined') {\n throw new Error(`input '${name}' is missing in 'feeds'.`);\n }\n }\n\n // if no fetches is specified, we use the full output names list\n if (isFetchesEmpty) {\n for (const name of this.outputNames) {\n fetches[name] = null;\n }\n }\n\n // feeds, fetches and options are prepared\n\n const results = await this.handler.run(feeds, fetches, options);\n const returnValue: { [name: string]: OnnxValue } = {};\n for (const key in results) {\n if (Object.hasOwnProperty.call(results, key)) {\n const result = results[key];\n if (result instanceof Tensor) {\n returnValue[key] = result;\n } else {\n returnValue[key] = new Tensor(result.type, result.data, result.dims);\n }\n }\n }\n TRACE_EVENT_END('InferenceSession.run');\n TRACE_FUNC_END();\n return returnValue;\n }\n\n async release(): Promise<void> {\n return this.handler.dispose();\n }\n\n static create(path: string, options?: SessionOptions): Promise<InferenceSessionInterface>;\n static create(buffer: ArrayBufferLike, options?: SessionOptions): Promise<InferenceSessionInterface>;\n static create(\n buffer: ArrayBufferLike,\n byteOffset: number,\n byteLength?: number,\n options?: SessionOptions,\n ): Promise<InferenceSessionInterface>;\n static create(buffer: Uint8Array, options?: SessionOptions): Promise<InferenceSessionInterface>;\n static async create(\n arg0: string | ArrayBufferLike | Uint8Array,\n arg1?: SessionOptions | number,\n arg2?: number,\n arg3?: SessionOptions,\n ): Promise<InferenceSessionInterface> {\n TRACE_FUNC_BEGIN();\n TRACE_EVENT_BEGIN('InferenceSession.create');\n // either load from a file or buffer\n let filePathOrUint8Array: string | Uint8Array;\n let options: SessionOptions = {};\n\n if (typeof arg0 === 'string') {\n filePathOrUint8Array = arg0;\n if (typeof arg1 === 'object' && arg1 !== null) {\n options = arg1;\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else if (arg0 instanceof Uint8Array) {\n filePathOrUint8Array = arg0;\n if (typeof arg1 === 'object' && arg1 !== null) {\n options = arg1;\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else if (\n arg0 instanceof ArrayBuffer ||\n (typeof SharedArrayBuffer !== 'undefined' && arg0 instanceof SharedArrayBuffer)\n ) {\n const buffer = arg0;\n let byteOffset = 0;\n let byteLength = arg0.byteLength;\n if (typeof arg1 === 'object' && arg1 !== null) {\n options = arg1;\n } else if (typeof arg1 === 'number') {\n byteOffset = arg1;\n if (!Number.isSafeInteger(byteOffset)) {\n throw new RangeError(\"'byteOffset' must be an integer.\");\n }\n if (byteOffset < 0 || byteOffset >= buffer.byteLength) {\n throw new RangeError(`'byteOffset' is out of range [0, ${buffer.byteLength}).`);\n }\n byteLength = arg0.byteLength - byteOffset;\n if (typeof arg2 === 'number') {\n byteLength = arg2;\n if (!Number.isSafeInteger(byteLength)) {\n throw new RangeError(\"'byteLength' must be an integer.\");\n }\n if (byteLength <= 0 || byteOffset + byteLength > buffer.byteLength) {\n throw new RangeError(`'byteLength' is out of range (0, ${buffer.byteLength - byteOffset}].`);\n }\n if (typeof arg3 === 'object' && arg3 !== null) {\n options = arg3;\n } else if (typeof arg3 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else if (typeof arg2 !== 'undefined') {\n throw new TypeError(\"'byteLength' must be a number.\");\n }\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n filePathOrUint8Array = new Uint8Array(buffer, byteOffset, byteLength);\n } else {\n throw new TypeError(\"Unexpected argument[0]: must be 'path' or 'buffer'.\");\n }\n\n // resolve backend, update session options with validated EPs, and create session handler\n const [backend, optionsWithValidatedEPs] = await resolveBackendAndExecutionProviders(options);\n const handler = await backend.createInferenceSessionHandler(filePathOrUint8Array, optionsWithValidatedEPs);\n TRACE_EVENT_END('InferenceSession.create');\n TRACE_FUNC_END();\n return new InferenceSession(handler);\n }\n\n startProfiling(): void {\n this.handler.startProfiling();\n }\n endProfiling(): void {\n this.handler.endProfiling();\n }\n\n get inputNames(): readonly string[] {\n return this.handler.inputNames;\n }\n get outputNames(): readonly string[] {\n return this.handler.outputNames;\n }\n\n get inputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] {\n return this.handler.inputMetadata;\n }\n\n get outputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] {\n return this.handler.outputMetadata;\n }\n\n private handler: InferenceSessionHandler;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession as InferenceSessionImpl } from './inference-session-impl.js';\nimport { OnnxModelOptions } from './onnx-model.js';\nimport { OnnxValue, OnnxValueDataLocation } from './onnx-value.js';\nimport type { Tensor } from './tensor.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\n/* eslint-disable @typescript-eslint/no-redeclare */\n\nexport declare namespace InferenceSession {\n // #region input/output types\n\n type OnnxValueMapType = { readonly [name: string]: OnnxValue };\n type NullableOnnxValueMapType = { readonly [name: string]: OnnxValue | null };\n\n /**\n * A feeds (model inputs) is an object that uses input names as keys and OnnxValue as corresponding values.\n */\n type FeedsType = OnnxValueMapType;\n\n /**\n * A fetches (model outputs) could be one of the following:\n *\n * - Omitted. Use model's output names definition.\n * - An array of string indicating the output names.\n * - An object that use output names as keys and OnnxValue or null as corresponding values.\n *\n * @remark\n * different from input argument, in output, OnnxValue is optional. If an OnnxValue is present it will be\n * used as a pre-allocated value by the inference engine; if omitted, inference engine will allocate buffer\n * internally.\n */\n type FetchesType = readonly string[] | NullableOnnxValueMapType;\n\n /**\n * A inferencing return type is an object that uses output names as keys and OnnxValue as corresponding values.\n */\n type ReturnType = OnnxValueMapType;\n\n // #endregion\n\n // #region session options\n\n /**\n * A set of configurations for session behavior.\n */\n export interface SessionOptions extends OnnxModelOptions {\n /**\n * An array of execution provider options.\n *\n * An execution provider option can be a string indicating the name of the execution provider,\n * or an object of corresponding type.\n */\n executionProviders?: readonly ExecutionProviderConfig[];\n\n /**\n * The intra OP threads number.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native).\n */\n intraOpNumThreads?: number;\n\n /**\n * The inter OP threads number.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native).\n */\n interOpNumThreads?: number;\n\n /**\n * The free dimension override.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n freeDimensionOverrides?: { readonly [dimensionName: string]: number };\n\n /**\n * The optimization level.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n graphOptimizationLevel?: 'disabled' | 'basic' | 'extended' | 'layout' | 'all';\n\n /**\n * Whether enable CPU memory arena.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n enableCpuMemArena?: boolean;\n\n /**\n * Whether enable memory pattern.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n enableMemPattern?: boolean;\n\n /**\n * Execution mode.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n executionMode?: 'sequential' | 'parallel';\n\n /**\n * Optimized model file path.\n *\n * If this setting is specified, the optimized model will be dumped. In browser, a blob will be created\n * with a pop-up window.\n */\n optimizedModelFilePath?: string;\n\n /**\n * Whether enable profiling.\n *\n * This setting is a placeholder for a future use.\n */\n enableProfiling?: boolean;\n\n /**\n * File prefix for profiling.\n *\n * This setting is a placeholder for a future use.\n */\n profileFilePrefix?: string;\n\n /**\n * Log ID.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n logId?: string;\n\n /**\n * Log severity level. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/logging/severity.h\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n logSeverityLevel?: 0 | 1 | 2 | 3 | 4;\n\n /**\n * Log verbosity level.\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n */\n logVerbosityLevel?: number;\n\n /**\n * Specify string as a preferred data location for all outputs, or an object that use output names as keys and a\n * preferred data location as corresponding values.\n *\n * This setting is available only in ONNXRuntime Web for WebGL and WebGPU EP.\n */\n preferredOutputLocation?: OnnxValueDataLocation | { readonly [outputName: string]: OnnxValueDataLocation };\n\n /**\n * Whether enable graph capture.\n * This setting is available only in ONNXRuntime Web for WebGPU EP.\n */\n enableGraphCapture?: boolean;\n\n /**\n * Store configurations for a session. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/session/\n * onnxruntime_session_options_config_keys.h\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n *\n * @example\n * ```js\n * extra: {\n * session: {\n * set_denormal_as_zero: \"1\",\n * disable_prepacking: \"1\"\n * },\n * optimization: {\n * enable_gelu_approximation: \"1\"\n * }\n * }\n * ```\n */\n extra?: Record<string, unknown>;\n }\n\n // #region execution providers\n\n // Currently, we have the following backends to support execution providers:\n // Backend Node.js binding: supports 'cpu', 'dml' (win32), 'coreml' (macOS) and 'cuda' (linux).\n // Backend WebAssembly: supports 'cpu', 'wasm', 'webgpu' and 'webnn'.\n // Backend ONNX.js: supports 'webgl'.\n // Backend React Native: supports 'cpu', 'xnnpack', 'coreml' (iOS), 'nnapi' (Android).\n interface ExecutionProviderOptionMap {\n coreml: CoreMLExecutionProviderOption;\n cpu: CpuExecutionProviderOption;\n cuda: CudaExecutionProviderOption;\n dml: DmlExecutionProviderOption;\n nnapi: NnapiExecutionProviderOption;\n tensorrt: TensorRtExecutionProviderOption;\n wasm: WebAssemblyExecutionProviderOption;\n webgl: WebGLExecutionProviderOption;\n webgpu: WebGpuExecutionProviderOption;\n webnn: WebNNExecutionProviderOption;\n qnn: QnnExecutionProviderOption;\n xnnpack: XnnpackExecutionProviderOption;\n }\n\n type ExecutionProviderName = keyof ExecutionProviderOptionMap;\n type ExecutionProviderConfig =\n | ExecutionProviderOptionMap[ExecutionProviderName]\n | ExecutionProviderOption\n | ExecutionProviderName\n | string;\n\n export interface ExecutionProviderOption {\n readonly name: string;\n }\n export interface CpuExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'cpu';\n useArena?: boolean;\n }\n export interface CudaExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'cuda';\n deviceId?: number;\n }\n export interface DmlExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'dml';\n deviceId?: number;\n }\n export interface TensorRtExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'tensorrt';\n deviceId?: number;\n }\n export interface WebAssemblyExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'wasm';\n }\n export interface WebGLExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'webgl';\n // TODO: add flags\n }\n export interface XnnpackExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'xnnpack';\n }\n export interface WebGpuExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'webgpu';\n\n /**\n * Specify the preferred layout when running layout sensitive operators.\n *\n * @default 'NCHW'\n */\n preferredLayout?: 'NCHW' | 'NHWC';\n\n /**\n * Specify a list of node names that should be executed on CPU even when WebGPU EP is used.\n */\n forceCpuNodeNames?: readonly string[];\n\n /**\n * Specify the validation mode for WebGPU execution provider.\n * - 'disabled': Disable all validation.\n * When used in Node.js, disable validation may cause process crash if WebGPU errors occur. Be cautious when using\n * this mode.\n * When used in web, this mode is equivalent to 'wgpuOnly'.\n * - 'wgpuOnly': Perform WebGPU internal validation only.\n * - 'basic': Perform basic validation including WebGPU internal validation. This is the default mode.\n * - 'full': Perform full validation. This mode may have performance impact. Use it for debugging purpose.\n *\n * @default 'basic'\n */\n validationMode?: 'disabled' | 'wgpuOnly' | 'basic' | 'full';\n\n /**\n * Specify an optional WebGPU device to be used by the WebGPU execution provider.\n */\n device?: TryGetGlobalType<'GPUDevice'>;\n }\n\n // #region WebNN options\n\n interface WebNNExecutionProviderName extends ExecutionProviderOption {\n readonly name: 'webnn';\n }\n\n /**\n * Represents a set of options for creating a WebNN MLContext.\n *\n * @see https://www.w3.org/TR/webnn/#dictdef-mlcontextoptions\n */\n export interface WebNNContextOptions {\n deviceType?: 'cpu' | 'gpu' | 'npu';\n numThreads?: number;\n powerPreference?: 'default' | 'low-power' | 'high-performance';\n }\n\n /**\n * Represents a set of options for WebNN execution provider without MLContext.\n */\n export interface WebNNOptionsWithoutMLContext extends WebNNExecutionProviderName, WebNNContextOptions {\n context?: never;\n }\n\n /**\n * Represents a set of options for WebNN execution provider with MLContext.\n *\n * When MLContext is provided, the deviceType is also required so that the WebNN EP can determine the preferred\n * channel layout.\n *\n * @see https://www.w3.org/TR/webnn/#dom-ml-createcontext\n */\n export interface WebNNOptionsWithMLContext\n extends WebNNExecutionProviderName,\n Omit<WebNNContextOptions, 'deviceType'>,\n Required<Pick<WebNNContextOptions, 'deviceType'>> {\n context: TryGetGlobalType<'MLContext'>;\n }\n\n /**\n * Represents a set of options for WebNN execution provider with MLContext which is created from GPUDevice.\n *\n * @see https://www.w3.org/TR/webnn/#dom-ml-createcontext-gpudevice\n */\n export interface WebNNOptionsWebGpu extends WebNNExecutionProviderName {\n context: TryGetGlobalType<'MLContext'>;\n gpuDevice: TryGetGlobalType<'GPUDevice'>;\n }\n\n /**\n * Options for WebNN execution provider.\n */\n export type WebNNExecutionProviderOption =\n | WebNNOptionsWithoutMLContext\n | WebNNOptionsWithMLContext\n | WebNNOptionsWebGpu;\n\n // #endregion\n\n export interface QnnExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'qnn';\n /**\n * Specify the QNN backend type. E.g., 'cpu' or 'htp'.\n * Mutually exclusive with `backendPath`.\n *\n * @default 'htp'\n */\n backendType?: string;\n /**\n * Specify a path to the QNN backend library.\n * Mutually exclusive with `backendType`.\n */\n backendPath?: string;\n /**\n * Specify whether to enable HTP FP16 precision.\n *\n * @default true\n */\n enableFp16Precision?: boolean;\n }\n export interface CoreMLExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'coreml';\n /**\n * The bit flags for CoreML execution provider.\n *\n * ```\n * COREML_FLAG_USE_CPU_ONLY = 0x001\n * COREML_FLAG_ENABLE_ON_SUBGRAPH = 0x002\n * COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE = 0x004\n * COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES = 0x008\n * COREML_FLAG_CREATE_MLPROGRAM = 0x010\n * COREML_FLAG_USE_CPU_AND_GPU = 0x020\n * ```\n *\n * See include/onnxruntime/core/providers/coreml/coreml_provider_factory.h for more details.\n *\n * This flag is available only in ONNXRuntime (Node.js binding).\n */\n coreMlFlags?: number;\n /**\n * Specify whether to use CPU only in CoreML EP.\n *\n * This setting is available only in ONNXRuntime (react-native).\n */\n useCPUOnly?: boolean;\n useCPUAndGPU?: boolean;\n /**\n * Specify whether to enable CoreML EP on subgraph.\n *\n * This setting is available only in ONNXRuntime (react-native).\n */\n enableOnSubgraph?: boolean;\n /**\n * Specify whether to only enable CoreML EP for Apple devices with ANE (Apple Neural Engine).\n *\n * This setting is available only in ONNXRuntime (react-native).\n */\n onlyEnableDeviceWithANE?: boolean;\n }\n export interface NnapiExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'nnapi';\n useFP16?: boolean;\n useNCHW?: boolean;\n cpuDisabled?: boolean;\n cpuOnly?: boolean;\n }\n // #endregion\n\n // #endregion\n\n // #region run options\n\n /**\n * A set of configurations for inference run behavior\n */\n export interface RunOptions {\n /**\n * Log severity level. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/logging/severity.h\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n logSeverityLevel?: 0 | 1 | 2 | 3 | 4;\n\n /**\n * Log verbosity level.\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n */\n logVerbosityLevel?: number;\n\n /**\n * Terminate all incomplete OrtRun calls as soon as possible if true\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n */\n terminate?: boolean;\n\n /**\n * A tag for the Run() calls using this\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n tag?: string;\n\n /**\n * Set a single run configuration entry. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/session/\n * onnxruntime_run_options_config_keys.h\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n *\n * @example\n *\n * ```js\n * extra: {\n * memory: {\n * enable_memory_arena_shrinkage: \"1\",\n * }\n * }\n * ```\n */\n extra?: Record<string, unknown>;\n }\n\n // #endregion\n\n // #region value metadata\n\n /**\n * The common part of the value metadata type for both tensor and non-tensor values.\n */\n export interface ValueMetadataBase {\n /**\n * The name of the specified input or output.\n */\n readonly name: string;\n }\n\n /**\n * Represents the metadata of a non-tensor value.\n */\n export interface NonTensorValueMetadata extends ValueMetadataBase {\n /**\n * Get a value indicating whether the value is a tensor.\n */\n readonly isTensor: false;\n }\n\n /**\n * Represents the metadata of a tensor value.\n */\n export interface TensorValueMetadata extends ValueMetadataBase {\n /**\n * Get a value indicating whether the value is a tensor.\n */\n readonly isTensor: true;\n /**\n * Get the data type of the tensor.\n */\n readonly type: Tensor.Type;\n /**\n * Get the shape of the tensor.\n *\n * If the shape is not defined, the value will an empty array. Otherwise, it will be an array representing the shape\n * of the tensor. Each element in the array can be a number or a string. If the element is a number, it represents\n * the corresponding dimension size. If the element is a string, it represents a symbolic dimension.\n */\n readonly shape: ReadonlyArray<number | string>;\n }\n\n /**\n * Represents the metadata of a value.\n */\n export type ValueMetadata = NonTensorValueMetadata | TensorValueMetadata;\n\n // #endregion\n}\n\n/**\n * Represent a runtime instance of an ONNX model.\n */\nexport interface InferenceSession {\n // #region run()\n\n /**\n * Execute the model asynchronously with the given feeds and options.\n *\n * @param feeds - Representation of the model input. See type description of `InferenceSession.InputType` for detail.\n * @param options - Optional. A set of options that controls the behavior of model inference.\n * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values.\n */\n run(feeds: InferenceSession.FeedsType, options?: InferenceSession.RunOptions): Promise<InferenceSession.ReturnType>;\n\n /**\n * Execute the model asynchronously with the given feeds, fetches and options.\n *\n * @param feeds - Representation of the model input. See type description of `InferenceSession.InputType` for detail.\n * @param fetches - Representation of the model output. See type description of `InferenceSession.OutputType` for\n * detail.\n * @param options - Optional. A set of options that controls the behavior of model inference.\n * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values.\n */\n run(\n feeds: InferenceSession.FeedsType,\n fetches: InferenceSession.FetchesType,\n options?: InferenceSession.RunOptions,\n ): Promise<InferenceSession.ReturnType>;\n\n // #endregion\n\n // #region release()\n\n /**\n * Release the inference session and the underlying resources.\n */\n release(): Promise<void>;\n\n // #endregion\n\n // #region profiling\n\n /**\n * Start profiling.\n */\n startProfiling(): void;\n\n /**\n * End profiling.\n */\n endProfiling(): void;\n\n // #endregion\n\n // #region metadata\n\n /**\n * Get input names of the loaded model.\n */\n readonly inputNames: readonly string[];\n\n /**\n * Get output names of the loaded model.\n */\n readonly outputNames: readonly string[];\n\n /**\n * Get input metadata of the loaded model.\n */\n readonly inputMetadata: readonly InferenceSession.ValueMetadata[];\n\n /**\n * Get output metadata of the loaded model.\n */\n readonly outputMetadata: readonly InferenceSession.ValueMetadata[];\n\n // #endregion\n}\n\nexport interface InferenceSessionFactory {\n // #region create()\n\n /**\n * Create a new inference session and load model asynchronously from an ONNX model file.\n *\n * @param uri - The URI or file path of the model to load.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(uri: string, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n /**\n * Create a new inference session and load model asynchronously from an array bufer.\n *\n * @param buffer - An ArrayBuffer representation of an ONNX model.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(buffer: ArrayBufferLike, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n /**\n * Create a new inference session and load model asynchronously from segment of an array bufer.\n *\n * @param buffer - An ArrayBuffer representation of an ONNX model.\n * @param byteOffset - The beginning of the specified portion of the array buffer.\n * @param byteLength - The length in bytes of the array buffer.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(\n buffer: ArrayBufferLike,\n byteOffset: number,\n byteLength?: number,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSession>;\n\n /**\n * Create a new inference session and load model asynchronously from a Uint8Array.\n *\n * @param buffer - A Uint8Array representation of an ONNX model.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(buffer: Uint8Array, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n // #endregion\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const InferenceSession: InferenceSessionFactory = InferenceSessionImpl;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { OptionsFormat, OptionsNormalizationParameters, OptionsTensorLayout } from './tensor-factory.js';\n\nexport interface TensorToDataUrlOptions extends OptionsTensorLayout, OptionsFormat, OptionsNormalizationParameters {}\n\nexport interface TensorToImageDataOptions extends OptionsTensorLayout, OptionsFormat, OptionsNormalizationParameters {}\n\nexport interface ConversionUtils {\n /**\n * creates a DataURL instance from tensor\n *\n * @param options - An optional object representing options for creating a DataURL instance from the tensor.\n *\n * The following default settings will be applied:\n * - `format`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * @returns a DataURL string representing the image converted from tensor data\n */\n toDataURL(options?: TensorToDataUrlOptions): string;\n\n /**\n * creates an ImageData instance from tensor\n *\n * @param options - An optional object representing options for creating an ImageData instance from the tensor.\n *\n * The following default settings will be applied:\n * - `format`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * @returns an ImageData instance representing the image converted from tensor data\n */\n toImageData(options?: TensorToImageDataOptions): ImageData;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor, TypedTensor } from './tensor.js';\n\nexport type ImageFormat = 'RGB' | 'RGBA' | 'BGR' | 'RBG';\nexport type ImageTensorLayout = 'NHWC' | 'NCHW';\n\n// the following region contains type definitions for constructing tensor from a specific location.\n\n// #region types for constructing a tensor from a specific location\n\n/**\n * represent common properties of the parameter for constructing a tensor from a specific location.\n */\ninterface CommonConstructorParameters<T> extends Pick<Tensor, 'dims'> {\n /**\n * Specify the data type of the tensor.\n */\n readonly type: T;\n}\n\n/**\n * represent the parameter for constructing a tensor from a GPU resource.\n */\ninterface GpuResourceConstructorParameters<T extends Tensor.Type> {\n /**\n * an optional callback function to download data from GPU to CPU.\n *\n * If not provided, the tensor treat the GPU data as external resource.\n */\n download?(): Promise<Tensor.DataTypeMap[T]>;\n\n /**\n * an optional callback function that will be called when the tensor is disposed.\n *\n * If not provided, the tensor treat the GPU data as external resource.\n */\n dispose?(): void;\n}\n\n/**\n * represent the parameter for constructing a tensor from a pinned CPU buffer\n */\nexport interface CpuPinnedConstructorParameters<T extends Tensor.CpuPinnedDataTypes = Tensor.CpuPinnedDataTypes>\n extends CommonConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'cpu-pinned'.\n */\n readonly location: 'cpu-pinned';\n /**\n * Specify the CPU pinned buffer that holds the tensor data.\n */\n readonly data: Tensor.DataTypeMap[T];\n}\n\n/**\n * represent the parameter for constructing a tensor from a WebGL texture\n */\nexport interface TextureConstructorParameters<T extends Tensor.TextureDataTypes = Tensor.TextureDataTypes>\n extends CommonConstructorParameters<T>,\n GpuResourceConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'texture'.\n */\n readonly location: 'texture';\n /**\n * Specify the WebGL texture that holds the tensor data.\n */\n readonly texture: Tensor.TextureType;\n}\n\n/**\n * represent the parameter for constructing a tensor from a WebGPU buffer\n */\nexport interface GpuBufferConstructorParameters<T extends Tensor.GpuBufferDataTypes = Tensor.GpuBufferDataTypes>\n extends CommonConstructorParameters<T>,\n GpuResourceConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'gpu-buffer'.\n */\n readonly location: 'gpu-buffer';\n /**\n * Specify the WebGPU buffer that holds the tensor data.\n */\n readonly gpuBuffer: Tensor.GpuBufferType;\n}\n\nexport interface MLTensorConstructorParameters<T extends Tensor.MLTensorDataTypes = Tensor.MLTensorDataTypes>\n extends CommonConstructorParameters<T>,\n GpuResourceConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'ml-tensor'.\n */\n readonly location: 'ml-tensor';\n\n /**\n * Specify the WebNN MLTensor that holds the tensor data.\n */\n readonly mlTensor: Tensor.MLTensorType;\n}\n\n// #endregion\n\n// the following region contains type definitions of each individual options.\n// the tensor factory functions use a composition of those options as the parameter type.\n\n// #region Options fields\n\nexport interface OptionsFormat {\n /**\n * Describes the image format represented in RGBA color space.\n */\n format?: ImageFormat;\n}\n\nexport interface OptionsTensorFormat {\n /**\n * Describes the image format of the tensor.\n *\n * NOTE: this is different from option 'format'. While option 'format' represents the original image, 'tensorFormat'\n * represents the target format of the tensor. A transpose will be performed if they are different.\n */\n tensorFormat?: ImageFormat;\n}\n\nexport interface OptionsTensorDataType {\n /**\n * Describes the data type of the tensor.\n */\n dataType?: 'float32' | 'uint8';\n}\n\nexport interface OptionsTensorLayout {\n /**\n * Describes the tensor layout when representing data of one or more image(s).\n */\n tensorLayout?: ImageTensorLayout;\n}\n\nexport interface OptionsDimensions {\n /**\n * Describes the image height in pixel\n */\n height?: number;\n /**\n * Describes the image width in pixel\n */\n width?: number;\n}\n\nexport interface OptionResizedDimensions {\n /**\n * Describes the resized height. If omitted, original height will be used.\n */\n resizedHeight?: number;\n /**\n * Describes resized width - can be accessed via tensor dimensions as well\n */\n resizedWidth?: number;\n}\n\nexport interface OptionsNormalizationParameters {\n /**\n * Describes normalization parameters when preprocessing the image as model input.\n *\n * Data element are ranged from 0 to 255.\n */\n norm?: {\n /**\n * The 'bias' value for image normalization.\n * - If omitted, use default value 0.\n * - If it's a single number, apply to each channel\n * - If it's an array of 3 or 4 numbers, apply element-wise. Number of elements need to match the number of channels\n * for the corresponding image format\n */\n bias?: number | [number, number, number] | [number, number, number, number];\n /**\n * The 'mean' value for image normalization.\n * - If omitted, use default value 255.\n * - If it's a single number, apply to each channel\n * - If it's an array of 3 or 4 numbers, apply element-wise. Number of elements need to match the number of channels\n * for the corresponding image format\n */\n mean?: number | [number, number, number] | [number, number, number, number];\n };\n}\n\n// #endregion\n\n// #region Options composition\n\nexport interface TensorFromImageDataOptions\n extends OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromImageElementOptions\n extends OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromUrlOptions\n extends OptionsDimensions,\n OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromImageBitmapOptions\n extends OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromTextureOptions<T extends Tensor.TextureDataTypes>\n extends Required<OptionsDimensions>,\n OptionsFormat,\n GpuResourceConstructorParameters<T> /* TODO: add more */ {}\n\nexport interface TensorFromGpuBufferOptions<T extends Tensor.GpuBufferDataTypes>\n extends Pick<Tensor, 'dims'>,\n GpuResourceConstructorParameters<T> {\n /**\n * Describes the data type of the tensor.\n */\n dataType?: T;\n}\n\nexport interface TensorFromMLTensorOptions<T extends Tensor.MLTensorDataTypes>\n extends Pick<Tensor, 'dims'>,\n GpuResourceConstructorParameters<T> {\n /**\n * Describes the data type of the tensor.\n */\n dataType?: T;\n}\n\n// #endregion\n\n/**\n * type TensorFactory defines the factory functions of 'Tensor' to create tensor instances from existing data or\n * resources.\n */\nexport interface TensorFactory {\n /**\n * create a tensor from an ImageData object\n *\n * @param imageData - the ImageData object to create tensor from\n * @param options - An optional object representing options for creating tensor from ImageData.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(\n imageData: ImageData,\n options?: TensorFromImageDataOptions,\n ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from a HTMLImageElement object\n *\n * @param imageElement - the HTMLImageElement object to create tensor from\n * @param options - An optional object representing options for creating tensor from HTMLImageElement.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(\n imageElement: HTMLImageElement,\n options?: TensorFromImageElementOptions,\n ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from URL\n *\n * @param urlSource - a string as a URL to the image or a data URL containing the image data.\n * @param options - An optional object representing options for creating tensor from URL.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(urlSource: string, options?: TensorFromUrlOptions): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from an ImageBitmap object\n *\n * @param bitmap - the ImageBitmap object to create tensor from\n * @param options - An optional object representing options for creating tensor from URL.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(\n bitmap: ImageBitmap,\n options: TensorFromImageBitmapOptions,\n ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from a WebGL texture\n *\n * @param texture - the WebGLTexture object to create tensor from\n * @param options - An optional object representing options for creating tensor from WebGL texture.\n *\n * The options include following properties:\n * - `width`: the width of the texture. Required.\n * - `height`: the height of the texture. Required.\n * - `format`: the format of the texture. If omitted, assume 'RGBA'.\n * - `download`: an optional function to download the tensor data from GPU to CPU. If omitted, the GPU data\n * will not be able to download. Usually, this is provided by a GPU backend for the inference outputs. Users don't\n * need to provide this function.\n * - `dispose`: an optional function to dispose the tensor data on GPU. If omitted, the GPU data will not be disposed.\n * Usually, this is provided by a GPU backend for the inference outputs. Users don't need to provide this function.\n *\n * @returns a tensor object\n */\n fromTexture<T extends Tensor.TextureDataTypes = 'float32'>(\n texture: Tensor.TextureType,\n options: TensorFromTextureOptions<T>,\n ): TypedTensor<'float32'>;\n\n /**\n * create a tensor from a WebGPU buffer\n *\n * @param buffer - the GPUBuffer object to create tensor from\n * @param options - An optional object representing options for creating tensor from WebGPU buffer.\n *\n * The options include following properties:\n * - `dataType`: the data type of the tensor. If omitted, assume 'float32'.\n * - `dims`: the dimension of the tensor. Required.\n * - `download`: an optional function to download the tensor data from GPU to CPU. If omitted, the GPU data\n * will not be able to download. Usually, this is provided by a GPU backend for the inference outputs. Users don't\n * need to provide this function.\n * - `dispose`: an optional function to dispose the tensor data on GPU. If omitted, the GPU data will not be disposed.\n * Usually, this is provided by a GPU backend for the inference outputs. Users don't need to provide this function.\n *\n * @returns a tensor object\n */\n fromGpuBuffer<T extends Tensor.GpuBufferDataTypes>(\n buffer: Tensor.GpuBufferType,\n options: TensorFromGpuBufferOptions<T>,\n ): TypedTensor<T>;\n\n /**\n * create a tensor from a WebNN MLTensor\n *\n * @param tensor - the MLTensor object to create tensor from\n * @param options - An optional object representing options for creating tensor from a WebNN MLTensor.\n *\n * The options include following properties:\n * - `dataType`: the data type of the tensor. If omitted, assume 'float32'.\n * - `dims`: the dimension of the tensor. Required.\n * - `download`: an optional function to download the tensor data from the MLTensor to CPU. If omitted, the MLTensor\n * data will not be able to download. Usually, this is provided by the WebNN backend for the inference outputs.\n * Users don't need to provide this function.\n * - `dispose`: an optional function to dispose the tensor data on the WebNN MLTensor. If omitted, the MLTensor will\n * not be disposed. Usually, this is provided by the WebNN backend for the inference outputs. Users don't need to\n * provide this function.\n *\n * @returns a tensor object\n */\n fromMLTensor<T extends Tensor.MLTensorDataTypes>(\n tensor: Tensor.MLTensorType,\n options: TensorFromMLTensorOptions<T>,\n ): TypedTensor<T>;\n\n /**\n * create a tensor from a pre-allocated buffer. The buffer will be used as a pinned buffer.\n *\n * @param type - the tensor element type.\n * @param buffer - a TypedArray corresponding to the type.\n * @param dims - specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n *\n * @returns a tensor object\n */\n fromPinnedBuffer<T extends Exclude<Tensor.Type, 'string'>>(\n type: T,\n buffer: Tensor.DataTypeMap[T],\n dims?: readonly number[],\n ): TypedTensor<T>;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/**\n * A string that represents a file's URL or path.\n *\n * Path is vailable only in onnxruntime-node or onnxruntime-web running in Node.js.\n */\nexport type FileUrlOrPath = string;\n\n/**\n * A Blob object that represents a file.\n */\nexport type FileBlob = Blob;\n\n/**\n * A Uint8Array, ArrayBuffer or SharedArrayBuffer object that represents a file content.\n *\n * When it is an ArrayBuffer or SharedArrayBuffer, the whole buffer is assumed to be the file content.\n */\nexport type FileData = Uint8Array | ArrayBufferLike;\n\n/**\n * Represents a file that can be loaded by the ONNX Runtime JavaScript API.\n */\nexport type FileType = FileUrlOrPath | FileBlob | FileData;\n\n/**\n * Represents an external data file.\n */\nexport interface ExternalDataFileDescription {\n /**\n * Specify the external data file.\n */\n data: FileType;\n /**\n * Specify the file path.\n */\n path: string;\n}\n\n/**\n * Represents an external data file.\n *\n * When using a string, it should be a file URL or path that in the same directory as the model file.\n */\nexport type ExternalDataFileType = ExternalDataFileDescription | FileUrlOrPath;\n\n/**\n * Options for model loading.\n */\nexport interface OnnxModelOptions {\n /**\n * Specifying a list of files that represents the external data.\n */\n externalData?: readonly ExternalDataFileType[];\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from './tensor.js';\n\nexport type NonTensorType = never;\n\n/**\n * Type OnnxValue Represents both tensors and non-tensors value for model's inputs/outputs.\n *\n * NOTE: currently not support non-tensor\n */\nexport type OnnxValue = Tensor | NonTensorType;\n\n/**\n * Type OnnxValueDataLocation represents the location of the data of an OnnxValue.\n */\nexport type OnnxValueDataLocation = Tensor.DataLocation;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/**\n * # ONNX Runtime JavaScript API\n *\n * ONNX Runtime JavaScript API is a unified API for all JavaScript usages, including the following NPM packages:\n *\n * - [onnxruntime-node](https://www.npmjs.com/package/onnxruntime-node)\n * - [onnxruntime-web](https://www.npmjs.com/package/onnxruntime-web)\n * - [onnxruntime-react-native](https://www.npmjs.com/package/onnxruntime-react-native)\n *\n * See also:\n * - [Get Started](https://onnxruntime.ai/docs/get-started/with-javascript/)\n * - [Inference examples](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js)\n *\n * @packageDocumentation\n */\n\nexport * from './backend.js';\nexport * from './env.js';\nexport * from './inference-session.js';\nexport * from './tensor.js';\nexport * from './tensor-conversion.js';\nexport * from './tensor-factory.js';\nexport * from './trace.js';\nexport * from './onnx-model.js';\nexport * from './onnx-value.js';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nexport const isNode = !!(typeof process !== 'undefined' && process.versions && process.versions.node);\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport type { OrtWasmModule } from './wasm-types';\nimport { isNode } from './wasm-utils-env';\n\n/**\n * The origin of the current location.\n *\n * In Node.js, this is undefined.\n */\nconst origin = isNode || typeof location === 'undefined' ? undefined : location.origin;\n\n/**\n * Some bundlers (eg. Webpack) will rewrite `import.meta.url` to a file URL at compile time.\n *\n * This function checks if `import.meta.url` starts with `file:`, but using the `>` and `<` operators instead of\n * `startsWith` function so that code minimizers can remove the dead code correctly.\n *\n * For example, if we use terser to minify the following code:\n * ```js\n * if (\"file://hard-coded-filename\".startsWith(\"file:\")) {\n * console.log(1)\n * } else {\n * console.log(2)\n * }\n *\n * if (\"file://hard-coded-filename\" > \"file:\" && \"file://hard-coded-filename\" < \"file;\") {\n * console.log(3)\n * } else {\n * console.log(4)\n * }\n * ```\n *\n * The minified code will be:\n * ```js\n * \"file://hard-coded-filename\".startsWith(\"file:\")?console.log(1):console.log(2),console.log(3);\n * ```\n *\n * (use Terser 5.39.0 with default options, https://try.terser.org/)\n *\n * @returns true if the import.meta.url is hardcoded as a file URI.\n */\nexport const isEsmImportMetaUrlHardcodedAsFileUri =\n BUILD_DEFS.IS_ESM && BUILD_DEFS.ESM_IMPORT_META_URL! > 'file:' && BUILD_DEFS.ESM_IMPORT_META_URL! < 'file;';\n\nconst getScriptSrc = (): string | undefined => {\n // if Nodejs, return undefined\n if (isNode) {\n return undefined;\n }\n // if It's ESM, use import.meta.url\n if (BUILD_DEFS.IS_ESM) {\n // For ESM, if the import.meta.url is a file URL, this usually means the bundler rewrites `import.meta.url` to\n // the file path at compile time. In this case, this file path cannot be used to determine the runtime URL.\n //\n // We need to use the URL constructor like this:\n // ```js\n // new URL('actual-bundle-name.js', import.meta.url).href\n // ```\n // So that bundler can preprocess the URL correctly.\n if (isEsmImportMetaUrlHardcodedAsFileUri) {\n // if the rewritten URL is a relative path, we need to use the origin to resolve the URL.\n\n // The following is a workaround for Vite.\n //\n // Vite uses a bundler(rollup/rolldown) that does not rewrite `import.meta.url` to a file URL. So in theory, this\n // code path should not be executed in Vite. However, the bundler does not know it and it still try to load the\n // following pattern:\n // - `return new URL('filename', import.meta.url).href`\n //\n // By replacing the pattern above with the following code, we can skip the resource loading behavior:\n // - `const URL2 = URL; return new URL2('filename', import.meta.url).href;`\n //\n // And it still works in Webpack.\n const URL2 = URL;\n return new URL(new URL2(BUILD_DEFS.BUNDLE_FILENAME, BUILD_DEFS.ESM_IMPORT_META_URL).href, origin).href;\n }\n\n return BUILD_DEFS.ESM_IMPORT_META_URL;\n }\n\n return typeof document !== 'undefined'\n ? (document.currentScript as HTMLScriptElement)?.src\n : // use `self.location.href` if available\n typeof self !== 'undefined'\n ? self.location?.href\n : undefined;\n};\n\n/**\n * The classic script source URL. This is not always available in non ESModule environments.\n *\n * In Node.js, this is undefined.\n */\nexport const scriptSrc = getScriptSrc();\n\n/**\n * Infer the wasm path prefix from the script source URL.\n *\n * @returns The inferred wasm path prefix, or undefined if the script source URL is not available or is a blob URL.\n */\nexport const inferWasmPathPrefixFromScriptSrc = (): string | undefined => {\n if (scriptSrc && !scriptSrc.startsWith('blob:')) {\n return scriptSrc.substring(0, scriptSrc.lastIndexOf('/') + 1);\n }\n return undefined;\n};\n\n/**\n * Check if the given filename with prefix is from the same origin.\n */\nconst isSameOrigin = (filename: string, prefixOverride?: string) => {\n try {\n const baseUrl = prefixOverride ?? scriptSrc;\n const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename);\n return url.origin === origin;\n } catch {\n return false;\n }\n};\n\n/**\n * Normalize the inputs to an absolute URL with the given prefix override. If failed, return undefined.\n */\nconst normalizeUrl = (filename: string, prefixOverride?: string) => {\n const baseUrl = prefixOverride ?? scriptSrc;\n try {\n const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename);\n return url.href;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Create a fallback URL if an absolute URL cannot be created by the normalizeUrl function.\n */\nconst fallbackUrl = (filename: string, prefixOverride?: string) => `${prefixOverride ?? './'}${filename}`;\n\n/**\n * This helper function is used to preload a module from a URL.\n *\n * If the origin of the worker URL is different from the current origin, the worker cannot be loaded directly.\n * See discussions in https://github.com/webpack-contrib/worker-loader/issues/154\n *\n * In this case, we will fetch the worker URL and create a new Blob URL with the same origin as a workaround.\n *\n * @param absoluteUrl - The absolute URL to preload.\n *\n * @returns - A promise that resolves to a new Blob URL\n */\nconst preload = async (absoluteUrl: string): Promise<string> => {\n const response = await fetch(absoluteUrl, { credentials: 'same-origin' });\n const blob = await response.blob();\n return URL.createObjectURL(blob);\n};\n\n/**\n * This helper function is used to dynamically import a module from a URL.\n *\n * The build script has special handling for this function to ensure that the URL is not bundled into the final output.\n *\n * @param url - The URL to import.\n *\n * @returns - A promise that resolves to the default export of the module.\n */\nconst dynamicImportDefault = async <T>(url: string): Promise<T> =>\n (await import(/* webpackIgnore: true */ /* @vite-ignore */ url)).default;\n\n/**\n * The proxy worker factory imported from the proxy worker module.\n *\n * This is only available when the WebAssembly proxy is not disabled.\n */\nconst createProxyWorker: ((urlOverride?: string) => Worker) | undefined =\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n BUILD_DEFS.DISABLE_WASM_PROXY ? undefined : require('./proxy-worker/main').default;\n\n/**\n * Import the proxy worker.\n *\n * This function will perform the following steps:\n * 1. If a preload is needed, it will preload the module and return the object URL.\n * 2. Use the proxy worker factory to create the proxy worker.\n *\n * @returns - A promise that resolves to a tuple of 2 elements:\n * - The object URL of the preloaded module, or undefined if no preload is needed.\n * - The proxy worker.\n */\nexport const importProxyWorker = async (): Promise<[undefined | string, Worker]> => {\n if (!scriptSrc) {\n throw new Error('Failed to load proxy worker: cannot determine the script source URL.');\n }\n\n // If the script source is from the same origin, we can use the embedded proxy module directly.\n if (isSameOrigin(scriptSrc)) {\n return [undefined, createProxyWorker!()];\n }\n\n // Otherwise, need to preload\n const url = await preload(scriptSrc);\n return [url, createProxyWorker!(url)];\n};\n\n/**\n * The embedded WebAssembly module.\n *\n * This is only available in ESM and when embedding is not disabled.\n */\nconst embeddedWasmModule: EmscriptenModuleFactory<OrtWasmModule> | undefined =\n BUILD_DEFS.IS_ESM && BUILD_DEFS.ENABLE_BUNDLE_WASM_JS\n ? // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n require(\n !BUILD_DEFS.DISABLE_JSEP\n ? '../../dist/ort-wasm-simd-threaded.jsep.mjs'\n : BUILD_DEFS.ENABLE_JSPI\n ? '../../dist/ort-wasm-simd-threaded.jspi.mjs'\n : !BUILD_DEFS.DISABLE_WEBGPU\n ? '../../dist/ort-wasm-simd-threaded.asyncify.mjs'\n : '../../dist/ort-wasm-simd-threaded.mjs',\n ).default\n : undefined;\n\n/**\n * Import the WebAssembly module.\n *\n * This function will perform the following steps:\n * 1. If the embedded module exists and no custom URL is specified, use the embedded module.\n * 2. If a preload is needed, it will preload the module and return the object URL.\n * 3. Otherwise, it will perform a dynamic import of the module.\n *\n * @returns - A promise that resolves to a tuple of 2 elements:\n * - The object URL of the preloaded module, or undefined if no preload is needed.\n * - The default export of the module, which is a factory function to create the WebAssembly module.\n */\nexport const importWasmModule = async (\n urlOverride: string | undefined,\n prefixOverride: string | undefined,\n isMultiThreaded: boolean,\n isWasmOverridden: boolean,\n): Promise<[undefined | string, EmscriptenModuleFactory<OrtWasmModule>]> => {\n //\n // Check if we should use the embedded module.\n //\n\n // To use the embedded module, it should be available, and no URL override or prefix override should be specified.\n let useEmbeddedModule = embeddedWasmModule && !(urlOverride || prefixOverride);\n if (useEmbeddedModule) {\n if (!scriptSrc) {\n // no URL info available.\n //\n // Note: when the embedded module is available, it means the current script is ESM. Usually, in ESM, the\n // `import.meta.url` is available. But in some cases (eg. Cloudflare Workers), the value of `import.meta.url`\n // can be `null` or `undefined`. In this case, we can only load the embedded module when:\n //\n // 1. The WebAssembly module binary is overridden:\n // ```js\n // env.wasm.wasmPaths = undefined; // or not specified\n // env.wasm.wasmBinary = /* a Uint8Array containing the WebAssembly binary */;\n // ```\n //\n // 2. The \".wasm\" only is overridden.\n // ```js\n // env.wasm.wasmPaths = { wasm: /* URL of the .wasm file */ };\n // ```\n //\n if (isWasmOverridden && !isMultiThreaded) {\n useEmbeddedModule = true;\n } else {\n throw new Error('cannot determine the script source URL.');\n }\n } else {\n // if the script source is available, we can check if it is from the same origin.\n useEmbeddedModule = isSameOrigin(scriptSrc);\n }\n }\n if (useEmbeddedModule) {\n return [undefined, embeddedWasmModule!];\n } else {\n const wasmModuleFilename = !BUILD_DEFS.DISABLE_JSEP\n ? 'ort-wasm-simd-threaded.jsep.mjs'\n : BUILD_DEFS.ENABLE_JSPI\n ? 'ort-wasm-simd-threaded.jspi.mjs'\n : !BUILD_DEFS.DISABLE_WEBGPU\n ? 'ort-wasm-simd-threaded.asyncify.mjs'\n : 'ort-wasm-simd-threaded.mjs';\n const wasmModuleUrl = urlOverride ?? normalizeUrl(wasmModuleFilename, prefixOverride);\n // need to preload if all of the following conditions are met:\n // 1. not in Node.js.\n // - Node.js does not have the same origin policy for creating workers.\n // 2. multi-threaded is enabled.\n // - If multi-threaded is disabled, no worker will be created. So we don't need to preload the module.\n // 3. the absolute URL is available.\n // - If the absolute URL is failed to be created, the origin cannot be determined. In this case, we will not\n // preload the module.\n // 4. the worker URL is not from the same origin.\n // - If the worker URL is from the same origin, we can create the worker directly.\n const needPreload = !isNode && isMultiThreaded && wasmModuleUrl && !isSameOrigin(wasmModuleUrl, prefixOverride);\n const url = needPreload\n ? await preload(wasmModuleUrl)\n : (wasmModuleUrl ?? fallbackUrl(wasmModuleFilename, prefixOverride));\n return [needPreload ? url : undefined, await dynamicImportDefault<EmscriptenModuleFactory<OrtWasmModule>>(url)];\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Env } from 'onnxruntime-common';\n\nimport type { OrtWasmModule } from './wasm-types';\nimport { importWasmModule, inferWasmPathPrefixFromScriptSrc } from './wasm-utils-import';\n\nlet wasm: OrtWasmModule | undefined;\nlet initialized = false;\nlet initializing = false;\nlet aborted = false;\n\nconst isMultiThreadSupported = (): boolean => {\n // If 'SharedArrayBuffer' is not available, WebAssembly threads will not work.\n if (typeof SharedArrayBuffer === 'undefined') {\n return false;\n }\n\n try {\n // Test for transferability of SABs (for browsers. needed for Firefox)\n // https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ\n if (typeof MessageChannel !== 'undefined') {\n new MessageChannel().port1.postMessage(new SharedArrayBuffer(1));\n }\n\n // Test for WebAssembly threads capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing threaded instructions.\n return WebAssembly.validate(\n new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16,\n 2, 0, 26, 11,\n ]),\n );\n } catch {\n return false;\n }\n};\n\nconst isSimdSupported = (): boolean => {\n try {\n // Test for WebAssembly SIMD capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing SIMD instructions.\n\n // The binary data is generated from the following code by wat2wasm:\n //\n // (module\n // (type $t0 (func))\n // (func $f0 (type $t0)\n // (drop\n // (i32x4.dot_i16x8_s\n // (i8x16.splat\n // (i32.const 0))\n // (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)))))\n\n return WebAssembly.validate(\n new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0, 253, 15, 253, 12, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11,\n ]),\n );\n } catch {\n return false;\n }\n};\n\nconst isRelaxedSimdSupported = (): boolean => {\n try {\n // Test for WebAssembly Relaxed SIMD capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing Relaxed SIMD instructions.\n\n // The binary data is generated from the following code by wat2wasm:\n // (module\n // (func (result v128)\n // i32.const 1\n // i8x16.splat\n // i32.const 2\n // i8x16.splat\n // i32.const 3\n // i8x16.splat\n // i32x4.relaxed_dot_i8x16_i7x16_add_s\n // )\n // )\n return WebAssembly.validate(\n new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 19, 1, 17, 0, 65, 1, 253, 15, 65, 2, 253,\n 15, 65, 3, 253, 15, 253, 147, 2, 11,\n ]),\n );\n } catch {\n return false;\n }\n};\n\nexport const initializeWebAssembly = async (flags: Env.WebAssemblyFlags): Promise<void> => {\n if (initialized) {\n return Promise.resolve();\n }\n if (initializing) {\n throw new Error(\"multiple calls to 'initializeWebAssembly()' detected.\");\n }\n if (aborted) {\n throw new Error(\"previous call to 'initializeWebAssembly()' failed.\");\n }\n\n initializing = true;\n\n // wasm flags are already initialized\n const timeout = flags.initTimeout!;\n let numThreads = flags.numThreads!;\n\n // ensure SIMD is supported\n if (flags.simd === false) {\n // skip SIMD feature checking as it is disabled explicitly by user\n } else if (flags.simd === 'relaxed') {\n // check if relaxed SIMD is supported\n if (!isRelaxedSimdSupported()) {\n throw new Error('Relaxed WebAssembly SIMD is not supported in the current environment.');\n }\n } else if (!isSimdSupported()) {\n throw new Error('WebAssembly SIMD is not supported in the current environment.');\n }\n\n if (BUILD_DEFS.ENABLE_JSPI) {\n if (!('Suspending' in WebAssembly)) {\n throw new Error('WebAssembly JSPI is not supported in the current environment.');\n }\n }\n\n // check if multi-threading is supported\n const multiThreadSupported = isMultiThreadSupported();\n if (numThreads > 1 && !multiThreadSupported) {\n if (typeof self !== 'undefined' && !self.crossOriginIsolated) {\n // eslint-disable-next-line no-console\n console.warn(\n 'env.wasm.numThreads is set to ' +\n numThreads +\n ', but this will not work unless you enable crossOriginIsolated mode. ' +\n 'See https://web.dev/cross-origin-isolation-guide/ for more info.',\n );\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n 'WebAssembly multi-threading is not supported in the current environment. ' + 'Falling back to single-threading.',\n );\n\n // set flags.numThreads to 1 so that OrtInit() will not create a global thread pool.\n flags.numThreads = numThreads = 1;\n }\n\n const wasmPaths = flags.wasmPaths;\n const wasmPrefixOverride = typeof wasmPaths === 'string' ? wasmPaths : undefined;\n const mjsPathOverrideFlag = (wasmPaths as Env.WasmFilePaths)?.mjs;\n const mjsPathOverride = (mjsPathOverrideFlag as URL)?.href ?? mjsPathOverrideFlag;\n const wasmPathOverrideFlag = (wasmPaths as Env.WasmFilePaths)?.wasm;\n const wasmPathOverride = (wasmPathOverrideFlag as URL)?.href ?? wasmPathOverrideFlag;\n const wasmBinaryOverride = flags.wasmBinary;\n\n const [objectUrl, ortWasmFactory] = await importWasmModule(\n mjsPathOverride,\n wasmPrefixOverride,\n numThreads > 1,\n !!wasmBinaryOverride || !!wasmPathOverride,\n );\n\n let isTimeout = false;\n\n const tasks: Array<Promise<void>> = [];\n\n // promise for timeout\n if (timeout > 0) {\n tasks.push(\n new Promise((resolve) => {\n setTimeout(() => {\n isTimeout = true;\n resolve();\n }, timeout);\n }),\n );\n }\n\n // promise for module initialization\n tasks.push(\n new Promise((resolve, reject) => {\n const config: Partial<OrtWasmModule> = {\n /**\n * The number of threads. WebAssembly will create (Module.numThreads - 1) workers. If it is 1, no worker will be\n * created.\n */\n numThreads,\n };\n\n if (wasmBinaryOverride) {\n // Set a custom buffer which contains the WebAssembly binary. This will skip the wasm file fetching.\n config.wasmBinary = wasmBinaryOverride;\n } else if (wasmPathOverride || wasmPrefixOverride) {\n // A callback function to locate the WebAssembly file. The function should return the full path of the file.\n //\n // Since Emscripten 3.1.58, this function is only called for the .wasm file.\n config.locateFile = (fileName) => wasmPathOverride ?? wasmPrefixOverride + fileName;\n } else if (mjsPathOverride && mjsPathOverride.indexOf('blob:') !== 0) {\n // if mjs path is specified, use it as the base path for the .wasm file.\n config.locateFile = (fileName) => new URL(fileName, mjsPathOverride).href;\n } else if (objectUrl) {\n const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc();\n if (inferredWasmPathPrefix) {\n // if the wasm module is preloaded, use the inferred wasm path as the base path for the .wasm file.\n config.locateFile = (fileName) => inferredWasmPathPrefix + fileName;\n }\n }\n\n ortWasmFactory(config).then(\n // wasm module initialized successfully\n (module) => {\n initializing = false;\n initialized = true;\n wasm = module;\n resolve();\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl);\n }\n },\n // wasm module failed to initialize\n (what) => {\n initializing = false;\n aborted = true;\n reject(what);\n },\n );\n }),\n );\n\n await Promise.race(tasks);\n\n if (isTimeout) {\n throw new Error(`WebAssembly backend initializing failed due to timeout: ${timeout}ms`);\n }\n};\n\nexport const getInstance = (): OrtWasmModule => {\n if (initialized && wasm) {\n return wasm;\n }\n\n throw new Error('WebAssembly is not initialized yet.');\n};\n\nexport const dispose = (): void => {\n if (initialized && !initializing && !aborted) {\n // TODO: currently \"PThread.terminateAllThreads()\" is not exposed in the wasm module.\n // And this function is not yet called by any code.\n // If it is needed in the future, we should expose it in the wasm module and uncomment the following line.\n\n // wasm?.PThread?.terminateAllThreads();\n wasm = undefined;\n\n initializing = false;\n initialized = false;\n aborted = true;\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { getInstance } from './wasm-factory';\n\nexport const allocWasmString = (data: string, allocs: number[]): number => {\n const wasm = getInstance();\n\n const dataLength = wasm.lengthBytesUTF8(data) + 1;\n const dataOffset = wasm._malloc(dataLength);\n wasm.stringToUTF8(data, dataOffset, dataLength);\n allocs.push(dataOffset);\n\n return dataOffset;\n};\n\ninterface ExtraOptionsHandler {\n (name: string, value: string): void;\n}\n\nexport const iterateExtraOptions = (\n options: Record<string, unknown>,\n prefix: string,\n seen: WeakSet<Record<string, unknown>>,\n handler: ExtraOptionsHandler,\n): void => {\n if (typeof options == 'object' && options !== null) {\n if (seen.has(options)) {\n throw new Error('Circular reference in options');\n } else {\n seen.add(options);\n }\n }\n\n Object.entries(options).forEach(([key, value]) => {\n const name = prefix ? prefix + key : key;\n if (typeof value === 'object') {\n iterateExtraOptions(value as Record<string, unknown>, name + '.', seen, handler);\n } else if (typeof value === 'string' || typeof value === 'number') {\n handler(name, value.toString());\n } else if (typeof value === 'boolean') {\n handler(name, value ? '1' : '0');\n } else {\n throw new Error(`Can't handle extra config type: ${typeof value}`);\n }\n });\n};\n\n/**\n * check web assembly API's last error and throw error if any error occurred.\n * @param message a message used when an error occurred.\n */\nexport const checkLastError = (message: string): void => {\n const wasm = getInstance();\n\n const stack = wasm.stackSave();\n try {\n const ptrSize = wasm.PTR_SIZE;\n const paramsOffset = wasm.stackAlloc(2 * ptrSize);\n wasm._OrtGetLastError(paramsOffset, paramsOffset + ptrSize);\n const errorCode = Number(wasm.getValue(paramsOffset, ptrSize === 4 ? 'i32' : 'i64'));\n const errorMessagePointer = wasm.getValue(paramsOffset + ptrSize, '*');\n const errorMessage = errorMessagePointer ? wasm.UTF8ToString(errorMessagePointer) : '';\n throw new Error(`${message} ERROR_CODE: ${errorCode}, ERROR_MESSAGE: ${errorMessage}`);\n } finally {\n wasm.stackRestore(stack);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession } from 'onnxruntime-common';\n\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils';\n\nexport const setRunOptions = (options: InferenceSession.RunOptions): [number, number[]] => {\n const wasm = getInstance();\n let runOptionsHandle = 0;\n const allocs: number[] = [];\n\n const runOptions: InferenceSession.RunOptions = options || {};\n\n try {\n if (options?.logSeverityLevel === undefined) {\n runOptions.logSeverityLevel = 2; // Default to warning\n } else if (\n typeof options.logSeverityLevel !== 'number' ||\n !Number.isInteger(options.logSeverityLevel) ||\n options.logSeverityLevel < 0 ||\n options.logSeverityLevel > 4\n ) {\n throw new Error(`log severity level is not valid: ${options.logSeverityLevel}`);\n }\n\n if (options?.logVerbosityLevel === undefined) {\n runOptions.logVerbosityLevel = 0; // Default to 0\n } else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) {\n throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`);\n }\n\n if (options?.terminate === undefined) {\n runOptions.terminate = false;\n }\n\n let tagDataOffset = 0;\n if (options?.tag !== undefined) {\n tagDataOffset = allocWasmString(options.tag, allocs);\n }\n\n runOptionsHandle = wasm._OrtCreateRunOptions(\n runOptions.logSeverityLevel!,\n runOptions.logVerbosityLevel!,\n !!runOptions.terminate!,\n tagDataOffset,\n );\n if (runOptionsHandle === 0) {\n checkLastError(\"Can't create run options.\");\n }\n\n if (options?.extra !== undefined) {\n iterateExtraOptions(options.extra, '', new WeakSet<Record<string, unknown>>(), (key, value) => {\n const keyDataOffset = allocWasmString(key, allocs);\n const valueDataOffset = allocWasmString(value, allocs);\n\n if (wasm._OrtAddRunConfigEntry(runOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n checkLastError(`Can't set a run config entry: ${key} - ${value}.`);\n }\n });\n }\n\n return [runOptionsHandle, allocs];\n } catch (e) {\n if (runOptionsHandle !== 0) {\n wasm._OrtReleaseRunOptions(runOptionsHandle);\n }\n allocs.forEach((alloc) => wasm._free(alloc));\n throw e;\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport type { InferenceSession } from 'onnxruntime-common';\n\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils';\n\nconst getGraphOptimzationLevel = (graphOptimizationLevel: string | unknown): number => {\n switch (graphOptimizationLevel) {\n case 'disabled':\n return 0;\n case 'basic':\n return 1;\n case 'extended':\n return 2;\n case 'layout':\n return 3;\n case 'all':\n return 99;\n default:\n throw new Error(`unsupported graph optimization level: ${graphOptimizationLevel}`);\n }\n};\n\nconst getExecutionMode = (executionMode: 'sequential' | 'parallel'): number => {\n switch (executionMode) {\n case 'sequential':\n return 0;\n case 'parallel':\n return 1;\n default:\n throw new Error(`unsupported execution mode: ${executionMode}`);\n }\n};\n\nconst appendDefaultOptions = (options: InferenceSession.SessionOptions): void => {\n if (!options.extra) {\n options.extra = {};\n }\n if (!options.extra.session) {\n options.extra.session = {};\n }\n const session = options.extra.session as Record<string, string>;\n if (!session.use_ort_model_bytes_directly) {\n // eslint-disable-next-line camelcase\n session.use_ort_model_bytes_directly = '1';\n }\n\n // if using JSEP with WebGPU, always disable memory pattern\n if (\n options.executionProviders &&\n options.executionProviders.some((ep) => (typeof ep === 'string' ? ep : ep.name) === 'webgpu')\n ) {\n options.enableMemPattern = false;\n }\n};\n\nconst appendSessionConfig = (sessionOptionsHandle: number, key: string, value: string, allocs: number[]): void => {\n const keyDataOffset = allocWasmString(key, allocs);\n const valueDataOffset = allocWasmString(value, allocs);\n if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n checkLastError(`Can't set a session config entry: ${key} - ${value}.`);\n }\n};\n\nconst appendEpOption = (epOptions: Array<[number, number]>, key: string, value: string, allocs: number[]): void => {\n const keyDataOffset = allocWasmString(key, allocs);\n const valueDataOffset = allocWasmString(value, allocs);\n epOptions.push([keyDataOffset, valueDataOffset]);\n};\n\nconst setExecutionProviders = async (\n sessionOptionsHandle: number,\n sessionOptions: InferenceSession.SessionOptions,\n allocs: number[],\n): Promise<void> => {\n const executionProviders = sessionOptions.executionProviders!;\n for (const ep of executionProviders) {\n let epName = typeof ep === 'string' ? ep : ep.name;\n const epOptions: Array<[number, number]> = [];\n\n // check EP name\n switch (epName) {\n case 'webnn':\n epName = 'WEBNN';\n if (typeof ep !== 'string') {\n const webnnOptions = ep as InferenceSession.WebNNExecutionProviderOption;\n // const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context;\n const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType;\n if (deviceType) {\n appendSessionConfig(sessionOptionsHandle, 'deviceType', deviceType, allocs);\n }\n }\n break;\n case 'webgpu':\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n epName = 'WebGPU';\n let customDevice: GPUDevice | undefined;\n\n if (typeof ep !== 'string') {\n const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption;\n\n // set custom GPU device\n if (webgpuOptions.device) {\n if (typeof GPUDevice !== 'undefined' && webgpuOptions.device instanceof GPUDevice) {\n customDevice = webgpuOptions.device;\n } else {\n throw new Error('Invalid GPU device set in WebGPU EP options.');\n }\n }\n\n // set graph capture option from session options\n const { enableGraphCapture } = sessionOptions;\n if (typeof enableGraphCapture === 'boolean' && enableGraphCapture) {\n appendEpOption(epOptions, 'enableGraphCapture', '1', allocs);\n }\n\n // set layout option\n if (typeof webgpuOptions.preferredLayout === 'string') {\n appendEpOption(epOptions, 'preferredLayout', webgpuOptions.preferredLayout, allocs);\n }\n\n // set force CPU fallback nodes\n if (webgpuOptions.forceCpuNodeNames) {\n const names = Array.isArray(webgpuOptions.forceCpuNodeNames)\n ? webgpuOptions.forceCpuNodeNames\n : [webgpuOptions.forceCpuNodeNames];\n\n appendEpOption(epOptions, 'forceCpuNodeNames', names.join('\\n'), allocs);\n }\n\n // set validation mode\n if (webgpuOptions.validationMode) {\n appendEpOption(epOptions, 'validationMode', webgpuOptions.validationMode, allocs);\n }\n }\n\n const info = getInstance().webgpuRegisterDevice!(customDevice);\n if (info) {\n const [deviceId, instanceHandle, deviceHandle] = info;\n appendEpOption(epOptions, 'deviceId', deviceId.toString(), allocs);\n appendEpOption(epOptions, 'webgpuInstance', instanceHandle.toString(), allocs);\n appendEpOption(epOptions, 'webgpuDevice', deviceHandle.toString(), allocs);\n }\n } else {\n epName = 'JS';\n if (typeof ep !== 'string') {\n const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption;\n if (webgpuOptions?.preferredLayout) {\n if (webgpuOptions.preferredLayout !== 'NCHW' && webgpuOptions.preferredLayout !== 'NHWC') {\n throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`);\n }\n appendSessionConfig(sessionOptionsHandle, 'preferredLayout', webgpuOptions.preferredLayout, allocs);\n }\n }\n }\n break;\n case 'wasm':\n case 'cpu':\n continue;\n default:\n throw new Error(`not supported execution provider: ${epName}`);\n }\n\n const epNameDataOffset = allocWasmString(epName, allocs);\n const epOptionsCount = epOptions.length;\n let keysOffset = 0;\n let valuesOffset = 0;\n if (epOptionsCount > 0) {\n keysOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE);\n allocs.push(keysOffset);\n valuesOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE);\n allocs.push(valuesOffset);\n for (let i = 0; i < epOptionsCount; i++) {\n getInstance().setValue(keysOffset + i * getInstance().PTR_SIZE, epOptions[i][0], '*');\n getInstance().setValue(valuesOffset + i * getInstance().PTR_SIZE, epOptions[i][1], '*');\n }\n }\n if (\n (await getInstance()._OrtAppendExecutionProvider(\n sessionOptionsHandle,\n epNameDataOffset,\n keysOffset,\n valuesOffset,\n epOptionsCount,\n )) !== 0\n ) {\n checkLastError(`Can't append execution provider: ${epName}.`);\n }\n }\n};\n\nexport const setSessionOptions = async (options?: InferenceSession.SessionOptions): Promise<[number, number[]]> => {\n const wasm = getInstance();\n let sessionOptionsHandle = 0;\n const allocs: number[] = [];\n\n const sessionOptions: InferenceSession.SessionOptions = options || {};\n appendDefaultOptions(sessionOptions);\n\n try {\n const graphOptimizationLevel = getGraphOptimzationLevel(sessionOptions.graphOptimizationLevel ?? 'all');\n const executionMode = getExecutionMode(sessionOptions.executionMode ?? 'sequential');\n const logIdDataOffset =\n typeof sessionOptions.logId === 'string' ? allocWasmString(sessionOptions.logId, allocs) : 0;\n\n const logSeverityLevel = sessionOptions.logSeverityLevel ?? 2; // Default to 2 - warning\n if (!Number.isInteger(logSeverityLevel) || logSeverityLevel < 0 || logSeverityLevel > 4) {\n throw new Error(`log severity level is not valid: ${logSeverityLevel}`);\n }\n\n const logVerbosityLevel = sessionOptions.logVerbosityLevel ?? 0; // Default to 0 - verbose\n if (!Number.isInteger(logVerbosityLevel) || logVerbosityLevel < 0 || logVerbosityLevel > 4) {\n throw new Error(`log verbosity level is not valid: ${logVerbosityLevel}`);\n }\n\n const optimizedModelFilePathOffset =\n typeof sessionOptions.optimizedModelFilePath === 'string'\n ? allocWasmString(sessionOptions.optimizedModelFilePath, allocs)\n : 0;\n\n sessionOptionsHandle = wasm._OrtCreateSessionOptions(\n graphOptimizationLevel,\n !!sessionOptions.enableCpuMemArena,\n !!sessionOptions.enableMemPattern,\n executionMode,\n !!sessionOptions.enableProfiling,\n 0,\n logIdDataOffset,\n logSeverityLevel,\n logVerbosityLevel,\n optimizedModelFilePathOffset,\n );\n if (sessionOptionsHandle === 0) {\n checkLastError(\"Can't create session options.\");\n }\n\n if (sessionOptions.executionProviders) {\n await setExecutionProviders(sessionOptionsHandle, sessionOptions, allocs);\n }\n\n if (sessionOptions.enableGraphCapture !== undefined) {\n if (typeof sessionOptions.enableGraphCapture !== 'boolean') {\n throw new Error(`enableGraphCapture must be a boolean value: ${sessionOptions.enableGraphCapture}`);\n }\n appendSessionConfig(\n sessionOptionsHandle,\n 'enableGraphCapture',\n sessionOptions.enableGraphCapture.toString(),\n allocs,\n );\n }\n\n if (sessionOptions.freeDimensionOverrides) {\n for (const [name, value] of Object.entries(sessionOptions.freeDimensionOverrides)) {\n if (typeof name !== 'string') {\n throw new Error(`free dimension override name must be a string: ${name}`);\n }\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new Error(`free dimension override value must be a non-negative integer: ${value}`);\n }\n const nameOffset = allocWasmString(name, allocs);\n if (wasm._OrtAddFreeDimensionOverride(sessionOptionsHandle, nameOffset, value) !== 0) {\n checkLastError(`Can't set a free dimension override: ${name} - ${value}.`);\n }\n }\n }\n\n if (sessionOptions.extra !== undefined) {\n iterateExtraOptions(sessionOptions.extra, '', new WeakSet<Record<string, unknown>>(), (key, value) => {\n appendSessionConfig(sessionOptionsHandle, key, value, allocs);\n });\n }\n\n return [sessionOptionsHandle, allocs];\n } catch (e) {\n if (sessionOptionsHandle !== 0) {\n if (wasm._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) {\n checkLastError(\"Can't release session options.\");\n }\n }\n allocs.forEach((alloc) => wasm._free(alloc));\n throw e;\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from 'onnxruntime-common';\n\n// a dummy type declaration for Float16Array in case any polyfill is available.\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any\n const Float16Array: any;\n}\n\n// This file includes common definitions. They do NOT have dependency on the WebAssembly instance.\n\n/**\n * Copied from ONNX definition. Use this to drop dependency 'onnx_proto' to decrease compiled .js file size.\n */\nexport const enum DataType {\n undefined = 0,\n float = 1,\n uint8 = 2,\n int8 = 3,\n uint16 = 4,\n int16 = 5,\n int32 = 6,\n int64 = 7,\n string = 8,\n bool = 9,\n float16 = 10,\n double = 11,\n uint32 = 12,\n uint64 = 13,\n complex64 = 14,\n complex128 = 15,\n bfloat16 = 16,\n\n // 4-bit data-types\n uint4 = 21,\n int4 = 22,\n}\n\n/**\n * Map string tensor data to enum value\n */\nexport const tensorDataTypeStringToEnum = (type: string): DataType => {\n switch (type) {\n case 'int8':\n return DataType.int8;\n case 'uint8':\n return DataType.uint8;\n case 'bool':\n return DataType.bool;\n case 'int16':\n return DataType.int16;\n case 'uint16':\n return DataType.uint16;\n case 'int32':\n return DataType.int32;\n case 'uint32':\n return DataType.uint32;\n case 'float16':\n return DataType.float16;\n case 'float32':\n return DataType.float;\n case 'float64':\n return DataType.double;\n case 'string':\n return DataType.string;\n case 'int64':\n return DataType.int64;\n case 'uint64':\n return DataType.uint64;\n case 'int4':\n return DataType.int4;\n case 'uint4':\n return DataType.uint4;\n\n default:\n throw new Error(`unsupported data type: ${type}`);\n }\n};\n\n/**\n * Map enum value to string tensor data\n */\nexport const tensorDataTypeEnumToString = (typeProto: DataType): Tensor.Type => {\n switch (typeProto) {\n case DataType.int8:\n return 'int8';\n case DataType.uint8:\n return 'uint8';\n case DataType.bool:\n return 'bool';\n case DataType.int16:\n return 'int16';\n case DataType.uint16:\n return 'uint16';\n case DataType.int32:\n return 'int32';\n case DataType.uint32:\n return 'uint32';\n case DataType.float16:\n return 'float16';\n case DataType.float:\n return 'float32';\n case DataType.double:\n return 'float64';\n case DataType.string:\n return 'string';\n case DataType.int64:\n return 'int64';\n case DataType.uint64:\n return 'uint64';\n case DataType.int4:\n return 'int4';\n case DataType.uint4:\n return 'uint4';\n\n default:\n throw new Error(`unsupported data type: ${typeProto}`);\n }\n};\n\n/**\n * get tensor size in bytes by the given data type and dimensions\n * @returns size in integer or undefined if the data type is not supported\n */\nexport const calculateTensorSizeInBytes = (\n dateType: number,\n dimsOrSize: readonly number[] | number,\n): number | undefined => {\n const elementSize = [\n -1, // undefined = 0\n 4, // float = 1\n 1, // uint8 = 2\n 1, // int8 = 3\n 2, // uint16 = 4\n 2, // int16 = 5\n 4, // int32 = 6\n 8, // int64 = 7\n -1, // string = 8\n 1, // bool = 9\n 2, // float16 = 10\n 8, // double = 11\n 4, // uint32 = 12\n 8, // uint64 = 13\n -1, // complex64 = 14\n -1, // complex128 = 15\n -1, // bfloat16 = 16\n -1, // FLOAT8E4M3FN = 17\n -1, // FLOAT8E4M3FNUZ = 18\n -1, // FLOAT8E5M2 = 19\n -1, // FLOAT8E5M2FNUZ = 20\n 0.5, // uint4 = 21\n 0.5, // int4 = 22\n ][dateType];\n\n const size = typeof dimsOrSize === 'number' ? dimsOrSize : dimsOrSize.reduce((a, b) => a * b, 1);\n return elementSize > 0 ? Math.ceil(size * elementSize) : undefined;\n};\n\n/**\n * get typed array constructor by the given tensor type\n */\nexport const tensorTypeToTypedArrayConstructor = (\n type: Tensor.Type,\n):\n | Float32ArrayConstructor\n | Uint8ArrayConstructor\n | Int8ArrayConstructor\n | Uint16ArrayConstructor\n | Int16ArrayConstructor\n | Int32ArrayConstructor\n | BigInt64ArrayConstructor\n | Uint8ArrayConstructor\n | Float64ArrayConstructor\n | Uint32ArrayConstructor\n | BigUint64ArrayConstructor => {\n switch (type) {\n case 'float16':\n // allow Float16Array polyfill.\n return typeof Float16Array !== 'undefined' && Float16Array.from ? Float16Array : Uint16Array;\n case 'float32':\n return Float32Array;\n case 'uint8':\n return Uint8Array;\n case 'int8':\n return Int8Array;\n case 'uint16':\n return Uint16Array;\n case 'int16':\n return Int16Array;\n case 'int32':\n return Int32Array;\n case 'bool':\n return Uint8Array;\n case 'float64':\n return Float64Array;\n case 'uint32':\n return Uint32Array;\n case 'int64':\n return BigInt64Array;\n case 'uint64':\n return BigUint64Array;\n default:\n throw new Error(`unsupported type: ${type}`);\n }\n};\n\n/**\n * Map string log level to integer value\n */\nexport const logLevelStringToEnum = (logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal'): number => {\n switch (logLevel) {\n case 'verbose':\n return 0;\n case 'info':\n return 1;\n case 'warning':\n return 2;\n case 'error':\n return 3;\n case 'fatal':\n return 4;\n default:\n throw new Error(`unsupported logging level: ${logLevel}`);\n }\n};\n\n/**\n * Check whether the given tensor type is supported by GPU buffer\n */\nexport const isGpuBufferSupportedType = (type: Tensor.Type): type is Tensor.GpuBufferDataTypes =>\n type === 'float32' ||\n type === 'float16' ||\n type === 'int32' ||\n type === 'int64' ||\n type === 'uint32' ||\n type === 'uint8' ||\n type === 'bool' ||\n type === 'uint4' ||\n type === 'int4';\n\n/**\n * Check whether the given tensor type is supported by WebNN MLTensor\n */\nexport const isMLTensorSupportedType = (type: Tensor.Type): type is Tensor.MLTensorDataTypes =>\n type === 'float32' ||\n type === 'float16' ||\n type === 'int32' ||\n type === 'int64' ||\n type === 'uint32' ||\n type === 'uint64' ||\n type === 'int8' ||\n type === 'uint8' ||\n type === 'bool' ||\n type === 'uint4' ||\n type === 'int4';\n\n/**\n * Map string data location to integer value\n */\nexport const dataLocationStringToEnum = (location: Tensor.DataLocation): number => {\n switch (location) {\n case 'none':\n return 0;\n case 'cpu':\n return 1;\n case 'cpu-pinned':\n return 2;\n case 'texture':\n return 3;\n case 'gpu-buffer':\n return 4;\n case 'ml-tensor':\n return 5;\n default:\n throw new Error(`unsupported data location: ${location}`);\n }\n};\n\n/**\n * Map integer data location to string value\n */\nexport const dataLocationEnumToString = (location: number): Tensor.DataLocation | undefined =>\n (['none', 'cpu', 'cpu-pinned', 'texture', 'gpu-buffer', 'ml-tensor'] as const)[location];\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { isNode } from './wasm-utils-env';\n\n/**\n * Load a file into a Uint8Array.\n *\n * @param file - the file to load. Can be a URL/path, a Blob, an ArrayBuffer, or a Uint8Array.\n * @returns a Uint8Array containing the file data.\n */\nexport const loadFile = async (file: string | Blob | ArrayBufferLike | Uint8Array): Promise<Uint8Array> => {\n if (typeof file === 'string') {\n if (isNode) {\n // load file into ArrayBuffer in Node.js\n try {\n const { readFile } = require('node:fs/promises');\n return new Uint8Array(await readFile(file));\n } catch (e) {\n if (e.code === 'ERR_FS_FILE_TOO_LARGE') {\n // file is too large, use fs.createReadStream instead\n const { createReadStream } = require('node:fs');\n const stream = createReadStream(file);\n const chunks: Uint8Array[] = [];\n for await (const chunk of stream) {\n chunks.push(chunk);\n }\n return new Uint8Array(Buffer.concat(chunks));\n }\n throw e;\n }\n } else {\n // load file into ArrayBuffer in browsers\n const response = await fetch(file);\n if (!response.ok) {\n throw new Error(`failed to load external data file: ${file}`);\n }\n const contentLengthHeader = response.headers.get('Content-Length');\n const fileSize = contentLengthHeader ? parseInt(contentLengthHeader, 10) : 0;\n if (fileSize < 1073741824 /* 1GB */) {\n // when Content-Length header is not set, we cannot determine the file size. We assume it is small enough to\n // load into memory.\n return new Uint8Array(await response.arrayBuffer());\n } else {\n // file is too large, use stream instead\n if (!response.body) {\n throw new Error(`failed to load external data file: ${file}, no response body.`);\n }\n const reader = response.body.getReader();\n\n let buffer;\n try {\n // try to create ArrayBuffer directly\n buffer = new ArrayBuffer(fileSize);\n } catch (e) {\n if (e instanceof RangeError) {\n // use WebAssembly Memory to allocate larger ArrayBuffer\n const pages = Math.ceil(fileSize / 65536);\n buffer = new WebAssembly.Memory({ initial: pages, maximum: pages }).buffer;\n } else {\n throw e;\n }\n }\n\n let offset = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n const chunkSize = value.byteLength;\n const chunk = new Uint8Array(buffer, offset, chunkSize);\n chunk.set(value);\n offset += chunkSize;\n }\n return new Uint8Array(buffer, 0, fileSize);\n }\n }\n } else if (file instanceof Blob) {\n return new Uint8Array(await file.arrayBuffer());\n } else if (file instanceof Uint8Array) {\n return file;\n } else {\n return new Uint8Array(file);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// WebNN API currently does not have a TypeScript definition file. This file is a workaround with types generated from\n// WebNN API specification.\n// https://github.com/webmachinelearning/webnn/issues/677\n/// <reference path=\"jsep/webnn/webnn.d.ts\" />\n\nimport { Env, InferenceSession, Tensor, TRACE_EVENT_BEGIN, TRACE_EVENT_END } from 'onnxruntime-common';\n\nimport {\n SerializableInternalBuffer,\n SerializableSessionMetadata,\n SerializableTensorMetadata,\n TensorMetadata,\n} from './proxy-messages';\nimport { setRunOptions } from './run-options';\nimport { setSessionOptions } from './session-options';\nimport {\n calculateTensorSizeInBytes,\n dataLocationStringToEnum,\n isGpuBufferSupportedType,\n isMLTensorSupportedType,\n logLevelStringToEnum,\n tensorDataTypeEnumToString,\n tensorDataTypeStringToEnum,\n tensorTypeToTypedArrayConstructor,\n} from './wasm-common';\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError } from './wasm-utils';\nimport { loadFile } from './wasm-utils-load-file';\n\n// #region Initializations\n\n/**\n * There are 4 different \"initialization\" steps for ORT. They happen in different places and different time.\n *\n * 1. JavaScript initialization for onnxruntime-common and onnxruntime-web.\n * This is the first initialization step. In this step, onnxruntime-web calls onnxruntime-common's registerBackend()\n * function multiple times to register all the available backends. The backend registration is very fast. It only\n * registers the backend name with the uninitialized backend object. No heavy initialization is done in this step.\n * Refer to web/lib/index.ts for the backend registration.\n *\n * 2. WebAssembly artifact initialization.\n * This happens when any registered wasm backend is used for the first time (ie. `ort.InferenceSession.create()` is\n * called). In this step, onnxruntime-web does the followings:\n * - create a proxy worker and make sure the proxy worker is ready to receive messages, if proxy is enabled.\n * - perform feature detection, locate correct WebAssembly artifact path and call the Emscripten generated\n * JavaScript code to initialize the WebAssembly runtime.\n * - if proxy is enabled, this step happens in the proxy worker using message 'init-wasm'.\n * - downloading the 'ort-wasm{...}.wasm' file is done in this step.\n * - if multi-thread is enabled, one or more webworker will be created to initialize the PThread threadpool.\n *\n * 3. ORT environment initialization.\n * This happens after step 2. In this step, onnxruntime-web performs ONNX Runtime environment initialization.\n * Function `_OrtInit()` is called in this step.\n * - if proxy is enabled, this step happens in the proxy worker using message 'init-ort'.\n * - logging level (ort.env.logLevel) and thread number (ort.env.wasm.numThreads) are set in this step.\n *\n * 4. Session initialization.\n * This happens when `ort.InferenceSession.create()` is called. Unlike the first 3 steps (they only called once),\n * this step will be done for each session. In this step, onnxruntime-web does the followings:\n * If the parameter is a URL:\n * - download the model data from the URL.\n * - copy the model data to the WASM heap. (proxy: 'copy-from')\n * - dereference the model buffer. This step allows the original ArrayBuffer to be garbage collected.\n * - call `_OrtCreateSession()` to create the session. (proxy: 'create')\n *\n * If the parameter is a Uint8Array object:\n * - copy the model data to the WASM heap. (proxy: 'copy-from')\n * - call `_OrtCreateSession()` to create the session. (proxy: 'create')\n *\n *\n */\n\n/**\n * initialize ORT environment.\n *\n * @param numThreads SetGlobalIntraOpNumThreads(numThreads)\n * @param loggingLevel CreateEnv(static_cast<OrtLoggingLevel>(logging_level))\n */\nconst initOrt = (numThreads: number, loggingLevel: number): void => {\n const errorCode = getInstance()._OrtInit(numThreads, loggingLevel);\n if (errorCode !== 0) {\n checkLastError(\"Can't initialize onnxruntime.\");\n }\n};\n\n/**\n * initialize runtime environment.\n * @param env passed in the environment config object.\n */\nexport const initRuntime = async (env: Env): Promise<void> => {\n // init ORT\n initOrt(env.wasm.numThreads!, logLevelStringToEnum(env.logLevel));\n};\n\n/**\n * perform EP specific initialization.\n *\n * @param env\n * @param epName\n */\nexport const initEp = async (env: Env, epName: string): Promise<void> => {\n // initialize ASYNCIFY support\n getInstance().asyncInit?.();\n\n // perform WebGPU availability check ( either JSEP or WebGPU EP )\n let webgpuAdapter = env.webgpu.adapter as GPUAdapter | null;\n if (epName === 'webgpu') {\n if (typeof navigator === 'undefined' || !navigator.gpu) {\n throw new Error('WebGPU is not supported in current environment');\n }\n if (!webgpuAdapter) {\n // if adapter is not set, request a new adapter.\n const powerPreference = env.webgpu.powerPreference;\n if (powerPreference !== undefined && powerPreference !== 'low-power' && powerPreference !== 'high-performance') {\n throw new Error(`Invalid powerPreference setting: \"${powerPreference}\"`);\n }\n const forceFallbackAdapter = env.webgpu.forceFallbackAdapter;\n if (forceFallbackAdapter !== undefined && typeof forceFallbackAdapter !== 'boolean') {\n throw new Error(`Invalid forceFallbackAdapter setting: \"${forceFallbackAdapter}\"`);\n }\n webgpuAdapter = await navigator.gpu.requestAdapter({ powerPreference, forceFallbackAdapter });\n if (!webgpuAdapter) {\n throw new Error(\n 'Failed to get GPU adapter. ' +\n 'You may need to enable flag \"--enable-unsafe-webgpu\" if you are using Chrome.',\n );\n }\n } else {\n // if adapter is set, validate it.\n if (\n typeof webgpuAdapter.limits !== 'object' ||\n typeof webgpuAdapter.features !== 'object' ||\n typeof webgpuAdapter.requestDevice !== 'function'\n ) {\n throw new Error('Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.');\n }\n }\n }\n\n // perform WebNN availability check ( either JSEP or WebNN EP )\n if (epName === 'webnn') {\n if (typeof navigator === 'undefined' || !(navigator as unknown as { ml: unknown }).ml) {\n throw new Error('WebNN is not supported in current environment');\n }\n }\n\n if (!BUILD_DEFS.DISABLE_JSEP) {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const initJsep = require('./jsep/init').init;\n\n if (epName === 'webgpu') {\n await initJsep('webgpu', getInstance(), env, webgpuAdapter);\n }\n if (epName === 'webnn') {\n await initJsep('webnn', getInstance(), env);\n }\n } else {\n if (!BUILD_DEFS.DISABLE_WEBGPU && epName === 'webgpu') {\n getInstance().webgpuInit!((device) => {\n env.webgpu.device = device;\n });\n }\n if (!BUILD_DEFS.DISABLE_WEBNN && epName === 'webnn') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const backend = new (require('./jsep/backend-webnn').WebNNBackend)(env);\n getInstance().webnnInit!([\n backend,\n // webnnReserveTensorId\n () => backend.reserveTensorId(),\n // webnnReleaseTensorId,\n (tensorId: number) => backend.releaseTensorId(tensorId),\n // webnnEnsureTensor\n async (sessionId: number | undefined, tensorId: number, onnxDataType: number, shape: number[], copyOld) =>\n backend.ensureTensor(sessionId, tensorId, onnxDataType, shape, copyOld),\n // webnnUploadTensor\n (tensorId: number, data: Uint8Array) => {\n backend.uploadTensor(tensorId, data);\n },\n // webnnDownloadTensor\n async (tensorId: number, dstBuffer: ArrayBufferView | ArrayBuffer) =>\n backend.downloadTensor(tensorId, dstBuffer),\n // webnnRegisterMLContext\n (sessionId: number, mlContext: MLContext) => backend.registerMLContext(sessionId, mlContext),\n // webnnEnableTraceEvent\n !!env.trace,\n ]);\n }\n }\n};\n\n// #endregion Initializations\n\n/**\n * valid data locations for input/output tensors.\n */\ntype SupportedTensorDataLocationForInputOutput =\n | 'cpu'\n | 'cpu-pinned'\n | 'gpu-buffer'\n | 'ml-tensor'\n // Use 'ml-tensor' during inference, but output a tensor located on the CPU.\n | 'ml-tensor-cpu-output';\n\ntype IOBindingState = {\n /**\n * the handle of IO binding.\n */\n readonly handle: number;\n\n /**\n * the preferred location for each output tensor.\n *\n * value is one of 'cpu', 'cpu-pinned', 'gpu-buffer', 'ml-tensor'.\n */\n readonly outputPreferredLocations: readonly SupportedTensorDataLocationForInputOutput[];\n\n /**\n * enum value of the preferred location for each output tensor.\n */\n readonly outputPreferredLocationsEncoded: readonly number[];\n};\n\n/**\n * tuple elements are: InferenceSession ID; inputNamesUTF8Encoded; outputNamesUTF8Encoded; bindingState\n */\ntype SessionMetadata = [\n inferenceSessionId: number,\n inputNamesUTF8Encoded: number[],\n outputNamesUTF8Encoded: number[],\n bindingState: IOBindingState | null,\n enableGraphCapture: boolean,\n inputOutputBound: boolean,\n];\n\nconst activeSessions = new Map<number, SessionMetadata>();\n\n/**\n * get the input/output count of the session.\n * @param sessionHandle the handle representing the session. should be non-zero.\n * @returns a tuple including 2 numbers, representing the input count and output count.\n */\nconst getSessionInputOutputCount = (sessionHandle: number): [number, number] => {\n const wasm = getInstance();\n const stack = wasm.stackSave();\n try {\n const ptrSize = wasm.PTR_SIZE;\n const dataOffset = wasm.stackAlloc(2 * ptrSize);\n const errorCode = wasm._OrtGetInputOutputCount(sessionHandle, dataOffset, dataOffset + ptrSize);\n if (errorCode !== 0) {\n checkLastError(\"Can't get session input/output count.\");\n }\n const type = ptrSize === 4 ? 'i32' : 'i64';\n return [Number(wasm.getValue(dataOffset, type)), Number(wasm.getValue(dataOffset + ptrSize, type))];\n } finally {\n wasm.stackRestore(stack);\n }\n};\n\nconst getSessionInputOutputMetadata = (\n sessionHandle: number,\n index: number,\n): [nameOffset: number, elementType: number, dims?: Array<number | string>] => {\n const wasm = getInstance();\n const stack = wasm.stackSave();\n let metadataOffset = 0;\n try {\n const ptrSize = wasm.PTR_SIZE;\n const dataOffset = wasm.stackAlloc(2 * ptrSize);\n const errorCode = wasm._OrtGetInputOutputMetadata(sessionHandle, index, dataOffset, dataOffset + ptrSize);\n if (errorCode !== 0) {\n checkLastError(\"Can't get session input/output metadata.\");\n }\n const nameOffset = Number(wasm.getValue(dataOffset, '*'));\n metadataOffset = Number(wasm.getValue(dataOffset + ptrSize, '*'));\n // get element type\n const elementType = wasm.HEAP32[metadataOffset / 4];\n if (elementType === 0) {\n return [nameOffset, 0]; // non-tensor\n }\n\n // get dims count\n const dimsCount = wasm.HEAPU32[metadataOffset / 4 + 1];\n // get dims\n const dims: Array<number | string> = [];\n for (let i = 0; i < dimsCount; i++) {\n const symbolicDimNameOffset = Number(wasm.getValue(metadataOffset + 8 + i * ptrSize, '*'));\n dims.push(\n symbolicDimNameOffset !== 0\n ? wasm.UTF8ToString(symbolicDimNameOffset)\n : Number(wasm.getValue(metadataOffset + 8 + (i + dimsCount) * ptrSize, '*')),\n );\n }\n return [nameOffset, elementType, dims];\n } finally {\n wasm.stackRestore(stack);\n if (metadataOffset !== 0) {\n wasm._OrtFree(metadataOffset);\n }\n }\n};\n\n/**\n * allocate the memory and memcpy the external buffer.\n *\n * @param model - the external buffer containing the model data. Must not be the same buffer as the WASM heap.\n * @returns a 2-elements tuple - the pointer and size of the allocated buffer\n */\nexport const copyFromExternalBuffer = (model: Uint8Array): [number, number] => {\n const wasm = getInstance();\n const modelDataOffset = wasm._malloc(model.byteLength);\n if (modelDataOffset === 0) {\n throw new Error(`Can't create a session. failed to allocate a buffer of size ${model.byteLength}.`);\n }\n wasm.HEAPU8.set(model, modelDataOffset);\n return [modelDataOffset, model.byteLength];\n};\n\n/**\n * create an inference session from a model data buffer.\n *\n * @param modelData - either a Uint8Array object representing the model data, or a 2-elements tuple containing the\n * pointer and size of the model data buffer.\n * @param options an optional session options object.\n * @returns a 3-elements tuple containing [session handle, input names, output names]\n */\nexport const createSession = async (\n modelData: Uint8Array | SerializableInternalBuffer,\n options?: InferenceSession.SessionOptions,\n): Promise<SerializableSessionMetadata> => {\n let modelDataOffset: number, modelDataLength: number;\n const wasm = getInstance();\n\n if (Array.isArray(modelData)) {\n // if model data is an array, it must be a 2-elements tuple containing the pointer and size of the model data\n [modelDataOffset, modelDataLength] = modelData;\n } else if (modelData.buffer === wasm.HEAPU8.buffer) {\n // if model data uses the same buffer as the WASM heap, we don't need to copy it.\n [modelDataOffset, modelDataLength] = [modelData.byteOffset, modelData.byteLength];\n } else {\n // otherwise, copy the model data to the WASM heap.\n [modelDataOffset, modelDataLength] = copyFromExternalBuffer(modelData);\n }\n\n let sessionHandle = 0;\n let sessionOptionsHandle = 0;\n let ioBindingHandle = 0;\n let allocs: number[] = [];\n const inputNamesUTF8Encoded = [];\n const outputNamesUTF8Encoded = [];\n\n try {\n [sessionOptionsHandle, allocs] = await setSessionOptions(options);\n\n if (options?.externalData && wasm.mountExternalData) {\n const loadingPromises = [];\n for (const file of options.externalData) {\n const path = typeof file === 'string' ? file : file.path;\n loadingPromises.push(\n loadFile(typeof file === 'string' ? file : file.data).then((data) => {\n wasm.mountExternalData(path, data);\n }),\n );\n }\n\n // wait for all external data files to be loaded\n await Promise.all(loadingPromises);\n }\n\n for (const provider of options?.executionProviders ?? []) {\n const providerName = typeof provider === 'string' ? provider : provider.name;\n if (providerName === 'webnn') {\n wasm.shouldTransferToMLTensor = false;\n if (typeof provider !== 'string') {\n const webnnOptions = provider as InferenceSession.WebNNExecutionProviderOption;\n const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context;\n const gpuDevice = (webnnOptions as InferenceSession.WebNNOptionsWebGpu)?.gpuDevice;\n const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType;\n const powerPreference = (webnnOptions as InferenceSession.WebNNContextOptions)?.powerPreference;\n if (context) {\n wasm.currentContext = context as MLContext;\n } else if (gpuDevice) {\n wasm.currentContext = await wasm.webnnCreateMLContext!(gpuDevice);\n } else {\n wasm.currentContext = await wasm.webnnCreateMLContext!({ deviceType, powerPreference });\n }\n } else {\n wasm.currentContext = await wasm.webnnCreateMLContext!();\n }\n break;\n }\n }\n\n sessionHandle = await wasm._OrtCreateSession(modelDataOffset, modelDataLength, sessionOptionsHandle);\n wasm.webgpuOnCreateSession?.(sessionHandle);\n if (sessionHandle === 0) {\n checkLastError(\"Can't create a session.\");\n }\n\n wasm.jsepOnCreateSession?.();\n\n // clear current MLContext after session creation\n if (wasm.currentContext) {\n wasm.webnnRegisterMLContext!(sessionHandle, wasm.currentContext);\n wasm.currentContext = undefined;\n wasm.shouldTransferToMLTensor = true;\n }\n\n const [inputCount, outputCount] = getSessionInputOutputCount(sessionHandle);\n\n const enableGraphCapture = !!options?.enableGraphCapture;\n\n const inputNames = [];\n const outputNames = [];\n const inputMetadata: InferenceSession.ValueMetadata[] = [];\n const outputMetadata: InferenceSession.ValueMetadata[] = [];\n const outputPreferredLocations: SupportedTensorDataLocationForInputOutput[] = [];\n for (let i = 0; i < inputCount; i++) {\n const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i);\n if (nameOffset === 0) {\n checkLastError(\"Can't get an input name.\");\n }\n inputNamesUTF8Encoded.push(nameOffset);\n const name = wasm.UTF8ToString(nameOffset);\n inputNames.push(name);\n inputMetadata.push(\n elementType === 0\n ? { name, isTensor: false }\n : { name, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! },\n );\n }\n for (let i = 0; i < outputCount; i++) {\n const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i + inputCount);\n if (nameOffset === 0) {\n checkLastError(\"Can't get an output name.\");\n }\n outputNamesUTF8Encoded.push(nameOffset);\n const nameString = wasm.UTF8ToString(nameOffset);\n outputNames.push(nameString);\n outputMetadata.push(\n elementType === 0\n ? { name: nameString, isTensor: false }\n : { name: nameString, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! },\n );\n\n if (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) {\n if (enableGraphCapture && options?.preferredOutputLocation === undefined) {\n outputPreferredLocations.push('gpu-buffer');\n continue;\n }\n const location =\n typeof options?.preferredOutputLocation === 'string'\n ? options.preferredOutputLocation\n : (options?.preferredOutputLocation?.[nameString] ?? 'cpu');\n const isGraphOutput = wasm.webnnIsGraphOutput;\n if (location === 'cpu' && isGraphOutput && isGraphOutput(sessionHandle, nameString)) {\n outputPreferredLocations.push('ml-tensor-cpu-output');\n continue;\n }\n if (location !== 'cpu' && location !== 'cpu-pinned' && location !== 'gpu-buffer' && location !== 'ml-tensor') {\n throw new Error(`Not supported preferred output location: ${location}.`);\n }\n if (enableGraphCapture && location !== 'gpu-buffer') {\n throw new Error(\n `Not supported preferred output location: ${location}. Only 'gpu-buffer' location is supported when enableGraphCapture is true.`,\n );\n }\n outputPreferredLocations.push(location);\n }\n }\n\n // use IO binding only when at least one output is preferred to be on GPU.\n let bindingState: IOBindingState | null = null;\n if (\n (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) &&\n outputPreferredLocations.some((l) => l === 'gpu-buffer' || l === 'ml-tensor' || l === 'ml-tensor-cpu-output')\n ) {\n ioBindingHandle = wasm._OrtCreateBinding(sessionHandle);\n if (ioBindingHandle === 0) {\n checkLastError(\"Can't create IO binding.\");\n }\n\n bindingState = {\n handle: ioBindingHandle,\n outputPreferredLocations,\n outputPreferredLocationsEncoded: outputPreferredLocations\n // 'ml-tensor-cpu-output' is treated as 'ml-tensor' for the purpose of IO binding.\n .map((l) => (l === 'ml-tensor-cpu-output' ? 'ml-tensor' : l))\n .map((l) => dataLocationStringToEnum(l)),\n };\n }\n\n activeSessions.set(sessionHandle, [\n sessionHandle,\n inputNamesUTF8Encoded,\n outputNamesUTF8Encoded,\n bindingState,\n enableGraphCapture,\n false,\n ]);\n return [sessionHandle, inputNames, outputNames, inputMetadata, outputMetadata];\n } catch (e) {\n inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n\n if (ioBindingHandle !== 0) {\n if (wasm._OrtReleaseBinding(ioBindingHandle) !== 0) {\n checkLastError(\"Can't release IO binding.\");\n }\n }\n\n if (sessionHandle !== 0) {\n if (wasm._OrtReleaseSession(sessionHandle) !== 0) {\n checkLastError(\"Can't release session.\");\n }\n }\n throw e;\n } finally {\n wasm._free(modelDataOffset);\n if (sessionOptionsHandle !== 0) {\n if (wasm._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) {\n checkLastError(\"Can't release session options.\");\n }\n }\n allocs.forEach((alloc) => wasm._free(alloc));\n\n // unmount external data if necessary\n wasm.unmountExternalData?.();\n }\n};\n\nexport const releaseSession = (sessionId: number): void => {\n const wasm = getInstance();\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error(`cannot release session. invalid session id: ${sessionId}`);\n }\n const [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture] = session;\n\n if (ioBindingState) {\n if (enableGraphCapture) {\n if (wasm._OrtClearBoundOutputs(ioBindingState.handle) !== 0) {\n checkLastError(\"Can't clear bound outputs.\");\n }\n }\n if (wasm._OrtReleaseBinding(ioBindingState.handle) !== 0) {\n checkLastError(\"Can't release IO binding.\");\n }\n }\n\n wasm.jsepOnReleaseSession?.(sessionId);\n wasm.webnnOnReleaseSession?.(sessionId);\n wasm.webgpuOnReleaseSession?.(sessionId);\n\n inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n if (wasm._OrtReleaseSession(sessionHandle) !== 0) {\n checkLastError(\"Can't release session.\");\n }\n activeSessions.delete(sessionId);\n};\n\nexport const prepareInputOutputTensor = async (\n tensor: TensorMetadata | null,\n tensorHandles: number[],\n allocs: number[],\n sessionId: number,\n tensorNameUTF8Encoded: number,\n index: number,\n enableGraphCapture = false,\n): Promise<void> => {\n if (!tensor) {\n tensorHandles.push(0);\n return;\n }\n\n const wasm = getInstance();\n const ptrSize = wasm.PTR_SIZE;\n\n const dataType = tensor[0];\n const dims = tensor[1];\n const location = tensor[3];\n let actualLocation = location;\n\n let rawData: number;\n let dataByteLength: number;\n\n if (dataType === 'string' && (location === 'gpu-buffer' || location === 'ml-tensor')) {\n throw new Error('String tensor is not supported on GPU.');\n }\n\n if (enableGraphCapture && location !== 'gpu-buffer') {\n throw new Error(\n `External buffer must be provided for input/output index ${index} when enableGraphCapture is true.`,\n );\n }\n\n if (location === 'gpu-buffer') {\n const gpuBuffer = tensor[2].gpuBuffer;\n dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!;\n\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n const registerBuffer = wasm.webgpuRegisterBuffer;\n if (!registerBuffer) {\n throw new Error('Tensor location \"gpu-buffer\" is not supported without using WebGPU.');\n }\n\n rawData = registerBuffer(gpuBuffer, sessionId);\n } else {\n const registerBuffer = wasm.jsepRegisterBuffer;\n if (!registerBuffer) {\n throw new Error('Tensor location \"gpu-buffer\" is not supported without using WebGPU.');\n }\n rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength);\n }\n } else if (location === 'ml-tensor') {\n const mlTensor = tensor[2].mlTensor as MLTensor;\n dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!;\n\n const registerMLTensor = wasm.webnnRegisterMLTensor;\n if (!registerMLTensor) {\n throw new Error('Tensor location \"ml-tensor\" is not supported without using WebNN.');\n }\n rawData = registerMLTensor(sessionId, mlTensor, tensorDataTypeStringToEnum(dataType), dims);\n } else {\n const data = tensor[2];\n\n if (Array.isArray(data)) {\n // string tensor\n dataByteLength = ptrSize * data.length;\n rawData = wasm._malloc(dataByteLength);\n allocs.push(rawData);\n for (let i = 0; i < data.length; i++) {\n if (typeof data[i] !== 'string') {\n throw new TypeError(`tensor data at index ${i} is not a string`);\n }\n wasm.setValue(rawData + i * ptrSize, allocWasmString(data[i], allocs), '*');\n }\n } else {\n const isGraphInput = wasm.webnnIsGraphInput;\n const isGraphOutput = wasm.webnnIsGraphOutput;\n if (dataType !== 'string' && isGraphInput && isGraphOutput) {\n const tensorName = wasm.UTF8ToString(tensorNameUTF8Encoded);\n // Promote the tensor to 'ml-tensor' if it is a graph input.\n if (isGraphInput(sessionId, tensorName) || isGraphOutput(sessionId, tensorName)) {\n const dataTypeEnum = tensorDataTypeStringToEnum(dataType);\n dataByteLength = calculateTensorSizeInBytes(dataTypeEnum, dims)!;\n actualLocation = 'ml-tensor';\n const createTemporaryTensor = wasm.webnnCreateTemporaryTensor;\n const uploadTensor = wasm.webnnUploadTensor;\n if (!createTemporaryTensor || !uploadTensor) {\n throw new Error('Tensor location \"ml-tensor\" is not supported without using WebNN.');\n }\n const tensorId = await createTemporaryTensor(sessionId, dataTypeEnum, dims as number[]);\n uploadTensor(tensorId, new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n rawData = tensorId;\n } else {\n dataByteLength = data.byteLength;\n rawData = wasm._malloc(dataByteLength);\n allocs.push(rawData);\n wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData);\n }\n } else {\n dataByteLength = data.byteLength;\n rawData = wasm._malloc(dataByteLength);\n allocs.push(rawData);\n wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData);\n }\n }\n }\n\n const stack = wasm.stackSave();\n const dimsOffset = wasm.stackAlloc(4 * dims.length);\n try {\n dims.forEach((d, index) => wasm.setValue(dimsOffset + index * ptrSize, d, ptrSize === 4 ? 'i32' : 'i64'));\n const tensor = wasm._OrtCreateTensor(\n tensorDataTypeStringToEnum(dataType),\n rawData,\n dataByteLength,\n dimsOffset,\n dims.length,\n dataLocationStringToEnum(actualLocation),\n );\n if (tensor === 0) {\n checkLastError(`Can't create tensor for input/output. session=${sessionId}, index=${index}.`);\n }\n tensorHandles.push(tensor);\n } finally {\n wasm.stackRestore(stack);\n }\n};\n\n/**\n * perform inference run\n */\nexport const run = async (\n sessionId: number,\n inputIndices: number[],\n inputTensors: TensorMetadata[],\n outputIndices: number[],\n outputTensors: Array<TensorMetadata | null>,\n options: InferenceSession.RunOptions,\n): Promise<TensorMetadata[]> => {\n const wasm = getInstance();\n const ptrSize = wasm.PTR_SIZE;\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error(`cannot run inference. invalid session id: ${sessionId}`);\n }\n const sessionHandle = session[0];\n const inputNamesUTF8Encoded = session[1];\n const outputNamesUTF8Encoded = session[2];\n const ioBindingState = session[3];\n const enableGraphCapture = session[4];\n const inputOutputBound = session[5];\n\n const inputCount = inputIndices.length;\n const outputCount = outputIndices.length;\n\n let runOptionsHandle = 0;\n let runOptionsAllocs: number[] = [];\n\n const inputTensorHandles: number[] = [];\n const outputTensorHandles: number[] = [];\n const inputOutputAllocs: number[] = [];\n const preAllocatedOutputs: number[] = [];\n\n const beforeRunStack = wasm.stackSave();\n const inputValuesOffset = wasm.stackAlloc(inputCount * ptrSize);\n const inputNamesOffset = wasm.stackAlloc(inputCount * ptrSize);\n const outputValuesOffset = wasm.stackAlloc(outputCount * ptrSize);\n const outputNamesOffset = wasm.stackAlloc(outputCount * ptrSize);\n\n try {\n [runOptionsHandle, runOptionsAllocs] = setRunOptions(options);\n\n TRACE_EVENT_BEGIN('wasm prepareInputOutputTensor');\n // create input tensors\n for (let i = 0; i < inputCount; i++) {\n await prepareInputOutputTensor(\n inputTensors[i],\n inputTensorHandles,\n inputOutputAllocs,\n sessionId,\n inputNamesUTF8Encoded[inputIndices[i]],\n inputIndices[i],\n enableGraphCapture,\n );\n }\n\n // create output tensors\n for (let i = 0; i < outputCount; i++) {\n await prepareInputOutputTensor(\n outputTensors[i],\n outputTensorHandles,\n inputOutputAllocs,\n sessionId,\n outputNamesUTF8Encoded[outputIndices[i]],\n inputCount + outputIndices[i],\n enableGraphCapture,\n );\n }\n TRACE_EVENT_END('wasm prepareInputOutputTensor');\n\n for (let i = 0; i < inputCount; i++) {\n wasm.setValue(inputValuesOffset + i * ptrSize, inputTensorHandles[i], '*');\n wasm.setValue(inputNamesOffset + i * ptrSize, inputNamesUTF8Encoded[inputIndices[i]], '*');\n }\n for (let i = 0; i < outputCount; i++) {\n wasm.setValue(outputValuesOffset + i * ptrSize, outputTensorHandles[i], '*');\n wasm.setValue(outputNamesOffset + i * ptrSize, outputNamesUTF8Encoded[outputIndices[i]], '*');\n }\n\n if ((!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) && ioBindingState && !inputOutputBound) {\n const { handle, outputPreferredLocations, outputPreferredLocationsEncoded } = ioBindingState;\n\n if (inputNamesUTF8Encoded.length !== inputCount) {\n throw new Error(\n `input count from feeds (${inputCount}) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).`,\n );\n }\n\n TRACE_EVENT_BEGIN('wasm bindInputsOutputs');\n // process inputs\n for (let i = 0; i < inputCount; i++) {\n const index = inputIndices[i];\n const errorCode = await wasm._OrtBindInput(handle, inputNamesUTF8Encoded[index], inputTensorHandles[i]);\n if (errorCode !== 0) {\n checkLastError(`Can't bind input[${i}] for session=${sessionId}.`);\n }\n }\n\n // process pre-allocated outputs\n for (let i = 0; i < outputCount; i++) {\n const index = outputIndices[i];\n const location = outputTensors[i]?.[3]; // undefined means output is not pre-allocated.\n\n if (location) {\n // output is pre-allocated, store and bind the tensor.\n preAllocatedOutputs.push(outputTensorHandles[i]);\n const errorCode = wasm._OrtBindOutput(handle, outputNamesUTF8Encoded[index], outputTensorHandles[i], 0);\n if (errorCode !== 0) {\n checkLastError(`Can't bind pre-allocated output[${i}] for session=${sessionId}.`);\n }\n } else {\n // output is not pre-allocated. reset preferred location.\n const errorCode = wasm._OrtBindOutput(\n handle,\n outputNamesUTF8Encoded[index],\n 0,\n outputPreferredLocationsEncoded[index],\n );\n if (errorCode !== 0) {\n checkLastError(`Can't bind output[${i}] to ${outputPreferredLocations[i]} for session=${sessionId}.`);\n }\n }\n }\n TRACE_EVENT_END('wasm bindInputsOutputs');\n activeSessions.set(sessionId, [\n sessionHandle,\n inputNamesUTF8Encoded,\n outputNamesUTF8Encoded,\n ioBindingState,\n enableGraphCapture,\n true,\n ]);\n }\n\n wasm.jsepOnRunStart?.(sessionHandle);\n wasm.webnnOnRunStart?.(sessionHandle);\n\n let errorCode: number;\n if ((!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) && ioBindingState) {\n errorCode = await wasm._OrtRunWithBinding(\n sessionHandle,\n ioBindingState.handle,\n outputCount,\n outputValuesOffset,\n runOptionsHandle,\n );\n } else {\n errorCode = await wasm._OrtRun(\n sessionHandle,\n inputNamesOffset,\n inputValuesOffset,\n inputCount,\n outputNamesOffset,\n outputCount,\n outputValuesOffset,\n runOptionsHandle,\n );\n }\n\n if (errorCode !== 0) {\n checkLastError('failed to call OrtRun().');\n }\n\n const output: TensorMetadata[] = [];\n const outputPromises: Array<Promise<[number, Tensor.DataType]>> = [];\n\n TRACE_EVENT_BEGIN('wasm ProcessOutputTensor');\n for (let i = 0; i < outputCount; i++) {\n const tensor = Number(wasm.getValue(outputValuesOffset + i * ptrSize, '*'));\n // TODO: revisit this part to ensure it works for WebGPU when both pre-allocated outputs and\n // preferred location are specified.\n // Certain pre-allocated tensors may already be bound in the IO binding. e.g. the WebNN backend\n // always binds its tensor to 'ml-tensor'. In such cases, the tensor ID might change after binding,\n // but copying data for these tensors should still be avoided.\n if (tensor === outputTensorHandles[i] || preAllocatedOutputs.includes(outputTensorHandles[i])) {\n // output tensor is pre-allocated. no need to copy data.\n output.push(outputTensors[i]!);\n if (tensor !== outputTensorHandles[i]) {\n // release redundant tensor earlier.\n if (wasm._OrtReleaseTensor(tensor) !== 0) {\n checkLastError(\"Can't release tensor.\");\n }\n }\n continue;\n }\n\n const beforeGetTensorDataStack = wasm.stackSave();\n // stack allocate 4 pointer value\n const tensorDataOffset = wasm.stackAlloc(4 * ptrSize);\n\n let keepOutputTensor = false;\n let type: Tensor.Type | undefined,\n dataOffset = 0;\n try {\n const errorCode = wasm._OrtGetTensorData(\n tensor,\n tensorDataOffset,\n tensorDataOffset + ptrSize,\n tensorDataOffset + 2 * ptrSize,\n\n tensorDataOffset + 3 * ptrSize,\n );\n if (errorCode !== 0) {\n checkLastError(`Can't access output tensor data on index ${i}.`);\n }\n const valueType = ptrSize === 4 ? 'i32' : 'i64';\n const dataType = Number(wasm.getValue(tensorDataOffset, valueType));\n dataOffset = wasm.getValue(tensorDataOffset + ptrSize, '*');\n const dimsOffset = wasm.getValue(tensorDataOffset + ptrSize * 2, '*');\n const dimsLength = Number(wasm.getValue(tensorDataOffset + ptrSize * 3, valueType));\n const dims = [];\n for (let i = 0; i < dimsLength; i++) {\n dims.push(Number(wasm.getValue(dimsOffset + i * ptrSize, valueType)));\n }\n if (wasm._OrtFree(dimsOffset) !== 0) {\n checkLastError(\"Can't free memory for tensor dims.\");\n }\n const size = dims.reduce((a, b) => a * b, 1);\n type = tensorDataTypeEnumToString(dataType);\n\n const preferredLocation = ioBindingState?.outputPreferredLocations[outputIndices[i]];\n\n if (type === 'string') {\n if (preferredLocation === 'gpu-buffer' || preferredLocation === 'ml-tensor') {\n throw new Error('String tensor is not supported on GPU.');\n }\n const stringData: string[] = [];\n for (let i = 0; i < size; i++) {\n const offset = wasm.getValue(dataOffset + i * ptrSize, '*');\n const nextOffset = wasm.getValue(dataOffset + (i + 1) * ptrSize, '*');\n const maxBytesToRead = i === size - 1 ? undefined : nextOffset - offset;\n stringData.push(wasm.UTF8ToString(offset, maxBytesToRead));\n }\n output.push([type, dims, stringData, 'cpu']);\n } else {\n // If a certain output's preferred location is GPU but the tensor is empty, we still need to create a CPU\n // tensor for it. There is no mapping GPU buffer for an empty tensor.\n if (preferredLocation === 'gpu-buffer' && size > 0) {\n const getBuffer = !BUILD_DEFS.DISABLE_WEBGPU ? wasm.webgpuGetBuffer : wasm.jsepGetBuffer;\n if (!getBuffer) {\n throw new Error('preferredLocation \"gpu-buffer\" is not supported without using WebGPU.');\n }\n const gpuBuffer = getBuffer(dataOffset);\n const bufferSize = calculateTensorSizeInBytes(dataType, size);\n if (bufferSize === undefined || !isGpuBufferSupportedType(type)) {\n throw new Error(`Unsupported data type: ${type}`);\n }\n\n // do not release the tensor right now. it will be released when user calls tensor.dispose().\n keepOutputTensor = true;\n\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n wasm.webgpuRegisterBuffer!(gpuBuffer, sessionId, dataOffset);\n const downloadDataFunction = wasm.webgpuCreateDownloader!(gpuBuffer, bufferSize, sessionId);\n output.push([\n type,\n dims,\n {\n gpuBuffer,\n download: async () => {\n const arrayBuffer = await downloadDataFunction();\n const data = new (tensorTypeToTypedArrayConstructor(type!))(arrayBuffer);\n return data as Tensor.DataTypeMap[Tensor.GpuBufferDataTypes];\n },\n dispose: () => {\n if (wasm._OrtReleaseTensor(tensor) !== 0) {\n checkLastError(\"Can't release tensor.\");\n }\n },\n },\n 'gpu-buffer',\n ]);\n } else {\n output.push([\n type,\n dims,\n {\n gpuBuffer,\n download: wasm.jsepCreateDownloader!(gpuBuffer, bufferSize, type),\n dispose: () => {\n if (wasm._OrtReleaseTensor(tensor) !== 0) {\n checkLastError(\"Can't release tensor.\");\n }\n },\n },\n 'gpu-buffer',\n ]);\n }\n } else if (preferredLocation === 'ml-tensor' && size > 0) {\n const ensureTensor = wasm.webnnEnsureTensor;\n const isGraphInputOutputTypeSupported = wasm.webnnIsGraphInputOutputTypeSupported;\n if (!ensureTensor || !isGraphInputOutputTypeSupported) {\n throw new Error('preferredLocation \"ml-tensor\" is not supported without using WebNN.');\n }\n const tensorSize = calculateTensorSizeInBytes(dataType, size);\n if (tensorSize === undefined || !isMLTensorSupportedType(type)) {\n throw new Error(`Unsupported data type: ${type}`);\n }\n if (!isGraphInputOutputTypeSupported(sessionId, type, false)) {\n throw new Error(\n `preferredLocation \"ml-tensor\" for ${type} output is not supported by current WebNN Context.`,\n );\n }\n\n // If the graph has been partitioned, the output tensor may have not been created. For this reason, we use\n // ensureTensor to get/create the MLTensor. In which case, we don't need to copy the data if a new tensor\n // has been created.\n const mlTensor = await ensureTensor(sessionId, dataOffset, dataType, dims, false);\n\n // do not release the tensor right now. it will be released when user calls tensor.dispose().\n keepOutputTensor = true;\n\n output.push([\n type,\n dims,\n {\n mlTensor,\n download: wasm.webnnCreateMLTensorDownloader!(dataOffset, type),\n dispose: () => {\n wasm.webnnReleaseTensorId!(dataOffset);\n wasm._OrtReleaseTensor(tensor);\n },\n },\n 'ml-tensor',\n ]);\n } else if (preferredLocation === 'ml-tensor-cpu-output' && size > 0) {\n const data = wasm.webnnCreateMLTensorDownloader!(dataOffset, type as Tensor.MLTensorDataTypes)();\n const index = output.length;\n // Delay the data download and releasing the tensor until we can wait for all output tensors to be downloaded.\n keepOutputTensor = true;\n outputPromises.push(\n (async () => {\n const result: [number, Tensor.DataType] = [index, await data];\n wasm.webnnReleaseTensorId!(dataOffset);\n wasm._OrtReleaseTensor(tensor);\n return result;\n })(),\n );\n output.push([type, dims, [], 'cpu']);\n } else {\n const typedArrayConstructor = tensorTypeToTypedArrayConstructor(type);\n const data = new typedArrayConstructor(size);\n new Uint8Array(data.buffer, data.byteOffset, data.byteLength).set(\n wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength),\n );\n output.push([type, dims, data, 'cpu']);\n }\n }\n } finally {\n wasm.stackRestore(beforeGetTensorDataStack);\n if (type === 'string' && dataOffset) {\n wasm._free(dataOffset);\n }\n if (!keepOutputTensor) {\n wasm._OrtReleaseTensor(tensor);\n }\n }\n }\n\n if (ioBindingState && !enableGraphCapture) {\n if (wasm._OrtClearBoundOutputs(ioBindingState.handle) !== 0) {\n checkLastError(\"Can't clear bound outputs.\");\n }\n activeSessions.set(sessionId, [\n sessionHandle,\n inputNamesUTF8Encoded,\n outputNamesUTF8Encoded,\n ioBindingState,\n enableGraphCapture,\n false,\n ]);\n }\n // Wait for all output tensor data to be downloaded.\n for (const [index, data] of await Promise.all(outputPromises)) {\n output[index][2] = data;\n }\n TRACE_EVENT_END('wasm ProcessOutputTensor');\n return output;\n } finally {\n wasm.webnnOnRunEnd?.(sessionHandle);\n\n wasm.stackRestore(beforeRunStack);\n\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n inputTensors.forEach((t) => {\n if (t && t[3] === 'gpu-buffer') {\n wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer);\n }\n });\n outputTensors.forEach((t) => {\n if (t && t[3] === 'gpu-buffer') {\n wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer);\n }\n });\n }\n inputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v));\n outputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v));\n inputOutputAllocs.forEach((p) => wasm._free(p));\n\n if (runOptionsHandle !== 0) {\n wasm._OrtReleaseRunOptions(runOptionsHandle);\n }\n runOptionsAllocs.forEach((p) => wasm._free(p));\n }\n};\n\n/**\n * end profiling\n */\nexport const endProfiling = (sessionId: number): void => {\n const wasm = getInstance();\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error('invalid session id');\n }\n const sessionHandle = session[0];\n\n // profile file name is not used yet, but it must be freed.\n const profileFileName = wasm._OrtEndProfiling(sessionHandle);\n if (profileFileName === 0) {\n checkLastError(\"Can't get an profile file name.\");\n }\n wasm._OrtFree(profileFileName);\n};\n\nexport const extractTransferableBuffers = (tensors: readonly SerializableTensorMetadata[]): ArrayBufferLike[] => {\n const buffers: ArrayBufferLike[] = [];\n for (const tensor of tensors) {\n const data = tensor[2];\n if (!Array.isArray(data) && 'buffer' in data) {\n buffers.push(data.buffer);\n }\n }\n return buffers;\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env, InferenceSession } from 'onnxruntime-common';\n\nimport {\n OrtWasmMessage,\n SerializableInternalBuffer,\n SerializableSessionMetadata,\n SerializableTensorMetadata,\n TensorMetadata,\n} from './proxy-messages';\nimport * as core from './wasm-core-impl';\nimport { initializeWebAssembly } from './wasm-factory';\nimport {\n importProxyWorker,\n inferWasmPathPrefixFromScriptSrc,\n isEsmImportMetaUrlHardcodedAsFileUri,\n} from './wasm-utils-import';\n\nconst isProxy = (): boolean => !!env.wasm.proxy && typeof document !== 'undefined';\nlet proxyWorker: Worker | undefined;\nlet initializing = false;\nlet initialized = false;\nlet aborted = false;\nlet temporaryObjectUrl: string | undefined;\n\ntype PromiseCallbacks<T = void> = [resolve: (result: T) => void, reject: (reason: unknown) => void];\nlet initWasmCallbacks: PromiseCallbacks;\nconst queuedCallbacks: Map<OrtWasmMessage['type'], Array<PromiseCallbacks<unknown>>> = new Map();\n\nconst enqueueCallbacks = (type: OrtWasmMessage['type'], callbacks: PromiseCallbacks<unknown>): void => {\n const queue = queuedCallbacks.get(type);\n if (queue) {\n queue.push(callbacks);\n } else {\n queuedCallbacks.set(type, [callbacks]);\n }\n};\n\nconst ensureWorker = (): void => {\n if (initializing || !initialized || aborted || !proxyWorker) {\n throw new Error('worker not ready');\n }\n};\n\nconst onProxyWorkerMessage = (ev: MessageEvent<OrtWasmMessage>): void => {\n switch (ev.data.type) {\n case 'init-wasm':\n initializing = false;\n if (ev.data.err) {\n aborted = true;\n initWasmCallbacks[1](ev.data.err);\n } else {\n initialized = true;\n initWasmCallbacks[0]();\n }\n if (temporaryObjectUrl) {\n URL.revokeObjectURL(temporaryObjectUrl);\n temporaryObjectUrl = undefined;\n }\n break;\n case 'init-ep':\n case 'copy-from':\n case 'create':\n case 'release':\n case 'run':\n case 'end-profiling': {\n const callbacks = queuedCallbacks.get(ev.data.type)!;\n if (ev.data.err) {\n callbacks.shift();\n } else {\n callbacks.shift();\n }\n break;\n }\n default:\n }\n};\n\nexport const initializeWebAssemblyAndOrtRuntime = async (): Promise<void> => {\n if (initialized) {\n return;\n }\n if (initializing) {\n throw new Error(\"multiple calls to 'initWasm()' detected.\");\n }\n if (aborted) {\n throw new Error(\"previous call to 'initWasm()' failed.\");\n }\n\n initializing = true;\n\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n return new Promise<void>((resolve, reject) => {\n proxyWorker?.terminate();\n\n void importProxyWorker().then(([objectUrl, worker]) => {\n try {\n proxyWorker = worker;\n proxyWorker.onerror = (ev: ErrorEvent) => reject(ev);\n proxyWorker.onmessage = onProxyWorkerMessage;\n initWasmCallbacks = [resolve, reject];\n const message: OrtWasmMessage = { type: 'init-wasm', in: env };\n\n // if the proxy worker is loaded from a blob URL, we need to make sure the path information is not lost.\n //\n // when `env.wasm.wasmPaths` is not set, we need to pass the path information to the worker.\n //\n if (!BUILD_DEFS.ENABLE_BUNDLE_WASM_JS && !message.in!.wasm.wasmPaths && objectUrl) {\n // for a build not bundled the wasm JS, we need to pass the path prefix to the worker.\n // the path prefix will be used to resolve the path to both the wasm JS and the wasm file.\n const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc();\n if (inferredWasmPathPrefix) {\n message.in!.wasm.wasmPaths = inferredWasmPathPrefix;\n }\n }\n\n if (\n BUILD_DEFS.IS_ESM &&\n BUILD_DEFS.ENABLE_BUNDLE_WASM_JS &&\n !message.in!.wasm.wasmPaths &&\n (objectUrl || isEsmImportMetaUrlHardcodedAsFileUri)\n ) {\n // for a build bundled the wasm JS, if either of the following conditions is met:\n // - the proxy worker is loaded from a blob URL\n // - `import.meta.url` is a file URL, it means it is overwritten by the bundler.\n //\n // in either case, the path information is lost, we need to pass the path of the .wasm file to the worker.\n // we need to use the bundler preferred URL format:\n // new URL('filename', import.meta.url)\n // so that the bundler can handle the file using corresponding loaders.\n message.in!.wasm.wasmPaths = {\n wasm: !BUILD_DEFS.DISABLE_JSEP\n ? new URL('ort-wasm-simd-threaded.jsep.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n : BUILD_DEFS.ENABLE_JSPI\n ? new URL('ort-wasm-simd-threaded.jspi.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n : !BUILD_DEFS.DISABLE_WEBGPU\n ? new URL('ort-wasm-simd-threaded.asyncify.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n : new URL('ort-wasm-simd-threaded.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href,\n };\n }\n proxyWorker.postMessage(message);\n temporaryObjectUrl = objectUrl;\n } catch (e) {\n reject(e);\n }\n }, reject);\n });\n } else {\n try {\n await initializeWebAssembly(env.wasm);\n await core.initRuntime(env);\n initialized = true;\n } catch (e) {\n aborted = true;\n throw e;\n } finally {\n initializing = false;\n }\n }\n};\n\nexport const initializeOrtEp = async (epName: string): Promise<void> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<void>((resolve, reject) => {\n enqueueCallbacks('init-ep', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'init-ep', in: { epName, env } };\n proxyWorker!.postMessage(message);\n });\n } else {\n await core.initEp(env, epName);\n }\n};\n\nexport const copyFromExternalBuffer = async (buffer: Uint8Array): Promise<SerializableInternalBuffer> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<SerializableInternalBuffer>((resolve, reject) => {\n enqueueCallbacks('copy-from', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'copy-from', in: { buffer } };\n proxyWorker!.postMessage(message, [buffer.buffer]);\n });\n } else {\n return core.copyFromExternalBuffer(buffer);\n }\n};\n\nexport const createSession = async (\n model: SerializableInternalBuffer | Uint8Array,\n options?: InferenceSession.SessionOptions,\n): Promise<SerializableSessionMetadata> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n // check unsupported options\n if (options?.preferredOutputLocation) {\n throw new Error('session option \"preferredOutputLocation\" is not supported for proxy.');\n }\n ensureWorker();\n return new Promise<SerializableSessionMetadata>((resolve, reject) => {\n enqueueCallbacks('create', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'create', in: { model, options: { ...options } } };\n const transferable: Transferable[] = [];\n if (model instanceof Uint8Array) {\n transferable.push(model.buffer);\n }\n proxyWorker!.postMessage(message, transferable);\n });\n } else {\n return core.createSession(model, options);\n }\n};\n\nexport const releaseSession = async (sessionId: number): Promise<void> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<void>((resolve, reject) => {\n enqueueCallbacks('release', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'release', in: sessionId };\n proxyWorker!.postMessage(message);\n });\n } else {\n core.releaseSession(sessionId);\n }\n};\n\nexport const run = async (\n sessionId: number,\n inputIndices: number[],\n inputs: TensorMetadata[],\n outputIndices: number[],\n outputs: Array<TensorMetadata | null>,\n options: InferenceSession.RunOptions,\n): Promise<TensorMetadata[]> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n // check inputs location\n if (inputs.some((t) => t[3] !== 'cpu')) {\n throw new Error('input tensor on GPU is not supported for proxy.');\n }\n // check outputs location\n if (outputs.some((t) => t)) {\n throw new Error('pre-allocated output tensor is not supported for proxy.');\n }\n ensureWorker();\n return new Promise<SerializableTensorMetadata[]>((resolve, reject) => {\n enqueueCallbacks('run', [resolve, reject]);\n const serializableInputs = inputs as SerializableTensorMetadata[]; // every input is on CPU.\n const message: OrtWasmMessage = {\n type: 'run',\n in: { sessionId, inputIndices, inputs: serializableInputs, outputIndices, options },\n };\n proxyWorker!.postMessage(message, core.extractTransferableBuffers(serializableInputs));\n });\n } else {\n return core.run(sessionId, inputIndices, inputs, outputIndices, outputs, options);\n }\n};\n\nexport const endProfiling = async (sessionId: number): Promise<void> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<void>((resolve, reject) => {\n enqueueCallbacks('end-profiling', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'end-profiling', in: sessionId };\n proxyWorker!.postMessage(message);\n });\n } else {\n core.endProfiling(sessionId);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n InferenceSession,\n InferenceSessionHandler,\n SessionHandler,\n Tensor,\n TRACE_FUNC_BEGIN,\n TRACE_FUNC_END,\n} from 'onnxruntime-common';\n\nimport { SerializableInternalBuffer, TensorMetadata } from './proxy-messages';\nimport { copyFromExternalBuffer, createSession, endProfiling, releaseSession, run } from './proxy-wrapper';\nimport { isGpuBufferSupportedType, isMLTensorSupportedType } from './wasm-common';\nimport { isNode } from './wasm-utils-env';\nimport { loadFile } from './wasm-utils-load-file';\n\nexport const encodeTensorMetadata = (tensor: Tensor, getName: () => string): TensorMetadata => {\n switch (tensor.location) {\n case 'cpu':\n return [tensor.type, tensor.dims, tensor.data, 'cpu'];\n case 'gpu-buffer':\n return [tensor.type, tensor.dims, { gpuBuffer: tensor.gpuBuffer }, 'gpu-buffer'];\n case 'ml-tensor':\n return [tensor.type, tensor.dims, { mlTensor: tensor.mlTensor }, 'ml-tensor'];\n default:\n throw new Error(`invalid data location: ${tensor.location} for ${getName()}`);\n }\n};\n\nexport const decodeTensorMetadata = (tensor: TensorMetadata): Tensor => {\n switch (tensor[3]) {\n case 'cpu':\n return new Tensor(tensor[0], tensor[2], tensor[1]);\n case 'gpu-buffer': {\n const dataType = tensor[0];\n if (!isGpuBufferSupportedType(dataType)) {\n throw new Error(`not supported data type: ${dataType} for deserializing GPU tensor`);\n }\n const { gpuBuffer, download, dispose } = tensor[2];\n return Tensor.fromGpuBuffer(gpuBuffer, { dataType, dims: tensor[1], download, dispose });\n }\n case 'ml-tensor': {\n const dataType = tensor[0];\n if (!isMLTensorSupportedType(dataType)) {\n throw new Error(`not supported data type: ${dataType} for deserializing MLTensor tensor`);\n }\n const { mlTensor, download, dispose } = tensor[2];\n return Tensor.fromMLTensor(mlTensor, { dataType, dims: tensor[1], download, dispose });\n }\n default:\n throw new Error(`invalid data location: ${tensor[3]}`);\n }\n};\n\nexport class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHandler {\n private sessionId: number;\n\n inputNames: readonly string[];\n outputNames: readonly string[];\n inputMetadata: readonly InferenceSession.ValueMetadata[];\n outputMetadata: readonly InferenceSession.ValueMetadata[];\n\n async fetchModelAndCopyToWasmMemory(path: string): Promise<SerializableInternalBuffer> {\n // fetch model from url and move to wasm heap.\n return copyFromExternalBuffer(await loadFile(path));\n }\n\n async loadModel(pathOrBuffer: string | Uint8Array, options?: InferenceSession.SessionOptions): Promise<void> {\n TRACE_FUNC_BEGIN();\n let model: Parameters<typeof createSession>[0];\n\n if (typeof pathOrBuffer === 'string') {\n if (isNode) {\n // node\n model = await loadFile(pathOrBuffer);\n } else {\n // browser\n // fetch model and copy to wasm heap.\n model = await this.fetchModelAndCopyToWasmMemory(pathOrBuffer);\n }\n } else {\n model = pathOrBuffer;\n }\n\n [this.sessionId, this.inputNames, this.outputNames, this.inputMetadata, this.outputMetadata] = await createSession(\n model,\n options,\n );\n TRACE_FUNC_END();\n }\n\n async dispose(): Promise<void> {\n return releaseSession(this.sessionId);\n }\n\n async run(\n feeds: SessionHandler.FeedsType,\n fetches: SessionHandler.FetchesType,\n options: InferenceSession.RunOptions,\n ): Promise<SessionHandler.ReturnType> {\n TRACE_FUNC_BEGIN();\n const inputArray: Tensor[] = [];\n const inputIndices: number[] = [];\n Object.entries(feeds).forEach((kvp) => {\n const name = kvp[0];\n const tensor = kvp[1];\n const index = this.inputNames.indexOf(name);\n if (index === -1) {\n throw new Error(`invalid input '${name}'`);\n }\n inputArray.push(tensor);\n inputIndices.push(index);\n });\n\n const outputArray: Array<Tensor | null> = [];\n const outputIndices: number[] = [];\n Object.entries(fetches).forEach((kvp) => {\n const name = kvp[0];\n const tensor = kvp[1];\n const index = this.outputNames.indexOf(name);\n if (index === -1) {\n throw new Error(`invalid output '${name}'`);\n }\n outputArray.push(tensor);\n outputIndices.push(index);\n });\n\n const inputs = inputArray.map((t, i) =>\n encodeTensorMetadata(t, () => `input \"${this.inputNames[inputIndices[i]]}\"`),\n );\n const outputs = outputArray.map((t, i) =>\n t ? encodeTensorMetadata(t, () => `output \"${this.outputNames[outputIndices[i]]}\"`) : null,\n );\n\n const results = await run(this.sessionId, inputIndices, inputs, outputIndices, outputs, options);\n\n const resultMap: SessionHandler.ReturnType = {};\n for (let i = 0; i < results.length; i++) {\n resultMap[this.outputNames[outputIndices[i]]] = outputArray[i] ?? decodeTensorMetadata(results[i]);\n }\n TRACE_FUNC_END();\n return resultMap;\n }\n\n startProfiling(): void {\n // TODO: implement profiling\n }\n\n endProfiling(): void {\n void endProfiling(this.sessionId);\n }\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Backend, env, InferenceSession, InferenceSessionHandler } from 'onnxruntime-common';\n\nimport { initializeOrtEp, initializeWebAssemblyAndOrtRuntime } from './wasm/proxy-wrapper';\nimport { OnnxruntimeWebAssemblySessionHandler } from './wasm/session-handler-inference';\n\n/**\n * This function initializes all flags for WebAssembly.\n *\n * Those flags are accessible from `ort.env.wasm`. Users are allow to set those flags before the first inference session\n * being created, to override default value.\n */\nexport const initializeFlags = (): void => {\n if (typeof env.wasm.initTimeout !== 'number' || env.wasm.initTimeout < 0) {\n env.wasm.initTimeout = 0;\n }\n\n const simd = env.wasm.simd;\n if (typeof simd !== 'boolean' && simd !== undefined && simd !== 'fixed' && simd !== 'relaxed') {\n // eslint-disable-next-line no-console\n console.warn(\n `Property \"env.wasm.simd\" is set to unknown value \"${simd}\". Reset it to \\`false\\` and ignore SIMD feature checking.`,\n );\n env.wasm.simd = false;\n }\n\n if (typeof env.wasm.proxy !== 'boolean') {\n env.wasm.proxy = false;\n }\n\n if (typeof env.wasm.trace !== 'boolean') {\n env.wasm.trace = false;\n }\n\n if (typeof env.wasm.numThreads !== 'number' || !Number.isInteger(env.wasm.numThreads) || env.wasm.numThreads <= 0) {\n // The following logic only applies when `ort.env.wasm.numThreads` is not set by user. We will always honor user's\n // setting if it is provided.\n\n // Browser: when crossOriginIsolated is false, SharedArrayBuffer is not available so WebAssembly threads will not\n // work. In this case, we will set numThreads to 1.\n //\n // There is an exception: when the browser is configured to force-enable SharedArrayBuffer (e.g. Chromuim with\n // --enable-features=SharedArrayBuffer), it is possible that `self.crossOriginIsolated` is false and\n // SharedArrayBuffer is available at the same time. This is usually for testing. In this case, we will still set\n // numThreads to 1 here. If we want to enable multi-threading in test, we should set `ort.env.wasm.numThreads` to a\n // value greater than 1.\n if (typeof self !== 'undefined' && !self.crossOriginIsolated) {\n env.wasm.numThreads = 1;\n } else {\n const numCpuLogicalCores =\n typeof navigator === 'undefined' ? require('node:os').cpus().length : navigator.hardwareConcurrency;\n env.wasm.numThreads = Math.min(4, Math.ceil((numCpuLogicalCores || 1) / 2));\n }\n }\n};\n\nexport class OnnxruntimeWebAssemblyBackend implements Backend {\n /**\n * This function initializes the WebAssembly backend.\n *\n * This function will be called only once for each backend name. It will be called the first time when\n * `ort.InferenceSession.create()` is called with a registered backend name.\n *\n * @param backendName - the registered backend name.\n */\n async init(backendName: string): Promise<void> {\n // populate wasm flags\n initializeFlags();\n\n // init wasm\n await initializeWebAssemblyAndOrtRuntime();\n\n // performe EP specific initialization\n await initializeOrtEp(backendName);\n }\n createInferenceSessionHandler(\n path: string,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler>;\n createInferenceSessionHandler(\n buffer: Uint8Array,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler>;\n async createInferenceSessionHandler(\n pathOrBuffer: string | Uint8Array,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler> {\n const handler = new OnnxruntimeWebAssemblySessionHandler();\n await handler.loadModel(pathOrBuffer, options);\n return handler;\n }\n}\n\nexport const wasmBackend = new OnnxruntimeWebAssemblyBackend();\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */\n\n// We use \"require\" instead of \"import\" here because import statement must be put in top level. Our current code does\n// not allow bundler to tree-shaking code as expected because some codes are treated as having side effects.\n// So we import code inside the if-clause to allow bundler remove the code safely.\n\nexport * from 'onnxruntime-common';\nimport * as ort from 'onnxruntime-common';\nexport default ort;\n\nimport { registerBackend, env } from 'onnxruntime-common';\nimport { version } from './version';\n\nif (!BUILD_DEFS.DISABLE_WEBGL) {\n const onnxjsBackend = require('./backend-onnxjs').onnxjsBackend;\n registerBackend('webgl', onnxjsBackend, -10);\n}\n\nif (!BUILD_DEFS.DISABLE_JSEP && !BUILD_DEFS.DISABLE_WEBGPU) {\n throw new Error(\n 'The current build is specified to enable both JSEP and WebGPU EP. This is not a valid configuration. ' +\n 'JSEP and WebGPU EPs cannot be enabled at the same time.',\n );\n}\n\nif (!BUILD_DEFS.DISABLE_WEBNN && BUILD_DEFS.DISABLE_JSEP && BUILD_DEFS.DISABLE_WEBGPU) {\n throw new Error(\n 'The current build is specified to enable WebNN EP without JSEP or WebGPU EP. This is not a valid configuration. ' +\n 'WebNN EP requires either JSEP or WebGPU EP to be enabled.',\n );\n}\n\nif (!BUILD_DEFS.DISABLE_WASM) {\n const wasmBackend = require('./backend-wasm').wasmBackend;\n if (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) {\n registerBackend('webgpu', wasmBackend, 5);\n }\n if (!BUILD_DEFS.DISABLE_WEBNN) {\n registerBackend('webnn', wasmBackend, 5);\n }\n registerBackend('cpu', wasmBackend, 10);\n registerBackend('wasm', wasmBackend, 10);\n}\n\nObject.defineProperty(env.versions, 'web', { value: version, enumerable: true });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// This file is generated by /js/scripts/update-version.ts\n// Do not modify file content manually.\n\nexport const version = '1.24.2';\n","// @guidekit/vad — Silero VAD ONNX model wrapper for voice activity detection\nimport * as ort from 'onnxruntime-web';\n\nexport const VAD_VERSION = '0.1.0-beta.2';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:VAD]';\n\n/** Default CDN URL for the Silero VAD ONNX model (v5). */\nconst DEFAULT_MODEL_URL =\n 'https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.20/dist/silero_vad_v5.onnx';\n\n/** Cache API key used for persisting the downloaded ONNX model. */\nconst CACHE_NAME = `guidekit-vad-v${VAD_VERSION}`;\nconst CACHE_MODEL_KEY = 'model.onnx';\n\n/** Silero VAD frame size: 512 samples at 16 kHz = 32 ms per frame. */\nconst FRAME_SIZE = 512;\n\n/** Target sample rate for VAD processing. */\nconst TARGET_SAMPLE_RATE = 16000;\n\n/** Duration (in ms) of audio collected for noise floor calibration. */\nconst CALIBRATION_DURATION_MS = 500;\n\n/** Hidden/cell state size for Silero VAD v5 LSTM. */\nconst STATE_SIZE = 128;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface VADOptions {\n /** Speech probability threshold (0-1). Default: 0.5 */\n threshold?: number;\n /** Minimum speech duration in ms to trigger start. Default: 300 */\n minSpeechDurationMs?: number;\n /** Silence duration in ms after speech to trigger end. Default: 500 */\n silenceDurationMs?: number;\n /** Sample rate. Default: 16000 */\n sampleRate?: number;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n /** Custom URL for the Silero VAD ONNX model file. */\n modelUrl?: string;\n}\n\nexport interface VADEvent {\n type: 'speech-start' | 'speech-end' | 'vad-ready';\n timestamp: number;\n /** Speech probability (0-1) at the moment of the event. */\n probability?: number;\n}\n\ntype VADEventType = VADEvent['type'];\ntype VADCallback = (event: VADEvent) => void;\n\n// ---------------------------------------------------------------------------\n// Utility: Cache API helpers\n// ---------------------------------------------------------------------------\n\nasync function loadModelFromCache(): Promise<ArrayBuffer | null> {\n if (typeof caches === 'undefined') return null;\n try {\n const cache = await caches.open(CACHE_NAME);\n const response = await cache.match(CACHE_MODEL_KEY);\n return response ? response.arrayBuffer() : null;\n } catch {\n // Cache API may be unavailable in certain contexts (e.g. opaque origins).\n return null;\n }\n}\n\nasync function saveModelToCache(data: ArrayBuffer): Promise<void> {\n if (typeof caches === 'undefined') return;\n try {\n const cache = await caches.open(CACHE_NAME);\n await cache.put(CACHE_MODEL_KEY, new Response(data));\n } catch {\n // Silently ignore cache write failures.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility: Resampler\n// ---------------------------------------------------------------------------\n\n/**\n * Simple linear-interpolation resampler from `inputRate` to `outputRate`.\n * Adequate for VAD where perceptual audio quality is irrelevant.\n */\nfunction resample(\n input: Float32Array,\n inputRate: number,\n outputRate: number,\n): Float32Array {\n if (inputRate === outputRate) return input;\n const ratio = inputRate / outputRate;\n const outputLength = Math.round(input.length / ratio);\n const output = new Float32Array(outputLength);\n for (let i = 0; i < outputLength; i++) {\n const srcIndex = i * ratio;\n const srcFloor = Math.floor(srcIndex);\n const srcCeil = Math.min(srcFloor + 1, input.length - 1);\n const frac = srcIndex - srcFloor;\n output[i] = (input[srcFloor] as number) * (1 - frac) + (input[srcCeil] as number) * frac;\n }\n return output;\n}\n\n// ---------------------------------------------------------------------------\n// SileroVAD\n// ---------------------------------------------------------------------------\n\nexport class SileroVAD {\n // Options (resolved with defaults)\n private readonly _threshold: number;\n private readonly _minSpeechDurationMs: number;\n private readonly _silenceDurationMs: number;\n private readonly _sampleRate: number;\n private readonly _debug: boolean;\n private readonly _modelUrl: string;\n\n // ONNX Runtime state\n private _session: ort.InferenceSession | null = null;\n private _h: ort.Tensor | null = null;\n private _c: ort.Tensor | null = null;\n\n // Audio pipeline\n private _audioContext: AudioContext | null = null;\n private _ownsAudioContext = false;\n private _sourceNode: MediaStreamAudioSourceNode | null = null;\n private _workletNode: AudioWorkletNode | ScriptProcessorNode | null = null;\n private _stream: MediaStream | null = null;\n\n // Frame buffer for accumulating resampled samples into FRAME_SIZE chunks\n private _frameBuffer: Float32Array = new Float32Array(0);\n private _frameBufferOffset = 0;\n\n // State tracking\n private _isReady = false;\n private _isSpeaking = false;\n private _isStarted = false;\n private _isDestroyed = false;\n\n // Duration tracking (in frames)\n private _consecutiveSpeechFrames = 0;\n private _consecutiveSilenceFrames = 0;\n private _frameDurationMs: number;\n private _minSpeechFrames: number;\n private _silenceFrames: number;\n\n // Noise floor calibration\n private _isCalibrating = false;\n private _calibrationSamples: number[] = [];\n private _calibrationFramesNeeded = 0;\n private _calibratedThreshold: number;\n\n // Event listeners\n private _listeners: Map<VADEventType, Set<VADCallback>> = new Map();\n\n // Processing lock to serialise frame inference\n private _processingPromise: Promise<void> = Promise.resolve();\n\n constructor(options?: VADOptions) {\n this._threshold = options?.threshold ?? 0.5;\n this._minSpeechDurationMs = options?.minSpeechDurationMs ?? 300;\n this._silenceDurationMs = options?.silenceDurationMs ?? 500;\n this._sampleRate = options?.sampleRate ?? TARGET_SAMPLE_RATE;\n this._debug = options?.debug ?? false;\n this._modelUrl = options?.modelUrl ?? DEFAULT_MODEL_URL;\n this._calibratedThreshold = this._threshold;\n\n // Pre-compute frame-duration-based counters\n this._frameDurationMs = (FRAME_SIZE / this._sampleRate) * 1000;\n this._minSpeechFrames = Math.ceil(this._minSpeechDurationMs / this._frameDurationMs);\n this._silenceFrames = Math.ceil(this._silenceDurationMs / this._frameDurationMs);\n\n this._log('Created with options', {\n threshold: this._threshold,\n minSpeechDurationMs: this._minSpeechDurationMs,\n silenceDurationMs: this._silenceDurationMs,\n sampleRate: this._sampleRate,\n modelUrl: this._modelUrl,\n });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Load the ONNX model. Uses Cache API for persistence across sessions. */\n async init(): Promise<void> {\n if (this._isDestroyed) {\n throw new Error(`${LOG_PREFIX} Cannot init after destroy`);\n }\n if (this._isReady) {\n this._log('Already initialised — skipping');\n return;\n }\n\n this._log('Initialising...');\n\n // 1. Attempt to load model bytes from cache, falling back to network.\n let modelBuffer = await loadModelFromCache();\n if (modelBuffer) {\n this._log('Loaded model from Cache API');\n } else {\n this._log('Fetching model from', this._modelUrl);\n const response = await fetch(this._modelUrl);\n if (!response.ok) {\n throw new Error(\n `${LOG_PREFIX} Failed to fetch model: ${response.status} ${response.statusText}`,\n );\n }\n modelBuffer = await response.arrayBuffer();\n this._log('Model fetched, size:', modelBuffer.byteLength, 'bytes');\n\n // Persist to Cache API for next time.\n await saveModelToCache(modelBuffer);\n this._log('Model saved to Cache API');\n }\n\n // 2. Create ONNX InferenceSession.\n this._session = await ort.InferenceSession.create(modelBuffer, {\n executionProviders: ['wasm'],\n graphOptimizationLevel: 'all',\n });\n\n // 3. Initialise LSTM hidden/cell state tensors (zeros).\n this._resetStates();\n\n this._isReady = true;\n this._log('Model loaded and ready');\n\n this._emit({\n type: 'vad-ready',\n timestamp: Date.now(),\n });\n }\n\n /**\n * Process a single audio frame (512 samples at 16 kHz).\n * Returns the speech probability (0-1).\n */\n async processFrame(audioData: Float32Array): Promise<number> {\n if (!this._session) {\n throw new Error(`${LOG_PREFIX} Model not loaded. Call init() first.`);\n }\n if (audioData.length !== FRAME_SIZE) {\n throw new Error(\n `${LOG_PREFIX} Expected ${FRAME_SIZE} samples, got ${audioData.length}`,\n );\n }\n\n const inputTensor = new ort.Tensor('float32', audioData, [1, FRAME_SIZE]);\n const srTensor = new ort.Tensor('int64', BigInt64Array.from([BigInt(this._sampleRate)]), [1]);\n\n const feeds: Record<string, ort.Tensor> = {\n input: inputTensor,\n sr: srTensor,\n h: this._h!,\n c: this._c!,\n };\n\n const results = await this._session.run(feeds);\n\n // Update LSTM hidden/cell states for the next frame.\n this._h = results['hn'] as ort.Tensor;\n this._c = results['cn'] as ort.Tensor;\n\n const probability = (results['output'] as ort.Tensor).data[0] as number;\n return probability;\n }\n\n /** Start VAD processing on a MediaStream (typically from getUserMedia). */\n start(stream: MediaStream): void {\n if (this._isDestroyed) {\n throw new Error(`${LOG_PREFIX} Cannot start after destroy`);\n }\n if (!this._isReady) {\n throw new Error(`${LOG_PREFIX} Model not loaded. Call init() first.`);\n }\n if (this._isStarted) {\n this._log('Already started — stopping previous session first');\n this.stop();\n }\n\n this._log('Starting VAD on MediaStream');\n this._stream = stream;\n this._isStarted = true;\n\n // Reset speech tracking state.\n this._isSpeaking = false;\n this._consecutiveSpeechFrames = 0;\n this._consecutiveSilenceFrames = 0;\n this._frameBuffer = new Float32Array(FRAME_SIZE);\n this._frameBufferOffset = 0;\n\n // Reset LSTM states for a fresh stream.\n this._resetStates();\n\n // Begin noise floor calibration.\n this._isCalibrating = true;\n this._calibrationSamples = [];\n this._calibrationFramesNeeded = Math.max(1, Math.floor(\n (CALIBRATION_DURATION_MS / 1000) * this._sampleRate / FRAME_SIZE,\n ));\n this._log('Calibrating noise floor for', this._calibrationFramesNeeded, 'frames');\n\n // Build the audio processing pipeline.\n this._setupAudioPipeline(stream);\n }\n\n /** Stop VAD processing and release audio resources (but keep the model). */\n stop(): void {\n if (!this._isStarted) return;\n\n this._log('Stopping VAD');\n\n // Tear down audio nodes.\n this._teardownAudioPipeline();\n\n // If we were speaking, emit speech-end.\n if (this._isSpeaking) {\n this._isSpeaking = false;\n this._emit({\n type: 'speech-end',\n timestamp: Date.now(),\n probability: 0,\n });\n }\n\n // Reset state.\n this._isStarted = false;\n this._isSpeaking = false;\n this._consecutiveSpeechFrames = 0;\n this._consecutiveSilenceFrames = 0;\n this._frameBufferOffset = 0;\n this._isCalibrating = false;\n this._calibrationSamples = [];\n this._processingPromise = Promise.resolve();\n\n this._log('VAD stopped');\n }\n\n /** Register a callback for speech-start events. Returns an unsubscribe function. */\n onSpeechStart(callback: VADCallback): () => void {\n return this._on('speech-start', callback);\n }\n\n /** Register a callback for speech-end events. Returns an unsubscribe function. */\n onSpeechEnd(callback: VADCallback): () => void {\n return this._on('speech-end', callback);\n }\n\n /** Register a callback for vad-ready events. Returns an unsubscribe function. */\n onReady(callback: VADCallback): () => void {\n return this._on('vad-ready', callback);\n }\n\n /** Whether the ONNX model is loaded and ready. */\n get isReady(): boolean {\n return this._isReady;\n }\n\n /** Whether speech is currently detected. */\n get isSpeaking(): boolean {\n return this._isSpeaking;\n }\n\n /** The MediaStream currently being processed, or null. */\n get stream(): MediaStream | null {\n return this._stream;\n }\n\n /** Release ONNX model session and all audio resources. */\n async destroy(): Promise<void> {\n if (this._isDestroyed) return;\n this._log('Destroying...');\n\n this.stop();\n\n if (this._session) {\n await this._session.release();\n this._session = null;\n }\n\n // Dispose tensors.\n this._h?.dispose();\n this._c?.dispose();\n this._h = null;\n this._c = null;\n\n this._isReady = false;\n this._isDestroyed = true;\n this._listeners.clear();\n\n this._log('Destroyed');\n }\n\n // -------------------------------------------------------------------------\n // Private: Event system\n // -------------------------------------------------------------------------\n\n private _on(type: VADEventType, callback: VADCallback): () => void {\n let set = this._listeners.get(type);\n if (!set) {\n set = new Set();\n this._listeners.set(type, set);\n }\n set.add(callback);\n return () => {\n set!.delete(callback);\n };\n }\n\n private _emit(event: VADEvent): void {\n const set = this._listeners.get(event.type);\n if (!set) return;\n for (const cb of set) {\n try {\n cb(event);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`${LOG_PREFIX} Error in ${event.type} callback:`, err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Audio pipeline\n // -------------------------------------------------------------------------\n\n private _setupAudioPipeline(stream: MediaStream): void {\n // Determine the incoming sample rate.\n const tracks = stream.getAudioTracks();\n const trackSettings = tracks[0]?.getSettings();\n const inputSampleRate = trackSettings?.sampleRate ?? 48000;\n\n this._log('Input sample rate:', inputSampleRate);\n\n // Create AudioContext at the input sample rate so we don't double-resample.\n // SSR guard: AudioContext may not exist.\n if (typeof AudioContext === 'undefined' && typeof webkitAudioContext === 'undefined') {\n throw new Error(`${LOG_PREFIX} AudioContext is not available in this environment`);\n }\n\n const AudioContextClass =\n typeof AudioContext !== 'undefined'\n ? AudioContext\n : // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (globalThis as any).webkitAudioContext as typeof AudioContext;\n\n this._audioContext = new AudioContextClass({ sampleRate: inputSampleRate });\n this._ownsAudioContext = true;\n\n this._sourceNode = this._audioContext.createMediaStreamSource(stream);\n\n // Try AudioWorklet first, fall back to ScriptProcessorNode.\n this._setupScriptProcessor(inputSampleRate);\n }\n\n /**\n * ScriptProcessorNode fallback (works everywhere, including Safari).\n * We use a buffer size of 4096 which gives ~85 ms of audio at 48 kHz.\n */\n private _setupScriptProcessor(inputSampleRate: number): void {\n if (!this._audioContext || !this._sourceNode) return;\n\n // Buffer size must be a power of 2: 256, 512, 1024, 2048, 4096, 8192, 16384.\n const bufferSize = 4096;\n const processor = this._audioContext.createScriptProcessor(bufferSize, 1, 1);\n\n processor.onaudioprocess = (event: AudioProcessingEvent) => {\n if (!this._isStarted) return;\n\n const inputData = event.inputBuffer.getChannelData(0);\n\n // Resample to target rate if needed.\n const resampled =\n inputSampleRate !== this._sampleRate\n ? resample(inputData, inputSampleRate, this._sampleRate)\n : new Float32Array(inputData);\n\n // Feed resampled audio into frame-sized chunks.\n this._feedAudio(resampled);\n };\n\n this._sourceNode.connect(processor);\n processor.connect(this._audioContext.destination);\n this._workletNode = processor;\n\n this._log('Audio pipeline set up (ScriptProcessorNode)');\n }\n\n /**\n * Accumulate resampled audio into FRAME_SIZE chunks and process each full frame.\n */\n private _feedAudio(samples: Float32Array): void {\n let offset = 0;\n\n while (offset < samples.length) {\n const remaining = FRAME_SIZE - this._frameBufferOffset;\n const available = samples.length - offset;\n const toCopy = Math.min(remaining, available);\n\n this._frameBuffer.set(\n samples.subarray(offset, offset + toCopy),\n this._frameBufferOffset,\n );\n this._frameBufferOffset += toCopy;\n offset += toCopy;\n\n if (this._frameBufferOffset === FRAME_SIZE) {\n const frame = new Float32Array(this._frameBuffer);\n this._frameBufferOffset = 0;\n\n // Serialise inference calls to avoid overlapping ONNX sessions.\n this._processingPromise = this._processingPromise.then(() =>\n this._handleFrame(frame),\n );\n }\n }\n }\n\n /**\n * Process a single FRAME_SIZE frame: run inference and update speech state.\n */\n private async _handleFrame(frame: Float32Array): Promise<void> {\n if (!this._isStarted || !this._session) return;\n\n let probability: number;\n try {\n probability = await this.processFrame(frame);\n } catch (err) {\n if (this._debug) {\n // eslint-disable-next-line no-console\n console.error(`${LOG_PREFIX} Inference error:`, err);\n }\n return;\n }\n\n // Noise floor calibration phase.\n if (this._isCalibrating) {\n this._calibrationSamples.push(probability);\n\n if (this._calibrationSamples.length >= this._calibrationFramesNeeded) {\n this._finishCalibration();\n }\n return;\n }\n\n // Speech state machine.\n const isSpeechFrame = probability >= this._calibratedThreshold;\n\n if (isSpeechFrame) {\n this._consecutiveSpeechFrames++;\n this._consecutiveSilenceFrames = 0;\n\n if (!this._isSpeaking && this._consecutiveSpeechFrames >= this._minSpeechFrames) {\n this._isSpeaking = true;\n this._log('Speech started, probability:', probability.toFixed(3));\n this._emit({\n type: 'speech-start',\n timestamp: Date.now(),\n probability,\n });\n }\n } else {\n this._consecutiveSilenceFrames++;\n // Do NOT reset _consecutiveSpeechFrames here — only reset when speech-end fires.\n\n if (this._isSpeaking && this._consecutiveSilenceFrames >= this._silenceFrames) {\n this._isSpeaking = false;\n this._consecutiveSpeechFrames = 0;\n this._log('Speech ended, probability:', probability.toFixed(3));\n this._emit({\n type: 'speech-end',\n timestamp: Date.now(),\n probability,\n });\n }\n }\n }\n\n private _finishCalibration(): void {\n if (this._calibrationSamples.length === 0) {\n this._isCalibrating = false;\n return;\n }\n\n // Compute average noise floor probability.\n const sum = this._calibrationSamples.reduce((a, b) => a + b, 0);\n const avgNoise = sum / this._calibrationSamples.length;\n\n // If the ambient noise floor is high, nudge the threshold above it.\n // We add a margin so we don't constantly trigger on background noise.\n const NOISE_MARGIN = 0.15;\n if (avgNoise + NOISE_MARGIN > this._threshold) {\n this._calibratedThreshold = Math.min(avgNoise + NOISE_MARGIN, 0.95);\n this._log(\n 'Noise floor is high. Adjusted threshold from',\n this._threshold.toFixed(3),\n 'to',\n this._calibratedThreshold.toFixed(3),\n '(avg noise:',\n avgNoise.toFixed(3) + ')',\n );\n } else {\n this._calibratedThreshold = this._threshold;\n this._log('Noise floor OK, avg:', avgNoise.toFixed(3), '— keeping threshold at', this._threshold.toFixed(3));\n }\n\n // Recompute frame counters in case threshold changed min speech behaviour.\n this._minSpeechFrames = Math.ceil(this._minSpeechDurationMs / this._frameDurationMs);\n this._silenceFrames = Math.ceil(this._silenceDurationMs / this._frameDurationMs);\n\n this._isCalibrating = false;\n this._calibrationSamples = [];\n }\n\n private _teardownAudioPipeline(): void {\n if (this._workletNode) {\n try {\n this._workletNode.disconnect();\n } catch {\n // Ignore disconnect errors.\n }\n if ('onaudioprocess' in this._workletNode) {\n (this._workletNode as ScriptProcessorNode).onaudioprocess = null;\n }\n this._workletNode = null;\n }\n\n if (this._sourceNode) {\n try {\n this._sourceNode.disconnect();\n } catch {\n // Ignore.\n }\n this._sourceNode = null;\n }\n\n if (this._audioContext && this._ownsAudioContext) {\n try {\n void this._audioContext.close();\n } catch {\n // Ignore.\n }\n this._audioContext = null;\n this._ownsAudioContext = false;\n }\n\n this._stream = null;\n }\n\n // -------------------------------------------------------------------------\n // Private: ONNX state helpers\n // -------------------------------------------------------------------------\n\n /** Reset the LSTM hidden and cell states to zeros. */\n private _resetStates(): void {\n // Dispose any existing tensors to free memory.\n this._h?.dispose();\n this._c?.dispose();\n\n const zeros = new Float32Array(2 * STATE_SIZE).fill(0);\n this._h = new ort.Tensor('float32', zeros.slice(0, STATE_SIZE), [2, 1, 64]);\n this._c = new ort.Tensor('float32', zeros.slice(STATE_SIZE), [2, 1, 64]);\n }\n\n // -------------------------------------------------------------------------\n // Private: Logging\n // -------------------------------------------------------------------------\n\n private _log(...args: unknown[]): void {\n if (!this._debug) return;\n // eslint-disable-next-line no-console\n console.log(LOG_PREFIX, ...args);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Convenience factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create and initialise a SileroVAD instance in one call.\n *\n * ```ts\n * const vad = await createVAD({ debug: true });\n * vad.onSpeechStart(() => console.log('speaking'));\n * vad.start(stream);\n * ```\n */\nexport async function createVAD(options?: VADOptions): Promise<SileroVAD> {\n const vad = new SileroVAD(options);\n await vad.init();\n return vad;\n}\n\n// Re-export the frame size constant so consumers can align their buffers.\nexport { FRAME_SIZE, TARGET_SAMPLE_RATE };\n\n// Type-only declaration for environments that provide webkitAudioContext.\ndeclare global {\n // eslint-disable-next-line no-var\n var webkitAudioContext: typeof AudioContext | undefined;\n}\n","// ---------------------------------------------------------------------------\n// @guidekit/vanilla — Non-React IIFE bundle for script-tag integration\n// ---------------------------------------------------------------------------\n//\n// Provides an imperative API for using GuideKit without React. Users include\n// the script via a <script> tag and interact with the global `GuideKit` object.\n//\n// Usage:\n// <script src=\"https://cdn.jsdelivr.net/npm/@guidekit/vanilla/dist/index.global.js\"></script>\n// <script>\n// GuideKit.init({\n// llm: { provider: 'gemini', apiKey: '...' },\n// agent: { name: 'Guide', greeting: 'Hello!' },\n// });\n// </script>\n// ---------------------------------------------------------------------------\n\nimport { GuideKitCore } from '@guidekit/core';\nimport type {\n GuideKitCoreOptions,\n AgentState,\n GuideKitEvent,\n GuideKitErrorType,\n PageModel,\n HealthCheckResult,\n I18nStrings,\n} from '@guidekit/core';\n\n// ---------------------------------------------------------------------------\n// Widget DOM (lightweight, no React — plain DOM manipulation)\n// ---------------------------------------------------------------------------\n\nconst WIDGET_CSS = /* css */ `\n :host {\n --gk-primary: #6366f1;\n --gk-primary-hover: #4f46e5;\n --gk-bg: #ffffff;\n --gk-bg-secondary: #f8fafc;\n --gk-text: #1e293b;\n --gk-text-secondary: #64748b;\n --gk-border: #e2e8f0;\n --gk-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);\n --gk-radius: 16px;\n --gk-fab-size: 56px;\n --gk-panel-width: 380px;\n --gk-panel-height: 520px;\n --gk-font: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n all: initial;\n font-family: var(--gk-font);\n position: fixed;\n z-index: 2147483647;\n bottom: 24px;\n right: 24px;\n }\n @media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n }\n .gk-fab {\n width: var(--gk-fab-size);\n height: var(--gk-fab-size);\n border-radius: 50%;\n border: none;\n background: var(--gk-primary);\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 16px rgba(99, 102, 241, 0.35);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n outline: none;\n }\n .gk-fab:hover {\n background: var(--gk-primary-hover);\n transform: scale(1.05);\n }\n .gk-fab:focus-visible {\n outline: 2px solid var(--gk-primary);\n outline-offset: 3px;\n }\n .gk-fab svg { width: 24px; height: 24px; fill: currentColor; }\n .gk-panel {\n position: absolute;\n bottom: calc(var(--gk-fab-size) + 16px);\n right: 0;\n width: var(--gk-panel-width);\n height: var(--gk-panel-height);\n background: var(--gk-bg);\n border-radius: var(--gk-radius);\n box-shadow: var(--gk-shadow);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n opacity: 0;\n transform: translateY(12px) scale(0.95);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n .gk-panel.gk-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n .gk-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--gk-border);\n flex-shrink: 0;\n }\n .gk-header-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--gk-text);\n margin: 0;\n }\n .gk-close-btn {\n width: 28px; height: 28px; border-radius: 8px;\n border: none; background: transparent; color: var(--gk-text-secondary);\n cursor: pointer; display: flex; align-items: center; justify-content: center;\n outline: none;\n }\n .gk-close-btn:hover { background: var(--gk-bg-secondary); color: var(--gk-text); }\n .gk-close-btn:focus-visible { outline: 2px solid var(--gk-primary); outline-offset: -2px; }\n .gk-close-btn svg { width: 16px; height: 16px; fill: currentColor; }\n .gk-transcript {\n flex: 1; overflow-y: auto; padding: 16px 20px;\n display: flex; flex-direction: column; gap: 12px; scroll-behavior: smooth;\n }\n .gk-empty {\n flex: 1; display: flex; flex-direction: column; align-items: center;\n justify-content: center; color: var(--gk-text-secondary); text-align: center;\n padding: 32px 16px; font-size: 13px;\n }\n .gk-msg {\n max-width: 85%; padding: 10px 14px; border-radius: 12px;\n font-size: 14px; line-height: 1.5; word-wrap: break-word; white-space: pre-wrap;\n }\n .gk-msg-user {\n align-self: flex-end; background: var(--gk-primary);\n color: #fff; border-bottom-right-radius: 4px;\n }\n .gk-msg-assistant {\n align-self: flex-start; background: var(--gk-bg-secondary);\n color: var(--gk-text); border-bottom-left-radius: 4px;\n }\n .gk-dots {\n align-self: flex-start; display: flex; gap: 4px; padding: 12px 16px;\n }\n .gk-dot {\n width: 6px; height: 6px; border-radius: 50%; background: var(--gk-text-secondary);\n animation: gk-bounce 1.4s ease-in-out infinite;\n }\n .gk-dot:nth-child(2) { animation-delay: 0.16s; }\n .gk-dot:nth-child(3) { animation-delay: 0.32s; }\n @keyframes gk-bounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-6px); }\n }\n .gk-input-area {\n display: flex; align-items: flex-end; gap: 8px;\n padding: 12px 16px; border-top: 1px solid var(--gk-border); flex-shrink: 0;\n }\n .gk-input {\n flex: 1; min-height: 40px; max-height: 120px; padding: 8px 14px;\n border: 1px solid var(--gk-border); border-radius: 12px;\n background: var(--gk-bg); color: var(--gk-text);\n font-family: var(--gk-font); font-size: 14px; line-height: 1.5;\n resize: none; outline: none;\n }\n .gk-input:focus { border-color: var(--gk-primary); box-shadow: 0 0 0 3px rgba(99,102,241,0.15); }\n .gk-send-btn {\n width: 40px; height: 40px; border-radius: 12px; border: none;\n background: var(--gk-primary); color: #fff; cursor: pointer;\n display: flex; align-items: center; justify-content: center; flex-shrink: 0;\n outline: none;\n }\n .gk-send-btn:hover:not(:disabled) { background: var(--gk-primary-hover); }\n .gk-send-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n .gk-send-btn:focus-visible { outline: 2px solid var(--gk-primary); outline-offset: 3px; }\n .gk-send-btn svg { width: 18px; height: 18px; fill: currentColor; }\n @media (hover: none) and (pointer: coarse), (max-width: 768px) {\n :host { bottom: 16px !important; right: 16px !important; }\n .gk-panel {\n position: fixed; bottom: 0; left: 0; right: 0;\n width: 100%; height: 70vh; max-height: 70vh;\n border-radius: var(--gk-radius) var(--gk-radius) 0 0;\n transform: translateY(100%);\n padding-bottom: env(safe-area-inset-bottom, 0px);\n }\n .gk-panel.gk-open { transform: translateY(0); }\n .gk-send-btn, .gk-close-btn { min-width: 44px; min-height: 44px; }\n .gk-input-area { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }\n }\n @media (forced-colors: active) {\n .gk-fab, .gk-send-btn { border: 2px solid ButtonText; }\n .gk-panel { border: 1px solid ButtonText; }\n }\n`;\n\nconst SVG_CHAT = '<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.17L4 17.17V4h16v12z\"/><path d=\"M7 9h10v2H7zm0-3h10v2H7z\"/></svg>';\nconst SVG_CLOSE = '<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/></svg>';\nconst SVG_SEND = '<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\"/></svg>';\n\n// ---------------------------------------------------------------------------\n// VanillaWidget — renders and manages the chat widget without React\n// ---------------------------------------------------------------------------\n\nclass VanillaWidget {\n private host: HTMLDivElement;\n private shadow: ShadowRoot;\n private panel!: HTMLDivElement;\n private transcript!: HTMLDivElement;\n private emptyState!: HTMLDivElement;\n private dotsEl!: HTMLDivElement;\n private input!: HTMLTextAreaElement;\n private sendBtn!: HTMLButtonElement;\n private fab!: HTMLButtonElement;\n private isOpen = false;\n private isSending = false;\n private core: GuideKitCore;\n\n constructor(core: GuideKitCore) {\n this.core = core;\n\n // Create Shadow DOM host\n this.host = document.createElement('div');\n this.host.id = 'guidekit-widget';\n this.host.style.cssText =\n 'position:fixed;z-index:2147483647;bottom:24px;right:24px;margin:0;padding:0;border:none;background:none;';\n document.body.appendChild(this.host);\n\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n // Inject styles\n const style = document.createElement('style');\n style.textContent = WIDGET_CSS;\n this.shadow.appendChild(style);\n\n this.buildDOM();\n this.bindEvents();\n }\n\n private buildDOM(): void {\n // Panel\n this.panel = document.createElement('div');\n this.panel.className = 'gk-panel';\n this.panel.setAttribute('role', 'dialog');\n this.panel.setAttribute('aria-label', 'GuideKit Assistant');\n this.panel.setAttribute('aria-hidden', 'true');\n\n // Header\n const header = document.createElement('div');\n header.className = 'gk-header';\n\n const title = document.createElement('div');\n title.className = 'gk-header-title';\n title.textContent = this.t('widgetTitle');\n header.appendChild(title);\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'gk-close-btn';\n closeBtn.setAttribute('aria-label', this.t('closePanel'));\n closeBtn.innerHTML = SVG_CLOSE;\n closeBtn.addEventListener('click', () => this.togglePanel(false));\n header.appendChild(closeBtn);\n\n this.panel.appendChild(header);\n\n // Transcript\n this.transcript = document.createElement('div');\n this.transcript.className = 'gk-transcript';\n this.transcript.setAttribute('role', 'log');\n this.transcript.setAttribute('aria-live', 'polite');\n\n this.emptyState = document.createElement('div');\n this.emptyState.className = 'gk-empty';\n this.emptyState.textContent = this.t('emptyStateMessage');\n this.transcript.appendChild(this.emptyState);\n\n // Dots indicator (hidden by default)\n this.dotsEl = document.createElement('div');\n this.dotsEl.className = 'gk-dots';\n this.dotsEl.setAttribute('role', 'status');\n this.dotsEl.setAttribute('aria-label', 'Processing');\n this.dotsEl.style.display = 'none';\n for (let i = 0; i < 3; i++) {\n const dot = document.createElement('div');\n dot.className = 'gk-dot';\n this.dotsEl.appendChild(dot);\n }\n this.transcript.appendChild(this.dotsEl);\n\n this.panel.appendChild(this.transcript);\n\n // Input area\n const inputArea = document.createElement('div');\n inputArea.className = 'gk-input-area';\n\n this.input = document.createElement('textarea');\n this.input.className = 'gk-input';\n this.input.placeholder = this.t('inputPlaceholder');\n this.input.setAttribute('aria-label', this.t('sendMessage'));\n this.input.rows = 1;\n inputArea.appendChild(this.input);\n\n this.sendBtn = document.createElement('button');\n this.sendBtn.className = 'gk-send-btn';\n this.sendBtn.setAttribute('aria-label', this.t('sendMessage'));\n this.sendBtn.innerHTML = SVG_SEND;\n inputArea.appendChild(this.sendBtn);\n\n this.panel.appendChild(inputArea);\n this.shadow.appendChild(this.panel);\n\n // FAB\n this.fab = document.createElement('button');\n this.fab.className = 'gk-fab';\n this.fab.setAttribute('aria-label', this.t('openAssistant'));\n this.fab.setAttribute('aria-expanded', 'false');\n this.fab.setAttribute('aria-haspopup', 'dialog');\n this.fab.innerHTML = SVG_CHAT;\n this.shadow.appendChild(this.fab);\n }\n\n private bindEvents(): void {\n this.fab.addEventListener('click', () => this.togglePanel(!this.isOpen));\n\n this.sendBtn.addEventListener('click', () => this.handleSend());\n\n this.input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.handleSend();\n }\n if (e.key === 'Escape') {\n this.togglePanel(false);\n this.fab.focus();\n }\n });\n }\n\n private togglePanel(open: boolean): void {\n this.isOpen = open;\n if (open) {\n this.panel.classList.add('gk-open');\n this.panel.setAttribute('aria-hidden', 'false');\n this.fab.setAttribute('aria-expanded', 'true');\n this.fab.innerHTML = SVG_CLOSE;\n this.fab.setAttribute('aria-label', this.t('closeAssistant'));\n setTimeout(() => this.input.focus(), 100);\n } else {\n this.panel.classList.remove('gk-open');\n this.panel.setAttribute('aria-hidden', 'true');\n this.fab.setAttribute('aria-expanded', 'false');\n this.fab.innerHTML = SVG_CHAT;\n this.fab.setAttribute('aria-label', this.t('openAssistant'));\n }\n }\n\n private async handleSend(): Promise<void> {\n const text = this.input.value.trim();\n if (!text || this.isSending) return;\n\n this.isSending = true;\n\n // Hide empty state\n this.emptyState.style.display = 'none';\n\n // Add user message\n this.addMessage('user', text);\n this.input.value = '';\n\n // Show processing dots\n this.dotsEl.style.display = 'flex';\n this.scrollToBottom();\n\n try {\n const response = await this.core.sendText(text);\n this.dotsEl.style.display = 'none';\n this.addMessage('assistant', response);\n } catch (err) {\n this.dotsEl.style.display = 'none';\n const msg = err instanceof Error ? err.message : 'Something went wrong.';\n this.addMessage('assistant', `Error: ${msg}`);\n } finally {\n this.isSending = false;\n }\n }\n\n private addMessage(role: 'user' | 'assistant', content: string): void {\n const el = document.createElement('div');\n el.className = `gk-msg gk-msg-${role}`;\n el.textContent = content;\n // Insert before the dots element\n this.transcript.insertBefore(el, this.dotsEl);\n this.scrollToBottom();\n }\n\n private scrollToBottom(): void {\n this.transcript.scrollTop = this.transcript.scrollHeight;\n }\n\n private t(key: string): string {\n try {\n return this.core.i18n.t(key as keyof I18nStrings) ?? key;\n } catch {\n return key;\n }\n }\n\n destroy(): void {\n this.host.remove();\n }\n}\n\n// ---------------------------------------------------------------------------\n// GuideKitVanilla — imperative wrapper around GuideKitCore\n// ---------------------------------------------------------------------------\n\nexport interface GuideKitVanillaOptions {\n tokenEndpoint?: string;\n stt?: GuideKitCoreOptions['stt'];\n tts?: GuideKitCoreOptions['tts'];\n llm?: GuideKitCoreOptions['llm'];\n agent?: GuideKitCoreOptions['agent'];\n contentMap?: GuideKitCoreOptions['contentMap'];\n options?: GuideKitCoreOptions['options'];\n instanceId?: string;\n rootElement?: HTMLElement;\n /** Disable the built-in widget UI (for headless use). */\n headless?: boolean;\n onError?: (error: GuideKitErrorType) => void;\n onEvent?: (event: GuideKitEvent) => void;\n onReady?: () => void;\n}\n\n/** Singleton state */\nlet _core: GuideKitCore | null = null;\nlet _widget: VanillaWidget | null = null;\nlet _initialized = false;\n\n/**\n * Initialize GuideKit. Must be called before any other methods.\n * Idempotent — calling multiple times is safe (returns existing instance).\n */\nexport async function init(options: GuideKitVanillaOptions): Promise<void> {\n if (_initialized && _core) return;\n\n _core = new GuideKitCore({\n tokenEndpoint: options.tokenEndpoint,\n stt: options.stt,\n tts: options.tts,\n llm: options.llm,\n agent: options.agent,\n contentMap: options.contentMap,\n options: options.options,\n instanceId: options.instanceId,\n rootElement: options.rootElement,\n onError: options.onError,\n onEvent: options.onEvent,\n onReady: options.onReady,\n });\n\n await _core.init();\n\n // Create widget unless headless\n if (!options.headless) {\n _widget = new VanillaWidget(_core);\n }\n\n _initialized = true;\n}\n\n/**\n * Send a text message to the assistant. Returns the response.\n */\nexport async function sendText(message: string): Promise<string> {\n assertInitialized();\n return _core!.sendText(message);\n}\n\n/**\n * Highlight an element on the page.\n */\nexport function highlight(params: {\n sectionId?: string;\n selector?: string;\n tooltip?: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n}): boolean {\n assertInitialized();\n return _core!.highlight(params);\n}\n\n/** Dismiss the current spotlight highlight. */\nexport function dismissHighlight(): void {\n assertInitialized();\n _core!.dismissHighlight();\n}\n\n/** Smooth scroll to a section by ID. */\nexport function scrollToSection(sectionId: string, offset?: number): void {\n assertInitialized();\n _core!.scrollToSection(sectionId, offset);\n}\n\n/** Start a guided tour. */\nexport function startTour(sectionIds: string[], mode?: 'auto' | 'manual'): void {\n assertInitialized();\n _core!.startTour(sectionIds, mode);\n}\n\n/** Stop the current tour. */\nexport function stopTour(): void {\n assertInitialized();\n _core!.stopTour();\n}\n\n/** Navigate to a URL (same-origin only). */\nexport async function navigate(href: string): Promise<boolean> {\n assertInitialized();\n return _core!.navigate(href);\n}\n\n/** Set developer page context for the LLM. */\nexport function setPageContext(context: Record<string, unknown>): void {\n assertInitialized();\n _core!.setPageContext(context);\n}\n\n/** Register a custom action the LLM can invoke. */\nexport function registerAction(\n actionId: string,\n action: {\n description: string;\n parameters: Record<string, unknown>;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n },\n): void {\n assertInitialized();\n _core!.registerAction(actionId, action);\n}\n\n/** Start voice input. */\nexport async function startListening(): Promise<void> {\n assertInitialized();\n await _core!.startListening();\n}\n\n/** Stop voice input. */\nexport function stopListening(): void {\n assertInitialized();\n _core!.stopListening();\n}\n\n/** Get current agent state. */\nexport function getAgentState(): AgentState {\n assertInitialized();\n return _core!.agentState;\n}\n\n/** Get current page model. */\nexport function getPageModel(): PageModel | null {\n assertInitialized();\n return _core!.pageModel;\n}\n\n/** Whether the SDK is ready. */\nexport function isReady(): boolean {\n return _core?.isReady ?? false;\n}\n\n/** Get/set quiet mode. */\nexport function getQuietMode(): boolean {\n assertInitialized();\n return _core!.quietMode;\n}\n\nexport function setQuietMode(value: boolean): void {\n assertInitialized();\n _core!.quietMode = value;\n}\n\n/** Check health of all connected services. */\nexport async function checkHealth(): Promise<HealthCheckResult> {\n assertInitialized();\n return _core!.checkHealth();\n}\n\n/** Destroy the instance and clean up. */\nexport async function destroy(): Promise<void> {\n if (_widget) {\n _widget.destroy();\n _widget = null;\n }\n if (_core) {\n await _core.destroy();\n _core = null;\n }\n _initialized = false;\n}\n\n/** Get the underlying GuideKitCore instance (escape hatch). */\nexport function getCore(): GuideKitCore | null {\n return _core;\n}\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nfunction assertInitialized(): void {\n if (!_core || !_initialized) {\n throw new Error(\n 'GuideKit not initialized. Call GuideKit.init({...}) first.',\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Version\n// ---------------------------------------------------------------------------\n\nexport const VERSION = '0.1.0-beta.2';\n","// ---------------------------------------------------------------------------\n// GuideKit SDK - Typed EventBus\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical map of every event in the GuideKit system.\n *\n * Keys use a `namespace:name` convention (except the top-level `error` event).\n * Values are the payload types that accompany each event.\n */\nexport interface EventMap {\n // -- DOM events -----------------------------------------------------------\n 'dom:scan-complete': { pageModel: unknown; durationMs: number };\n 'dom:mutation-detected': { mutations: number; debounced: boolean };\n 'dom:route-change': { from: string; to: string };\n\n // -- LLM events -----------------------------------------------------------\n 'llm:response-start': { conversationId: string };\n 'llm:response-chunk': { text: string; done: boolean };\n 'llm:response-end': { conversationId: string; totalTokens: number };\n 'llm:tool-call': { name: string; arguments: Record<string, unknown> };\n 'llm:token-usage': { prompt: number; completion: number; total: number };\n\n // -- Voice events ---------------------------------------------------------\n 'voice:state-change': { from: string; to: string };\n 'voice:transcript': { text: string; isFinal: boolean; confidence: number };\n 'voice:tts-start': { utterance: string };\n 'voice:tts-end': { utterance: string; durationMs: number };\n 'voice:degraded': { reason: string; fallback: 'text' };\n\n // -- Auth events ----------------------------------------------------------\n 'auth:token-refreshed': { expiresAt: number };\n 'auth:token-refresh-failed': { error: Error; attemptsRemaining: number };\n 'auth:token-expired': Record<string, never>;\n\n // -- Connectivity events --------------------------------------------------\n 'connectivity:state-change': {\n state: 'online' | 'degraded' | 'offline';\n previous: 'online' | 'degraded' | 'offline';\n };\n\n // -- Awareness events -----------------------------------------------------\n 'awareness:dwell': { sectionId: string; durationMs: number };\n 'awareness:idle': { durationMs: number };\n 'awareness:rage-click': { selector: string; clicks: number };\n 'awareness:section-visible': { sectionId: string; ratio: number };\n\n // -- Visual events --------------------------------------------------------\n 'visual:spotlight-shown': { selector: string; sectionId?: string };\n 'visual:spotlight-dismissed': Record<string, never>;\n 'visual:tour-step': {\n stepIndex: number;\n totalSteps: number;\n sectionId: string;\n };\n\n // -- Top-level error event ------------------------------------------------\n error: Error;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helper types\n// ---------------------------------------------------------------------------\n\n/** Handler for a concrete, known event key. */\ntype TypedHandler<K extends keyof EventMap> = (data: EventMap[K]) => void;\n\n/** Handler for a wildcard (namespace) subscription. */\ntype WildcardHandler = (data: unknown, eventName: string) => void;\n\n/** Discriminated wrapper so we can store both kinds in one map. */\ntype StoredHandler =\n | { kind: 'typed'; fn: TypedHandler<any> }\n | { kind: 'wildcard'; fn: WildcardHandler };\n\n// ---------------------------------------------------------------------------\n// EventBus\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Bus]';\n\nexport class EventBus {\n /** Per-event listeners. Wildcard keys end with `:*`. */\n private readonly listeners = new Map<string, StoredHandler[]>();\n\n /** Listeners registered via `onAny`. */\n private readonly anyListeners: WildcardHandler[] = [];\n\n /** When true, every `emit` is logged to the console. */\n private readonly debug: boolean;\n\n constructor(options?: { debug?: boolean }) {\n this.debug = options?.debug ?? false;\n }\n\n // ---- on (specific event) ------------------------------------------------\n\n /**\n * Subscribe to a specific typed event.\n *\n * @returns An unsubscribe function.\n */\n on<K extends keyof EventMap>(\n event: K,\n handler: (data: EventMap[K]) => void,\n ): () => void;\n\n /**\n * Subscribe to a namespace wildcard (e.g. `'dom:*'`).\n * The handler receives `(data, eventName)`.\n *\n * @returns An unsubscribe function.\n */\n on(\n event: `${string}:*`,\n handler: (data: unknown, eventName: string) => void,\n ): () => void;\n\n /** Unified implementation. */\n on(event: string, handler: (...args: any[]) => void): () => void {\n const isWildcard = event.endsWith(':*');\n const stored: StoredHandler = isWildcard\n ? { kind: 'wildcard', fn: handler as WildcardHandler }\n : { kind: 'typed', fn: handler as TypedHandler<any> };\n\n let list = this.listeners.get(event);\n if (!list) {\n list = [];\n this.listeners.set(event, list);\n }\n list.push(stored);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n const arr = this.listeners.get(event);\n if (!arr) return;\n const idx = arr.indexOf(stored);\n if (idx !== -1) arr.splice(idx, 1);\n if (arr.length === 0) this.listeners.delete(event);\n };\n }\n\n // ---- onAny --------------------------------------------------------------\n\n /**\n * Subscribe to **every** event emitted on the bus.\n *\n * @returns An unsubscribe function.\n */\n onAny(handler: (data: unknown, eventName: string) => void): () => void {\n this.anyListeners.push(handler);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n const idx = this.anyListeners.indexOf(handler);\n if (idx !== -1) this.anyListeners.splice(idx, 1);\n };\n }\n\n // ---- emit ---------------------------------------------------------------\n\n /**\n * Emit a typed event.\n *\n * Handlers are invoked synchronously in registration order. If a handler\n * throws, the error is logged and remaining handlers still execute.\n */\n emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void {\n if (this.debug) {\n console.log(LOG_PREFIX, event, data);\n }\n\n const eventKey = event as string;\n\n // 1. Exact-match listeners\n const exact = this.listeners.get(eventKey);\n if (exact) {\n // Snapshot to avoid issues if a handler adds/removes listeners\n const snapshot = exact.slice();\n for (const entry of snapshot) {\n this.invokeSafe(entry.fn, data, eventKey);\n }\n }\n\n // 2. Namespace wildcard listeners (e.g. \"dom:*\" matches \"dom:scan-complete\")\n const colonIdx = eventKey.indexOf(':');\n if (colonIdx !== -1) {\n const ns = eventKey.slice(0, colonIdx);\n const wildcardKey = `${ns}:*`;\n const wildcardList = this.listeners.get(wildcardKey);\n if (wildcardList) {\n const snapshot = wildcardList.slice();\n for (const entry of snapshot) {\n this.invokeSafe(entry.fn, data, eventKey);\n }\n }\n }\n\n // 3. `onAny` listeners\n if (this.anyListeners.length > 0) {\n const snapshot = this.anyListeners.slice();\n for (const fn of snapshot) {\n this.invokeSafe(fn, data, eventKey);\n }\n }\n }\n\n // ---- once ---------------------------------------------------------------\n\n /**\n * Subscribe to a specific event, automatically unsubscribing after the\n * first invocation.\n *\n * @returns An unsubscribe function (also cancels a not-yet-fired listener).\n */\n once<K extends keyof EventMap>(\n event: K,\n handler: (data: EventMap[K]) => void,\n ): () => void {\n const unsub = this.on(event, ((data: EventMap[K]) => {\n unsub();\n handler(data);\n }) as any);\n return unsub;\n }\n\n // ---- removeAll ----------------------------------------------------------\n\n /** Remove **all** listeners from the bus. */\n removeAll(): void {\n this.listeners.clear();\n this.anyListeners.length = 0;\n }\n\n // ---- listenerCount ------------------------------------------------------\n\n /**\n * Return the number of registered listeners.\n *\n * - If `event` is provided, returns the count for that specific event key\n * (including wildcard keys like `'dom:*'`).\n * - If omitted, returns the total across all events plus `onAny` listeners.\n */\n listenerCount(event?: string): number {\n if (event !== undefined) {\n return this.listeners.get(event)?.length ?? 0;\n }\n\n let total = this.anyListeners.length;\n for (const list of this.listeners.values()) {\n total += list.length;\n }\n return total;\n }\n\n // ---- private helpers ----------------------------------------------------\n\n /**\n * Invoke a handler inside a try/catch so one misbehaving handler never\n * prevents the remaining handlers from executing.\n */\n private invokeSafe(fn: (...args: any[]) => void, ...args: any[]): void {\n try {\n fn(...args);\n } catch (err) {\n console.error(\n LOG_PREFIX,\n 'Handler threw an error:',\n err,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new {@link EventBus} instance.\n *\n * ```ts\n * const bus = createEventBus({ debug: true });\n * const unsub = bus.on('dom:scan-complete', (data) => {\n * console.log(data.pageModel, data.durationMs);\n * });\n * bus.emit('dom:scan-complete', { pageModel: {}, durationMs: 42 });\n * unsub();\n * ```\n */\nexport function createEventBus(options?: { debug?: boolean }): EventBus {\n return new EventBus(options);\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Resource Lifecycle Manager\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Resources]';\n\n/** Timeout in milliseconds for each resource cleanup operation. */\nconst CLEANUP_TIMEOUT_MS = 2_000;\n\n// ---------------------------------------------------------------------------\n// Resource interface\n// ---------------------------------------------------------------------------\n\n/**\n * A disposable resource that the SDK tracks for deterministic cleanup.\n * Each resource has a unique name and a cleanup function that may be async.\n */\nexport interface Resource {\n name: string;\n cleanup: () => void | Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// ResourceManager\n// ---------------------------------------------------------------------------\n\n/** Lifecycle states for a ResourceManager instance. */\nexport type ResourceManagerState =\n | 'initializing'\n | 'ready'\n | 'tearing_down'\n | 'torn_down';\n\n/**\n * Manages the lifecycle of SDK resources (AbortControllers, event listeners,\n * WebSocket connections, etc.) and ensures deterministic cleanup on unmount.\n *\n * Resources are cleaned up sequentially — order matters because later\n * resources may depend on earlier ones still being alive during their own\n * cleanup phase.\n */\nexport class ResourceManager {\n readonly instanceId: string;\n\n private _state: ResourceManagerState = 'initializing';\n private readonly _resources: Map<string, Resource> = new Map();\n private _destroyPromise: Promise<void> | null = null;\n private _destroyCancelled = false;\n\n constructor(instanceId?: string) {\n this.instanceId = instanceId ?? generateId();\n debug(`Created ResourceManager \"${this.instanceId}\"`);\n }\n\n // -------------------------------------------------------------------------\n // State\n // -------------------------------------------------------------------------\n\n /** Current lifecycle state. */\n get state(): ResourceManagerState {\n return this._state;\n }\n\n /** Number of currently registered resources. */\n get resourceCount(): number {\n return this._resources.size;\n }\n\n // -------------------------------------------------------------------------\n // Registration\n // -------------------------------------------------------------------------\n\n /**\n * Register a resource for cleanup tracking.\n *\n * @throws If the manager has already been torn down.\n */\n register(resource: Resource): void {\n if (this._state === 'torn_down') {\n throw new Error(\n `${LOG_PREFIX} Cannot register resource \"${resource.name}\" — manager is torn down`,\n );\n }\n\n if (this._resources.has(resource.name)) {\n debug(\n `Replacing existing resource \"${resource.name}\" in \"${this.instanceId}\"`,\n );\n }\n\n this._resources.set(resource.name, resource);\n debug(\n `Registered \"${resource.name}\" in \"${this.instanceId}\" (total: ${this._resources.size})`,\n );\n }\n\n /**\n * Unregister a specific resource by name without invoking its cleanup.\n */\n unregister(name: string): void {\n const deleted = this._resources.delete(name);\n if (deleted) {\n debug(\n `Unregistered \"${name}\" from \"${this.instanceId}\" (total: ${this._resources.size})`,\n );\n }\n }\n\n // -------------------------------------------------------------------------\n // AbortController helper\n // -------------------------------------------------------------------------\n\n /**\n * Create a tracked AbortController. On destroy, its `abort()` method will\n * be called automatically.\n */\n createAbortController(name: string): AbortController {\n const controller = new AbortController();\n\n this.register({\n name,\n cleanup: () => {\n if (!controller.signal.aborted) {\n controller.abort();\n }\n },\n });\n\n return controller;\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle transitions\n // -------------------------------------------------------------------------\n\n /** Transition from `initializing` to `ready`. */\n markReady(): void {\n if (this._state === 'initializing') {\n this._state = 'ready';\n debug(`\"${this.instanceId}\" is now ready`);\n }\n }\n\n /**\n * Destroy all registered resources sequentially.\n *\n * Each resource gets up to {@link CLEANUP_TIMEOUT_MS}ms to complete.\n * If cleanup exceeds the timeout a warning is logged and the manager\n * proceeds to the next resource.\n *\n * After all resources are processed the state transitions to `torn_down`.\n * Calling `destroy()` multiple times returns the same promise.\n */\n async destroy(): Promise<void> {\n // Idempotent — return existing promise if already running / finished.\n if (this._destroyPromise) {\n return this._destroyPromise;\n }\n\n this._state = 'tearing_down';\n this._destroyCancelled = false;\n\n debug(\n `Destroying \"${this.instanceId}\" (${this._resources.size} resource(s))`,\n );\n\n this._destroyPromise = this._performDestroy();\n return this._destroyPromise;\n }\n\n /**\n * Cancel a pending destroy, transitioning back to `ready`.\n *\n * This exists to support React 18 StrictMode which unmounts then\n * immediately re-mounts components. If the re-mount arrives while\n * teardown is still in progress, cancelling prevents resource loss.\n *\n * @returns `true` if teardown was pending and has been cancelled.\n * `false` if already torn down or not currently tearing down.\n */\n cancelDestroy(): boolean {\n if (this._state !== 'tearing_down') {\n return false;\n }\n\n debug(`Cancelling destroy for \"${this.instanceId}\"`);\n this._destroyCancelled = true;\n this._state = 'ready';\n this._destroyPromise = null;\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Internal\n // -------------------------------------------------------------------------\n\n /** Sequential cleanup with per-resource timeout. */\n private async _performDestroy(): Promise<void> {\n // Snapshot the resource names so we iterate a stable list.\n const names = Array.from(this._resources.keys());\n\n for (const name of names) {\n // If cancelDestroy() was called mid-teardown, bail out early.\n if (this._destroyCancelled) {\n debug(\n `Destroy cancelled mid-teardown for \"${this.instanceId}\" — stopping cleanup`,\n );\n return;\n }\n\n const resource = this._resources.get(name);\n if (!resource) {\n continue;\n }\n\n try {\n /**\n * Cleanup timeout: logs warning but resolves promise regardless.\n * Resources may leak if cleanup takes longer than the timeout period.\n */\n await withTimeout(resource.cleanup(), CLEANUP_TIMEOUT_MS, () => {\n console.warn(\n `${LOG_PREFIX} Cleanup timeout for \"${name}\" (${CLEANUP_TIMEOUT_MS}ms)`,\n );\n });\n } catch (err) {\n console.warn(\n `${LOG_PREFIX} Cleanup error for \"${name}\":`,\n err,\n );\n }\n\n this._resources.delete(name);\n }\n\n // Only transition to torn_down if we were not cancelled.\n if (!this._destroyCancelled) {\n this._state = 'torn_down';\n debug(`\"${this.instanceId}\" is now torn down`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SingletonGuard – ref-counted singleton map\n// ---------------------------------------------------------------------------\n\ninterface GuardEntry {\n manager: ResourceManager;\n refCount: number;\n pendingDestroyTimer: ReturnType<typeof setTimeout> | null;\n}\n\n/**\n * Ref-counted singleton guard keyed by `instanceId`.\n *\n * - `acquire()` increments the ref count (or creates the manager).\n * - `release()` decrements the ref count. When it reaches 0 a\n * `setTimeout(0)` is scheduled to allow React StrictMode re-mount to\n * reclaim the instance before it is destroyed.\n * - If a mount arrives during `TEARING_DOWN`, the teardown is cancelled\n * and the manager transitions back to `READY`.\n */\nexport class SingletonGuard {\n private static readonly _entries: Map<string, GuardEntry> = new Map();\n\n /**\n * Acquire (or create) a ResourceManager for the given instanceId.\n *\n * @param instanceId Unique identifier for the singleton slot.\n * @param factory Called to create a fresh ResourceManager when none\n * exists or the previous one has been torn down.\n */\n static acquire(\n instanceId: string,\n factory: () => ResourceManager,\n ): ResourceManager {\n const existing = SingletonGuard._entries.get(instanceId);\n\n if (existing) {\n // Cancel any pending deferred destruction.\n if (existing.pendingDestroyTimer !== null) {\n clearTimeout(existing.pendingDestroyTimer);\n existing.pendingDestroyTimer = null;\n debug(`Cleared pending destroy timer for \"${instanceId}\"`);\n }\n\n // If the manager is mid-teardown, cancel it.\n if (existing.manager.state === 'tearing_down') {\n const cancelled = existing.manager.cancelDestroy();\n if (cancelled) {\n debug(\n `Re-acquired \"${instanceId}\" — cancelled in-flight teardown`,\n );\n }\n }\n\n // If the previous manager was fully torn down, replace it.\n if (existing.manager.state === 'torn_down') {\n debug(\n `Previous manager for \"${instanceId}\" is torn down — creating new one`,\n );\n const manager = factory();\n SingletonGuard._entries.set(instanceId, {\n manager,\n refCount: 1,\n pendingDestroyTimer: null,\n });\n return manager;\n }\n\n existing.refCount += 1;\n debug(\n `Acquired \"${instanceId}\" (refCount: ${existing.refCount})`,\n );\n return existing.manager;\n }\n\n // First acquisition — create a new entry.\n const manager = factory();\n SingletonGuard._entries.set(instanceId, {\n manager,\n refCount: 1,\n pendingDestroyTimer: null,\n });\n debug(`Created new singleton for \"${instanceId}\"`);\n return manager;\n }\n\n /**\n * Release a reference to the manager. When the ref count drops to 0 a\n * `setTimeout(0)` delay is introduced before destruction so that React\n * StrictMode's synchronous re-mount can reclaim the instance.\n */\n static release(instanceId: string): void {\n const entry = SingletonGuard._entries.get(instanceId);\n if (!entry) {\n debug(`Release called for unknown instanceId \"${instanceId}\"`);\n return;\n }\n\n entry.refCount = Math.max(0, entry.refCount - 1);\n debug(`Released \"${instanceId}\" (refCount: ${entry.refCount})`);\n\n if (entry.refCount === 0) {\n // Defer destruction so StrictMode re-mount can reclaim.\n entry.pendingDestroyTimer = setTimeout(() => {\n entry.pendingDestroyTimer = null;\n\n // Double-check nobody re-acquired in the meantime.\n if (entry.refCount > 0) {\n return;\n }\n\n debug(`Destroying singleton \"${instanceId}\" (refCount is 0)`);\n entry.manager.destroy().then(() => {\n // Only remove from the map if it is still the same entry and\n // the manager successfully tore down.\n if (\n SingletonGuard._entries.get(instanceId) === entry &&\n entry.manager.state === 'torn_down'\n ) {\n SingletonGuard._entries.delete(instanceId);\n debug(`Removed singleton entry for \"${instanceId}\"`);\n }\n });\n }, 0);\n }\n }\n\n /**\n * Retrieve a manager by instanceId without affecting the ref count.\n * Returns `undefined` if no manager exists for the given id.\n */\n static get(instanceId: string): ResourceManager | undefined {\n return SingletonGuard._entries.get(instanceId)?.manager;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Race a (possibly async) operation against a timeout.\n * If the timeout wins, `onTimeout` is called and the function resolves\n * (it does **not** reject — the next resource should still be processed).\n */\nfunction withTimeout(\n work: void | Promise<void>,\n ms: number,\n onTimeout: () => void,\n): Promise<void> {\n // Synchronous cleanup — no timeout needed.\n if (!(work instanceof Promise)) {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve) => {\n let settled = false;\n\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n onTimeout();\n resolve();\n }\n }, ms);\n\n work.then(\n () => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n resolve();\n }\n },\n (err) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n // Re-throw so the caller's catch block can log it.\n // We wrap in a rejected promise to keep the signature clean.\n resolve(Promise.reject(err));\n }\n },\n );\n });\n}\n\n/** Simple random ID generator (no crypto dependency required). */\nfunction generateId(): string {\n return `gk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/** Conditional debug logging — only logs when globalThis has a truthy `__GUIDEKIT_DEBUG__` flag. */\nfunction debug(...args: unknown[]): void {\n if (\n typeof globalThis !== 'undefined' &&\n (globalThis as Record<string, unknown>).__GUIDEKIT_DEBUG__\n ) {\n console.debug(LOG_PREFIX, ...args);\n }\n}\n","/**\n * @module @guidekit/core/dom\n *\n * DOM intelligence engine for the GuideKit SDK.\n * Scans the current page and builds a structured PageModel that serves as\n * grounding context for the LLM on every turn.\n *\n * Key design decisions:\n * - SSR-safe: every browser API is guarded behind `typeof document/window`.\n * - Privacy-first: password fields and PII patterns are never captured.\n * - Budget-constrained: hard limits on node count and tree depth prevent\n * runaway scans on large pages.\n * - Mutation-resilient: MutationObserver is throttled and circuit-broken.\n */\n\nimport type {\n PageModel,\n PageSection,\n NavItem,\n InteractiveElement,\n FormSummary,\n FormField,\n OverlayElement,\n ScanMetadata,\n} from '../types/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_MAX_NODES = 5000;\nconst DEFAULT_MAX_SECTIONS = 20;\nconst DEFAULT_MAX_DEPTH = 15;\n\nconst MUTATION_DEBOUNCE_MS = 500;\nconst MUTATION_CIRCUIT_BREAKER_THRESHOLD = 100; // mutations per second\nconst CIRCUIT_BREAKER_COOLDOWN_MS = 2000;\nconst MIN_RESCAN_INTERVAL_MS = 2000;\n\nconst LOG_PREFIX = '[GuideKit:DOM]';\n\n/** Semantic tags that qualify as sections without additional attributes. */\nconst SECTION_TAGS = new Set([\n 'SECTION',\n 'ARTICLE',\n 'MAIN',\n 'ASIDE',\n 'HEADER',\n 'FOOTER',\n 'NAV',\n]);\n\n/** Tags that map to landmark roles for scoring. */\nconst LANDMARK_TAG_MAP: Record<string, string> = {\n HEADER: 'banner',\n FOOTER: 'contentinfo',\n NAV: 'navigation',\n MAIN: 'main',\n ASIDE: 'complementary',\n};\n\n/** Interactive element selectors. */\nconst INTERACTIVE_SELECTOR =\n 'button, a[href], input, select, textarea, [role=\"button\"], [role=\"link\"], [tabindex]';\n\n/** Tags whose text value must never be captured. */\nconst SENSITIVE_INPUT_TYPES = new Set(['password', 'tel', 'email']);\n\n/** PII regex patterns stripped from text content. */\nconst PII_PATTERNS: RegExp[] = [\n // Email addresses\n /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g,\n // US phone numbers (various formats)\n /(\\+?1[-.\\s]?)?(\\(?\\d{3}\\)?[-.\\s]?)?\\d{3}[-.\\s]?\\d{4}/g,\n // SSN\n /\\b\\d{3}[-]?\\d{2}[-]?\\d{4}\\b/g,\n // Credit card numbers (basic)\n /\\b(?:\\d[ -]*?){13,19}\\b/g,\n];\n\n// ---------------------------------------------------------------------------\n// Utility helpers\n// ---------------------------------------------------------------------------\n\n/** Simple string hash (djb2). */\nfunction djb2Hash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/** Strip PII from a string. */\nfunction stripPII(text: string): string {\n let result = text;\n for (const pattern of PII_PATTERNS) {\n // Reset lastIndex for global regexps that are reused\n pattern.lastIndex = 0;\n result = result.replace(pattern, '[REDACTED]');\n }\n return result;\n}\n\n/** Truncate a string to a max length, adding ellipsis if needed. */\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max).trimEnd() + '\\u2026';\n}\n\n/** Collapse whitespace in a string. */\nfunction collapseWhitespace(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n\n/** Get visible text content from an element, limited in length. */\nfunction getTextContent(el: Element, maxLen: number = 200): string {\n const raw = el.textContent ?? '';\n return stripPII(truncate(collapseWhitespace(raw), maxLen));\n}\n\n/** Check whether an element is visible in the layout sense (not IntersectionObserver). */\nfunction isElementVisible(el: Element): boolean {\n if (typeof window === 'undefined') return false;\n const style = window.getComputedStyle(el);\n return (\n style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0'\n );\n}\n\n/** Get an accessible label for an element. */\nfunction getAccessibleLabel(el: Element): string {\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n const ariaLabelledBy = el.getAttribute('aria-labelledby');\n if (ariaLabelledBy && typeof document !== 'undefined') {\n const labelEl = document.getElementById(ariaLabelledBy);\n if (labelEl) return collapseWhitespace(labelEl.textContent ?? '');\n }\n\n return '';\n}\n\n/** Request idle callback with fallback. */\nfunction scheduleIdle(cb: () => void): void {\n if (typeof window !== 'undefined' && 'requestIdleCallback' in window) {\n (window as unknown as { requestIdleCallback: (cb: () => void) => void }).requestIdleCallback(cb);\n } else if (typeof setTimeout !== 'undefined') {\n setTimeout(cb, 0);\n } else {\n cb();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Selector builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build a stable CSS selector for an element following the priority hierarchy:\n * 1. data-guidekit-target\n * 2. id\n * 3. data-testid\n * 4. aria-label\n * 5. Structural path fallback\n */\nfunction buildSelector(el: Element): string {\n // 1. GuideKit target (highest priority)\n const guideKitTarget = el.getAttribute('data-guidekit-target');\n if (guideKitTarget) {\n return `[data-guidekit-target=\"${guideKitTarget}\"]`;\n }\n\n // 2. ID\n const id = el.id;\n if (id && typeof document !== 'undefined') {\n // Verify uniqueness\n try {\n const matches = document.querySelectorAll(`#${CSS.escape(id)}`);\n if (matches.length === 1) {\n return `#${CSS.escape(id)}`;\n }\n } catch {\n // CSS.escape may not be available; fall through\n }\n }\n\n // 3. data-testid\n const testId = el.getAttribute('data-testid');\n if (testId) {\n return `[data-testid=\"${testId}\"]`;\n }\n\n // 4. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) {\n return `[aria-label=\"${ariaLabel}\"]`;\n }\n\n // 5. Structural path fallback\n return buildStructuralPath(el);\n}\n\n/** Build a structural CSS selector path from root to the element. */\nfunction buildStructuralPath(el: Element): string {\n const parts: string[] = [];\n let current: Element | null = el;\n\n while (current && current !== document.documentElement) {\n const tag = current.tagName.toLowerCase();\n\n if (tag === 'body' || tag === 'html') {\n parts.unshift(tag);\n current = current.parentElement;\n continue;\n }\n\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c) => c.tagName === current!.tagName,\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n parts.unshift(`${tag}:nth-child(${index})`);\n } else {\n parts.unshift(tag);\n }\n } else {\n parts.unshift(tag);\n }\n\n current = parent;\n }\n\n return parts.join(' > ');\n}\n\n// ---------------------------------------------------------------------------\n// Section ID generation\n// ---------------------------------------------------------------------------\n\nlet sectionCounter = 0;\n\nfunction generateSectionId(el: Element): string {\n const guideKitTarget = el.getAttribute('data-guidekit-target');\n if (guideKitTarget) return guideKitTarget;\n\n const id = el.id;\n if (id) return id;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) {\n return ariaLabel\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n }\n\n sectionCounter += 1;\n return `section-${sectionCounter}`;\n}\n\n// ---------------------------------------------------------------------------\n// DOMScanner\n// ---------------------------------------------------------------------------\n\nexport interface DOMScannerOptions {\n rootElement?: HTMLElement;\n debug?: boolean;\n maxNodes?: number;\n maxSections?: number;\n maxDepth?: number;\n}\n\nexport class DOMScanner {\n private readonly root: HTMLElement | null;\n private readonly debug: boolean;\n private readonly maxNodes: number;\n private readonly maxSections: number;\n private readonly maxDepth: number;\n\n private cachedModel: PageModel | null = null;\n\n // Visibility tracking (updated via IntersectionObserver)\n private visibilityMap: Map<Element, number> = new Map();\n\n // MutationObserver state\n private observer: MutationObserver | null = null;\n private mutationCount = 0;\n private mutationWindowStart = 0;\n private circuitBroken = false;\n private circuitBrokenTimer: ReturnType<typeof setTimeout> | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private lastScanTime = 0;\n\n constructor(options?: DOMScannerOptions) {\n const isBrowser =\n typeof document !== 'undefined' && typeof window !== 'undefined';\n\n this.root = options?.rootElement ?? (isBrowser ? document.body : null);\n this.debug = options?.debug ?? false;\n this.maxNodes = options?.maxNodes ?? DEFAULT_MAX_NODES;\n this.maxSections = options?.maxSections ?? DEFAULT_MAX_SECTIONS;\n this.maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;\n\n this.log('Initialised', {\n root: this.root?.tagName,\n maxNodes: this.maxNodes,\n maxSections: this.maxSections,\n maxDepth: this.maxDepth,\n });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Perform a full scan and return a PageModel. */\n scan(): PageModel {\n if (typeof document === 'undefined' || typeof window === 'undefined') {\n this.log('SSR environment detected, returning empty model');\n return this.emptyModel();\n }\n\n if (!this.root) {\n this.log('No root element available, returning empty model');\n return this.emptyModel();\n }\n\n this.log('Starting scan');\n const startTime = performance.now();\n\n // Reset section counter per scan\n sectionCounter = 0;\n\n let nodesScanned = 0;\n let budgetExhausted = false;\n\n // Phase 1: Walk DOM and collect candidate section elements\n const candidateSections: Array<{ el: Element; depth: number }> = [];\n const allElements: Element[] = [];\n\n const walker = document.createTreeWalker(\n this.root,\n NodeFilter.SHOW_ELEMENT,\n {\n acceptNode: (node: Node): number => {\n const el = node as Element;\n\n // Skip guidekit-ignore subtrees\n if (el.hasAttribute('data-guidekit-ignore')) {\n return NodeFilter.FILTER_REJECT;\n }\n\n // Budget check\n if (nodesScanned >= this.maxNodes) {\n budgetExhausted = true;\n return NodeFilter.FILTER_REJECT;\n }\n\n nodesScanned++;\n return NodeFilter.FILTER_ACCEPT;\n },\n },\n );\n\n // Walk the tree\n let currentNode = walker.nextNode();\n while (currentNode) {\n const el = currentNode as Element;\n allElements.push(el);\n\n // Check if this is a candidate section\n const depth = this.getDepth(el);\n if (depth <= this.maxDepth && this.isSectionCandidate(el)) {\n candidateSections.push({ el, depth });\n }\n\n currentNode = walker.nextNode();\n }\n\n this.log(`Walked ${nodesScanned} nodes, found ${candidateSections.length} section candidates`);\n\n // Phase 2: Extract page data\n const sections = this.extractSections(candidateSections);\n const navigation = this.extractNavigation();\n const interactiveElements = this.extractInteractiveElements();\n const forms = this.extractForms();\n const activeOverlays = this.extractOverlays();\n const meta = this.extractMeta();\n\n const scanMetadata: ScanMetadata = {\n totalSectionsFound: candidateSections.length,\n sectionsIncluded: sections.length,\n totalNodesScanned: nodesScanned,\n scanBudgetExhausted: budgetExhausted,\n };\n\n const model: PageModel = {\n url: window.location.href,\n title: document.title ?? '',\n meta,\n sections,\n navigation,\n interactiveElements,\n forms,\n activeOverlays,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n orientation:\n window.innerWidth >= window.innerHeight ? 'landscape' : 'portrait',\n },\n allSectionsSummary: sections.map(\n (s) => `[${s.label}] ${s.summary}`,\n ),\n hash: '',\n timestamp: Date.now(),\n scanMetadata,\n };\n\n // Generate hash from key model content\n model.hash = this.generateHash(model);\n\n this.cachedModel = model;\n\n const elapsed = (performance.now() - startTime).toFixed(1);\n this.log(`Scan complete in ${elapsed}ms`, {\n sections: sections.length,\n navItems: navigation.length,\n interactive: interactiveElements.length,\n forms: forms.length,\n overlays: activeOverlays.length,\n nodesScanned,\n budgetExhausted,\n });\n\n return model;\n }\n\n /**\n * Set up a MutationObserver that rescans on DOM changes.\n * Returns a cleanup function to disconnect the observer.\n */\n observe(callback: (model: PageModel) => void): () => void {\n if (typeof MutationObserver === 'undefined' || !this.root) {\n this.log('MutationObserver not available or no root');\n return () => {};\n }\n\n this.log('Starting observation');\n\n const handleMutations = (_mutations: MutationRecord[]) => {\n const now = Date.now();\n\n // --- Circuit breaker ---\n if (now - this.mutationWindowStart > 1000) {\n // New one-second window\n this.mutationCount = _mutations.length;\n this.mutationWindowStart = now;\n } else {\n this.mutationCount += _mutations.length;\n }\n\n if (this.mutationCount > MUTATION_CIRCUIT_BREAKER_THRESHOLD) {\n if (!this.circuitBroken) {\n this.circuitBroken = true;\n this.log('Circuit breaker tripped — pausing observation');\n\n // Disconnect temporarily\n this.observer?.disconnect();\n\n this.circuitBrokenTimer = setTimeout(() => {\n this.circuitBroken = false;\n this.mutationCount = 0;\n this.log('Circuit breaker reset — resuming observation');\n this.startObserving();\n this.triggerRescan(callback);\n }, CIRCUIT_BREAKER_COOLDOWN_MS);\n }\n return;\n }\n\n // --- Debounce ---\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n }\n\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.triggerRescan(callback);\n }, MUTATION_DEBOUNCE_MS);\n };\n\n this.observer = new MutationObserver(handleMutations);\n this.startObserving();\n\n // Return cleanup function\n return () => {\n this.log('Stopping observation');\n this.cleanup();\n };\n }\n\n /** Update visibility data from an IntersectionObserver. */\n updateVisibility(entries: IntersectionObserverEntry[]): void {\n for (const entry of entries) {\n this.visibilityMap.set(entry.target, entry.intersectionRatio);\n }\n }\n\n /** Get the current cached page model. */\n get currentModel(): PageModel | null {\n return this.cachedModel;\n }\n\n // -------------------------------------------------------------------------\n // Private: Observation helpers\n // -------------------------------------------------------------------------\n\n private startObserving(): void {\n if (!this.observer || !this.root) return;\n\n this.observer.observe(this.root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\n 'class',\n 'style',\n 'hidden',\n 'aria-hidden',\n 'aria-label',\n 'role',\n 'data-guidekit-target',\n 'data-guidekit-ignore',\n 'disabled',\n ],\n });\n }\n\n private triggerRescan(callback: (model: PageModel) => void): void {\n const now = Date.now();\n if (now - this.lastScanTime < MIN_RESCAN_INTERVAL_MS) {\n this.log('Rescan throttled');\n return;\n }\n\n this.lastScanTime = now;\n\n scheduleIdle(() => {\n const model = this.scan();\n callback(model);\n });\n }\n\n private cleanup(): void {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n if (this.circuitBrokenTimer !== null) {\n clearTimeout(this.circuitBrokenTimer);\n this.circuitBrokenTimer = null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Section extraction\n // -------------------------------------------------------------------------\n\n private isSectionCandidate(el: Element): boolean {\n const tag = el.tagName;\n\n // Semantic section tags\n if (SECTION_TAGS.has(tag)) return true;\n\n // Divs or other elements with role, aria-label, or id\n if (\n el.getAttribute('role') ||\n el.getAttribute('aria-label') ||\n el.id\n ) {\n return true;\n }\n\n return false;\n }\n\n private extractSections(\n candidates: Array<{ el: Element; depth: number }>,\n ): PageSection[] {\n const scored: PageSection[] = [];\n\n for (const { el, depth } of candidates) {\n const section = this.buildPageSection(el, depth);\n scored.push(section);\n }\n\n // Sort by score descending\n scored.sort((a, b) => b.score - a.score);\n\n // Take top N\n return scored.slice(0, this.maxSections);\n }\n\n private buildPageSection(el: Element, depth: number): PageSection {\n const tag = el.tagName;\n const selector = buildSelector(el);\n\n // Determine label\n const label = this.getSectionLabel(el);\n\n // Get summary from first ~100 chars of text\n const summary = getTextContent(el, 100);\n\n // Check visibility\n const visRatio = this.visibilityMap.get(el) ?? 0;\n const isVisible = visRatio > 0 || this.isInViewport(el);\n\n // Check for interactive elements\n const hasInteractive =\n el.querySelector(INTERACTIVE_SELECTOR) !== null;\n\n // Determine landmark\n const landmark = this.getLandmark(el);\n\n // Has heading?\n const hasHeading = el.querySelector('h1, h2, h3, h4, h5, h6') !== null;\n\n // Score\n const score = this.scoreSection({\n isVisible,\n hasInteractive,\n landmark,\n hasHeading,\n depth,\n el,\n });\n\n return {\n id: generateSectionId(el),\n selector,\n tagName: tag.toLowerCase(),\n label,\n summary,\n isVisible,\n visibilityRatio: visRatio,\n score,\n landmark: landmark ?? undefined,\n hasInteractiveElements: hasInteractive,\n depth,\n };\n }\n\n private getSectionLabel(el: Element): string {\n // 1. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n // 2. First heading\n const heading = el.querySelector('h1, h2, h3, h4, h5, h6');\n if (heading) {\n const text = collapseWhitespace(heading.textContent ?? '');\n if (text) return stripPII(truncate(text, 80));\n }\n\n // 3. id as fallback\n if (el.id) return el.id;\n\n // 4. Tag name\n return el.tagName.toLowerCase();\n }\n\n private getLandmark(el: Element): string | null {\n // Explicit role\n const role = el.getAttribute('role');\n if (role) return role;\n\n // Implicit landmark via tag\n const implicit = LANDMARK_TAG_MAP[el.tagName];\n if (implicit) return implicit;\n\n // section/article with aria-label count as landmarks\n if (\n (el.tagName === 'SECTION' || el.tagName === 'ARTICLE') &&\n el.getAttribute('aria-label')\n ) {\n return el.tagName === 'SECTION' ? 'region' : 'article';\n }\n\n return null;\n }\n\n private scoreSection(params: {\n isVisible: boolean;\n hasInteractive: boolean;\n landmark: string | null;\n hasHeading: boolean;\n depth: number;\n el: Element;\n }): number {\n let score = 0;\n\n if (params.isVisible) score += 100;\n if (params.hasInteractive) score += 20;\n if (params.landmark) score += 15;\n\n // Near scroll position\n if (typeof window !== 'undefined') {\n const rect = params.el.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n if (\n rect.top >= -viewportHeight &&\n rect.top <= viewportHeight * 2\n ) {\n score += 10;\n }\n }\n\n if (params.hasHeading) score += 5;\n\n // Depth penalty\n score -= params.depth * 2;\n\n return score;\n }\n\n // -------------------------------------------------------------------------\n // Private: Navigation extraction\n // -------------------------------------------------------------------------\n\n private extractNavigation(): NavItem[] {\n if (typeof document === 'undefined') return [];\n\n const navElements = this.root?.querySelectorAll('nav') ?? [];\n const items: NavItem[] = [];\n\n navElements.forEach((nav) => {\n if (nav.hasAttribute('data-guidekit-ignore')) return;\n\n const links = nav.querySelectorAll('a[href]');\n links.forEach((link) => {\n const anchor = link as HTMLAnchorElement;\n const label = collapseWhitespace(anchor.textContent ?? '');\n if (!label) return;\n\n const href = anchor.getAttribute('href') ?? '';\n const isCurrent =\n anchor.getAttribute('aria-current') === 'page' ||\n anchor.classList.contains('active') ||\n (typeof window !== 'undefined' && anchor.href === window.location.href);\n\n items.push({\n label: stripPII(truncate(label, 60)),\n href,\n isCurrent,\n selector: buildSelector(anchor),\n });\n });\n });\n\n return items;\n }\n\n // -------------------------------------------------------------------------\n // Private: Interactive elements extraction\n // -------------------------------------------------------------------------\n\n private extractInteractiveElements(): InteractiveElement[] {\n if (typeof document === 'undefined' || !this.root) return [];\n\n const elements = this.root.querySelectorAll(INTERACTIVE_SELECTOR);\n const result: InteractiveElement[] = [];\n\n elements.forEach((el) => {\n // Skip elements inside ignored subtrees\n if (el.closest('[data-guidekit-ignore]')) return;\n\n const htmlEl = el as HTMLElement;\n const tag = el.tagName.toLowerCase();\n const type = el.getAttribute('type') ?? undefined;\n\n // Skip sensitive input types — never capture their labels from value/placeholder\n const isSensitive =\n tag === 'input' && SENSITIVE_INPUT_TYPES.has(type ?? '');\n\n // Get label\n let label = getAccessibleLabel(el);\n if (!label && !isSensitive) {\n label = collapseWhitespace(el.textContent ?? '');\n }\n if (!label) {\n const placeholder = el.getAttribute('placeholder');\n if (placeholder && !isSensitive) {\n label = placeholder;\n }\n }\n if (!label && el.getAttribute('title')) {\n label = el.getAttribute('title') ?? '';\n }\n if (!label && isSensitive) {\n label = type ?? 'input';\n }\n label = stripPII(truncate(label, 60));\n\n const role = el.getAttribute('role') ?? undefined;\n const isDisabled =\n htmlEl.hasAttribute('disabled') ||\n htmlEl.getAttribute('aria-disabled') === 'true';\n const guideKitTarget =\n el.getAttribute('data-guidekit-target') ?? undefined;\n\n result.push({\n selector: buildSelector(el),\n tagName: tag,\n type,\n label,\n role,\n isDisabled,\n guideKitTarget,\n });\n });\n\n return result;\n }\n\n // -------------------------------------------------------------------------\n // Private: Form extraction\n // -------------------------------------------------------------------------\n\n private extractForms(): FormSummary[] {\n if (typeof document === 'undefined' || !this.root) return [];\n\n const formElements = this.root.querySelectorAll('form');\n const result: FormSummary[] = [];\n\n formElements.forEach((form) => {\n if (form.closest('[data-guidekit-ignore]')) return;\n\n const fields = this.extractFormFields(form);\n const hasValidationErrors = fields.some((f) => f.hasError);\n\n result.push({\n selector: buildSelector(form),\n id: form.id || undefined,\n action: form.action || undefined,\n fields,\n hasValidationErrors,\n });\n });\n\n return result;\n }\n\n private extractFormFields(form: HTMLFormElement): FormField[] {\n const fields: FormField[] = [];\n const fieldElements = form.querySelectorAll(\n 'input, select, textarea',\n );\n\n fieldElements.forEach((el) => {\n const input = el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n const name = input.name || input.id || '';\n const type =\n el.tagName === 'SELECT'\n ? 'select'\n : el.tagName === 'TEXTAREA'\n ? 'textarea'\n : (el as HTMLInputElement).type || 'text';\n\n // Find label\n let label = '';\n if (input.id && typeof document !== 'undefined') {\n const labelEl = document.querySelector(\n `label[for=\"${CSS.escape(input.id)}\"]`,\n );\n if (labelEl) {\n label = collapseWhitespace(labelEl.textContent ?? '');\n }\n }\n if (!label) {\n // Check for wrapping label\n const parentLabel = input.closest('label');\n if (parentLabel) {\n label = collapseWhitespace(parentLabel.textContent ?? '');\n }\n }\n if (!label) {\n label = getAccessibleLabel(el);\n }\n if (!label) {\n const placeholder = el.getAttribute('placeholder');\n label = placeholder ?? name;\n }\n label = stripPII(truncate(label, 60));\n\n // Required?\n const isRequired =\n input.hasAttribute('required') ||\n input.getAttribute('aria-required') === 'true';\n\n // Validation error\n const hasError =\n input.getAttribute('aria-invalid') === 'true' ||\n (input instanceof HTMLInputElement && !input.validity.valid && input.value !== '');\n\n let errorMessage: string | undefined;\n const errorId = input.getAttribute('aria-errormessage') ?? input.getAttribute('aria-describedby');\n if (hasError && errorId && typeof document !== 'undefined') {\n const errorEl = document.getElementById(errorId);\n if (errorEl) {\n errorMessage = collapseWhitespace(errorEl.textContent ?? '');\n }\n }\n if (hasError && !errorMessage && input instanceof HTMLInputElement) {\n errorMessage = input.validationMessage || undefined;\n }\n\n fields.push({\n selector: buildSelector(el),\n name,\n type,\n label,\n isRequired,\n hasError,\n errorMessage,\n });\n });\n\n return fields;\n }\n\n // -------------------------------------------------------------------------\n // Private: Overlay detection\n // -------------------------------------------------------------------------\n\n private extractOverlays(): OverlayElement[] {\n if (typeof document === 'undefined' || typeof window === 'undefined' || !this.root) {\n return [];\n }\n\n const result: OverlayElement[] = [];\n\n // 1. Elements with explicit dialog roles\n const dialogElements = this.root.querySelectorAll(\n '[role=\"dialog\"], [role=\"alertdialog\"], dialog',\n );\n dialogElements.forEach((el) => {\n if (el.closest('[data-guidekit-ignore]')) return;\n const label = getAccessibleLabel(el) || getTextContent(el, 40) || 'dialog';\n result.push({\n selector: buildSelector(el),\n type: 'modal',\n label: stripPII(label),\n isVisible: isElementVisible(el),\n });\n });\n\n // 2. Common modal patterns: high z-index + fixed/absolute positioning\n const allElements = this.root.querySelectorAll('*');\n const seen = new Set<Element>(dialogElements);\n\n allElements.forEach((el) => {\n if (seen.has(el)) return;\n if (el.closest('[data-guidekit-ignore]')) return;\n\n const style = window.getComputedStyle(el);\n const position = style.position;\n const zIndex = parseInt(style.zIndex, 10) || 0;\n\n if (\n (position === 'fixed' || position === 'absolute') &&\n !isNaN(zIndex) &&\n zIndex >= 1000\n ) {\n const visible = isElementVisible(el);\n if (!visible) return;\n\n // Determine overlay type heuristically\n const overlayType = this.classifyOverlay(el, style);\n if (!overlayType) return;\n\n const label =\n getAccessibleLabel(el) || getTextContent(el, 40) || overlayType;\n\n result.push({\n selector: buildSelector(el),\n type: overlayType,\n label: stripPII(label),\n isVisible: visible,\n });\n }\n });\n\n return result;\n }\n\n private classifyOverlay(\n el: Element,\n style: CSSStyleDeclaration,\n ): OverlayElement['type'] | null {\n const role = el.getAttribute('role');\n if (role === 'dialog' || role === 'alertdialog') return 'modal';\n if (role === 'menu' || role === 'listbox') return 'dropdown';\n\n // Check class names for hints\n const className = el.className?.toString?.() ?? '';\n const lower = className.toLowerCase();\n\n if (lower.includes('modal') || lower.includes('dialog')) return 'modal';\n if (lower.includes('drawer') || lower.includes('sidebar')) return 'drawer';\n if (\n lower.includes('dropdown') ||\n lower.includes('menu') ||\n lower.includes('popover')\n )\n return 'dropdown';\n\n // Fixed elements covering large area are likely modals\n const width = parseFloat(style.width);\n const height = parseFloat(style.height);\n if (\n typeof window !== 'undefined' &&\n !isNaN(width) &&\n !isNaN(height) &&\n width > window.innerWidth * 0.5 &&\n height > window.innerHeight * 0.5\n ) {\n return 'modal';\n }\n\n // Small positioned element is likely a popover\n if (!isNaN(width) && width < 400) return 'popover';\n\n return null;\n }\n\n // -------------------------------------------------------------------------\n // Private: Meta extraction\n // -------------------------------------------------------------------------\n\n private extractMeta(): PageModel['meta'] {\n if (typeof document === 'undefined') {\n return { description: '', h1: null, language: 'en' };\n }\n\n const descMeta = document.querySelector('meta[name=\"description\"]');\n const description = descMeta?.getAttribute('content') ?? '';\n\n const h1El = document.querySelector('h1');\n const h1 = h1El ? stripPII(collapseWhitespace(h1El.textContent ?? '')) : null;\n\n const language =\n document.documentElement.getAttribute('lang') ?? 'en';\n\n return {\n description: stripPII(description),\n h1,\n language,\n };\n }\n\n // -------------------------------------------------------------------------\n // Private: Helpers\n // -------------------------------------------------------------------------\n\n private getDepth(el: Element): number {\n let depth = 0;\n let current: Element | null = el;\n const root = this.root;\n\n while (current && current !== root && depth < this.maxDepth + 1) {\n current = current.parentElement;\n depth++;\n }\n\n return depth;\n }\n\n private isInViewport(el: Element): boolean {\n if (typeof window === 'undefined') return false;\n try {\n const rect = el.getBoundingClientRect();\n return (\n rect.top < window.innerHeight &&\n rect.bottom > 0 &&\n rect.left < window.innerWidth &&\n rect.right > 0\n );\n } catch {\n return false;\n }\n }\n\n private generateHash(model: PageModel): string {\n // Hash key structural content for change detection\n const content = [\n model.url,\n model.title,\n model.meta.h1 ?? '',\n model.sections.map((s) => `${s.id}:${s.label}`).join(','),\n model.navigation.map((n) => n.href).join(','),\n model.interactiveElements.length.toString(),\n model.forms.length.toString(),\n model.activeOverlays.length.toString(),\n ].join('|');\n\n return djb2Hash(content);\n }\n\n private emptyModel(): PageModel {\n return {\n url: typeof window !== 'undefined' ? window.location.href : '',\n title: typeof document !== 'undefined' ? document.title ?? '' : '',\n meta: { description: '', h1: null, language: 'en' },\n sections: [],\n navigation: [],\n interactiveElements: [],\n forms: [],\n activeOverlays: [],\n viewport: { width: 0, height: 0, orientation: 'portrait' },\n allSectionsSummary: [],\n hash: '',\n timestamp: Date.now(),\n scanMetadata: {\n totalSectionsFound: 0,\n sectionsIncluded: 0,\n totalNodesScanned: 0,\n scanBudgetExhausted: false,\n },\n };\n }\n\n private log(message: string, data?: Record<string, unknown>): void {\n if (!this.debug) return;\n if (typeof console !== 'undefined') {\n if (data) {\n console.log(`${LOG_PREFIX} ${message}`, data);\n } else {\n console.log(`${LOG_PREFIX} ${message}`);\n }\n }\n }\n}\n","/**\n * @module @guidekit/core/context\n *\n * Context manager for the GuideKit SDK.\n * Assembles the LLM system prompt from the current page model, manages\n * conversation history with automatic eviction, resolves content-map entries,\n * and persists session state across page navigations via sessionStorage.\n */\n\nimport type {\n PageModel,\n ConversationTurn,\n ContentMapInput,\n ContentMap,\n ContentMapEntry,\n AgentConfig,\n ToolDefinition,\n SessionState,\n} from '../types/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst SESSION_STORAGE_KEY = 'guidekit:session';\nconst DEFAULT_MAX_TURNS = 20;\nconst DEFAULT_MAX_SESSION_SIZE_BYTES = 50_000; // 50 KB\nconst DEFAULT_TOKEN_BUDGET = 6_000; // ~1 500 tokens\nconst CONTENT_MAP_TIMEOUT_MS = 2_000;\nconst CONTENT_CACHE_TTL_MS = 30_000; // 30 seconds\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Measure byte-length of a string in UTF-8. */\nfunction byteLength(str: string): number {\n if (typeof TextEncoder !== 'undefined') {\n return new TextEncoder().encode(str).byteLength;\n }\n // Fallback for environments without TextEncoder (unlikely in modern runtimes)\n let bytes = 0;\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n if (code <= 0x7f) bytes += 1;\n else if (code <= 0x7ff) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdfff) {\n bytes += 4;\n i++; // surrogate pair\n } else bytes += 3;\n }\n return bytes;\n}\n\n/** Race a promise against a timeout, returning `null` on timeout. */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T | null> {\n return new Promise<T | null>((resolve) => {\n let settled = false;\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n resolve(null);\n }\n }, ms);\n\n promise\n .then((value) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n resolve(value);\n }\n })\n .catch(() => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n resolve(null);\n }\n });\n });\n}\n\n/** Check whether sessionStorage is available (SSR-safe). */\nfunction hasSessionStorage(): boolean {\n try {\n return (\n typeof window !== 'undefined' &&\n typeof window.sessionStorage !== 'undefined'\n );\n } catch {\n // In some environments, accessing sessionStorage itself can throw (e.g. sandboxed iframes).\n return false;\n }\n}\n\n/** Truncate a string to a maximum character count, appending an ellipsis if trimmed. */\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + '\\u2026';\n}\n\n// ---------------------------------------------------------------------------\n// Content cache entry\n// ---------------------------------------------------------------------------\n\ninterface CachedContent {\n entry: ContentMapEntry | null;\n expiresAt: number;\n}\n\n// ---------------------------------------------------------------------------\n// ContextManager\n// ---------------------------------------------------------------------------\n\nexport interface ContextManagerOptions {\n agent?: AgentConfig;\n contentMap?: ContentMapInput;\n maxTurns?: number;\n maxSessionSizeBytes?: number;\n tokenBudget?: number;\n debug?: boolean;\n}\n\nexport class ContextManager {\n private agent: AgentConfig;\n private contentMap: ContentMapInput | undefined;\n private maxTurns: number;\n private maxSessionSizeBytes: number;\n private tokenBudget: number;\n private debug: boolean;\n\n private history: ConversationTurn[] = [];\n private contentCache: Map<string, CachedContent> = new Map();\n\n // Session preferences (persisted across navigations)\n private _userPreference: 'voice' | 'text' = 'text';\n private _quietMode = false;\n private _pageContext: Record<string, unknown> = {};\n\n constructor(options?: ContextManagerOptions) {\n this.agent = options?.agent ?? {};\n this.contentMap = options?.contentMap;\n this.maxTurns = options?.maxTurns ?? DEFAULT_MAX_TURNS;\n this.maxSessionSizeBytes =\n options?.maxSessionSizeBytes ?? DEFAULT_MAX_SESSION_SIZE_BYTES;\n this.tokenBudget = options?.tokenBudget ?? DEFAULT_TOKEN_BUDGET;\n this.debug = options?.debug ?? false;\n }\n\n // -------------------------------------------------------------------------\n // System prompt\n // -------------------------------------------------------------------------\n\n /**\n * Build the full system prompt from the current page model and available\n * tools. The output is capped at `tokenBudget` characters so it fits\n * comfortably inside the LLM context window alongside conversation history.\n */\n buildSystemPrompt(pageModel: PageModel, tools: ToolDefinition[]): string {\n const parts: string[] = [];\n\n // -- Role ----------------------------------------------------------------\n parts.push(this.buildRoleSection());\n\n // -- Current Page --------------------------------------------------------\n parts.push(this.buildCurrentPageSection(pageModel));\n\n // -- Page Sections -------------------------------------------------------\n parts.push(this.buildPageSectionsSection(pageModel));\n\n // -- Navigation ----------------------------------------------------------\n if (pageModel.navigation.length > 0) {\n parts.push(this.buildNavigationSection(pageModel));\n }\n\n // -- Interactive Elements ------------------------------------------------\n if (pageModel.interactiveElements.length > 0) {\n parts.push(this.buildInteractiveElementsSection(pageModel));\n }\n\n // -- Forms ---------------------------------------------------------------\n if (pageModel.forms.length > 0) {\n parts.push(this.buildFormsSection(pageModel));\n }\n\n // -- User Viewport -------------------------------------------------------\n parts.push(this.buildViewportSection(pageModel));\n\n // -- Available Actions ---------------------------------------------------\n if (tools.length > 0) {\n parts.push(this.buildToolsSection(tools));\n }\n\n // -- Developer Context ---------------------------------------------------\n const pageCtxKeys = Object.keys(this._pageContext);\n if (pageCtxKeys.length > 0) {\n parts.push(this.buildPageContextSection());\n }\n\n // -- Guidelines ----------------------------------------------------------\n parts.push(this.buildGuidelinesSection());\n\n // Join and enforce budget\n let prompt = parts.join('\\n\\n');\n if (prompt.length > this.tokenBudget) {\n prompt = this.trimPromptToBudget(prompt, pageModel, tools);\n }\n\n return prompt;\n }\n\n // -------------------------------------------------------------------------\n // Conversation history\n // -------------------------------------------------------------------------\n\n /** Append a turn to the conversation history, enforcing size constraints. */\n addTurn(turn: ConversationTurn): void {\n this.history.push(turn);\n this.enforceHistoryLimits();\n }\n\n /** Return a copy of the current conversation history. */\n getHistory(): ConversationTurn[] {\n return this.history.slice();\n }\n\n /** Clear all conversation history. */\n clearHistory(): void {\n this.history = [];\n }\n\n // -------------------------------------------------------------------------\n // Content map\n // -------------------------------------------------------------------------\n\n /**\n * Resolve a `ContentMapEntry` for the given `sectionId`.\n *\n * - Static maps are looked up directly.\n * - Function-based maps are called with a 2-second timeout.\n * - Results are cached for 30 seconds per section ID.\n */\n async getContent(sectionId: string): Promise<ContentMapEntry | null> {\n // Check cache first\n const cached = this.contentCache.get(sectionId);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.entry;\n }\n\n if (this.contentMap === undefined) {\n return null;\n }\n\n let entry: ContentMapEntry | null;\n\n if (typeof this.contentMap === 'function') {\n try {\n const result = this.contentMap(sectionId);\n if (result instanceof Promise) {\n entry = await withTimeout(result, CONTENT_MAP_TIMEOUT_MS);\n } else {\n entry = result;\n }\n } catch (err) {\n this.log('Content map function threw for sectionId:', sectionId, err);\n entry = null;\n }\n } else {\n // Static Record<string, ContentMapEntry>\n entry = (this.contentMap as ContentMap)[sectionId] ?? null;\n }\n\n // Cache the result\n this.contentCache.set(sectionId, {\n entry,\n expiresAt: Date.now() + CONTENT_CACHE_TTL_MS,\n });\n\n return entry;\n }\n\n /** Replace the content map used for section lookups. Clears the cache. */\n setContentMap(contentMap: ContentMapInput): void {\n this.contentMap = contentMap;\n this.contentCache.clear();\n }\n\n // -------------------------------------------------------------------------\n // Session preferences\n // -------------------------------------------------------------------------\n\n get userPreference(): 'voice' | 'text' {\n return this._userPreference;\n }\n\n set userPreference(value: 'voice' | 'text') {\n this._userPreference = value;\n }\n\n get quietMode(): boolean {\n return this._quietMode;\n }\n\n set quietMode(value: boolean) {\n this._quietMode = value;\n }\n\n // -------------------------------------------------------------------------\n // Page context (dynamic context injection)\n // -------------------------------------------------------------------------\n\n /** Set developer-supplied page context (merged into system prompt). */\n setPageContext(context: Record<string, unknown>): void {\n this._pageContext = { ...this._pageContext, ...context };\n this.log('Page context updated', Object.keys(context));\n }\n\n /** Get the current page context. */\n getPageContext(): Record<string, unknown> {\n return { ...this._pageContext };\n }\n\n /** Clear all page context. */\n clearPageContext(): void {\n this._pageContext = {};\n }\n\n // -------------------------------------------------------------------------\n // Session persistence\n // -------------------------------------------------------------------------\n\n /** Persist the current session state to `sessionStorage`. */\n saveSession(): void {\n if (!hasSessionStorage()) return;\n\n const state = this.getSessionState();\n try {\n window.sessionStorage.setItem(\n SESSION_STORAGE_KEY,\n JSON.stringify(state),\n );\n } catch (err) {\n this.log('Failed to save session:', err);\n }\n }\n\n /** Restore a previously persisted session from `sessionStorage`. */\n restoreSession(): SessionState | null {\n if (!hasSessionStorage()) return null;\n\n try {\n const raw = window.sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) return null;\n\n const state = JSON.parse(raw) as SessionState;\n\n // Validate minimal shape\n if (\n !Array.isArray(state.conversationHistory) ||\n typeof state.currentUrl !== 'string'\n ) {\n this.log('Invalid session state, discarding.');\n return null;\n }\n\n // Restore conversation history\n this.history = state.conversationHistory;\n this.enforceHistoryLimits();\n\n // Restore preferences\n if (state.userPreference === 'voice' || state.userPreference === 'text') {\n this._userPreference = state.userPreference;\n }\n if (typeof state.quietMode === 'boolean') {\n this._quietMode = state.quietMode;\n }\n\n return state;\n } catch (err) {\n this.log('Failed to restore session:', err);\n return null;\n }\n }\n\n /** Build the current session state snapshot. */\n getSessionState(): SessionState {\n const serialised = JSON.stringify(this.history);\n const currentUrl =\n typeof window !== 'undefined' ? window.location.href : '';\n\n return {\n conversationHistory: this.history,\n currentUrl,\n agentStatus: 'idle',\n userPreference: this._userPreference,\n quietMode: this._quietMode,\n totalSizeBytes: byteLength(serialised),\n };\n }\n\n // -------------------------------------------------------------------------\n // Private — prompt section builders\n // -------------------------------------------------------------------------\n\n private buildRoleSection(): string {\n const name = this.agent.name || 'GuideKit';\n const personality =\n this.agent.personality ||\n 'You help users understand and navigate the site.';\n return `# Role\\nYou are ${name}, an AI guide embedded on this website.\\n${personality}`;\n }\n\n private buildCurrentPageSection(pageModel: PageModel): string {\n const lines = ['# Current Page'];\n lines.push(`URL: ${pageModel.url}`);\n lines.push(`Title: ${pageModel.title}`);\n if (pageModel.meta.description) {\n lines.push(`Description: ${pageModel.meta.description}`);\n }\n lines.push(`Language: ${pageModel.meta.language}`);\n return lines.join('\\n');\n }\n\n private buildPageSectionsSection(pageModel: PageModel): string {\n const { sectionsIncluded, totalSectionsFound } = pageModel.scanMetadata;\n const lines = [\n `# Page Sections (${sectionsIncluded} of ${totalSectionsFound})`,\n ];\n\n for (const section of pageModel.sections) {\n const vis = section.isVisible ? 'visible' : 'hidden';\n lines.push(\n `- [${section.id}] ${section.label}: ${truncate(section.summary, 120)} (${vis})`,\n );\n }\n\n if (sectionsIncluded < totalSectionsFound) {\n lines.push(\n `\\nNote: You see ${sectionsIncluded} of ${totalSectionsFound} sections. Use readPageContent to access more.`,\n );\n }\n\n return lines.join('\\n');\n }\n\n private buildNavigationSection(pageModel: PageModel): string {\n const lines = ['# Navigation'];\n for (const nav of pageModel.navigation) {\n const current = nav.isCurrent ? ' (current)' : '';\n lines.push(`- ${nav.label}: ${nav.href}${current}`);\n }\n return lines.join('\\n');\n }\n\n private buildInteractiveElementsSection(pageModel: PageModel): string {\n const lines = ['# Interactive Elements'];\n for (const el of pageModel.interactiveElements) {\n const disabled = el.isDisabled ? ' [disabled]' : '';\n lines.push(\n `- ${el.tagName}${el.type ? `[${el.type}]` : ''}: ${el.label}${disabled} (${el.selector})`,\n );\n }\n return lines.join('\\n');\n }\n\n private buildFormsSection(pageModel: PageModel): string {\n const lines = ['# Forms'];\n for (const form of pageModel.forms) {\n const formId = form.id ? ` id=\"${form.id}\"` : '';\n const errors = form.hasValidationErrors ? ' [has errors]' : '';\n lines.push(`- <form${formId}>${errors}`);\n for (const field of form.fields) {\n const req = field.isRequired ? ' *' : '';\n const err = field.hasError\n ? ` [error: ${field.errorMessage || 'invalid'}]`\n : '';\n lines.push(\n ` - ${field.label || field.name} (${field.type})${req}${err}`,\n );\n }\n }\n return lines.join('\\n');\n }\n\n private buildViewportSection(pageModel: PageModel): string {\n const { width, height, orientation } = pageModel.viewport;\n return `# User Viewport\\n${width}x${height}, ${orientation}`;\n }\n\n private buildToolsSection(tools: ToolDefinition[]): string {\n const lines = ['# Available Actions'];\n for (const tool of tools) {\n lines.push(`- ${tool.name}: ${tool.description}`);\n }\n return lines.join('\\n');\n }\n\n private buildPageContextSection(): string {\n const lines = ['# Developer Context'];\n for (const [key, value] of Object.entries(this._pageContext)) {\n const valStr =\n typeof value === 'string'\n ? value\n : JSON.stringify(value);\n lines.push(`- ${key}: ${truncate(String(valStr), 200)}`);\n }\n return lines.join('\\n');\n }\n\n private buildGuidelinesSection(): string {\n return [\n '# Guidelines',\n '- Always reference specific sections by their ID when guiding users',\n '- Use highlight() to point at elements you are discussing',\n '- Use scrollToSection() before highlighting offscreen elements',\n '- Never make up information not present in the page context',\n '- If asked about content you cannot see, use readPageContent to access it',\n '- Keep responses concise — 2-3 sentences unless the user asks for detail',\n ].join('\\n');\n }\n\n // -------------------------------------------------------------------------\n // Private — prompt trimming\n // -------------------------------------------------------------------------\n\n /**\n * When the assembled prompt exceeds the budget, progressively trim\n * lower-priority sections to fit.\n */\n private trimPromptToBudget(\n _fullPrompt: string,\n pageModel: PageModel,\n tools: ToolDefinition[],\n ): string {\n // Rebuild with trimming strategies applied in priority order:\n // 1. Truncate interactive elements list\n // 2. Truncate navigation list\n // 3. Truncate forms\n // 4. Truncate page sections\n\n const essentialParts: string[] = [\n this.buildRoleSection(),\n this.buildCurrentPageSection(pageModel),\n this.buildViewportSection(pageModel),\n this.buildGuidelinesSection(),\n ];\n\n if (tools.length > 0) {\n essentialParts.push(this.buildToolsSection(tools));\n }\n\n const essentialLength = essentialParts.reduce(\n (sum, p) => sum + p.length + 2,\n 0,\n );\n let remaining = this.tokenBudget - essentialLength;\n\n const optionalSections: string[] = [];\n\n // Page sections — highest priority optional section\n const sectionsStr = this.buildPageSectionsSection(pageModel);\n if (sectionsStr.length <= remaining) {\n optionalSections.push(sectionsStr);\n remaining -= sectionsStr.length + 2;\n } else if (remaining > 100) {\n optionalSections.push(truncate(sectionsStr, remaining));\n remaining = 0;\n }\n\n // Navigation\n if (remaining > 0 && pageModel.navigation.length > 0) {\n const navStr = this.buildNavigationSection(pageModel);\n if (navStr.length <= remaining) {\n optionalSections.push(navStr);\n remaining -= navStr.length + 2;\n } else if (remaining > 80) {\n optionalSections.push(truncate(navStr, remaining));\n remaining = 0;\n }\n }\n\n // Forms\n if (remaining > 0 && pageModel.forms.length > 0) {\n const formsStr = this.buildFormsSection(pageModel);\n if (formsStr.length <= remaining) {\n optionalSections.push(formsStr);\n remaining -= formsStr.length + 2;\n } else if (remaining > 80) {\n optionalSections.push(truncate(formsStr, remaining));\n remaining = 0;\n }\n }\n\n // Interactive elements\n if (remaining > 0 && pageModel.interactiveElements.length > 0) {\n const ieStr = this.buildInteractiveElementsSection(pageModel);\n if (ieStr.length <= remaining) {\n optionalSections.push(ieStr);\n } else if (remaining > 80) {\n optionalSections.push(truncate(ieStr, remaining));\n }\n }\n\n // Insert optional sections after current-page and before viewport\n const result = [\n essentialParts[0], // Role\n essentialParts[1], // Current Page\n ...optionalSections,\n essentialParts[2], // Viewport\n ...essentialParts.slice(3), // Tools + Guidelines\n ];\n\n return result.join('\\n\\n');\n }\n\n // -------------------------------------------------------------------------\n // Private — history management\n // -------------------------------------------------------------------------\n\n /**\n * Enforce `maxTurns` and `maxSessionSizeBytes` constraints on the\n * conversation history. When the history approaches 80% of `maxTurns`,\n * the oldest turns are summarised into a single recap turn.\n */\n private enforceHistoryLimits(): void {\n // -- Summarise when near capacity (>80% of maxTurns) --------------------\n const summariseThreshold = Math.floor(this.maxTurns * 0.8);\n if (this.history.length > summariseThreshold) {\n this.summariseOldestTurns();\n }\n\n // -- Hard cap on turn count ---------------------------------------------\n while (this.history.length > this.maxTurns) {\n this.history.shift();\n }\n\n // -- Enforce byte-size limit --------------------------------------------\n this.enforceByteLimit();\n }\n\n /**\n * Compress the oldest half of turns into a single recap turn so the\n * context window is used more efficiently.\n */\n private summariseOldestTurns(): void {\n if (this.history.length < 4) return; // Not enough to summarise\n\n const splitIndex = Math.floor(this.history.length / 2);\n const oldTurns = this.history.slice(0, splitIndex);\n const recentTurns = this.history.slice(splitIndex);\n\n // Build a compact recap from the old turns\n const recapLines: string[] = [];\n for (const turn of oldTurns) {\n const role = turn.role === 'user' ? 'User' : 'Assistant';\n recapLines.push(`${role}: ${truncate(turn.content, 150)}`);\n }\n\n const recapTurn: ConversationTurn = {\n role: 'assistant',\n content: `[Conversation recap]\\n${recapLines.join('\\n')}`,\n timestamp: oldTurns[oldTurns.length - 1]!.timestamp,\n };\n\n this.history = [recapTurn, ...recentTurns];\n }\n\n /** Evict oldest turns until the serialised history fits within the byte budget. */\n private enforceByteLimit(): void {\n while (this.history.length > 1) {\n const serialised = JSON.stringify(this.history);\n if (byteLength(serialised) <= this.maxSessionSizeBytes) break;\n this.history.shift();\n }\n }\n\n // -------------------------------------------------------------------------\n // Private — debug logging\n // -------------------------------------------------------------------------\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.debug('[GuideKit:ContextManager]', ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Error Hierarchy\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical error codes emitted by the SDK.\n * Keyed as `DOMAIN_DETAIL` so consumers can match on prefixes or exact values.\n */\nexport const ErrorCodes = {\n // Auth\n AUTH_INVALID_KEY: 'AUTH_INVALID_KEY',\n AUTH_EXPIRED_TOKEN: 'AUTH_EXPIRED_TOKEN',\n AUTH_TOKEN_REFRESH_FAILED: 'AUTH_TOKEN_REFRESH_FAILED',\n AUTH_ENDPOINT_FAILED: 'AUTH_ENDPOINT_FAILED',\n\n // Config\n CONFIG_INVALID_PROVIDER: 'CONFIG_INVALID_PROVIDER',\n CONFIG_MISSING_REQUIRED: 'CONFIG_MISSING_REQUIRED',\n\n // Init\n INIT_SHADOW_DOM_FAILED: 'INIT_SHADOW_DOM_FAILED',\n INIT_BROWSER_UNSUPPORTED: 'INIT_BROWSER_UNSUPPORTED',\n\n // Rate limit\n RATE_LIMIT_PROVIDER: 'RATE_LIMIT_PROVIDER',\n RATE_LIMIT_CLIENT: 'RATE_LIMIT_CLIENT',\n\n // Resources\n RESOURCE_EXHAUSTED_LLM: 'RESOURCE_EXHAUSTED_LLM',\n RESOURCE_EXHAUSTED_STT: 'RESOURCE_EXHAUSTED_STT',\n RESOURCE_EXHAUSTED_TTS: 'RESOURCE_EXHAUSTED_TTS',\n\n // Permission\n PERMISSION_MIC_DENIED: 'PERMISSION_MIC_DENIED',\n PERMISSION_MIC_UNAVAILABLE: 'PERMISSION_MIC_UNAVAILABLE',\n\n // Network\n NETWORK_WEBSOCKET_FAILED: 'NETWORK_WEBSOCKET_FAILED',\n NETWORK_CONNECTION_LOST: 'NETWORK_CONNECTION_LOST',\n NETWORK_TIMEOUT: 'NETWORK_TIMEOUT',\n\n // Timeout\n TIMEOUT_STT_CONNECT: 'TIMEOUT_STT_CONNECT',\n TIMEOUT_LLM_RESPONSE: 'TIMEOUT_LLM_RESPONSE',\n TIMEOUT_TTS_CONNECT: 'TIMEOUT_TTS_CONNECT',\n TIMEOUT_TTS_FIRST_AUDIO: 'TIMEOUT_TTS_FIRST_AUDIO',\n\n // Browser\n BROWSER_NO_WEB_AUDIO: 'BROWSER_NO_WEB_AUDIO',\n BROWSER_NO_WASM: 'BROWSER_NO_WASM',\n VAD_PACKAGE_MISSING: 'VAD_PACKAGE_MISSING',\n\n // Content\n CONTENT_FILTER_TRIGGERED: 'CONTENT_FILTER_TRIGGERED',\n\n // Privacy\n PRIVACY_HOOK_CANCELLED: 'PRIVACY_HOOK_CANCELLED',\n\n // General\n UNKNOWN: 'UNKNOWN',\n} as const;\n\n/** Union of every known error code string. */\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n// ---------------------------------------------------------------------------\n// Provider type\n// ---------------------------------------------------------------------------\n\nexport type Provider = 'deepgram' | 'elevenlabs' | 'gemini' | 'openai' | 'web-speech' | (string & {});\n\n// ---------------------------------------------------------------------------\n// Base options shared by every error constructor\n// ---------------------------------------------------------------------------\n\nexport interface GuideKitErrorOptions {\n code: string;\n message: string;\n provider?: Provider;\n recoverable: boolean;\n suggestion: string;\n docsUrl?: string;\n cause?: Error;\n}\n\n// ---------------------------------------------------------------------------\n// Base error class\n// ---------------------------------------------------------------------------\n\n/**\n * Root error for every failure surfaced by the GuideKit SDK.\n *\n * Every instance carries structured metadata so UI layers can present\n * actionable feedback without parsing message strings.\n */\nexport class GuideKitError extends Error {\n readonly code: string;\n readonly provider?: Provider;\n readonly recoverable: boolean;\n readonly suggestion: string;\n readonly docsUrl: string;\n\n constructor(options: GuideKitErrorOptions) {\n super(options.message, { cause: options.cause });\n\n // Fix the prototype chain so `instanceof` works correctly when\n // compiling to ES5 or when subclassing built-in Error.\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = 'GuideKitError';\n this.code = options.code;\n this.provider = options.provider;\n this.recoverable = options.recoverable;\n this.suggestion = options.suggestion;\n this.docsUrl =\n options.docsUrl ?? `https://guidekit.dev/docs/error-codes#${options.code}`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Specific error subclasses\n// ---------------------------------------------------------------------------\n\n/** Wrong or expired API key / token. */\nexport class AuthenticationError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'AuthenticationError';\n }\n}\n\n/** Invalid provider configuration supplied at init time. */\nexport class ConfigurationError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'ConfigurationError';\n }\n}\n\n/** SDK startup failure (Shadow DOM creation, browser too old, etc.). */\nexport class InitializationError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'InitializationError';\n }\n}\n\n/** Provider-side rate limit hit. Includes a retry hint. */\nexport class RateLimitError extends GuideKitError {\n readonly retryAfterMs: number;\n\n constructor(\n options: GuideKitErrorOptions & { retryAfterMs: number },\n ) {\n super({ ...options, recoverable: true });\n this.name = 'RateLimitError';\n this.retryAfterMs = options.retryAfterMs;\n }\n}\n\n/** Client-side cost / usage limits exhausted. */\nexport class ResourceExhaustedError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'ResourceExhaustedError';\n }\n}\n\n/** Microphone permission denied or device not available. */\nexport class PermissionError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'PermissionError';\n }\n}\n\n/** WebSocket dropped, HTTP connection failed, etc. */\nexport class NetworkError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: true, ...options });\n this.name = 'NetworkError';\n }\n}\n\n/** An operation exceeded its deadline. */\nexport class TimeoutError extends GuideKitError {\n readonly operationName: string;\n readonly timeoutMs: number;\n\n constructor(\n options: GuideKitErrorOptions & {\n operationName: string;\n timeoutMs: number;\n },\n ) {\n super({ ...options, recoverable: true });\n this.name = 'TimeoutError';\n this.operationName = options.operationName;\n this.timeoutMs = options.timeoutMs;\n }\n}\n\n/** Missing browser capability (Web Audio, WASM, VAD). */\nexport class BrowserSupportError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'BrowserSupportError';\n }\n}\n\n/** LLM safety / content filter triggered. */\nexport class ContentFilterError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'ContentFilterError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type guard\n// ---------------------------------------------------------------------------\n\n/**\n * Narrows an unknown caught value to `GuideKitError`.\n *\n * ```ts\n * try { ... } catch (err) {\n * if (isGuideKitError(err)) {\n * console.log(err.code, err.suggestion);\n * }\n * }\n * ```\n */\nexport function isGuideKitError(error: unknown): error is GuideKitError {\n return error instanceof GuideKitError;\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – OpenAI Adapter\n// ---------------------------------------------------------------------------\n\nimport type {\n LLMProviderAdapter,\n ToolDefinition,\n ToolCall,\n TextChunk,\n ConversationTurn,\n} from '../types/index.js';\n\nimport {\n AuthenticationError,\n RateLimitError,\n NetworkError,\n TimeoutError,\n ContentFilterError,\n ErrorCodes,\n} from '../errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_OPENAI_MODEL = 'gpt-4o';\nconst DEFAULT_TIMEOUT_MS = 15_000;\nconst OPENAI_CHAT_URL = 'https://api.openai.com/v1/chat/completions';\n\n// ---------------------------------------------------------------------------\n// Token usage helper\n// ---------------------------------------------------------------------------\n\ninterface TokenUsage {\n prompt: number;\n completion: number;\n total: number;\n}\n\nfunction emptyUsage(): TokenUsage {\n return { prompt: 0, completion: 0, total: 0 };\n}\n\n// ---------------------------------------------------------------------------\n// OpenAI adapter config\n// ---------------------------------------------------------------------------\n\n/** Configuration for the OpenAI adapter (custom adapter pattern). */\nexport interface OpenAIAdapterConfig {\n apiKey: string;\n model?: 'gpt-4o' | 'gpt-4o-mini' | (string & {});\n}\n\n// ---------------------------------------------------------------------------\n// OpenAIAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Adapter that translates between GuideKit's internal types and the\n * OpenAI Chat Completions API wire format. Handles streaming via SSE,\n * tool formatting, and response parsing.\n *\n * Usage as a custom adapter:\n * ```ts\n * import { OpenAIAdapter } from '@guidekit/core';\n * const llmConfig = { adapter: new OpenAIAdapter({ apiKey: '...', model: 'gpt-4o' }) };\n * ```\n */\nexport class OpenAIAdapter implements LLMProviderAdapter {\n private readonly apiKey: string;\n private readonly model: string;\n\n /** Tracks whether the last extractChunks call emitted a done chunk. */\n private lastExtractEmittedDone = false;\n\n /**\n * Token usage extracted from the most recent `parseResponse` call.\n * Updated as each SSE chunk is parsed.\n */\n private _lastUsage: TokenUsage = emptyUsage();\n\n constructor(config: OpenAIAdapterConfig) {\n this.apiKey = config.apiKey;\n this.model = config.model ?? DEFAULT_OPENAI_MODEL;\n }\n\n /** Token usage from the most recent parseResponse call. */\n get lastUsage(): TokenUsage {\n return this._lastUsage;\n }\n\n // -----------------------------------------------------------------------\n // LLMProviderAdapter implementation\n // -----------------------------------------------------------------------\n\n /**\n * Convert GuideKit tool definitions into OpenAI's `tools` format.\n * Each tool is wrapped as `{ type: 'function', function: { name, description, parameters } }`.\n */\n formatTools(tools: ToolDefinition[]): unknown {\n if (tools.length === 0) return undefined;\n\n return tools.map((tool) => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: { ...tool.parameters },\n required: tool.required ?? [],\n },\n },\n }));\n }\n\n /**\n * Convert an array of `ConversationTurn` objects into OpenAI's messages\n * format with `role: 'user' | 'assistant'`.\n */\n formatConversation(\n history: ConversationTurn[],\n ): Array<{ role: 'user' | 'assistant'; content: string }> {\n return history.map((turn) => ({\n role: turn.role,\n content: turn.content,\n }));\n }\n\n /**\n * Parse an OpenAI SSE streaming response into an async iterable of\n * `TextChunk` and `ToolCall` objects.\n *\n * The OpenAI streaming endpoint sends each chunk as a JSON object\n * prefixed by `data: `. The final line is `data: [DONE]`.\n * Text content arrives in `choices[0].delta.content` and tool calls\n * arrive in `choices[0].delta.tool_calls`.\n *\n * This method also:\n * - Detects content filtering and throws `ContentFilterError`.\n * - Tracks token usage (accessible via `lastUsage` after iteration).\n */\n async *parseResponse(\n stream: ReadableStream<Uint8Array>,\n ): AsyncIterable<TextChunk | ToolCall> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let doneEmitted = false;\n this._lastUsage = emptyUsage();\n\n // Accumulators for tool calls that arrive incrementally across chunks.\n const pendingToolCalls = new Map<\n number,\n { id: string; name: string; argumentsJson: string }\n >();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n // Keep the last (possibly incomplete) line in the buffer.\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // SSE lines that are not data payloads.\n if (!trimmed.startsWith('data:')) continue;\n\n const jsonStr = trimmed.slice(5).trim();\n if (jsonStr === '' || jsonStr === '[DONE]') {\n if (jsonStr === '[DONE]') {\n // Flush any accumulated tool calls.\n yield* this.flushPendingToolCalls(pendingToolCalls);\n if (!doneEmitted) {\n doneEmitted = true;\n yield { text: '', done: true } as TextChunk;\n }\n }\n continue;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(jsonStr) as Record<string, unknown>;\n } catch {\n // Malformed JSON chunk -- skip silently.\n continue;\n }\n\n // Check for content filtering — throws if blocked.\n if (this.isContentFiltered(parsed)) {\n throw new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message: 'Response was blocked by provider content safety filter.',\n provider: 'openai',\n suggestion: 'Rephrase your question or adjust safety settings.',\n });\n }\n\n // Track token usage.\n const chunkUsage = this.extractUsage(parsed);\n if (chunkUsage) {\n this._lastUsage = chunkUsage;\n }\n\n yield* this.extractChunks(parsed, pendingToolCalls, doneEmitted);\n if (!doneEmitted && this.lastExtractEmittedDone) {\n doneEmitted = true;\n }\n }\n }\n\n // Flush any remaining data in the buffer.\n if (buffer.trim().startsWith('data:')) {\n const jsonStr = buffer.trim().slice(5).trim();\n if (jsonStr === '[DONE]') {\n yield* this.flushPendingToolCalls(pendingToolCalls);\n if (!doneEmitted) {\n doneEmitted = true;\n yield { text: '', done: true } as TextChunk;\n }\n } else if (jsonStr !== '') {\n try {\n const parsed = JSON.parse(jsonStr) as Record<string, unknown>;\n\n if (this.isContentFiltered(parsed)) {\n throw new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message: 'Response was blocked by provider content safety filter.',\n provider: 'openai',\n suggestion: 'Rephrase your question or adjust safety settings.',\n });\n }\n\n const chunkUsage = this.extractUsage(parsed);\n if (chunkUsage) {\n this._lastUsage = chunkUsage;\n }\n\n yield* this.extractChunks(parsed, pendingToolCalls, doneEmitted);\n if (!doneEmitted && this.lastExtractEmittedDone) {\n doneEmitted = true;\n }\n } catch (error: unknown) {\n // Re-throw ContentFilterError, ignore other parse errors.\n if (error instanceof ContentFilterError) throw error;\n }\n }\n }\n\n // Flush any remaining tool calls that were not emitted.\n yield* this.flushPendingToolCalls(pendingToolCalls);\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Format a tool result so it can be sent back to OpenAI as a\n * `tool` role message with the `tool_call_id`.\n */\n formatToolResult(\n callId: string,\n result: unknown,\n ): { role: 'tool'; tool_call_id: string; content: string } {\n return {\n role: 'tool',\n tool_call_id: callId,\n content: typeof result === 'string' ? result : JSON.stringify(result),\n };\n }\n\n // -----------------------------------------------------------------------\n // Streaming request\n // -----------------------------------------------------------------------\n\n /**\n * Build and execute a streaming request to the OpenAI Chat Completions API.\n * Returns the raw `ReadableStream` for the response body together with\n * the raw Response object.\n */\n async streamRequest(params: {\n systemPrompt: string;\n contents: unknown;\n userMessage?: string;\n tools?: unknown;\n signal?: AbortSignal;\n timeoutMs?: number;\n }): Promise<{\n stream: ReadableStream<Uint8Array>;\n response: Response;\n }> {\n // Build the full messages array: system prompt + history + user message.\n const contentsArray = params.contents as Array<{ role: string; content: string }>;\n const messages: Array<{ role: string; content: string }> = [\n { role: 'system', content: params.systemPrompt },\n ...contentsArray,\n ];\n\n if (params.userMessage) {\n messages.push({ role: 'user', content: params.userMessage });\n }\n\n const body: Record<string, unknown> = {\n model: this.model,\n messages,\n stream: true,\n temperature: 0.7,\n top_p: 0.95,\n };\n\n if (params.tools) {\n body.tools = params.tools;\n }\n\n const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const controller = new AbortController();\n\n // Combine the external signal with our timeout signal.\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n if (params.signal) {\n // If the caller aborts, propagate to our controller.\n params.signal.addEventListener(\n 'abort',\n () => controller.abort(params.signal!.reason),\n { once: true },\n );\n }\n\n let response: Response;\n try {\n response = await fetch(OPENAI_CHAT_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n\n if (\n error instanceof DOMException &&\n error.name === 'AbortError'\n ) {\n // Distinguish caller abort from timeout.\n if (params.signal?.aborted) {\n throw error; // Re-throw caller abort as-is.\n }\n throw new TimeoutError({\n code: ErrorCodes.TIMEOUT_LLM_RESPONSE,\n message: `OpenAI request timed out after ${timeoutMs}ms`,\n provider: 'openai',\n recoverable: true,\n suggestion: 'Try again or increase the timeout.',\n operationName: 'openai.chatCompletions',\n timeoutMs,\n });\n }\n\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `Failed to connect to OpenAI API: ${(error as Error).message}`,\n provider: 'openai',\n suggestion:\n 'Check your network connection and try again.',\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n clearTimeout(timeoutId);\n\n // Handle HTTP-level errors.\n if (!response.ok) {\n await this.handleHttpError(response);\n }\n\n if (!response.body) {\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: 'OpenAI response body is null -- streaming unavailable.',\n provider: 'openai',\n suggestion: 'Retry the request.',\n });\n }\n\n return { stream: response.body, response };\n }\n\n // -----------------------------------------------------------------------\n // Internal helpers\n // -----------------------------------------------------------------------\n\n /**\n * Extract `TextChunk` and accumulate `ToolCall` data from a single parsed\n * OpenAI SSE JSON object.\n *\n * OpenAI tool calls arrive incrementally: the first chunk for a tool call\n * carries the `id` and `function.name`, while subsequent chunks append to\n * `function.arguments`. We accumulate these in `pendingToolCalls` and only\n * yield complete `ToolCall` objects when the finish_reason is 'tool_calls'\n * or when flushed.\n */\n private *extractChunks(\n parsed: Record<string, unknown>,\n pendingToolCalls: Map<\n number,\n { id: string; name: string; argumentsJson: string }\n >,\n doneEmitted: boolean,\n ): Generator<TextChunk | ToolCall> {\n this.lastExtractEmittedDone = false;\n\n const choices = parsed.choices as\n | Array<Record<string, unknown>>\n | undefined;\n\n if (!choices || choices.length === 0) return;\n\n for (const choice of choices) {\n const delta = choice.delta as Record<string, unknown> | undefined;\n const finishReason = choice.finish_reason as string | null | undefined;\n\n if (delta) {\n // Handle text content.\n if (typeof delta.content === 'string' && delta.content !== '') {\n yield {\n text: delta.content,\n done: false,\n } as TextChunk;\n }\n\n // Handle incremental tool calls.\n const toolCallDeltas = delta.tool_calls as\n | Array<{\n index: number;\n id?: string;\n function?: { name?: string; arguments?: string };\n }>\n | undefined;\n\n if (toolCallDeltas) {\n for (const tc of toolCallDeltas) {\n const existing = pendingToolCalls.get(tc.index);\n if (existing) {\n // Append to existing tool call.\n if (tc.function?.arguments) {\n existing.argumentsJson += tc.function.arguments;\n }\n } else {\n // Start a new tool call accumulation.\n pendingToolCalls.set(tc.index, {\n id: tc.id ?? '',\n name: tc.function?.name ?? '',\n argumentsJson: tc.function?.arguments ?? '',\n });\n }\n }\n }\n }\n\n // When finish_reason is 'tool_calls', flush the accumulated tool calls.\n if (finishReason === 'tool_calls') {\n yield* this.flushPendingToolCalls(pendingToolCalls);\n }\n\n // When finish_reason is 'stop', yield a done text chunk (once only).\n if (finishReason === 'stop' && !doneEmitted && !this.lastExtractEmittedDone) {\n this.lastExtractEmittedDone = true;\n yield { text: '', done: true } as TextChunk;\n }\n }\n }\n\n /**\n * Flush all accumulated pending tool calls as complete `ToolCall` objects.\n */\n private *flushPendingToolCalls(\n pendingToolCalls: Map<\n number,\n { id: string; name: string; argumentsJson: string }\n >,\n ): Generator<ToolCall> {\n // Sort by index to maintain order.\n const sorted = [...pendingToolCalls.entries()].sort(\n ([a], [b]) => a - b,\n );\n\n for (const [, tc] of sorted) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(tc.argumentsJson) as Record<string, unknown>;\n } catch (_e) {\n console.warn('[GuideKit:LLM] Failed to parse tool call arguments:', tc.argumentsJson);\n }\n\n yield {\n id: tc.id,\n name: tc.name,\n arguments: args,\n } as ToolCall;\n }\n\n pendingToolCalls.clear();\n }\n\n /**\n * Extract token usage from a parsed OpenAI response chunk.\n * Usage data typically appears in the final chunk when `stream_options`\n * includes `include_usage`, or in the non-streaming response.\n * Returns `null` if no usage data is present.\n */\n extractUsage(parsed: Record<string, unknown>): TokenUsage | null {\n const usage = parsed.usage as\n | {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n }\n | undefined;\n\n if (!usage) return null;\n\n return {\n prompt: usage.prompt_tokens ?? 0,\n completion: usage.completion_tokens ?? 0,\n total: usage.total_tokens ?? 0,\n };\n }\n\n /**\n * Check whether a parsed OpenAI chunk indicates the response was\n * blocked by a content filter.\n *\n * OpenAI signals content filtering through:\n * - `choices[].finish_reason === 'content_filter'`\n * - `choices[].content_filter_results` with `filtered: true`\n */\n isContentFiltered(parsed: Record<string, unknown>): boolean {\n const choices = parsed.choices as\n | Array<Record<string, unknown>>\n | undefined;\n\n if (!choices || choices.length === 0) return false;\n\n return choices.some((choice) => {\n // Check finish_reason.\n if (choice.finish_reason === 'content_filter') return true;\n\n // Check content_filter_results (Azure OpenAI style).\n const filterResults = choice.content_filter_results as\n | Record<string, { filtered?: boolean }>\n | undefined;\n\n if (filterResults) {\n return Object.values(filterResults).some((r) => r.filtered === true);\n }\n\n return false;\n });\n }\n\n /**\n * Translate an HTTP error response from OpenAI into the appropriate\n * GuideKit error class.\n */\n private async handleHttpError(response: Response): Promise<never> {\n let errorBody = '';\n try {\n errorBody = await response.text();\n } catch {\n // Ignore read failure.\n }\n\n const status = response.status;\n\n if (status === 401 || status === 403) {\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_INVALID_KEY,\n message: `OpenAI API authentication failed (${status}): ${errorBody}`,\n provider: 'openai',\n suggestion:\n 'Verify your OpenAI API key is correct and has not expired.',\n });\n }\n\n if (status === 429) {\n const retryAfterHeader = response.headers.get('retry-after');\n const retryAfterMs = retryAfterHeader\n ? parseInt(retryAfterHeader, 10) * 1000\n : 60_000;\n\n throw new RateLimitError({\n code: ErrorCodes.RATE_LIMIT_PROVIDER,\n message: `OpenAI API rate limit exceeded (429): ${errorBody}`,\n provider: 'openai',\n recoverable: true,\n suggestion: `Rate limited by OpenAI. Retry after ${Math.ceil(retryAfterMs / 1000)}s.`,\n retryAfterMs,\n });\n }\n\n if (status >= 500) {\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `OpenAI API server error (${status}): ${errorBody}`,\n provider: 'openai',\n suggestion:\n 'The OpenAI API is experiencing issues. Please try again later.',\n });\n }\n\n // Fallback for other 4xx errors.\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `OpenAI API request failed (${status}): ${errorBody}`,\n provider: 'openai',\n suggestion: 'Check the request parameters and try again.',\n });\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – LLM Orchestrator & Gemini Adapter\n// ---------------------------------------------------------------------------\n\nimport type {\n LLMConfig,\n LLMProviderAdapter,\n ToolDefinition,\n ToolCall,\n TextChunk,\n ConversationTurn,\n} from '../types/index.js';\n\nimport {\n AuthenticationError,\n RateLimitError,\n NetworkError,\n TimeoutError,\n ContentFilterError,\n ErrorCodes,\n} from '../errors/index.js';\n\nexport { OpenAIAdapter } from './openai-adapter.js';\nexport type { OpenAIAdapterConfig } from './openai-adapter.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_GEMINI_MODEL = 'gemini-2.5-flash';\nconst DEFAULT_TIMEOUT_MS = 15_000;\nconst GEMINI_BASE_URL =\n 'https://generativelanguage.googleapis.com/v1beta/models';\n\n/**\n * Gemini safety categories with their corresponding enum names.\n * We apply `BLOCK_ONLY_HIGH` to every category by default so the model\n * is usable for general-purpose assistance without over-blocking.\n */\nconst DEFAULT_SAFETY_SETTINGS = [\n { category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_ONLY_HIGH' },\n { category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_ONLY_HIGH' },\n { category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT', threshold: 'BLOCK_ONLY_HIGH' },\n { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' },\n];\n\n// ---------------------------------------------------------------------------\n// Token usage helper\n// ---------------------------------------------------------------------------\n\ninterface TokenUsage {\n prompt: number;\n completion: number;\n total: number;\n}\n\nfunction emptyUsage(): TokenUsage {\n return { prompt: 0, completion: 0, total: 0 };\n}\n\n// ---------------------------------------------------------------------------\n// GeminiAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Adapter that translates between GuideKit's internal types and the\n * Gemini REST API wire format. Handles streaming via SSE, tool formatting,\n * and response parsing.\n */\nexport class GeminiAdapter implements LLMProviderAdapter {\n private readonly apiKey: string;\n private readonly model: string;\n\n /**\n * Token usage extracted from the most recent `parseResponse` call.\n * Updated as each SSE chunk is parsed; the final value reflects the\n * cumulative usage metadata sent by Gemini (typically in the last chunk).\n */\n private _lastUsage: TokenUsage = emptyUsage();\n\n constructor(config: Extract<LLMConfig, { provider: 'gemini' }>) {\n this.apiKey = config.apiKey;\n this.model = config.model ?? DEFAULT_GEMINI_MODEL;\n }\n\n /** Token usage from the most recent parseResponse call. */\n get lastUsage(): TokenUsage {\n return this._lastUsage;\n }\n\n // -----------------------------------------------------------------------\n // LLMProviderAdapter implementation\n // -----------------------------------------------------------------------\n\n /**\n * Convert GuideKit tool definitions into Gemini's `functionDeclarations`\n * format, wrapped inside a `tools` array.\n */\n formatTools(tools: ToolDefinition[]): unknown {\n if (tools.length === 0) return undefined;\n\n return [\n {\n functionDeclarations: tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: { ...tool.parameters },\n required: tool.required ?? [],\n },\n })),\n },\n ];\n }\n\n /**\n * Convert an array of `ConversationTurn` objects into Gemini's `contents`\n * array with `role: 'user' | 'model'`.\n */\n formatConversation(\n history: ConversationTurn[],\n ): Array<{ role: string; parts: Array<{ text: string }> }> {\n return history.map((turn) => ({\n role: turn.role === 'assistant' ? 'model' : 'user',\n parts: [{ text: turn.content }],\n }));\n }\n\n /**\n * Parse a Gemini SSE streaming response into an async iterable of\n * `TextChunk` and `ToolCall` objects.\n *\n * The Gemini `streamGenerateContent?alt=sse` endpoint sends each chunk\n * as a JSON object prefixed by `data: `. We parse line-by-line, extract\n * text parts and function call parts, and yield the appropriate types.\n *\n * This method also:\n * - Detects content filtering and throws `ContentFilterError`.\n * - Tracks token usage (accessible via `lastUsage` after iteration).\n */\n async *parseResponse(\n stream: ReadableStream<Uint8Array>,\n ): AsyncIterable<TextChunk | ToolCall> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n this._lastUsage = emptyUsage();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n // Keep the last (possibly incomplete) line in the buffer.\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // SSE lines that are not data payloads.\n if (!trimmed.startsWith('data:')) continue;\n\n const jsonStr = trimmed.slice(5).trim();\n if (jsonStr === '' || jsonStr === '[DONE]') continue;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(jsonStr) as Record<string, unknown>;\n } catch {\n // Malformed JSON chunk – skip silently.\n continue;\n }\n\n // Check for content filtering — throws if blocked.\n if (this.isContentFiltered(parsed)) {\n throw new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message: 'Response was blocked by provider content safety filter.',\n provider: 'gemini',\n suggestion: 'Rephrase your question or adjust safety settings.',\n });\n }\n\n // Track token usage (usually present in the last chunk).\n const chunkUsage = this.extractUsage(parsed);\n if (chunkUsage) {\n this._lastUsage = chunkUsage;\n }\n\n yield* this.extractChunks(parsed);\n }\n }\n\n // Flush any remaining data in the buffer.\n if (buffer.trim().startsWith('data:')) {\n const jsonStr = buffer.trim().slice(5).trim();\n if (jsonStr !== '' && jsonStr !== '[DONE]') {\n try {\n const parsed = JSON.parse(jsonStr) as Record<string, unknown>;\n\n if (this.isContentFiltered(parsed)) {\n throw new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message: 'Response was blocked by provider content safety filter.',\n provider: 'gemini',\n suggestion: 'Rephrase your question or adjust safety settings.',\n });\n }\n\n const chunkUsage = this.extractUsage(parsed);\n if (chunkUsage) {\n this._lastUsage = chunkUsage;\n }\n\n yield* this.extractChunks(parsed);\n } catch (error: unknown) {\n // Re-throw ContentFilterError, ignore other parse errors.\n if (error instanceof ContentFilterError) throw error;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Format a tool result so it can be sent back to Gemini as a\n * `functionResponse` part.\n */\n formatToolResult(\n callId: string,\n result: unknown,\n ): {\n role: string;\n parts: Array<{\n functionResponse: { name: string; response: { result: unknown } };\n }>;\n } {\n return {\n role: 'function',\n parts: [\n {\n functionResponse: {\n name: callId,\n response: { result },\n },\n },\n ],\n };\n }\n\n // -----------------------------------------------------------------------\n // Streaming request\n // -----------------------------------------------------------------------\n\n /**\n * Build and execute a streaming request to the Gemini API.\n * Returns the raw `ReadableStream` for the response body together with\n * the raw Response object.\n *\n * Note: The Gemini API key is passed as a URL query parameter (`key=`).\n * This is inherent to the Gemini REST SSE endpoint design; the key is\n * transmitted over HTTPS so it remains encrypted in transit. (H3)\n */\n async streamRequest(params: {\n systemPrompt: string;\n contents: unknown;\n userMessage?: string;\n tools?: unknown;\n signal?: AbortSignal;\n timeoutMs?: number;\n }): Promise<{\n stream: ReadableStream<Uint8Array>;\n response: Response;\n }> {\n // Build the full contents array: formatted history + the new user message.\n const contentsArray = params.contents as Array<unknown>;\n const fullContents = params.userMessage\n ? [...contentsArray, { role: 'user', parts: [{ text: params.userMessage }] }]\n : contentsArray;\n\n const url = `${GEMINI_BASE_URL}/${this.model}:streamGenerateContent?alt=sse&key=${this.apiKey}`;\n\n const body: Record<string, unknown> = {\n systemInstruction: {\n parts: [{ text: params.systemPrompt }],\n },\n contents: fullContents,\n safetySettings: DEFAULT_SAFETY_SETTINGS,\n generationConfig: {\n temperature: 0.7,\n topP: 0.95,\n topK: 40,\n },\n };\n\n if (params.tools) {\n body.tools = params.tools;\n }\n\n const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const controller = new AbortController();\n\n // Combine the external signal with our timeout signal.\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n if (params.signal) {\n // If the caller aborts, propagate to our controller.\n params.signal.addEventListener(\n 'abort',\n () => controller.abort(params.signal!.reason),\n { once: true },\n );\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n\n if (\n error instanceof DOMException &&\n error.name === 'AbortError'\n ) {\n // Distinguish caller abort from timeout.\n if (params.signal?.aborted) {\n throw error; // Re-throw caller abort as-is.\n }\n throw new TimeoutError({\n code: ErrorCodes.TIMEOUT_LLM_RESPONSE,\n message: `Gemini request timed out after ${timeoutMs}ms`,\n provider: 'gemini',\n recoverable: true,\n suggestion: 'Try again or increase the timeout.',\n operationName: 'gemini.streamGenerateContent',\n timeoutMs,\n });\n }\n\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `Failed to connect to Gemini API: ${(error as Error).message}`,\n provider: 'gemini',\n suggestion:\n 'Check your network connection and try again.',\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n clearTimeout(timeoutId);\n\n // Handle HTTP-level errors.\n if (!response.ok) {\n await this.handleHttpError(response);\n }\n\n if (!response.body) {\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: 'Gemini response body is null – streaming unavailable.',\n provider: 'gemini',\n suggestion: 'Retry the request.',\n });\n }\n\n return { stream: response.body, response };\n }\n\n // -----------------------------------------------------------------------\n // Public helpers (LLMProviderAdapter interface)\n // -----------------------------------------------------------------------\n\n /**\n * Extract `TextChunk` and `ToolCall` items from a single parsed Gemini\n * SSE JSON object.\n */\n private *extractChunks(\n parsed: Record<string, unknown>,\n ): Generator<TextChunk | ToolCall> {\n const candidates = parsed.candidates as\n | Array<Record<string, unknown>>\n | undefined;\n\n if (!candidates || candidates.length === 0) return;\n\n for (const candidate of candidates) {\n const content = candidate.content as\n | { parts?: Array<Record<string, unknown>> }\n | undefined;\n\n if (!content?.parts) continue;\n\n const finishReason = candidate.finishReason as string | undefined;\n const isDone =\n finishReason === 'STOP' || finishReason === 'MAX_TOKENS';\n\n for (const part of content.parts) {\n // Text part\n if (typeof part.text === 'string') {\n const textChunk: TextChunk = {\n text: part.text,\n done: isDone,\n };\n yield textChunk;\n }\n\n // Function call part\n if (part.functionCall) {\n const fc = part.functionCall as {\n name: string;\n args?: Record<string, unknown>;\n };\n const toolCall: ToolCall = {\n id: fc.name,\n name: fc.name,\n arguments: fc.args ?? {},\n };\n yield toolCall;\n }\n }\n }\n }\n\n /**\n * Extract token usage from a parsed Gemini response chunk.\n * Returns `null` if no usage metadata is present.\n */\n extractUsage(parsed: Record<string, unknown>): TokenUsage | null {\n const meta = parsed.usageMetadata as\n | {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n }\n | undefined;\n\n if (!meta) return null;\n\n return {\n prompt: meta.promptTokenCount ?? 0,\n completion: meta.candidatesTokenCount ?? 0,\n total: meta.totalTokenCount ?? 0,\n };\n }\n\n /**\n * Check whether a parsed Gemini chunk indicates the response was\n * blocked by a safety filter.\n */\n isContentFiltered(parsed: Record<string, unknown>): boolean {\n const candidates = parsed.candidates as\n | Array<Record<string, unknown>>\n | undefined;\n\n if (!candidates || candidates.length === 0) {\n // If there is a promptFeedback.blockReason the response was blocked\n // before generation even started.\n const feedback = parsed.promptFeedback as\n | { blockReason?: string }\n | undefined;\n return feedback?.blockReason != null;\n }\n\n return candidates.some(\n (c) =>\n c.finishReason === 'SAFETY' ||\n c.finishReason === 'BLOCKED_REASON' ||\n c.finishReason === 'OTHER',\n );\n }\n\n /**\n * Translate an HTTP error response from Gemini into the appropriate\n * GuideKit error class.\n */\n private async handleHttpError(response: Response): Promise<never> {\n let errorBody = '';\n try {\n errorBody = await response.text();\n } catch {\n // Ignore read failure.\n }\n\n const status = response.status;\n\n if (status === 401 || status === 403) {\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_INVALID_KEY,\n message: `Gemini API authentication failed (${status}): ${errorBody}`,\n provider: 'gemini',\n suggestion:\n 'Verify your Gemini API key is correct and has not expired.',\n });\n }\n\n if (status === 429) {\n const retryAfterHeader = response.headers.get('retry-after');\n const retryAfterMs = retryAfterHeader\n ? parseInt(retryAfterHeader, 10) * 1000\n : 60_000;\n\n throw new RateLimitError({\n code: ErrorCodes.RATE_LIMIT_PROVIDER,\n message: `Gemini API rate limit exceeded (429): ${errorBody}`,\n provider: 'gemini',\n recoverable: true,\n suggestion: `Rate limited by Gemini. Retry after ${Math.ceil(retryAfterMs / 1000)}s.`,\n retryAfterMs,\n });\n }\n\n if (status >= 500) {\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `Gemini API server error (${status}): ${errorBody}`,\n provider: 'gemini',\n suggestion:\n 'The Gemini API is experiencing issues. Please try again later.',\n });\n }\n\n // Fallback for other 4xx errors.\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `Gemini API request failed (${status}): ${errorBody}`,\n provider: 'gemini',\n suggestion: 'Check the request parameters and try again.',\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// LLMOrchestrator\n// ---------------------------------------------------------------------------\n\n/** Callback options accepted by `LLMOrchestrator`. */\ninterface OrchestratorCallbacks {\n onChunk?: (chunk: TextChunk) => void;\n onToolCall?: (toolCall: ToolCall) => void;\n onTokenUsage?: (usage: TokenUsage) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * High-level orchestrator that manages LLM interactions for the GuideKit SDK.\n *\n * Responsibilities:\n * - Owns the active `LLMProviderAdapter`.\n * - Streams responses from the provider, emitting callbacks for text chunks,\n * tool calls, and token usage.\n * - Handles content filter retries: if the initial response is blocked, it\n * retries once with a stripped-down prompt (no tools).\n * - Surfaces all errors through the SDK error hierarchy.\n *\n * The orchestrator is fully adapter-agnostic: all provider-specific logic\n * (SSE parsing, content filter detection, usage extraction) lives in the\n * adapter implementations.\n */\nexport class LLMOrchestrator {\n private _adapter: LLMProviderAdapter;\n private _config: LLMConfig;\n private readonly debug: boolean;\n private readonly callbacks: OrchestratorCallbacks;\n\n constructor(options: {\n config: LLMConfig;\n debug?: boolean;\n onChunk?: (chunk: TextChunk) => void;\n onToolCall?: (toolCall: ToolCall) => void;\n onTokenUsage?: (usage: TokenUsage) => void;\n onError?: (error: Error) => void;\n }) {\n this._config = options.config;\n this.debug = options.debug ?? false;\n this.callbacks = {\n onChunk: options.onChunk,\n onToolCall: options.onToolCall,\n onTokenUsage: options.onTokenUsage,\n onError: options.onError,\n };\n this._adapter = this.createAdapter(options.config);\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Send a message and stream the response from the LLM.\n *\n * Accumulates text and tool calls from the stream, invoking callbacks\n * as chunks arrive, and returns the complete result once the stream ends.\n */\n async sendMessage(params: {\n systemPrompt: string;\n history: ConversationTurn[];\n userMessage: string;\n tools?: ToolDefinition[];\n signal?: AbortSignal;\n }): Promise<{\n text: string;\n toolCalls: ToolCall[];\n usage: TokenUsage;\n }> {\n try {\n return await this.executeStream(params, /* isRetry */ false);\n } catch (error: unknown) {\n if (error instanceof ContentFilterError) {\n // Retry once without tools (simplified prompt).\n this.log('Content filter triggered – retrying without tools');\n try {\n return await this.executeStream(\n { ...params, tools: undefined },\n /* isRetry */ true,\n );\n } catch (_retryError: unknown) {\n const cfError = new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message:\n 'Response blocked by content safety filter after retry.',\n provider: this.providerName,\n suggestion:\n 'Rephrase your question or adjust safety settings.',\n });\n this.callbacks.onError?.(cfError);\n throw cfError;\n }\n }\n\n // For non-content-filter errors, notify and re-throw.\n if (error instanceof Error) {\n this.callbacks.onError?.(error);\n }\n throw error;\n }\n }\n\n /**\n * Hot-swap the LLM configuration. Creates a new adapter for the\n * updated provider/model.\n */\n updateConfig(config: LLMConfig): void {\n this._config = config;\n this._adapter = this.createAdapter(config);\n const label = 'provider' in config ? config.provider : 'custom adapter';\n this.log(`Config updated: ${label}`);\n }\n\n /** Get the current provider adapter. */\n get adapter(): LLMProviderAdapter {\n return this._adapter;\n }\n\n // -----------------------------------------------------------------------\n // Internal helpers\n // -----------------------------------------------------------------------\n\n /**\n * Execute a streaming LLM request and collect the results.\n *\n * This method is fully adapter-agnostic: it delegates streaming,\n * response parsing, content-filter detection, and usage extraction\n * entirely to the active `LLMProviderAdapter`. No provider-specific\n * SSE parsing lives in the orchestrator.\n */\n private async executeStream(\n params: {\n systemPrompt: string;\n history: ConversationTurn[];\n userMessage: string;\n tools?: ToolDefinition[];\n signal?: AbortSignal;\n },\n _isRetry: boolean,\n ): Promise<{\n text: string;\n toolCalls: ToolCall[];\n usage: TokenUsage;\n }> {\n const adapter = this._adapter;\n\n // Format conversation history via the adapter.\n const historyContents = adapter.formatConversation(params.history);\n\n // Format tools if provided.\n const tools =\n params.tools && params.tools.length > 0\n ? adapter.formatTools(params.tools)\n : undefined;\n\n // Execute the streaming request via the adapter.\n // The adapter's streamRequest accepts the formatted history as `contents`\n // and appends the user message internally using `userMessage`.\n const { stream } = await adapter.streamRequest({\n systemPrompt: params.systemPrompt,\n contents: historyContents,\n userMessage: params.userMessage,\n tools,\n signal: params.signal,\n });\n\n // Parse the stream using the adapter's parseResponse.\n // Content filter detection and usage tracking are handled within\n // the adapter's parseResponse — a ContentFilterError will propagate\n // up naturally from the async iteration.\n let fullText = '';\n const toolCalls: ToolCall[] = [];\n\n for await (const item of adapter.parseResponse(stream)) {\n if ('name' in item && 'arguments' in item) {\n // ToolCall\n const toolCall = item as ToolCall;\n toolCalls.push(toolCall);\n this.callbacks.onToolCall?.(toolCall);\n } else {\n // TextChunk\n const chunk = item as TextChunk;\n if (chunk.text) {\n fullText += chunk.text;\n }\n this.callbacks.onChunk?.(chunk);\n }\n }\n\n // Always emit a final \"done\" chunk to signal stream completion,\n // regardless of whether text was received (M3 fix).\n this.callbacks.onChunk?.({ text: '', done: true });\n\n // Retrieve token usage from the adapter. The adapter tracks usage\n // internally during parseResponse via the `lastUsage` property.\n let usage: TokenUsage = emptyUsage();\n if ('lastUsage' in adapter) {\n usage = (adapter as unknown as { lastUsage: TokenUsage }).lastUsage;\n }\n\n // Report token usage.\n if (usage.total > 0) {\n this.callbacks.onTokenUsage?.(usage);\n }\n\n this.log(\n `Response complete: ${fullText.length} chars, ` +\n `${toolCalls.length} tool calls, ` +\n `${usage.total} tokens`,\n );\n\n return { text: fullText, toolCalls, usage };\n }\n\n /**\n * Create the appropriate adapter for the given config.\n *\n * Built-in providers:\n * - `'gemini'` — uses the bundled `GeminiAdapter`.\n *\n * Custom adapters:\n * - Pass `{ adapter: myAdapter }` to use any `LLMProviderAdapter`.\n * Example: `llm: { adapter: new OpenAIAdapter({ ... }) }`\n */\n private createAdapter(config: LLMConfig): LLMProviderAdapter {\n // Custom adapter — pass-through.\n if ('adapter' in config) {\n return config.adapter;\n }\n\n // Built-in providers.\n switch (config.provider) {\n case 'gemini':\n return new GeminiAdapter(config);\n default:\n throw new Error(\n `LLM provider \"${(config as { provider: string }).provider}\" is not yet supported. ` +\n 'Use { adapter: yourAdapter } for custom providers.',\n );\n }\n }\n\n /** Convenience accessor for the current provider name. */\n private get providerName(): string | undefined {\n if ('provider' in this._config) return this._config.provider;\n return undefined;\n }\n\n /** Log a debug message if debug mode is enabled. */\n private log(message: string): void {\n if (this.debug) {\n console.debug(`[GuideKit:LLM] ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Multi-Turn Tool Executor\n// ---------------------------------------------------------------------------\n//\n// Implements a multi-turn tool execution loop that sits between the\n// LLMOrchestrator and callers. When the LLM returns tool calls, this\n// executor runs them, feeds results back, and repeats until the LLM\n// produces a text-only response or the round limit is reached.\n// ---------------------------------------------------------------------------\n\nimport type {\n ToolDefinition,\n ToolCall,\n ConversationTurn,\n} from '../types/index.js';\nimport type { LLMOrchestrator } from './index.js';\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\n/**\n * A registered handler for a specific tool. The `name` must match the tool\n * definition's `name` field exactly.\n */\nexport interface ToolHandler {\n name: string;\n execute: (args: Record<string, unknown>) => Promise<unknown>;\n}\n\n/** Options for configuring the ToolExecutor. */\nexport interface ToolExecutorOptions {\n /** Max number of tool call rounds before forcing text response. Default: 5 */\n maxRounds?: number;\n /** Enable debug logging. */\n debug?: boolean;\n /** Called when a tool is about to be executed. */\n onToolCall?: (name: string, args: Record<string, unknown>) => void;\n /** Called when a tool execution completes. */\n onToolResult?: (name: string, result: unknown, durationMs: number) => void;\n /** Called when a tool execution fails. */\n onToolError?: (name: string, error: Error) => void;\n}\n\n/** A single executed tool call with its outcome. */\nexport interface ToolCallRecord {\n name: string;\n args: Record<string, unknown>;\n result: unknown;\n durationMs: number;\n error?: string;\n}\n\n/** Aggregated token usage across all rounds. */\nexport interface AggregatedUsage {\n prompt: number;\n completion: number;\n total: number;\n}\n\n/** The complete result of a multi-turn tool execution session. */\nexport interface ToolExecutionResult {\n /** The final text response from the LLM. */\n text: string;\n /** All tool calls that were executed across every round. */\n toolCallsExecuted: ToolCallRecord[];\n /** Accumulated token usage across all LLM calls. */\n totalUsage: AggregatedUsage;\n /** Number of LLM round-trips performed. */\n rounds: number;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types for tool-augmented conversation turns\n// ---------------------------------------------------------------------------\n\n/**\n * Internally, the tool executor needs richer turn types than the public\n * `ConversationTurn` (which only supports 'user' | 'assistant'). These\n * extended types carry tool call metadata and tool results so that each\n * LLM provider adapter can format them correctly.\n */\ninterface AssistantToolCallTurn {\n role: 'assistant';\n content: string;\n toolCalls: Array<{ id: string; name: string; args: Record<string, unknown> }>;\n timestamp: number;\n}\n\ninterface ToolResultTurn {\n role: 'tool';\n content: string;\n toolCallId: string;\n toolName: string;\n timestamp: number;\n}\n\n/**\n * A conversation turn that may be a standard turn, an assistant turn\n * with tool calls, or a tool result turn.\n */\ntype InternalTurn = ConversationTurn | AssistantToolCallTurn | ToolResultTurn;\n\n// ---------------------------------------------------------------------------\n// ToolExecutor\n// ---------------------------------------------------------------------------\n\n/**\n * Manages multi-turn LLM interactions involving tool calls.\n *\n * Flow:\n * 1. Send the user message to the LLM along with available tool definitions.\n * 2. If the LLM response includes tool calls, execute them in parallel.\n * 3. Feed tool results back to the LLM as additional conversation context.\n * 4. Repeat until the LLM produces a text-only response or `maxRounds`\n * is exceeded.\n */\nexport class ToolExecutor {\n private readonly maxRounds: number;\n private readonly debugEnabled: boolean;\n private readonly handlers = new Map<string, ToolHandler>();\n\n // Callbacks\n private readonly onToolCallCb?: (name: string, args: Record<string, unknown>) => void;\n private readonly onToolResultCb?: (name: string, result: unknown, durationMs: number) => void;\n private readonly onToolErrorCb?: (name: string, error: Error) => void;\n\n constructor(options?: ToolExecutorOptions) {\n this.maxRounds = options?.maxRounds ?? 5;\n this.debugEnabled = options?.debug ?? false;\n this.onToolCallCb = options?.onToolCall;\n this.onToolResultCb = options?.onToolResult;\n this.onToolErrorCb = options?.onToolError;\n }\n\n // -----------------------------------------------------------------------\n // Tool registration\n // -----------------------------------------------------------------------\n\n /** Register a tool handler. Overwrites any existing handler with the same name. */\n registerTool(handler: ToolHandler): void {\n this.handlers.set(handler.name, handler);\n this.log(`Registered tool: ${handler.name}`);\n }\n\n /** Unregister a tool by name. No-op if the tool is not registered. */\n unregisterTool(name: string): void {\n const deleted = this.handlers.delete(name);\n if (deleted) {\n this.log(`Unregistered tool: ${name}`);\n }\n }\n\n /** Check whether a tool handler is registered. */\n hasTool(name: string): boolean {\n return this.handlers.has(name);\n }\n\n /**\n * Build `ToolDefinition[]` from all registered handlers.\n *\n * Since `ToolHandler` only carries `name` and `execute`, the returned\n * definitions have empty descriptions and parameters. Callers that need\n * richer definitions should maintain their own `ToolDefinition[]` and\n * pass them directly to `executeWithTools`.\n */\n getToolDefinitions(): ToolDefinition[] {\n const definitions: ToolDefinition[] = [];\n for (const handler of this.handlers.values()) {\n definitions.push({\n name: handler.name,\n description: '',\n parameters: {},\n schemaVersion: 1,\n });\n }\n return definitions;\n }\n\n // -----------------------------------------------------------------------\n // Multi-turn execution loop\n // -----------------------------------------------------------------------\n\n /**\n * Execute a multi-turn conversation with tool calls.\n *\n * The method sends the initial user message to the LLM. If the LLM\n * responds with tool calls, each call is executed in parallel, the\n * results are appended to the conversation, and the updated context\n * is sent back to the LLM. This loop repeats until:\n *\n * - The LLM returns a text-only response (no tool calls), or\n * - `maxRounds` consecutive tool-calling rounds have been exhausted.\n *\n * When `maxRounds` is exceeded the executor returns whatever text the\n * LLM has produced so far (which may be empty).\n */\n async executeWithTools(params: {\n llm: LLMOrchestrator;\n systemPrompt: string;\n history: ConversationTurn[];\n userMessage: string;\n tools: ToolDefinition[];\n signal?: AbortSignal;\n }): Promise<ToolExecutionResult> {\n const { llm, systemPrompt, userMessage, tools, signal } = params;\n\n // Accumulate results across rounds.\n const allToolCalls: ToolCallRecord[] = [];\n const totalUsage: AggregatedUsage = { prompt: 0, completion: 0, total: 0 };\n let rounds = 0;\n let finalText = '';\n\n // Build the running conversation. We start with the caller-supplied\n // history and progressively append assistant / tool turns as the\n // loop executes. The initial history uses the standard ConversationTurn\n // type; tool-related turns use our internal extended types.\n const internalHistory: InternalTurn[] = [...params.history];\n\n // The user message for the *first* round. On subsequent rounds the\n // LLM is called with an empty user message because the new context\n // is conveyed through the tool result turns appended to the history.\n let currentUserMessage = userMessage;\n\n while (rounds < this.maxRounds) {\n // Check for abort before each round.\n if (signal?.aborted) {\n this.log('Aborted before round ' + (rounds + 1));\n break;\n }\n\n rounds++;\n this.log(`--- Round ${rounds} ---`);\n\n // Convert internal history to standard ConversationTurn[] for the\n // LLMOrchestrator, which only understands 'user' | 'assistant' roles.\n const llmHistory = this.flattenHistory(internalHistory);\n\n // Send to LLM.\n const response = await llm.sendMessage({\n systemPrompt,\n history: llmHistory,\n userMessage: currentUserMessage,\n tools,\n signal,\n });\n\n // Accumulate token usage.\n totalUsage.prompt += response.usage.prompt;\n totalUsage.completion += response.usage.completion;\n totalUsage.total += response.usage.total;\n\n // Capture any text the LLM produced alongside tool calls.\n if (response.text) {\n finalText = response.text;\n }\n\n // If there are no tool calls, we are done.\n if (response.toolCalls.length === 0) {\n this.log(`Round ${rounds}: text-only response, finishing loop`);\n break;\n }\n\n this.log(\n `Round ${rounds}: ${response.toolCalls.length} tool call(s) received`,\n );\n\n // Record the assistant turn with its tool calls.\n const assistantTurn: AssistantToolCallTurn = {\n role: 'assistant',\n content: response.text,\n toolCalls: response.toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: tc.arguments,\n })),\n timestamp: Date.now(),\n };\n internalHistory.push(assistantTurn);\n\n // Execute all tool calls from this round in parallel.\n const toolResults = await this.executeToolCallsInParallel(\n response.toolCalls,\n signal,\n );\n\n // Append each tool result as a separate turn and record it.\n for (const tr of toolResults) {\n allToolCalls.push(tr.record);\n\n const resultTurn: ToolResultTurn = {\n role: 'tool',\n content: JSON.stringify(\n tr.record.error != null\n ? { error: tr.record.error }\n : tr.record.result,\n ),\n toolCallId: tr.toolCallId,\n toolName: tr.record.name,\n timestamp: Date.now(),\n };\n internalHistory.push(resultTurn);\n }\n\n // On subsequent rounds the new context is carried by the tool\n // result turns, so we send an empty user message.\n currentUserMessage = '';\n\n // Check abort again before looping.\n if (signal?.aborted) {\n this.log('Aborted after tool execution in round ' + rounds);\n break;\n }\n }\n\n if (rounds >= this.maxRounds) {\n this.log(\n `Max rounds (${this.maxRounds}) reached. Returning current text.`,\n );\n }\n\n this.log(\n `Execution complete: ${rounds} round(s), ` +\n `${allToolCalls.length} tool call(s), ` +\n `${totalUsage.total} total tokens`,\n );\n\n return {\n text: finalText,\n toolCallsExecuted: allToolCalls,\n totalUsage,\n rounds,\n };\n }\n\n // -----------------------------------------------------------------------\n // Private: execute a single tool call\n // -----------------------------------------------------------------------\n\n /**\n * Execute a single tool call by looking up the registered handler and\n * invoking it. Returns the result, any error message, and the wall-clock\n * duration in milliseconds.\n */\n private async executeTool(\n toolCall: ToolCall,\n ): Promise<{ result: unknown; error?: string; durationMs: number }> {\n const handler = this.handlers.get(toolCall.name);\n\n if (!handler) {\n const errorMsg = `Unknown tool: ${toolCall.name}`;\n this.log(errorMsg);\n return { result: undefined, error: errorMsg, durationMs: 0 };\n }\n\n this.onToolCallCb?.(toolCall.name, toolCall.arguments);\n\n const startTime = performance.now();\n\n try {\n const result = await handler.execute(toolCall.arguments);\n const durationMs = Math.round(performance.now() - startTime);\n\n this.onToolResultCb?.(toolCall.name, result, durationMs);\n this.log(\n `Tool \"${toolCall.name}\" completed in ${durationMs}ms`,\n );\n\n return { result, durationMs };\n } catch (err: unknown) {\n const durationMs = Math.round(performance.now() - startTime);\n const error = err instanceof Error ? err : new Error(String(err));\n\n this.onToolErrorCb?.(toolCall.name, error);\n this.log(\n `Tool \"${toolCall.name}\" failed after ${durationMs}ms: ${error.message}`,\n );\n\n return { result: undefined, error: error.message, durationMs };\n }\n }\n\n // -----------------------------------------------------------------------\n // Private: execute tool calls in parallel\n // -----------------------------------------------------------------------\n\n /**\n * Execute an array of tool calls concurrently. If the abort signal fires\n * mid-execution, already-started calls run to completion but the results\n * of all settled calls are still returned.\n */\n private async executeToolCallsInParallel(\n toolCalls: ToolCall[],\n signal?: AbortSignal,\n ): Promise<\n Array<{\n toolCallId: string;\n record: ToolCallRecord;\n }>\n > {\n // If already aborted, skip execution entirely.\n if (signal?.aborted) {\n return toolCalls.map((tc) => ({\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: undefined,\n durationMs: 0,\n error: 'Execution aborted',\n },\n }));\n }\n\n const settled = await Promise.allSettled(\n toolCalls.map(async (tc) => {\n // Check abort before starting each call. Already-queued microtasks\n // will still run, but this avoids starting new work when possible.\n if (signal?.aborted) {\n return {\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: undefined,\n durationMs: 0,\n error: 'Execution aborted',\n } satisfies ToolCallRecord,\n };\n }\n\n const outcome = await this.executeTool(tc);\n\n return {\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: outcome.result,\n durationMs: outcome.durationMs,\n ...(outcome.error != null ? { error: outcome.error } : {}),\n } satisfies ToolCallRecord,\n };\n }),\n );\n\n // Collect results. Rejected promises are converted to error records.\n return settled.map((s, i) => {\n if (s.status === 'fulfilled') {\n return s.value;\n }\n\n // This branch should be unreachable because executeTool catches all\n // errors, but we handle it defensively.\n const tc = toolCalls[i];\n if (!tc) {\n const errorMsg =\n s.reason instanceof Error ? s.reason.message : String(s.reason);\n return {\n toolCallId: `unknown-${i}`,\n record: {\n name: 'unknown',\n args: {},\n result: undefined,\n durationMs: 0,\n error: errorMsg,\n },\n };\n }\n const errorMsg =\n s.reason instanceof Error ? s.reason.message : String(s.reason);\n\n return {\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: undefined,\n durationMs: 0,\n error: errorMsg,\n },\n };\n });\n }\n\n // -----------------------------------------------------------------------\n // Private: flatten internal history for the LLMOrchestrator\n // -----------------------------------------------------------------------\n\n /**\n * Convert the internal turn representation (which includes 'tool' roles\n * and assistant turns with tool call metadata) into the flat\n * `ConversationTurn[]` that `LLMOrchestrator.sendMessage` expects.\n *\n * Strategy:\n * - Standard `ConversationTurn` objects pass through unchanged.\n * - `AssistantToolCallTurn` objects are converted to an assistant turn\n * whose content describes the tool calls that were made.\n * - `ToolResultTurn` objects are converted to user turns that report\n * the tool results so the LLM can incorporate them.\n *\n * This approach works with any LLM provider since it only uses the\n * 'user' | 'assistant' role discriminator.\n */\n private flattenHistory(turns: InternalTurn[]): ConversationTurn[] {\n const flat: ConversationTurn[] = [];\n\n for (const turn of turns) {\n if (this.isToolResultTurn(turn)) {\n // Encode tool results as user turns so the LLM sees them as\n // new information to process.\n flat.push({\n role: 'user',\n content: `[Tool result for \"${turn.toolName}\" (id: ${turn.toolCallId})]: ${turn.content}`,\n timestamp: turn.timestamp,\n });\n } else if (this.isAssistantToolCallTurn(turn)) {\n // Encode the assistant's tool call request as an assistant turn.\n const callDescriptions = turn.toolCalls\n .map(\n (tc) =>\n `[Calling tool \"${tc.name}\" (id: ${tc.id}) with args: ${JSON.stringify(tc.args)}]`,\n )\n .join('\\n');\n\n const content = turn.content\n ? `${turn.content}\\n\\n${callDescriptions}`\n : callDescriptions;\n\n flat.push({\n role: 'assistant',\n content,\n timestamp: turn.timestamp,\n });\n } else {\n // Standard ConversationTurn — pass through.\n flat.push(turn);\n }\n }\n\n return flat;\n }\n\n // -----------------------------------------------------------------------\n // Type guards\n // -----------------------------------------------------------------------\n\n private isToolResultTurn(turn: InternalTurn): turn is ToolResultTurn {\n return (turn as ToolResultTurn).role === 'tool';\n }\n\n private isAssistantToolCallTurn(\n turn: InternalTurn,\n ): turn is AssistantToolCallTurn {\n return (\n turn.role === 'assistant' &&\n Array.isArray((turn as AssistantToolCallTurn).toolCalls)\n );\n }\n\n // -----------------------------------------------------------------------\n // Debug logging\n // -----------------------------------------------------------------------\n\n private log(message: string): void {\n if (this.debugEnabled) {\n console.debug(`[GuideKit:ToolExecutor] ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Network Connectivity Manager\n// ---------------------------------------------------------------------------\n\nimport type { ConnectionState } from '../types/index.js';\n\nconst LOG_PREFIX = '[GuideKit:Connectivity]';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Maximum number of messages held in the offline queue. */\nconst MAX_QUEUE_SIZE = 5;\n\n/** Number of recent pings used to compute rolling average latency. */\nconst ROLLING_WINDOW = 3;\n\n/** Latency threshold (ms) above which the connection is considered degraded. */\nconst DEGRADED_THRESHOLD_MS = 2_000;\n\n/** Ping intervals per state (ms). */\nconst PING_INTERVALS: Record<ConnectionState, number> = {\n online: 30_000,\n degraded: 5_000,\n offline: 10_000,\n};\n\n/** Timeout applied to each health-check fetch (ms). */\nconst PING_TIMEOUT_MS = 5_000;\n\n// ---------------------------------------------------------------------------\n// QueuedMessage\n// ---------------------------------------------------------------------------\n\n/** A message held for replay once connectivity is restored. */\nexport interface QueuedMessage {\n content: string;\n timestamp: number;\n pageUrl: string;\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface ConnectionManagerOptions {\n /** Server endpoint for lightweight health-check pings. */\n healthEndpoint?: string;\n /** When `true`, diagnostic messages are logged to the console. */\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// State-change subscriber\n// ---------------------------------------------------------------------------\n\ntype StateChangeCallback = (\n state: ConnectionState,\n previous: ConnectionState,\n) => void;\n\n// ---------------------------------------------------------------------------\n// ConnectionManager\n// ---------------------------------------------------------------------------\n\n/**\n * Monitors network connectivity and exposes a reactive {@link ConnectionState}.\n *\n * Strategy:\n * 1. Listen to `window.online` / `window.offline` events (coarse signal).\n * 2. Periodically ping the configured `healthEndpoint` (fine-grained signal).\n * 3. Compute a rolling average of the last {@link ROLLING_WINDOW} ping\n * latencies to detect degraded connections (> {@link DEGRADED_THRESHOLD_MS}).\n * 4. When fully offline (`navigator.onLine === false`), suspend pinging and\n * wait for the browser's `online` event before resuming.\n *\n * All browser APIs are gated behind `typeof window !== 'undefined'` so the\n * class can be safely imported (though not meaningfully used) in SSR contexts.\n */\nexport class ConnectionManager {\n // ---- Configuration ------------------------------------------------------\n\n private readonly healthEndpoint: string | undefined;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state -----------------------------------------------------\n\n private _state: ConnectionState = 'online';\n private _running = false;\n\n /** Rolling window of recent ping latencies (ms). */\n private readonly pingLatencies: number[] = [];\n\n /** Queued messages awaiting replay on reconnect. */\n private readonly messageQueue: QueuedMessage[] = [];\n\n /** Registered state-change subscribers. */\n private readonly subscribers: Set<StateChangeCallback> = new Set();\n\n /** Timer handle for the periodic ping loop. */\n private pingTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Bound event handlers (stored for deterministic removal). */\n private readonly handleOnline: () => void;\n private readonly handleOffline: () => void;\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options?: ConnectionManagerOptions) {\n this.healthEndpoint = options?.healthEndpoint;\n this.debugEnabled = options?.debug ?? false;\n\n // Pre-bind handlers so we can add/remove the exact same references.\n this.handleOnline = this.onBrowserOnline.bind(this);\n this.handleOffline = this.onBrowserOffline.bind(this);\n\n this.log('ConnectionManager created');\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Current connection state. */\n get state(): ConnectionState {\n return this._state;\n }\n\n /**\n * Start monitoring connectivity.\n *\n * Attaches browser event listeners and begins the periodic ping loop.\n * Calling `start()` when already running is a no-op.\n */\n start(): void {\n if (this._running) {\n return;\n }\n\n this._running = true;\n this.log('Monitoring started');\n\n if (typeof window !== 'undefined') {\n window.addEventListener('online', this.handleOnline);\n window.addEventListener('offline', this.handleOffline);\n\n // Seed initial state from the browser.\n if (!navigator.onLine) {\n this.transition('offline');\n }\n }\n\n this.schedulePing();\n }\n\n /**\n * Stop monitoring connectivity.\n *\n * Removes all event listeners, clears timers, and resets internal state.\n */\n stop(): void {\n if (!this._running) {\n return;\n }\n\n this._running = false;\n this.log('Monitoring stopped');\n\n if (typeof window !== 'undefined') {\n window.removeEventListener('online', this.handleOnline);\n window.removeEventListener('offline', this.handleOffline);\n }\n\n this.clearPingTimer();\n this.pingLatencies.length = 0;\n }\n\n /**\n * Subscribe to connection state changes.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onStateChange(callback: StateChangeCallback): () => void {\n this.subscribers.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.subscribers.delete(callback);\n };\n }\n\n /**\n * Queue a message for replay once the connection is restored.\n *\n * The queue is capped at {@link MAX_QUEUE_SIZE} messages. When the cap is\n * exceeded the oldest message is discarded.\n */\n queueMessage(message: QueuedMessage): void {\n if (this.messageQueue.length >= MAX_QUEUE_SIZE) {\n const discarded = this.messageQueue.shift();\n this.log('Queue full — discarded oldest message', discarded);\n }\n\n this.messageQueue.push(message);\n this.log(`Message queued (${this.messageQueue.length}/${MAX_QUEUE_SIZE})`);\n }\n\n /**\n * Drain the message queue and return its contents.\n *\n * Messages whose `pageUrl` no longer matches the current browser URL are\n * silently discarded (the user has navigated away since queueing).\n */\n drainQueue(): QueuedMessage[] {\n const currentUrl = this.getCurrentUrl();\n const valid: QueuedMessage[] = [];\n\n for (const msg of this.messageQueue) {\n if (msg.pageUrl === currentUrl) {\n valid.push(msg);\n } else {\n this.log('Discarded stale message (URL changed)', msg.pageUrl);\n }\n }\n\n this.messageQueue.length = 0;\n this.log(`Drained ${valid.length} message(s)`);\n return valid;\n }\n\n /**\n * Force an immediate connectivity check.\n *\n * @returns The updated {@link ConnectionState} after the check completes.\n */\n async checkNow(): Promise<ConnectionState> {\n // If the browser reports offline, skip the network request entirely.\n if (typeof window !== 'undefined' && !navigator.onLine) {\n this.transition('offline');\n return this._state;\n }\n\n await this.ping();\n return this._state;\n }\n\n // -----------------------------------------------------------------------\n // Browser event handlers\n // -----------------------------------------------------------------------\n\n private onBrowserOnline(): void {\n this.log('Browser \"online\" event received');\n\n // Reset latency history — the previous measurements are stale.\n this.pingLatencies.length = 0;\n\n // Optimistically assume online; the next ping will refine the state.\n this.transition('online');\n\n // Resume pinging if we are still in monitoring mode.\n if (this._running) {\n this.schedulePing();\n }\n }\n\n private onBrowserOffline(): void {\n this.log('Browser \"offline\" event received');\n this.transition('offline');\n\n // Suspend pinging — no point hitting the network when the browser\n // itself says we are offline. We will resume via `handleOnline`.\n this.clearPingTimer();\n }\n\n // -----------------------------------------------------------------------\n // Ping logic\n // -----------------------------------------------------------------------\n\n /**\n * Execute a single health-check ping and update state accordingly.\n */\n private async ping(): Promise<void> {\n if (!this.healthEndpoint) {\n // Without an endpoint we can only rely on navigator.onLine.\n if (typeof window !== 'undefined') {\n this.transition(navigator.onLine ? 'online' : 'offline');\n }\n return;\n }\n\n const start = Date.now();\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), PING_TIMEOUT_MS);\n\n try {\n await fetch(this.healthEndpoint, {\n method: 'HEAD',\n mode: 'no-cors',\n cache: 'no-store',\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeout);\n }\n\n const latency = Date.now() - start;\n this.recordLatency(latency);\n this.log(`Ping OK (${latency}ms)`);\n\n // Evaluate rolling average to decide between online / degraded.\n const avg = this.rollingAverage();\n if (avg > DEGRADED_THRESHOLD_MS) {\n this.transition('degraded');\n } else {\n this.transition('online');\n }\n } catch {\n this.log('Ping failed');\n\n // A failed ping when navigator reports offline is a clear offline.\n if (typeof window !== 'undefined' && !navigator.onLine) {\n this.transition('offline');\n } else {\n // Network may still be up, but the endpoint is unreachable —\n // treat as degraded rather than outright offline.\n this.transition('degraded');\n }\n }\n }\n\n /**\n * Record a latency sample, keeping only the last {@link ROLLING_WINDOW}\n * entries.\n */\n private recordLatency(ms: number): void {\n this.pingLatencies.push(ms);\n if (this.pingLatencies.length > ROLLING_WINDOW) {\n this.pingLatencies.shift();\n }\n }\n\n /** Compute the arithmetic mean of recorded latencies. */\n private rollingAverage(): number {\n if (this.pingLatencies.length === 0) return 0;\n\n let sum = 0;\n for (const v of this.pingLatencies) {\n sum += v;\n }\n return sum / this.pingLatencies.length;\n }\n\n // -----------------------------------------------------------------------\n // Ping scheduling\n // -----------------------------------------------------------------------\n\n /**\n * Schedule the next ping according to the current state's interval.\n *\n * When in the `offline` state, pinging is suspended entirely — the\n * manager waits for the browser's `online` event to resume.\n */\n private schedulePing(): void {\n this.clearPingTimer();\n\n if (!this._running) {\n return;\n }\n\n // While offline, do not ping. The browser `online` event will resume.\n if (this._state === 'offline') {\n return;\n }\n\n const interval = PING_INTERVALS[this._state];\n\n this.pingTimer = setTimeout(async () => {\n if (!this._running) return;\n\n await this.ping();\n\n // Schedule the next iteration (interval may have changed due to\n // a state transition during the ping).\n this.schedulePing();\n }, interval);\n }\n\n private clearPingTimer(): void {\n if (this.pingTimer !== null) {\n clearTimeout(this.pingTimer);\n this.pingTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // State transitions\n // -----------------------------------------------------------------------\n\n /**\n * Transition to a new state, notifying subscribers if the state actually\n * changed.\n */\n private transition(next: ConnectionState): void {\n const previous = this._state;\n if (previous === next) {\n return;\n }\n\n this._state = next;\n this.log(`State: ${previous} -> ${next}`);\n\n // Notify subscribers. Errors in callbacks are caught so one bad\n // subscriber does not prevent the rest from being notified.\n for (const cb of this.subscribers) {\n try {\n cb(next, previous);\n } catch (err) {\n console.error(LOG_PREFIX, 'Subscriber threw an error:', err);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n /** Return the current page URL, or an empty string in SSR contexts. */\n private getCurrentUrl(): string {\n if (typeof window !== 'undefined') {\n return window.location.href;\n }\n return '';\n }\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Navigation Controller\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Nav]';\n\nexport interface NavigationControllerOptions {\n debug?: boolean;\n /** Developer-provided router for guaranteed SPA navigation. */\n router?: {\n push: (href: string) => void | Promise<void>;\n };\n}\n\n/**\n * Manages SPA navigation detection and programmatic routing.\n *\n * - Prefers the Navigation API (Chrome 102+) where available.\n * - Falls back to `popstate` + periodic URL polling (200ms).\n * - Developer can pass a `router` prop for guaranteed SPA nav.\n */\nexport class NavigationController {\n private readonly debug: boolean;\n private readonly router?: { push: (href: string) => void | Promise<void> };\n\n private currentUrl: string = '';\n private pollingTimer: ReturnType<typeof setInterval> | null = null;\n private callbacks: Array<(from: string, to: string) => void> = [];\n private cleanups: Array<() => void> = [];\n\n constructor(options?: NavigationControllerOptions) {\n this.debug = options?.debug ?? false;\n this.router = options?.router;\n }\n\n /** Start listening for navigation events. */\n start(): void {\n if (typeof window === 'undefined') return;\n\n this.currentUrl = window.location.href;\n\n // Prefer Navigation API\n if ('navigation' in window && typeof (window as any).navigation?.addEventListener === 'function') {\n const nav = (window as any).navigation;\n const handler = (event: any) => {\n const to = event.destination?.url ?? window.location.href;\n this.handleRouteChange(to);\n };\n nav.addEventListener('navigate', handler);\n this.cleanups.push(() => nav.removeEventListener('navigate', handler));\n\n if (this.debug) console.debug(LOG_PREFIX, 'Using Navigation API');\n } else {\n // Fallback: popstate + polling\n const popHandler = () => {\n this.handleRouteChange(window.location.href);\n };\n window.addEventListener('popstate', popHandler);\n this.cleanups.push(() => window.removeEventListener('popstate', popHandler));\n\n // Poll every 200ms for pushState changes\n this.pollingTimer = setInterval(() => {\n if (window.location.href !== this.currentUrl) {\n this.handleRouteChange(window.location.href);\n }\n }, 200);\n\n if (this.debug) console.debug(LOG_PREFIX, 'Using popstate + URL polling fallback');\n }\n }\n\n /** Stop listening for navigation events. */\n stop(): void {\n for (const cleanup of this.cleanups) {\n cleanup();\n }\n this.cleanups = [];\n\n if (this.pollingTimer !== null) {\n clearInterval(this.pollingTimer);\n this.pollingTimer = null;\n }\n }\n\n /**\n * Subscribe to route changes.\n * @returns Unsubscribe function.\n */\n onRouteChange(callback: (from: string, to: string) => void): () => void {\n this.callbacks.push(callback);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n const idx = this.callbacks.indexOf(callback);\n if (idx !== -1) this.callbacks.splice(idx, 1);\n };\n }\n\n /**\n * Programmatically navigate to a URL.\n * Validates same-origin before navigating.\n */\n async navigate(href: string): Promise<boolean> {\n if (typeof window === 'undefined') return false;\n\n // Same-origin validation\n try {\n const target = new URL(href, window.location.origin);\n if (target.origin !== window.location.origin) {\n if (this.debug) console.warn(LOG_PREFIX, 'Blocked cross-origin navigation to', href);\n return false;\n }\n href = target.href;\n } catch {\n if (this.debug) console.warn(LOG_PREFIX, 'Invalid URL:', href);\n return false;\n }\n\n // Use developer-provided router if available\n if (this.router) {\n await this.router.push(href);\n return true;\n }\n\n // Fallback: update location\n window.location.href = href;\n return true;\n }\n\n /** Get the current URL. */\n get url(): string {\n if (typeof window === 'undefined') return '';\n return window.location.href;\n }\n\n private handleRouteChange(newUrl: string): void {\n if (newUrl === this.currentUrl) return;\n\n const from = this.currentUrl;\n this.currentUrl = newUrl;\n\n if (this.debug) console.debug(LOG_PREFIX, `Route change: ${from} → ${newUrl}`);\n\n for (const callback of this.callbacks.slice()) {\n try {\n callback(from, newUrl);\n } catch (err) {\n console.error(LOG_PREFIX, 'Route change handler error:', err);\n }\n }\n }\n}\n","// ----------------------------------------------------------------------------\n// WebSocket Connection Manager for STT/TTS\n// Manages WebSocket connections with automatic reconnection, exponential\n// backoff, send queueing, and SSR safety.\n// ----------------------------------------------------------------------------\n\nexport type WSState =\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'failed'\n | 'suspended';\n\nexport interface WebSocketManagerOptions {\n url: string | (() => string | Promise<string>);\n /** Max reconnection attempts before entering FAILED state. Default: 5 */\n maxReconnectAttempts?: number;\n /** Initial reconnect delay in ms. Default: 1000 */\n initialDelay?: number;\n /** Max reconnect delay in ms. Default: 30000 */\n maxDelay?: number;\n /** Connection timeout in ms. Default: 5000 */\n connectTimeoutMs?: number;\n /** Protocols to pass to WebSocket constructor */\n protocols?: string | string[];\n /** Debug logging */\n debug?: boolean;\n /** Label for logging (e.g., 'STT', 'TTS') */\n label?: string;\n}\n\ntype MessagePayload = string | ArrayBuffer | Blob;\n\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;\nconst DEFAULT_INITIAL_DELAY = 1000;\nconst DEFAULT_MAX_DELAY = 30_000;\nconst DEFAULT_CONNECT_TIMEOUT_MS = 5000;\nconst MAX_QUEUE_SIZE = 50;\n\ninterface ListenerRefs {\n onOpen: () => void;\n onClose: (e: CloseEvent) => void;\n onError: (e: Event) => void;\n onMessage: (e: MessageEvent) => void;\n}\n\nexport class WebSocketManager {\n // ── Options (resolved with defaults) ────────────────────────────────\n private readonly _url: string | (() => string | Promise<string>);\n private readonly _maxReconnectAttempts: number;\n private readonly _initialDelay: number;\n private readonly _maxDelay: number;\n private readonly _connectTimeoutMs: number;\n private readonly _protocols: string | string[] | undefined;\n private readonly _debug: boolean;\n private readonly _label: string;\n\n // ── Internal state ──────────────────────────────────────────────────\n private _state: WSState = 'disconnected';\n private _socket: WebSocket | null = null;\n private _reconnectAttempts = 0;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _connectTimer: ReturnType<typeof setTimeout> | null = null;\n private _destroyed = false;\n\n // ── Listener references (for proper cleanup) ──────────────────────\n private _listenerRefs = new WeakMap<WebSocket, ListenerRefs>();\n\n // ── Send queue ──────────────────────────────────────────────────────\n private _queue: MessagePayload[] = [];\n\n // ── Event listeners ─────────────────────────────────────────────────\n private _onOpenCallbacks: Set<() => void> = new Set();\n private _onCloseCallbacks: Set<(code: number, reason: string) => void> = new Set();\n private _onMessageCallbacks: Set<(data: MessageEvent) => void> = new Set();\n private _onErrorCallbacks: Set<(error: Event) => void> = new Set();\n private _onStateChangeCallbacks: Set<(state: WSState, previous: WSState) => void> = new Set();\n\n // ── Constructor ─────────────────────────────────────────────────────\n\n constructor(options: WebSocketManagerOptions) {\n this._url = options.url;\n this._maxReconnectAttempts = options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n this._initialDelay = options.initialDelay ?? DEFAULT_INITIAL_DELAY;\n this._maxDelay = options.maxDelay ?? DEFAULT_MAX_DELAY;\n this._connectTimeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;\n this._protocols = options.protocols;\n this._debug = options.debug ?? false;\n this._label = options.label ?? 'WS';\n }\n\n // ── Public getters ──────────────────────────────────────────────────\n\n /** Current connection state */\n get state(): WSState {\n return this._state;\n }\n\n /** The underlying WebSocket (null if not connected) */\n get socket(): WebSocket | null {\n return this._socket;\n }\n\n // ── Connection lifecycle ────────────────────────────────────────────\n\n /** Connect to the WebSocket server */\n async connect(): Promise<void> {\n if (this._destroyed) {\n this._log('Cannot connect — manager is destroyed');\n return;\n }\n\n // SSR guard\n if (typeof WebSocket === 'undefined') {\n this._log('WebSocket is not available in this environment');\n return;\n }\n\n // If already connected or connecting, no-op\n if (this._state === 'connected' || this._state === 'connecting') {\n this._log(`Already in state \"${this._state}\", ignoring connect()`);\n return;\n }\n\n // A manual connect() call from FAILED state resets the attempt counter\n if (this._state === 'failed') {\n this._reconnectAttempts = 0;\n }\n\n this._setState('connecting');\n await this._attemptConnection();\n }\n\n /** Gracefully close the connection */\n close(code?: number, reason?: string): void {\n this._log('close() called');\n this._clearTimers();\n this._reconnectAttempts = 0;\n\n if (this._socket) {\n // Remove listeners before closing to prevent the close handler from\n // triggering reconnection logic.\n this._detachSocketListeners(this._socket);\n try {\n this._socket.close(code ?? 1000, reason ?? 'Client closed');\n } catch {\n // Socket may already be closed; ignore.\n }\n this._socket = null;\n }\n\n this._setState('disconnected');\n }\n\n /**\n * Send data through the WebSocket.\n * - If state is `connecting` or `reconnecting`, the message is queued.\n * - If state is `connected`, the message is sent immediately.\n * - If state is `failed` or `suspended`, an error is thrown.\n * - If state is `disconnected`, the message is queued (a reconnect may follow).\n */\n send(data: MessagePayload): void {\n if (this._state === 'failed') {\n throw new Error(\n `[GuideKit:WS:${this._label}] Cannot send — connection is in FAILED state. Call connect() to retry.`,\n );\n }\n\n if (this._state === 'suspended') {\n throw new Error(\n `[GuideKit:WS:${this._label}] Cannot send — connection is SUSPENDED. Call resume() first.`,\n );\n }\n\n if (this._state === 'connected' && this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(data);\n return;\n }\n\n // Queue the message for later delivery\n this._enqueue(data);\n }\n\n // ── Suspend / Resume ────────────────────────────────────────────────\n\n /** Suspend reconnection (e.g., during confirmed offline). No reconnection attempts. */\n suspend(): void {\n if (this._state === 'failed' || this._state === 'suspended') {\n this._log(`suspend() ignored — already in \"${this._state}\"`);\n return;\n }\n\n this._log('Suspending');\n this._clearTimers();\n\n // If there is an active socket, close it\n if (this._socket) {\n this._detachSocketListeners(this._socket);\n try {\n this._socket.close(1000, 'Suspended');\n } catch {\n // ignore\n }\n this._socket = null;\n }\n\n this._setState('suspended');\n }\n\n /** Resume from suspended state. Triggers reconnection. */\n resume(): void {\n if (this._state !== 'suspended') {\n this._log(`resume() ignored — not in SUSPENDED state (current: \"${this._state}\")`);\n return;\n }\n\n this._log('Resuming');\n this._reconnectAttempts = 0;\n this._setState('reconnecting');\n this._scheduleReconnect();\n }\n\n // ── Event registration ──────────────────────────────────────────────\n\n /** Register an onOpen handler. Returns an unsubscribe function. */\n onOpen(callback: () => void): () => void {\n this._onOpenCallbacks.add(callback);\n return () => {\n this._onOpenCallbacks.delete(callback);\n };\n }\n\n /** Register an onClose handler. Returns an unsubscribe function. */\n onClose(callback: (code: number, reason: string) => void): () => void {\n this._onCloseCallbacks.add(callback);\n return () => {\n this._onCloseCallbacks.delete(callback);\n };\n }\n\n /** Register an onMessage handler. Returns an unsubscribe function. */\n onMessage(callback: (data: MessageEvent) => void): () => void {\n this._onMessageCallbacks.add(callback);\n return () => {\n this._onMessageCallbacks.delete(callback);\n };\n }\n\n /** Register an onError handler. Returns an unsubscribe function. */\n onError(callback: (error: Event) => void): () => void {\n this._onErrorCallbacks.add(callback);\n return () => {\n this._onErrorCallbacks.delete(callback);\n };\n }\n\n /** Register a state change handler. Returns an unsubscribe function. */\n onStateChange(callback: (state: WSState, previous: WSState) => void): () => void {\n this._onStateChangeCallbacks.add(callback);\n return () => {\n this._onStateChangeCallbacks.delete(callback);\n };\n }\n\n // ── Destroy ─────────────────────────────────────────────────────────\n\n /** Destroy the manager and clean up all resources */\n destroy(): void {\n if (this._destroyed) return;\n this._destroyed = true;\n this._log('Destroying');\n\n this.close();\n this._queue = [];\n this._onOpenCallbacks.clear();\n this._onCloseCallbacks.clear();\n this._onMessageCallbacks.clear();\n this._onErrorCallbacks.clear();\n this._onStateChangeCallbacks.clear();\n }\n\n // ── Private: Connection logic ───────────────────────────────────────\n\n private async _resolveUrl(): Promise<string> {\n if (typeof this._url === 'function') {\n return await this._url();\n }\n return this._url;\n }\n\n private async _attemptConnection(): Promise<void> {\n // SSR guard\n if (typeof WebSocket === 'undefined') return;\n\n let url: string;\n try {\n url = await this._resolveUrl();\n } catch (err) {\n this._log(`URL resolution failed: ${err}`);\n this._handleConnectionFailure();\n return;\n }\n\n this._log(`Connecting to ${url}`);\n\n let ws: WebSocket;\n try {\n ws = this._protocols ? new WebSocket(url, this._protocols) : new WebSocket(url);\n } catch (err) {\n this._log(`WebSocket constructor threw: ${err}`);\n this._handleConnectionFailure();\n return;\n }\n\n // Binary type: arraybuffer is generally more useful than blob\n ws.binaryType = 'arraybuffer';\n\n this._socket = ws;\n\n // ── Connection timeout ──────────────────────────────────────────\n this._connectTimer = setTimeout(() => {\n if (ws.readyState === WebSocket.CONNECTING) {\n this._log('Connection timed out');\n // Force-close the socket; the close handler will trigger reconnection.\n ws.close();\n }\n }, this._connectTimeoutMs);\n\n // ── Socket event handlers ───────────────────────────────────────\n const onOpen = () => {\n this._clearConnectTimer();\n this._reconnectAttempts = 0;\n this._setState('connected');\n this._log('Connected');\n\n // Notify listeners\n for (const cb of this._onOpenCallbacks) {\n try {\n cb();\n } catch {\n // Swallow listener errors\n }\n }\n\n // Flush queued messages\n this._flushQueue();\n };\n\n const onClose = (event: CloseEvent) => {\n this._clearConnectTimer();\n this._log(`Socket closed — code=${event.code} reason=\"${event.reason}\"`);\n\n // Notify close listeners\n for (const cb of this._onCloseCallbacks) {\n try {\n cb(event.code, event.reason);\n } catch {\n // Swallow listener errors\n }\n }\n\n // Clean up this socket reference if it is the current one\n if (this._socket === ws) {\n this._socket = null;\n }\n\n // Only attempt reconnection if the manager hasn't been destroyed or\n // intentionally closed (state would be 'disconnected' in that case).\n if (\n !this._destroyed &&\n this._state !== 'disconnected' &&\n this._state !== 'suspended' &&\n this._state !== 'failed'\n ) {\n this._setState('disconnected');\n this._handleConnectionFailure();\n }\n };\n\n const onError = (event: Event) => {\n this._log('Socket error');\n for (const cb of this._onErrorCallbacks) {\n try {\n cb(event);\n } catch {\n // Swallow listener errors\n }\n }\n // The `close` event will follow the `error` event, so reconnection\n // logic is handled there.\n };\n\n const onMessage = (event: MessageEvent) => {\n for (const cb of this._onMessageCallbacks) {\n try {\n cb(event);\n } catch {\n // Swallow listener errors\n }\n }\n };\n\n ws.addEventListener('open', onOpen);\n ws.addEventListener('close', onClose);\n ws.addEventListener('error', onError);\n ws.addEventListener('message', onMessage);\n\n // Store references for later removal\n this._listenerRefs.set(ws, { onOpen, onClose, onError, onMessage });\n }\n\n private _detachSocketListeners(ws: WebSocket): void {\n const listeners = this._listenerRefs.get(ws);\n if (!listeners) return;\n ws.removeEventListener('open', listeners.onOpen);\n ws.removeEventListener('close', listeners.onClose);\n ws.removeEventListener('error', listeners.onError);\n ws.removeEventListener('message', listeners.onMessage);\n this._listenerRefs.delete(ws);\n }\n\n // ── Private: Reconnection ───────────────────────────────────────────\n\n private _handleConnectionFailure(): void {\n if (this._destroyed || this._state === 'suspended') return;\n\n this._reconnectAttempts++;\n\n if (this._reconnectAttempts > this._maxReconnectAttempts) {\n this._log(\n `Max reconnect attempts (${this._maxReconnectAttempts}) reached — entering FAILED state`,\n );\n this._setState('failed');\n return;\n }\n\n this._setState('reconnecting');\n this._scheduleReconnect();\n }\n\n private _scheduleReconnect(): void {\n if (this._destroyed) return;\n\n const delay = this._calculateBackoff(this._reconnectAttempts - 1);\n this._log(`Reconnecting in ${delay}ms (attempt ${this._reconnectAttempts}/${this._maxReconnectAttempts})`);\n\n this._reconnectTimer = setTimeout(async () => {\n this._reconnectTimer = null;\n if (this._destroyed || this._state === 'suspended' || this._state === 'failed') return;\n\n this._setState('connecting');\n await this._attemptConnection();\n }, delay);\n }\n\n /**\n * Exponential backoff with jitter.\n * delay = initialDelay * 2^attempt, capped at maxDelay, with +/-25% jitter.\n */\n private _calculateBackoff(attempt: number): number {\n const exponential = this._initialDelay * Math.pow(2, attempt);\n const capped = Math.min(exponential, this._maxDelay);\n // Jitter: random value between 0.75 and 1.25 of the capped delay\n const jitter = 0.75 + Math.random() * 0.5;\n return Math.round(capped * jitter);\n }\n\n // ── Private: Send queue ─────────────────────────────────────────────\n\n private _enqueue(data: MessagePayload): void {\n if (this._queue.length >= MAX_QUEUE_SIZE) {\n this._log('Send queue full — dropping oldest message');\n this._queue.shift();\n }\n this._queue.push(data);\n }\n\n private _flushQueue(): void {\n if (\n this._queue.length === 0 ||\n !this._socket ||\n this._socket.readyState !== WebSocket.OPEN\n ) {\n return;\n }\n\n this._log(`Flushing ${this._queue.length} queued message(s)`);\n const pending = this._queue.slice();\n this._queue = [];\n\n for (const msg of pending) {\n try {\n this._socket.send(msg);\n } catch (err) {\n this._log(`Failed to send queued message: ${err}`);\n // Re-queue remaining messages on failure\n // The current message is lost but remaining ones are preserved.\n break;\n }\n }\n }\n\n // ── Private: State management ───────────────────────────────────────\n\n private _setState(next: WSState): void {\n const prev = this._state;\n if (prev === next) return;\n\n this._state = next;\n this._log(`State: ${prev} -> ${next}`);\n\n for (const cb of this._onStateChangeCallbacks) {\n try {\n cb(next, prev);\n } catch {\n // Swallow listener errors\n }\n }\n }\n\n // ── Private: Timer management ───────────────────────────────────────\n\n private _clearTimers(): void {\n this._clearConnectTimer();\n this._clearReconnectTimer();\n }\n\n private _clearConnectTimer(): void {\n if (this._connectTimer !== null) {\n clearTimeout(this._connectTimer);\n this._connectTimer = null;\n }\n }\n\n private _clearReconnectTimer(): void {\n if (this._reconnectTimer !== null) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n\n // ── Private: Logging ────────────────────────────────────────────────\n\n private _log(message: string): void {\n if (this._debug) {\n console.log(`[GuideKit:WS:${this._label}] ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Deepgram Nova Real-Time Speech-to-Text Adapter\n// ---------------------------------------------------------------------------\n//\n// Streams microphone audio to Deepgram over a WebSocket and emits interim /\n// final transcript events. Designed for browser use; all browser-only APIs are\n// guarded behind `typeof window` checks so the module is safe to import at\n// build time in SSR environments.\n// ---------------------------------------------------------------------------\n\nimport { WebSocketManager } from './websocket-manager.js';\nimport type { STTTranscriptEvent } from '../types/index.js';\n\n// Re-export the shared type for consumers that only import from this module\nexport type { STTTranscriptEvent };\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:STT]';\n\n/** Interval (ms) between KeepAlive messages sent to Deepgram. */\nconst KEEPALIVE_INTERVAL_MS = 10_000;\n\n/** Default Deepgram model. */\nconst DEFAULT_MODEL = 'nova-3';\n\n/** Default language. */\nconst DEFAULT_LANGUAGE = 'en';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface DeepgramSTTOptions {\n apiKey: string;\n model?: 'nova-2' | 'nova-3';\n language?: string;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert Float32Array PCM samples (range -1..1) to Int16Array (linear16).\n * Deepgram expects linear16 encoded audio frames.\n */\nfunction float32ToInt16(float32: Float32Array): Int16Array {\n const int16 = new Int16Array(float32.length);\n for (let i = 0; i < float32.length; i++) {\n // Clamp to [-1, 1] then scale to Int16 range.\n const s = Math.max(-1, Math.min(1, float32[i]!));\n int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n return int16;\n}\n\n// ---------------------------------------------------------------------------\n// DeepgramSTT\n// ---------------------------------------------------------------------------\n\nexport class DeepgramSTT {\n // ---- Configuration ------------------------------------------------------\n\n private readonly apiKey: string;\n private readonly model: 'nova-2' | 'nova-3';\n private readonly language: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state -----------------------------------------------------\n\n private wsManager: WebSocketManager | null = null;\n private keepAliveTimer: ReturnType<typeof setInterval> | null = null;\n private _connected = false;\n private _suspended = false;\n\n /** Registered transcript callbacks. */\n private readonly transcriptCallbacks: Set<(event: STTTranscriptEvent) => void> =\n new Set();\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options: DeepgramSTTOptions) {\n this.apiKey = options.apiKey;\n this.model = options.model ?? DEFAULT_MODEL;\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.debugEnabled = options.debug ?? false;\n\n this.log('DeepgramSTT created', {\n model: this.model,\n language: this.language,\n });\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Whether the WebSocket is currently connected and ready. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Open a WebSocket connection to Deepgram's real-time STT endpoint.\n *\n * Resolves once the connection is established and the socket is ready to\n * receive audio frames. Rejects if the connection cannot be established.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof WebSocket === 'undefined') {\n this.log('WebSocket API not available (SSR?) — cannot connect');\n return;\n }\n\n const url = this.buildUrl();\n this.log('Connecting to', url.replace(this.apiKey, '***'));\n\n this.wsManager = new WebSocketManager({\n url,\n protocols: [],\n debug: this.debugEnabled,\n label: 'Deepgram-STT',\n });\n\n this.wsManager.onOpen(() => {\n this._connected = true;\n this.startKeepAlive();\n this.log('Connected');\n });\n this.wsManager.onMessage((event: MessageEvent) => {\n this.handleMessage(event);\n });\n this.wsManager.onClose((code: number, reason: string) => {\n this.log('Connection closed', { code, reason });\n this.cleanup();\n });\n this.wsManager.onError((event: Event) => {\n this.log('WebSocket error', event);\n });\n\n return this.wsManager.connect();\n }\n\n /**\n * Send audio data to Deepgram for transcription.\n *\n * Accepts either `Float32Array` (Web Audio API output) or `Int16Array`\n * (already encoded as linear16). Float32 data is automatically converted\n * to Int16 before sending.\n */\n sendAudio(audioData: Float32Array | Int16Array): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n return;\n }\n\n let buffer: ArrayBuffer;\n if (audioData instanceof Float32Array) {\n buffer = float32ToInt16(audioData).buffer as ArrayBuffer;\n } else {\n buffer = audioData.buffer as ArrayBuffer;\n }\n\n this.wsManager.send(buffer);\n }\n\n /**\n * Register a callback to receive transcript events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onTranscript(callback: (event: STTTranscriptEvent) => void): () => void {\n this.transcriptCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.transcriptCallbacks.delete(callback);\n };\n }\n\n /**\n * Gracefully close the connection.\n *\n * Sends a `CloseStream` message to Deepgram so the server can finalise\n * any pending transcription before the socket is torn down.\n */\n close(): void {\n if (!this._connected || !this.wsManager) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Sending CloseStream and closing');\n this.stopKeepAlive();\n\n try {\n this.wsManager.send(JSON.stringify({ type: 'CloseStream' }));\n } catch {\n // Socket may already be closing — ignore.\n }\n\n this.wsManager.close();\n this.cleanup();\n }\n\n /** Force-destroy the connection without a graceful handshake. */\n destroy(): void {\n this.log('Destroying');\n this.stopKeepAlive();\n\n if (this.wsManager) {\n this.wsManager.destroy();\n this.wsManager = null;\n }\n\n this.cleanup();\n this.transcriptCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Stops the keepalive timer and marks the adapter as suspended so that\n * incoming `sendAudio` calls are silently dropped. The WebSocket itself\n * is left open; Deepgram will close it after an inactivity timeout if\n * the network truly went away.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this.stopKeepAlive();\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`. If the underlying connection is\n * still alive, the keepalive timer is restarted. If the connection was\n * lost while suspended, callers should `close()` / `destroy()` and\n * create a new instance.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this.log('Resumed');\n\n if (this._connected && this.wsManager) {\n this.startKeepAlive();\n }\n }\n\n // -----------------------------------------------------------------------\n // Message handling\n // -----------------------------------------------------------------------\n\n /**\n * Parse incoming Deepgram JSON messages and emit transcript events.\n *\n * Deepgram sends `Results` messages with the following shape:\n * ```json\n * {\n * \"type\": \"Results\",\n * \"channel\": {\n * \"alternatives\": [{ \"transcript\": \"...\", \"confidence\": 0.97 }]\n * },\n * \"is_final\": true,\n * \"speech_final\": true\n * }\n * ```\n */\n private handleMessage(event: MessageEvent): void {\n // Binary messages are not expected — ignore.\n if (typeof event.data !== 'string') {\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n this.log('Failed to parse message', event.data);\n return;\n }\n\n const type = parsed['type'] as string | undefined;\n\n if (type === 'Results') {\n this.handleResultsMessage(parsed);\n } else if (type === 'Metadata') {\n this.log('Received metadata', parsed);\n } else if (type === 'Error') {\n this.log('Deepgram error', parsed);\n } else {\n this.log('Unknown message type', type, parsed);\n }\n }\n\n /**\n * Extract transcript data from a `Results` message and notify subscribers.\n */\n private handleResultsMessage(parsed: Record<string, unknown>): void {\n const channel = parsed['channel'] as\n | { alternatives?: { transcript?: string; confidence?: number }[] }\n | undefined;\n\n const alternatives = channel?.alternatives;\n if (!alternatives || alternatives.length === 0) {\n return;\n }\n\n const best = alternatives[0];\n if (!best) return;\n const transcript = best.transcript ?? '';\n const confidence = best.confidence ?? 0;\n\n // Deepgram sends empty transcripts for silence — skip those.\n if (transcript.trim() === '') {\n return;\n }\n\n const isFinal =\n (parsed['is_final'] === true) && (parsed['speech_final'] === true);\n\n const transcriptEvent: STTTranscriptEvent = {\n text: transcript,\n isFinal,\n confidence,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final transcript:' : 'Interim transcript:',\n transcript,\n `(${(confidence * 100).toFixed(1)}%)`,\n );\n\n this.emitTranscript(transcriptEvent);\n }\n\n // -----------------------------------------------------------------------\n // Keepalive\n // -----------------------------------------------------------------------\n\n /** Start the periodic KeepAlive heartbeat. */\n private startKeepAlive(): void {\n this.stopKeepAlive();\n\n this.keepAliveTimer = setInterval(() => {\n if (this._connected && this.wsManager && !this._suspended) {\n try {\n this.wsManager.send(JSON.stringify({ type: 'KeepAlive' }));\n this.log('Sent KeepAlive');\n } catch {\n this.log('Failed to send KeepAlive');\n }\n }\n }, KEEPALIVE_INTERVAL_MS);\n }\n\n /** Stop the KeepAlive heartbeat. */\n private stopKeepAlive(): void {\n if (this.keepAliveTimer !== null) {\n clearInterval(this.keepAliveTimer);\n this.keepAliveTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // Subscriber notification\n // -----------------------------------------------------------------------\n\n /**\n * Emit a transcript event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitTranscript(event: STTTranscriptEvent): void {\n for (const cb of this.transcriptCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // URL building\n // -----------------------------------------------------------------------\n\n /** Build the Deepgram streaming endpoint URL with query parameters. */\n private buildUrl(): string {\n // NOTE: API key in WebSocket URL is inherent to Deepgram's WS protocol.\n // This is a known limitation — keys should only be session-scoped tokens.\n const params = new URLSearchParams({\n model: this.model,\n language: this.language,\n punctuate: 'true',\n interim_results: 'true',\n endpointing: '300',\n token: this.apiKey,\n });\n\n return `wss://api.deepgram.com/v1/listen?${params.toString()}`;\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n this.stopKeepAlive();\n }\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – ElevenLabs Real-Time Speech-to-Text Adapter\n// ---------------------------------------------------------------------------\n//\n// Streams microphone audio to ElevenLabs over a WebSocket using JSON messages\n// with base64-encoded PCM audio. Emits interim / final transcript events.\n//\n// Protocol:\n// - Send: { type: 'input_audio_chunk', audio: <base64>, sample_rate: 16000 }\n// - Receive: { type: 'partial_transcript', result: { text, confidence } }\n// { type: 'committed_transcript', result: { text, confidence } }\n// - Close: send { type: 'commit_audio' } before closing socket\n// ---------------------------------------------------------------------------\n\nimport { WebSocketManager } from './websocket-manager.js';\nimport type { STTTranscriptEvent } from '../types/index.js';\n\n// Re-export the shared type for consumers that only import from this module\nexport type { STTTranscriptEvent };\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:ElevenLabs-STT]';\n\nconst ELEVENLABS_STT_ENDPOINT =\n 'wss://api.elevenlabs.io/v1/speech-to-text/realtime';\n\nconst DEFAULT_LANGUAGE = 'en';\nconst INACTIVITY_TIMEOUT_S = 30;\nconst SAMPLE_RATE = 16_000;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ElevenLabsSTTOptions {\n apiKey: string;\n language?: string;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert Float32Array PCM samples (range -1..1) to Int16Array (linear16).\n */\nfunction float32ToInt16(float32: Float32Array): Int16Array {\n const int16 = new Int16Array(float32.length);\n for (let i = 0; i < float32.length; i++) {\n const s = Math.max(-1, Math.min(1, float32[i]!));\n int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n return int16;\n}\n\n/**\n * Encode an Int16Array as a base64 string.\n * Uses chunked encoding to avoid stack overflow on large buffers.\n */\nfunction int16ToBase64(int16: Int16Array): string {\n const bytes = new Uint8Array(int16.buffer);\n // Replace character-by-character loop with chunked encoding\n const CHUNK_SIZE = 8192;\n let binary = '';\n for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {\n const chunk = bytes.subarray(i, i + CHUNK_SIZE);\n binary += String.fromCharCode(...chunk);\n }\n return btoa(binary);\n}\n\n// ---------------------------------------------------------------------------\n// ElevenLabsSTT\n// ---------------------------------------------------------------------------\n\nexport class ElevenLabsSTT {\n // ---- Configuration -------------------------------------------------------\n\n private readonly apiKey: string;\n private readonly language: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state ------------------------------------------------------\n\n private wsManager: WebSocketManager | null = null;\n private _connected = false;\n private _suspended = false;\n\n /** Registered transcript callbacks. */\n private readonly transcriptCallbacks: Set<(event: STTTranscriptEvent) => void> =\n new Set();\n\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(options: ElevenLabsSTTOptions) {\n this.apiKey = options.apiKey;\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.debugEnabled = options.debug ?? false;\n\n this.log('ElevenLabsSTT created', { language: this.language });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Whether the WebSocket is currently connected and ready. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Open a WebSocket connection to ElevenLabs' real-time STT endpoint.\n *\n * Resolves once the connection is established and the socket is ready to\n * receive audio frames. Rejects if the connection cannot be established.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n if (typeof WebSocket === 'undefined') {\n this.log('WebSocket API not available (SSR?) — cannot connect');\n return;\n }\n\n const url = this.buildUrl();\n this.log('Connecting to', url.replace(this.apiKey, '***'));\n\n this.wsManager = new WebSocketManager({\n url,\n protocols: [],\n debug: this.debugEnabled,\n label: 'ElevenLabs-STT',\n });\n\n this.wsManager.onOpen(() => {\n this._connected = true;\n this.log('Connected');\n });\n this.wsManager.onMessage((event: MessageEvent) => {\n this.handleMessage(event);\n });\n this.wsManager.onClose((code: number, reason: string) => {\n this.log('Connection closed', { code, reason });\n this.cleanup();\n });\n this.wsManager.onError((event: Event) => {\n this.log('WebSocket error', event);\n });\n\n return this.wsManager.connect();\n }\n\n /**\n * Send audio data to ElevenLabs for transcription.\n *\n * Accepts either `Float32Array` (Web Audio API output) or `Int16Array`\n * (already encoded as linear16). Float32 data is automatically converted\n * to Int16 before encoding. Audio is sent as a base64-encoded JSON message.\n */\n sendAudio(audioData: Float32Array | Int16Array): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n return;\n }\n\n const int16 =\n audioData instanceof Float32Array ? float32ToInt16(audioData) : audioData;\n\n const base64 = int16ToBase64(int16);\n\n this.wsManager.send(\n JSON.stringify({\n type: 'input_audio_chunk',\n audio: base64,\n sample_rate: SAMPLE_RATE,\n }),\n );\n }\n\n /**\n * Register a callback to receive transcript events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onTranscript(callback: (event: STTTranscriptEvent) => void): () => void {\n this.transcriptCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.transcriptCallbacks.delete(callback);\n };\n }\n\n /**\n * Gracefully close the connection.\n *\n * Sends a `commit_audio` message so ElevenLabs can finalise any pending\n * transcription before the socket is torn down.\n */\n close(): void {\n if (!this._connected || !this.wsManager) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Sending commit_audio and closing');\n\n try {\n this.wsManager.send(JSON.stringify({ type: 'commit_audio' }));\n } catch {\n // Socket may already be closing — ignore.\n }\n\n this.wsManager.close();\n this.cleanup();\n }\n\n /** Force-destroy the connection without a graceful handshake. */\n destroy(): void {\n this.log('Destroying');\n\n if (this.wsManager) {\n this.wsManager.destroy();\n this.wsManager = null;\n }\n\n this.cleanup();\n this.transcriptCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Marks the adapter as suspended so that incoming `sendAudio` calls are\n * silently dropped. The WebSocket itself is left open.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this.log('Resumed');\n }\n\n // -------------------------------------------------------------------------\n // Message handling\n // -------------------------------------------------------------------------\n\n /**\n * Parse incoming ElevenLabs JSON messages and emit transcript events.\n *\n * ElevenLabs sends two transcript message types:\n * - `partial_transcript`: interim result, `isFinal = false`\n * - `committed_transcript`: final result, `isFinal = true`\n */\n private handleMessage(event: MessageEvent): void {\n if (typeof event.data !== 'string') {\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n this.log('Failed to parse message', event.data);\n return;\n }\n\n const type = parsed['type'] as string | undefined;\n\n if (type === 'committed_transcript' || type === 'partial_transcript') {\n this.handleTranscriptMessage(parsed, type === 'committed_transcript');\n } else {\n this.log('Received message', type, parsed);\n }\n }\n\n /**\n * Extract transcript data from a transcript message and notify subscribers.\n */\n private handleTranscriptMessage(\n parsed: Record<string, unknown>,\n isFinal: boolean,\n ): void {\n const result = parsed['result'] as\n | { text?: string; confidence?: number }\n | undefined;\n\n const text = result?.text ?? '';\n const confidence = result?.confidence ?? 0;\n\n if (text.trim() === '') {\n return;\n }\n\n const transcriptEvent: STTTranscriptEvent = {\n text,\n isFinal,\n confidence,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final transcript:' : 'Interim transcript:',\n text,\n `(${(confidence * 100).toFixed(1)}%)`,\n );\n\n this.emitTranscript(transcriptEvent);\n }\n\n // -------------------------------------------------------------------------\n // Subscriber notification\n // -------------------------------------------------------------------------\n\n /**\n * Emit a transcript event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitTranscript(event: STTTranscriptEvent): void {\n for (const cb of this.transcriptCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // URL building\n // -------------------------------------------------------------------------\n\n /** Build the ElevenLabs streaming STT endpoint URL with auth query params. */\n private buildUrl(): string {\n const params = new URLSearchParams({\n xi_api_key: this.apiKey,\n language: this.language,\n inactivity_timeout: String(INACTIVITY_TIMEOUT_S),\n });\n\n return `${ELEVENLABS_STT_ENDPOINT}?${params.toString()}`;\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n }\n\n // -------------------------------------------------------------------------\n // Logging\n // -------------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – ElevenLabs Real-Time Text-to-Speech Adapter\n// ---------------------------------------------------------------------------\n//\n// Streams text to ElevenLabs over a WebSocket and receives audio chunks in\n// real time. Designed for browser use; all browser-only APIs are guarded\n// behind `typeof window` checks so the module is safe to import at build\n// time in SSR environments.\n// ---------------------------------------------------------------------------\n\nimport { WebSocketManager } from './websocket-manager.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:TTS]';\n\n/** Default ElevenLabs voice ID (Rachel). */\nconst DEFAULT_VOICE_ID = '21m00Tcm4TlvDq8ikWAM';\n\n/** Default model — ElevenLabs Flash v2.5 for lowest latency. */\nconst DEFAULT_MODEL_ID = 'eleven_flash_v2_5';\n\n/** Default voice stability setting (0–1). */\nconst DEFAULT_STABILITY = 0.5;\n\n/** Default similarity boost setting (0–1). */\nconst DEFAULT_SIMILARITY_BOOST = 0.75;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ElevenLabsTTSOptions {\n apiKey: string;\n voiceId?: string;\n modelId?: string;\n debug?: boolean;\n}\n\nexport interface TTSAudioEvent {\n audio: ArrayBuffer;\n /** Whether this is the final chunk for the current utterance. */\n isFinal: boolean;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Decode a base64-encoded string into an `ArrayBuffer`.\n *\n * Uses the native `atob` function available in browsers. In SSR contexts\n * the adapter will never reach this code path because `connect()` is\n * guarded by a WebSocket availability check.\n */\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = atob(base64);\n const length = binaryString.length;\n const bytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n// ---------------------------------------------------------------------------\n// ElevenLabsTTS\n// ---------------------------------------------------------------------------\n\nexport class ElevenLabsTTS {\n // ---- Configuration ------------------------------------------------------\n\n private readonly apiKey: string;\n private readonly voiceId: string;\n private readonly modelId: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state -----------------------------------------------------\n\n private wsManager: WebSocketManager | null = null;\n private _connected = false;\n private _suspended = false;\n\n /**\n * Whether the BOS (beginning-of-stream) handshake has been sent for the\n * current WebSocket session. ElevenLabs requires the first message to\n * contain voice settings and the API key before any text chunks.\n */\n private bosSent = false;\n\n /** Registered audio-event callbacks. */\n private readonly audioCallbacks: Set<(event: TTSAudioEvent) => void> =\n new Set();\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options: ElevenLabsTTSOptions) {\n this.apiKey = options.apiKey;\n this.voiceId = options.voiceId ?? DEFAULT_VOICE_ID;\n this.modelId = options.modelId ?? DEFAULT_MODEL_ID;\n this.debugEnabled = options.debug ?? false;\n\n this.log('ElevenLabsTTS created', {\n voiceId: this.voiceId,\n modelId: this.modelId,\n });\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Whether the WebSocket is currently connected and ready. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Open a WebSocket connection to the ElevenLabs streaming TTS endpoint.\n *\n * Resolves once the connection is established and the BOS handshake has\n * been sent. Rejects if the connection cannot be established.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof WebSocket === 'undefined') {\n this.log('WebSocket API not available (SSR?) — cannot connect');\n return;\n }\n\n const url = this.buildUrl();\n this.log('Connecting to', url);\n\n this.wsManager = new WebSocketManager({\n url,\n protocols: [],\n debug: this.debugEnabled,\n label: 'ElevenLabs-TTS',\n });\n\n this.wsManager.onOpen(() => {\n this._connected = true;\n this.sendBOS();\n this.log('Connected and BOS sent');\n });\n this.wsManager.onMessage((event: MessageEvent) => {\n this.handleMessage(event);\n });\n this.wsManager.onClose((code: number, reason: string) => {\n this.log('Connection closed', { code, reason });\n this.cleanup();\n });\n this.wsManager.onError((event: Event) => {\n this.log('WebSocket error', event);\n });\n\n return this.wsManager.connect();\n }\n\n /**\n * Send text to be synthesised into speech.\n *\n * May be called multiple times to stream text incrementally. Each call\n * sends a text chunk with `try_trigger_generation: true` so ElevenLabs\n * can begin synthesising as soon as it has enough context.\n *\n * Call {@link flush} when the complete utterance has been sent.\n */\n speak(text: string): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n this.log('Cannot speak — not connected or suspended');\n return;\n }\n\n if (!text) {\n return;\n }\n\n const message = JSON.stringify({\n text,\n try_trigger_generation: true,\n });\n\n this.log('Sending text chunk:', text.slice(0, 80) + (text.length > 80 ? '...' : ''));\n this.wsManager.send(message);\n }\n\n /**\n * Signal the end of text input for the current utterance.\n *\n * Sends the EOS (end-of-stream) marker to ElevenLabs. The server will\n * flush any remaining audio and send a final chunk with `isFinal: true`.\n */\n flush(): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n this.log('Cannot flush — not connected or suspended');\n return;\n }\n\n const message = JSON.stringify({ text: '' });\n this.log('Sending EOS (flush)');\n this.wsManager.send(message);\n }\n\n /**\n * Register a callback to receive audio output events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onAudio(callback: (event: TTSAudioEvent) => void): () => void {\n this.audioCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.audioCallbacks.delete(callback);\n };\n }\n\n /** Gracefully close the connection by sending EOS then closing. */\n close(): void {\n if (!this._connected || !this.wsManager) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Closing connection');\n\n // Send EOS to let the server finalise any pending audio.\n try {\n this.wsManager.send(JSON.stringify({ text: '' }));\n } catch {\n // Socket may already be closing — ignore.\n }\n\n this.wsManager.close();\n this.cleanup();\n }\n\n /** Force-destroy the connection without a graceful handshake. */\n destroy(): void {\n this.log('Destroying');\n\n if (this.wsManager) {\n this.wsManager.destroy();\n this.wsManager = null;\n }\n\n this.cleanup();\n this.audioCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Marks the adapter as suspended so that calls to `speak()` and `flush()`\n * are silently dropped. The WebSocket itself is left open; ElevenLabs\n * will close it after an inactivity timeout if the network went away.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`. If the underlying connection is\n * still alive, the adapter returns to normal operation. If the connection\n * was lost while suspended, callers should `close()` / `destroy()` and\n * create a new instance.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this.log('Resumed');\n }\n\n // -----------------------------------------------------------------------\n // BOS handshake\n // -----------------------------------------------------------------------\n\n /**\n * Send the BOS (beginning-of-stream) message.\n *\n * This must be the very first message on a new WebSocket session. It\n * carries the API key and voice settings.\n */\n private sendBOS(): void {\n if (!this.wsManager || this.bosSent) {\n return;\n }\n\n const bos = JSON.stringify({\n text: ' ',\n voice_settings: {\n stability: DEFAULT_STABILITY,\n similarity_boost: DEFAULT_SIMILARITY_BOOST,\n },\n xi_api_key: this.apiKey,\n });\n\n this.wsManager.send(bos);\n this.bosSent = true;\n this.log('BOS handshake sent');\n }\n\n // -----------------------------------------------------------------------\n // Message handling\n // -----------------------------------------------------------------------\n\n /**\n * Parse incoming ElevenLabs JSON messages and emit audio events.\n *\n * ElevenLabs sends messages with the following shape:\n * ```json\n * { \"audio\": \"base64encoded...\", \"isFinal\": false }\n * ```\n *\n * When `isFinal` is `true`, the server has finished synthesising the\n * current utterance (i.e. after EOS was sent).\n */\n private handleMessage(event: MessageEvent): void {\n // Binary messages are not expected from ElevenLabs — ignore.\n if (typeof event.data !== 'string') {\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n this.log('Failed to parse message', event.data);\n return;\n }\n\n // Handle error responses from ElevenLabs.\n if (parsed['error'] !== undefined) {\n this.log('ElevenLabs error:', parsed['error']);\n return;\n }\n\n // Handle alignment / metadata messages (no audio payload).\n if (parsed['audio'] === undefined || parsed['audio'] === null) {\n this.log('Non-audio message received', parsed);\n return;\n }\n\n const audioBase64 = parsed['audio'] as string;\n const isFinal = parsed['isFinal'] === true;\n\n // Skip empty audio chunks.\n if (!audioBase64 || audioBase64.length === 0) {\n if (isFinal) {\n // Emit a final event even without audio so consumers know the\n // utterance has ended.\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n }\n return;\n }\n\n let audioBuffer: ArrayBuffer;\n try {\n audioBuffer = base64ToArrayBuffer(audioBase64);\n } catch (err) {\n this.log('Failed to decode base64 audio', err);\n return;\n }\n\n const audioEvent: TTSAudioEvent = {\n audio: audioBuffer,\n isFinal,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final audio chunk:' : 'Audio chunk:',\n `${audioBuffer.byteLength} bytes`,\n );\n\n this.emitAudio(audioEvent);\n }\n\n // -----------------------------------------------------------------------\n // Subscriber notification\n // -----------------------------------------------------------------------\n\n /**\n * Emit an audio event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitAudio(event: TTSAudioEvent): void {\n for (const cb of this.audioCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Audio callback threw:', err);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // URL building\n // -----------------------------------------------------------------------\n\n /** Build the ElevenLabs streaming TTS endpoint URL. */\n private buildUrl(): string {\n const params = new URLSearchParams({\n model_id: this.modelId,\n });\n\n return `wss://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(this.voiceId)}/stream-input?${params.toString()}`;\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n this.bosSent = false;\n }\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Web Speech API Speech-to-Text Adapter\n// ---------------------------------------------------------------------------\n//\n// Browser-native SpeechRecognition adapter that requires no API keys or\n// external services. Uses the Web Speech API (SpeechRecognition) available\n// in most modern browsers. Designed as the zero-config default when no STT\n// provider is explicitly configured.\n//\n// SSR safe: all browser APIs are guarded behind `typeof window` checks so\n// the module is safe to import at build time in SSR environments.\n// ---------------------------------------------------------------------------\n\nimport type { STTTranscriptEvent } from '../types/index.js';\n\n// Re-export the shared type for consumers that only import from this module\nexport type { STTTranscriptEvent };\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:WebSpeech-STT]';\n\n/** Default language for speech recognition. */\nconst DEFAULT_LANGUAGE = 'en-US';\n\n// ---------------------------------------------------------------------------\n// Browser type declarations\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal type declarations for the Web Speech API SpeechRecognition\n * interface. These cover the subset used by this adapter. Full type\n * definitions are available in lib.dom.d.ts but may not be present in\n * all TS configurations.\n */\ninterface SpeechRecognitionEvent {\n readonly resultIndex: number;\n readonly results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionResultList {\n readonly length: number;\n item(index: number): SpeechRecognitionResult;\n [index: number]: SpeechRecognitionResult;\n}\n\ninterface SpeechRecognitionResult {\n readonly length: number;\n readonly isFinal: boolean;\n item(index: number): SpeechRecognitionAlternative;\n [index: number]: SpeechRecognitionAlternative;\n}\n\ninterface SpeechRecognitionAlternative {\n readonly transcript: string;\n readonly confidence: number;\n}\n\ninterface SpeechRecognitionErrorEvent {\n readonly error: string;\n readonly message: string;\n}\n\ninterface SpeechRecognitionInstance extends EventTarget {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n maxAlternatives: number;\n onresult: ((event: SpeechRecognitionEvent) => void) | null;\n onerror: ((event: SpeechRecognitionErrorEvent) => void) | null;\n onend: (() => void) | null;\n onstart: (() => void) | null;\n start(): void;\n stop(): void;\n abort(): void;\n}\n\ninterface SpeechRecognitionConstructor {\n new (): SpeechRecognitionInstance;\n}\n\n// Extend globalThis for webkit-prefixed SpeechRecognition\ndeclare global {\n // eslint-disable-next-line no-var\n var webkitSpeechRecognition: SpeechRecognitionConstructor | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface WebSpeechSTTOptions {\n language?: string;\n continuous?: boolean;\n interimResults?: boolean;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// WebSpeechSTT\n// ---------------------------------------------------------------------------\n\nexport class WebSpeechSTT {\n // ---- Configuration -------------------------------------------------------\n\n private readonly language: string;\n private readonly continuous: boolean;\n private readonly interimResultsEnabled: boolean;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state ------------------------------------------------------\n\n private recognition: SpeechRecognitionInstance | null = null;\n private _connected = false;\n private _suspended = false;\n\n /**\n * Whether we intentionally stopped recognition. Used to distinguish\n * between intentional stop and unexpected end (for auto-restart in\n * continuous mode).\n */\n private _intentionalStop = false;\n\n /** Registered transcript callbacks. */\n private readonly transcriptCallbacks: Set<(event: STTTranscriptEvent) => void> =\n new Set();\n\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(options: WebSpeechSTTOptions = {}) {\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.continuous = options.continuous ?? true;\n this.interimResultsEnabled = options.interimResults ?? true;\n this.debugEnabled = options.debug ?? false;\n\n this.log('WebSpeechSTT created', {\n language: this.language,\n continuous: this.continuous,\n interimResults: this.interimResultsEnabled,\n });\n }\n\n // -------------------------------------------------------------------------\n // Static methods\n // -------------------------------------------------------------------------\n\n /**\n * Check whether the Web Speech API SpeechRecognition is supported in the\n * current environment. Safe to call in SSR (returns false).\n */\n static isSupported(): boolean {\n if (typeof window === 'undefined') return false;\n return (\n typeof (window as unknown as Record<string, unknown>)['SpeechRecognition'] !== 'undefined' ||\n typeof globalThis.webkitSpeechRecognition !== 'undefined'\n );\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Whether recognition is currently active and connected. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Start speech recognition.\n *\n * Creates the SpeechRecognition instance and begins listening. Resolves\n * once the recognition session has started. Rejects if the API is not\n * supported or the browser denies permission.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined') {\n this.log('SSR environment detected — cannot connect');\n return;\n }\n\n const SpeechRecognitionClass = this.resolveSpeechRecognition();\n if (!SpeechRecognitionClass) {\n throw new Error(\n 'Web Speech API (SpeechRecognition) is not supported in this browser.',\n );\n }\n\n this.recognition = new SpeechRecognitionClass();\n this.recognition.lang = this.language;\n this.recognition.continuous = this.continuous;\n this.recognition.interimResults = this.interimResultsEnabled;\n this.recognition.maxAlternatives = 1;\n\n // Wire event handlers\n this.recognition.onstart = () => {\n this._connected = true;\n this._intentionalStop = false;\n this.log('Recognition started');\n };\n\n this.recognition.onresult = (event: SpeechRecognitionEvent) => {\n this.handleResult(event);\n };\n\n this.recognition.onerror = (event: SpeechRecognitionErrorEvent) => {\n this.handleError(event);\n };\n\n this.recognition.onend = () => {\n this.log('Recognition ended');\n const wasConnected = this._connected;\n this._connected = false;\n\n // In continuous mode, auto-restart if not intentionally stopped\n // and we were previously connected (not an error during startup).\n if (\n this.continuous &&\n !this._intentionalStop &&\n !this._suspended &&\n wasConnected\n ) {\n this.log('Auto-restarting continuous recognition');\n try {\n this.recognition?.start();\n } catch {\n this.log('Failed to auto-restart recognition');\n }\n }\n };\n\n // Start recognition\n return new Promise<void>((resolve, reject) => {\n const onStart = (): void => {\n cleanup();\n resolve();\n };\n\n const onError = (event: SpeechRecognitionErrorEvent): void => {\n cleanup();\n reject(new Error(`SpeechRecognition error: ${event.error} — ${event.message}`));\n };\n\n const cleanup = (): void => {\n if (this.recognition) {\n // Remove the one-shot listeners (keep the persistent ones)\n this.recognition.removeEventListener('start', onStart as unknown as EventListener);\n this.recognition.removeEventListener('error', onError as unknown as EventListener);\n }\n };\n\n this.recognition!.addEventListener('start', onStart as unknown as EventListener, { once: true });\n this.recognition!.addEventListener('error', onError as unknown as EventListener, { once: true });\n\n try {\n this.recognition!.start();\n } catch (err) {\n cleanup();\n reject(err);\n }\n });\n }\n\n /**\n * Send audio data. No-op for Web Speech API since it captures audio\n * directly from the microphone via the browser's internal pipeline.\n *\n * Provided for interface compatibility with WebSocket-based STT adapters\n * (DeepgramSTT, ElevenLabsSTT).\n */\n sendAudio(_audioData: Float32Array | Int16Array): void {\n // Web Speech API manages its own audio capture — nothing to do here.\n }\n\n /**\n * Register a callback to receive transcript events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onTranscript(callback: (event: STTTranscriptEvent) => void): () => void {\n this.transcriptCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.transcriptCallbacks.delete(callback);\n };\n }\n\n /**\n * Gracefully stop recognition.\n *\n * Calls `stop()` on the SpeechRecognition instance which allows it to\n * deliver any pending final results before ending.\n */\n close(): void {\n if (!this.recognition) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Closing recognition');\n this._intentionalStop = true;\n\n try {\n this.recognition.stop();\n } catch {\n // Recognition may already be stopped\n }\n\n this.cleanup();\n }\n\n /** Force-destroy the recognition without waiting for pending results. */\n destroy(): void {\n this.log('Destroying');\n this._intentionalStop = true;\n\n if (this.recognition) {\n try {\n this.recognition.abort();\n } catch {\n // Recognition may already be stopped\n }\n this.recognition.onresult = null;\n this.recognition.onerror = null;\n this.recognition.onend = null;\n this.recognition.onstart = null;\n this.recognition = null;\n }\n\n this.cleanup();\n this.transcriptCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Stops recognition and marks the adapter as suspended so that auto-restart\n * does not trigger.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this._intentionalStop = true;\n\n if (this.recognition && this._connected) {\n try {\n this.recognition.stop();\n } catch {\n // Ignore\n }\n }\n\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`. Restarts recognition if it was\n * running before suspension.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this._intentionalStop = false;\n this.log('Resumed');\n\n // Restart recognition if we have an instance\n if (this.recognition && !this._connected) {\n try {\n this.recognition.start();\n } catch {\n this.log('Failed to restart recognition after resume');\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Result handling\n // -------------------------------------------------------------------------\n\n /**\n * Handle SpeechRecognition result events.\n *\n * The `results` property is a SpeechRecognitionResultList containing all\n * results accumulated during this recognition session. We only process\n * results from `resultIndex` onward to avoid re-emitting old results.\n */\n private handleResult(event: SpeechRecognitionEvent): void {\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n if (!result) continue;\n\n const alternative = result[0];\n if (!alternative) continue;\n\n const transcript = alternative.transcript;\n if (!transcript || transcript.trim() === '') continue;\n\n const isFinal = result.isFinal;\n // Web Speech API confidence is 0 for interim results in some browsers\n const confidence = alternative.confidence > 0 ? alternative.confidence : 0.85;\n\n const transcriptEvent: STTTranscriptEvent = {\n text: transcript,\n isFinal,\n confidence,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final transcript:' : 'Interim transcript:',\n transcript,\n `(${(confidence * 100).toFixed(1)}%)`,\n );\n\n this.emitTranscript(transcriptEvent);\n }\n }\n\n // -------------------------------------------------------------------------\n // Error handling\n // -------------------------------------------------------------------------\n\n /**\n * Handle SpeechRecognition errors.\n *\n * Some errors are recoverable (e.g. `no-speech`) and some are fatal\n * (e.g. `not-allowed`). For recoverable errors in continuous mode,\n * recognition will auto-restart via the `onend` handler.\n */\n private handleError(event: SpeechRecognitionErrorEvent): void {\n const errorType = event.error;\n\n this.log('Recognition error:', errorType, event.message);\n\n // 'no-speech' and 'aborted' are common non-fatal errors\n // In continuous mode, the onend handler will auto-restart\n if (errorType === 'no-speech' || errorType === 'aborted') {\n this.log('Non-fatal error — will recover');\n return;\n }\n\n // 'network' errors may be transient\n if (errorType === 'network') {\n this.log('Network error — recognition may auto-restart');\n return;\n }\n\n // Fatal errors: 'not-allowed', 'service-not-allowed', 'language-not-supported'\n // For these, mark as intentionally stopped to prevent auto-restart\n if (\n errorType === 'not-allowed' ||\n errorType === 'service-not-allowed' ||\n errorType === 'language-not-supported'\n ) {\n this._intentionalStop = true;\n this.log('Fatal recognition error — stopping');\n }\n }\n\n // -------------------------------------------------------------------------\n // Subscriber notification\n // -------------------------------------------------------------------------\n\n /**\n * Emit a transcript event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitTranscript(event: STTTranscriptEvent): void {\n for (const cb of this.transcriptCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // SpeechRecognition resolution\n // -------------------------------------------------------------------------\n\n /**\n * Resolve the SpeechRecognition constructor, with the webkit-prefixed\n * fallback. Returns null if not available.\n */\n private resolveSpeechRecognition(): SpeechRecognitionConstructor | null {\n if (typeof window === 'undefined') return null;\n\n const win = window as unknown as Record<string, unknown>;\n if (typeof win['SpeechRecognition'] !== 'undefined') {\n return win['SpeechRecognition'] as SpeechRecognitionConstructor;\n }\n if (typeof globalThis.webkitSpeechRecognition !== 'undefined') {\n return globalThis.webkitSpeechRecognition;\n }\n return null;\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n }\n\n // -------------------------------------------------------------------------\n // Logging\n // -------------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Web Speech API Text-to-Speech Adapter\n// ---------------------------------------------------------------------------\n//\n// Browser-native SpeechSynthesis adapter that requires no API keys or\n// external services. Uses the Web Speech API (SpeechSynthesis) available\n// in all modern browsers. Designed as the zero-config default when no TTS\n// provider is explicitly configured.\n//\n// Unlike the WebSocket-based ElevenLabsTTS adapter, this adapter does not\n// stream audio chunks. Instead it uses the browser's built-in speech\n// synthesis engine and returns a Promise from speak() that resolves when\n// the utterance completes.\n//\n// SSR safe: all browser APIs are guarded behind `typeof window` checks so\n// the module is safe to import at build time in SSR environments.\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:WebSpeech-TTS]';\n\n/** Default speech rate (1.0 is normal speed). */\nconst DEFAULT_RATE = 1.0;\n\n/** Default pitch (1.0 is normal pitch). */\nconst DEFAULT_PITCH = 1.0;\n\n/** Default language. */\nconst DEFAULT_LANGUAGE = 'en-US';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface WebSpeechTTSOptions {\n voice?: string;\n rate?: number;\n pitch?: number;\n language?: string;\n debug?: boolean;\n}\n\n/**\n * Audio event compatible with the TTSAudioEvent shape used by\n * VoicePipeline for ElevenLabs TTS. Web Speech API does not produce\n * raw audio buffers, so we emit events with empty buffers and use\n * isFinal to signal utterance completion.\n */\nexport interface WebSpeechTTSAudioEvent {\n audio: ArrayBuffer;\n isFinal: boolean;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// WebSpeechTTS\n// ---------------------------------------------------------------------------\n\nexport class WebSpeechTTS {\n // ---- Configuration -------------------------------------------------------\n\n private readonly voiceName: string | null;\n private readonly rate: number;\n private readonly pitch: number;\n private readonly language: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state ------------------------------------------------------\n\n private _connected = false;\n private _suspended = false;\n\n /** Cached voice object resolved from voiceName. */\n private _resolvedVoice: SpeechSynthesisVoice | null = null;\n\n /** Whether voices have been loaded (they load async in some browsers). */\n private _voicesLoaded = false;\n\n /** Registered audio-event callbacks. */\n private readonly audioCallbacks: Set<(event: WebSpeechTTSAudioEvent) => void> =\n new Set();\n\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(options: WebSpeechTTSOptions = {}) {\n this.voiceName = options.voice ?? null;\n this.rate = options.rate ?? DEFAULT_RATE;\n this.pitch = options.pitch ?? DEFAULT_PITCH;\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.debugEnabled = options.debug ?? false;\n\n this.log('WebSpeechTTS created', {\n voice: this.voiceName,\n rate: this.rate,\n pitch: this.pitch,\n language: this.language,\n });\n }\n\n // -------------------------------------------------------------------------\n // Static methods\n // -------------------------------------------------------------------------\n\n /**\n * Check whether the Web Speech API SpeechSynthesis is supported in the\n * current environment. Safe to call in SSR (returns false).\n */\n static isSupported(): boolean {\n if (typeof window === 'undefined') return false;\n return typeof window.speechSynthesis !== 'undefined';\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Whether the adapter is connected (ready for speech). */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Initialize the adapter.\n *\n * Loads available voices and resolves the requested voice name. Voice\n * loading is async in some browsers (notably Chrome) so we wait for\n * the `voiceschanged` event if needed.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n this.log('SpeechSynthesis not available — cannot connect');\n return;\n }\n\n // Load voices\n await this.loadVoices();\n\n // Resolve the requested voice\n if (this.voiceName) {\n this._resolvedVoice = this.findVoice(this.voiceName);\n if (this._resolvedVoice) {\n this.log('Resolved voice:', this._resolvedVoice.name);\n } else {\n this.log('Requested voice not found:', this.voiceName, '— using browser default');\n }\n }\n\n this._connected = true;\n this.log('Connected');\n }\n\n /**\n * Speak the given text using the browser's speech synthesis engine.\n *\n * Returns a Promise that resolves when the utterance completes or is\n * cancelled. Rejects if an error occurs during synthesis.\n *\n * Also emits audio events to registered callbacks for VoicePipeline\n * compatibility.\n */\n speak(text: string): void {\n if (!this._connected || this._suspended) {\n this.log('Cannot speak — not connected or suspended');\n return;\n }\n\n if (!text || !text.trim()) {\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n return;\n }\n\n const synth = window.speechSynthesis;\n const utterance = new SpeechSynthesisUtterance(text);\n\n // Apply settings\n utterance.lang = this.language;\n utterance.rate = this.rate;\n utterance.pitch = this.pitch;\n\n if (this._resolvedVoice) {\n utterance.voice = this._resolvedVoice;\n }\n\n\n\n utterance.onstart = () => {\n this.log('Utterance started:', text.slice(0, 80) + (text.length > 80 ? '...' : ''));\n // Emit a non-final event to signal playback has started\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: false,\n timestamp: Date.now(),\n });\n };\n\n utterance.onend = () => {\n \n this.log('Utterance ended');\n // Emit final event to signal completion\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n };\n\n utterance.onerror = (event: SpeechSynthesisErrorEvent) => {\n \n // 'canceled' is not a real error — it occurs when stop() is called\n if (event.error === 'canceled') {\n this.log('Utterance cancelled');\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n return;\n }\n this.log('Utterance error:', event.error);\n // Still emit final to unblock the pipeline\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n };\n\n this.log('Speaking:', text.slice(0, 80) + (text.length > 80 ? '...' : ''));\n synth.speak(utterance);\n }\n\n /**\n * Flush / finalize the current utterance.\n *\n * No-op for Web Speech API since each speak() call is a complete\n * utterance. Provided for interface compatibility with ElevenLabsTTS.\n */\n flush(): void {\n // Web Speech API utterances are self-contained — nothing to flush.\n }\n\n /**\n * Register a callback to receive audio output events.\n *\n * For Web Speech API, these events have empty audio buffers and are\n * used to signal utterance start/end for VoicePipeline state management.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onAudio(callback: (event: WebSpeechTTSAudioEvent) => void): () => void {\n this.audioCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.audioCallbacks.delete(callback);\n };\n }\n\n /** Stop current speech synthesis and cancel any queued utterances. */\n stop(): void {\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n return;\n }\n\n this.log('Stopping speech synthesis');\n window.speechSynthesis.cancel();\n\n }\n\n /** Gracefully close the adapter. */\n close(): void {\n this.log('Closing');\n this.stop();\n this.cleanup();\n }\n\n /** Force-destroy the adapter. */\n destroy(): void {\n this.log('Destroying');\n this.stop();\n this.cleanup();\n this.audioCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Pauses any active speech synthesis and marks the adapter as suspended.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n\n if (typeof window !== 'undefined' && typeof window.speechSynthesis !== 'undefined') {\n window.speechSynthesis.pause();\n }\n\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n\n if (typeof window !== 'undefined' && typeof window.speechSynthesis !== 'undefined') {\n window.speechSynthesis.resume();\n }\n\n this.log('Resumed');\n }\n\n // -------------------------------------------------------------------------\n // Voice loading\n // -------------------------------------------------------------------------\n\n /**\n * Load available voices from the browser.\n *\n * In Chrome and some other browsers, voices load asynchronously after\n * the page loads. We wait for the `voiceschanged` event with a timeout.\n */\n private async loadVoices(): Promise<void> {\n if (this._voicesLoaded) return;\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') return;\n\n const synth = window.speechSynthesis;\n let voices = synth.getVoices();\n\n if (voices.length > 0) {\n this._voicesLoaded = true;\n this.log('Voices loaded:', voices.length, 'available');\n return;\n }\n\n // Wait for voiceschanged event (Chrome loads voices async)\n await new Promise<void>((resolve) => {\n const onVoicesChanged = (): void => {\n synth.removeEventListener('voiceschanged', onVoicesChanged);\n clearTimeout(timeout);\n voices = synth.getVoices();\n this._voicesLoaded = true;\n this.log('Voices loaded (async):', voices.length, 'available');\n resolve();\n };\n\n // Timeout after 2 seconds — some browsers never fire voiceschanged\n const timeout = setTimeout(() => {\n synth.removeEventListener('voiceschanged', onVoicesChanged);\n this._voicesLoaded = true;\n this.log('Voices loading timed out — proceeding with defaults');\n resolve();\n }, 2_000);\n\n synth.addEventListener('voiceschanged', onVoicesChanged);\n });\n }\n\n /**\n * Find a voice by name (case-insensitive partial match).\n */\n private findVoice(name: string): SpeechSynthesisVoice | null {\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n return null;\n }\n\n const voices = window.speechSynthesis.getVoices();\n const lowerName = name.toLowerCase();\n\n // Try exact match first\n const exact = voices.find((v) => v.name.toLowerCase() === lowerName);\n if (exact) return exact;\n\n // Try partial match\n const partial = voices.find((v) => v.name.toLowerCase().includes(lowerName));\n if (partial) return partial;\n\n // Try matching by language if voice name looks like a language code\n if (lowerName.includes('-') || lowerName.length <= 5) {\n const langMatch = voices.find((v) => v.lang.toLowerCase().startsWith(lowerName));\n if (langMatch) return langMatch;\n }\n\n return null;\n }\n\n // -------------------------------------------------------------------------\n // Subscriber notification\n // -------------------------------------------------------------------------\n\n /**\n * Emit an audio event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitAudio(event: WebSpeechTTSAudioEvent): void {\n for (const cb of this.audioCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Audio callback threw:', err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n /** Reset internal state. */\n private cleanup(): void {\n this._connected = false;\n\n }\n\n // -------------------------------------------------------------------------\n // Logging\n // -------------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Voice Pipeline (Phase 1b)\n// ---------------------------------------------------------------------------\n//\n// Orchestrates the full voice flow: Mic → VAD → STT → LLM → TTS → Speaker.\n//\n// Half-duplex state machine:\n// IDLE ──startListening()──► LISTENING\n// LISTENING ──final transcript──► PROCESSING\n// PROCESSING ──LLM response──► SPEAKING\n// SPEAKING ──TTS done──► IDLE\n// SPEAKING ──barge-in──► LISTENING\n// Any ──error──► ERROR\n// ERROR ──startListening()──► LISTENING\n//\n// SSR safe: all browser APIs are guarded behind `typeof window` checks.\n// AudioContext is only created in init() which must be called after a user\n// gesture to satisfy browser autoplay policies.\n// ---------------------------------------------------------------------------\n\nimport { EventBus, createEventBus } from '../bus/index.js';\nimport { BrowserSupportError, ErrorCodes, PermissionError } from '../errors/index.js';\nimport { DeepgramSTT } from './deepgram-stt.js';\nimport { ElevenLabsSTT } from './elevenlabs-stt.js';\nimport { ElevenLabsTTS } from './elevenlabs-tts.js';\nimport { WebSpeechSTT } from './web-speech-stt.js';\nimport { WebSpeechTTS } from './web-speech-tts.js';\n\nimport type { STTTranscriptEvent } from '../types/index.js';\nimport type { TTSAudioEvent } from './elevenlabs-tts.js';\nimport type { WebSpeechTTSAudioEvent } from './web-speech-tts.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Voice]';\n\n/** Jitter buffer: accumulate this many ms of audio before starting playback. */\nconst JITTER_BUFFER_MS = 150;\n\n/** Echo detection: discard transcript if >60% word overlap within this window. */\nconst ECHO_WINDOW_MS = 3_000;\n\n/** Echo detection: minimum word overlap ratio to classify as echo. */\nconst ECHO_OVERLAP_THRESHOLD = 0.6;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type VoiceState = 'idle' | 'listening' | 'processing' | 'speaking' | 'error';\n\nexport interface VoicePipelineOptions {\n sttConfig:\n | { provider: 'deepgram'; apiKey: string; model?: 'nova-2' | 'nova-3' }\n | { provider: 'elevenlabs'; apiKey: string; language?: string }\n | { provider: 'web-speech'; language?: string; continuous?: boolean; interimResults?: boolean };\n ttsConfig:\n | { provider: 'elevenlabs'; apiKey: string; voiceId?: string; modelId?: string }\n | { provider: 'web-speech'; voice?: string; rate?: number; pitch?: number; language?: string };\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Type declarations for environments with webkitAudioContext\n// ---------------------------------------------------------------------------\n\ndeclare global {\n // eslint-disable-next-line no-var\n var webkitAudioContext: typeof AudioContext | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internals: VAD interface (dynamically imported from @guidekit/vad)\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal interface mirroring the public API of SileroVAD from @guidekit/vad.\n * Declared here so we can type the dynamically imported instance without a\n * hard compile-time dependency.\n */\ninterface VADInstance {\n init(): Promise<void>;\n start(stream: MediaStream): void;\n stop(): void;\n destroy(): Promise<void>;\n onSpeechStart(cb: (event: { type: string; timestamp: number; probability?: number }) => void): () => void;\n onSpeechEnd(cb: (event: { type: string; timestamp: number; probability?: number }) => void): () => void;\n readonly isSpeaking: boolean;\n readonly isReady: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Internals: Echo tracker\n// ---------------------------------------------------------------------------\n\ninterface EchoRecord {\n words: Set<string>;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// VoicePipeline\n// ---------------------------------------------------------------------------\n\nexport class VoicePipeline {\n // ── Configuration ────────────────────────────────────────────────────\n private readonly _sttConfig: VoicePipelineOptions['sttConfig'];\n private readonly _ttsConfig: VoicePipelineOptions['ttsConfig'];\n private readonly _debug: boolean;\n\n // ── State ────────────────────────────────────────────────────────────\n private _state: VoiceState = 'idle';\n private _destroyed = false;\n\n // ── EventBus (internal, for voice-specific events) ──────────────────\n private readonly _bus: EventBus;\n\n // ── Audio pipeline components ────────────────────────────────────────\n private _audioContext: AudioContext | null = null;\n private _mediaStream: MediaStream | null = null;\n private _vad: VADInstance | null = null;\n private _stt: DeepgramSTT | ElevenLabsSTT | WebSpeechSTT | null = null;\n private _tts: ElevenLabsTTS | WebSpeechTTS | null = null;\n\n // ── Audio capture (mic → ScriptProcessor → STT) ─────────────────────\n private _micSourceNode: MediaStreamAudioSourceNode | null = null;\n private _captureProcessor: ScriptProcessorNode | null = null;\n private _isForwardingToSTT = false;\n\n // ── TTS playback ────────────────────────────────────────────────────\n private _playbackQueue: ArrayBuffer[] = [];\n private _jitterBufferTimer: ReturnType<typeof setTimeout> | null = null;\n private _isPlaybackStarted = false;\n private _nextPlaybackTime = 0;\n private _activeSourceNodes: Set<AudioBufferSourceNode> = new Set();\n private _lastScheduledSource: AudioBufferSourceNode | null = null;\n\n // ── Echo detection ──────────────────────────────────────────────────\n private _lastTTSEcho: EchoRecord | null = null;\n\n // ── Barge-in / abort ────────────────────────────────────────────────\n private _pendingLLMAbort: AbortController | null = null;\n\n // ── Subscriber management ───────────────────────────────────────────\n private readonly _stateChangeCallbacks: Set<(state: VoiceState, previous: VoiceState) => void> = new Set();\n private readonly _transcriptCallbacks: Set<(text: string, isFinal: boolean) => void> = new Set();\n\n // ── Cleanup handles ─────────────────────────────────────────────────\n private _unsubVADSpeechStart: (() => void) | null = null;\n private _unsubVADSpeechEnd: (() => void) | null = null;\n private _unsubSTTTranscript: (() => void) | null = null;\n private _unsubTTSAudio: (() => void) | null = null;\n\n // ────────────────────────────────────────────────────────────────────\n // Constructor\n // ────────────────────────────────────────────────────────────────────\n\n constructor(options: VoicePipelineOptions) {\n this._sttConfig = options.sttConfig;\n this._ttsConfig = options.ttsConfig;\n this._debug = options.debug ?? false;\n this._bus = createEventBus({ debug: this._debug });\n\n this._log('VoicePipeline created');\n }\n\n // ────────────────────────────────────────────────────────────────────\n // Public getters\n // ────────────────────────────────────────────────────────────────────\n\n /** Current pipeline state. */\n get state(): VoiceState {\n return this._state;\n }\n\n // ────────────────────────────────────────────────────────────────────\n // init() — call after user gesture\n // ────────────────────────────────────────────────────────────────────\n\n /**\n * Initialize AudioContext, VAD model, and STT/TTS connections.\n *\n * **Must be called in response to a user gesture** (click / tap) to\n * satisfy browser autoplay policies.\n */\n async init(): Promise<void> {\n if (this._destroyed) {\n this._log('Cannot init — pipeline is destroyed');\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined') {\n this._log('SSR environment detected — skipping init');\n return;\n }\n\n if (this._audioContext) {\n this._log('Already initialized — skipping');\n return;\n }\n\n this._log('Initializing...');\n\n // ── 1. Create AudioContext ───────────────────────────────────────\n const AudioContextClass = this._resolveAudioContext();\n if (!AudioContextClass) {\n throw new BrowserSupportError({\n code: ErrorCodes.BROWSER_NO_WEB_AUDIO,\n message: 'Web Audio API is not supported in this browser.',\n suggestion: 'Use a modern browser such as Chrome, Firefox, or Safari.',\n });\n }\n\n this._audioContext = new AudioContextClass();\n this._log('AudioContext created, sampleRate:', this._audioContext.sampleRate);\n\n // Pre-warm the AudioContext with a silent buffer to avoid first-play delay\n this._prewarmAudioContext(this._audioContext);\n\n // ── 2. Load VAD model ───────────────────────────────────────────\n try {\n const vadModule = await import('@guidekit/vad');\n const SileroVAD = vadModule.SileroVAD;\n this._vad = new SileroVAD({ debug: this._debug }) as unknown as VADInstance;\n await this._vad.init();\n this._log('VAD model loaded');\n } catch (err) {\n throw new BrowserSupportError({\n code: ErrorCodes.VAD_PACKAGE_MISSING,\n message:\n 'Failed to load @guidekit/vad. Ensure the package is installed.',\n suggestion:\n 'Run: npm install @guidekit/vad — or check that WASM is supported.',\n cause: err instanceof Error ? err : undefined,\n });\n }\n\n // ── 3. Create STT adapter ───────────────────────────────────────\n if (this._sttConfig.provider === 'deepgram') {\n this._stt = new DeepgramSTT({\n apiKey: this._sttConfig.apiKey,\n model: this._sttConfig.model,\n debug: this._debug,\n });\n } else if (this._sttConfig.provider === 'elevenlabs') {\n this._stt = new ElevenLabsSTT({\n apiKey: this._sttConfig.apiKey,\n language: this._sttConfig.language,\n debug: this._debug,\n });\n } else {\n // web-speech provider (browser-native, zero-config)\n this._stt = new WebSpeechSTT({\n language: this._sttConfig.language,\n continuous: this._sttConfig.continuous,\n interimResults: this._sttConfig.interimResults,\n debug: this._debug,\n });\n }\n\n // ── 4. Create TTS adapter ───────────────────────────────────────\n if (this._ttsConfig.provider === 'elevenlabs') {\n this._tts = new ElevenLabsTTS({\n apiKey: this._ttsConfig.apiKey,\n voiceId: this._ttsConfig.voiceId,\n modelId: 'modelId' in this._ttsConfig ? this._ttsConfig.modelId : undefined,\n debug: this._debug,\n });\n } else {\n // web-speech provider (browser-native, zero-config)\n this._tts = new WebSpeechTTS({\n voice: this._ttsConfig.voice,\n rate: this._ttsConfig.rate,\n pitch: this._ttsConfig.pitch,\n language: this._ttsConfig.language,\n debug: this._debug,\n });\n }\n\n this._log('Initialization complete');\n }\n\n // ────────────────────────────────────────────────────────────────────\n // startListening()\n // ────────────────────────────────────────────────────────────────────\n\n /**\n * Start listening: activate microphone, begin VAD + STT pipeline.\n *\n * Valid from: IDLE, ERROR, SPEAKING (barge-in path calls this internally).\n */\n async startListening(): Promise<void> {\n if (this._destroyed) return;\n\n if (!this._audioContext || !this._vad || !this._stt) {\n throw new BrowserSupportError({\n code: ErrorCodes.BROWSER_NO_WEB_AUDIO,\n message: 'Voice pipeline not initialized. Call init() first.',\n suggestion: 'Ensure init() is called after a user gesture before startListening().',\n });\n }\n\n // Resume AudioContext if it was suspended (browser policy)\n if (this._audioContext.state === 'suspended') {\n try {\n await this._audioContext.resume();\n } catch {\n // Ignore resume errors — the context may auto-resume on interaction\n }\n }\n\n // ── Get mic access ──────────────────────────────────────────────\n try {\n this._mediaStream = await navigator.mediaDevices.getUserMedia({\n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n },\n });\n this._log('Microphone access granted');\n } catch (err) {\n const isNotAllowed =\n err instanceof DOMException &&\n (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError');\n\n if (isNotAllowed) {\n const permErr = new PermissionError({\n code: ErrorCodes.PERMISSION_MIC_DENIED,\n message: 'Microphone permission was denied by the user.',\n suggestion: 'Allow microphone access in your browser settings and try again.',\n });\n this._setState('error');\n this._bus.emit('error', permErr);\n throw permErr;\n }\n\n const unavailErr = new PermissionError({\n code: ErrorCodes.PERMISSION_MIC_UNAVAILABLE,\n message: 'No microphone device available.',\n suggestion: 'Connect a microphone and try again.',\n cause: err instanceof Error ? err : undefined,\n });\n this._setState('error');\n this._bus.emit('error', unavailErr);\n throw unavailErr;\n }\n\n // ── Connect STT ─────────────────────────────────────────────────\n try {\n await this._stt.connect();\n this._log('STT connected');\n } catch (_err) {\n this._log('STT connection failed — degrading to text mode');\n this._bus.emit('voice:degraded', { reason: 'STT connection failed', fallback: 'text' });\n this._stopMicTracks();\n this._setState('error');\n return;\n }\n\n // ── Wire STT transcript events ──────────────────────────────────\n this._unsubSTTTranscript?.();\n this._unsubSTTTranscript = this._stt.onTranscript((event: STTTranscriptEvent) => {\n this._handleTranscript(event);\n });\n\n // ── Set up mic → ScriptProcessor for STT forwarding ─────────────\n this._setupMicCapture();\n\n // ── Start VAD on the MediaStream ────────────────────────────────\n this._unsubVADSpeechStart?.();\n this._unsubVADSpeechEnd?.();\n\n this._unsubVADSpeechStart = this._vad.onSpeechStart(() => {\n this._handleVADSpeechStart();\n });\n this._unsubVADSpeechEnd = this._vad.onSpeechEnd(() => {\n this._handleVADSpeechEnd();\n });\n\n this._vad.start(this._mediaStream);\n this._log('VAD started');\n\n // ── Transition state ────────────────────────────────────────────\n this._setState('listening');\n }\n\n // ────────────────────────────────────────────────────────────────────\n // stopListening()\n // ────────────────────────────────────────────────────────────────────\n\n /** Stop listening: deactivate mic and VAD. */\n stopListening(): void {\n if (this._destroyed) return;\n\n this._log('stopListening()');\n this._isForwardingToSTT = false;\n this._teardownMicCapture();\n this._vad?.stop();\n this._stt?.close();\n this._stopMicTracks();\n\n if (this._state === 'listening') {\n this._setState('idle');\n }\n }\n\n // ────────────────────────────────────────────────────────────────────\n // processTranscript()\n // ────────────────────────────────────────────────────────────────────\n\n /**\n * Process a transcript through an LLM callback and speak the response.\n *\n * @param text - The user's transcript text.\n * @param sendToLLM - Async callback that sends text to the LLM and returns the response.\n */\n async processTranscript(\n text: string,\n sendToLLM: (text: string) => Promise<string>,\n ): Promise<void> {\n if (this._destroyed) return;\n\n this._setState('processing');\n\n // Set up abort controller for barge-in\n this._pendingLLMAbort = new AbortController();\n const signal = this._pendingLLMAbort.signal;\n\n let response: string;\n try {\n response = await sendToLLM(text);\n\n // Check if aborted during LLM call (barge-in)\n if (signal.aborted) {\n this._log('LLM response discarded (barge-in during processing)');\n return;\n }\n } catch (err) {\n if (signal.aborted) {\n this._log('LLM call aborted (barge-in)');\n return;\n }\n this._log('LLM call failed:', err);\n this._setState('error');\n return;\n } finally {\n this._pendingLLMAbort = null;\n }\n\n // Speak the response\n if (response && response.trim()) {\n await this.speak(response);\n } else {\n this._setState('idle');\n }\n }\n\n // ────────────────────────────────────────────────────────────────────\n // speak()\n // ────────────────────────────────────────────────────────────────────\n\n /** Speak text via TTS (ElevenLabs or Web Speech API). */\n async speak(text: string): Promise<void> {\n if (this._destroyed || !text.trim()) return;\n\n // Web Speech TTS does not require AudioContext for playback\n const isWebSpeechTTS = this._tts instanceof WebSpeechTTS;\n if (!this._tts || (!this._audioContext && !isWebSpeechTTS)) {\n this._log('TTS or AudioContext not available — cannot speak');\n this._bus.emit('voice:degraded', { reason: 'TTS not available', fallback: 'text' });\n this._setState('idle');\n return;\n }\n\n this._setState('speaking');\n // Record echo info for later detection\n this._lastTTSEcho = {\n words: new Set(this._normalizeWords(text)),\n timestamp: Date.now(),\n };\n\n this._bus.emit('voice:tts-start', { utterance: text });\n\n // Connect TTS if needed\n try {\n if (!this._tts.isConnected) {\n await this._tts.connect();\n this._log('TTS connected');\n }\n } catch (_err) {\n this._log('TTS connection failed — degrading to text mode');\n this._bus.emit('voice:degraded', { reason: 'TTS connection failed', fallback: 'text' });\n this._bus.emit('voice:tts-end', { utterance: text, durationMs: 0 });\n this._setState('idle');\n return;\n }\n\n // Reset playback state\n this._playbackQueue = [];\n this._isPlaybackStarted = false;\n this._nextPlaybackTime = 0;\n this._jitterBufferTimer = null;\n\n // Wire TTS audio events\n this._unsubTTSAudio?.();\n const ttsStartTime = Date.now();\n\n await new Promise<void>((resolve) => {\n let resolved = false;\n const done = () => {\n if (resolved) return;\n resolved = true;\n this._unsubTTSAudio?.();\n this._unsubTTSAudio = null;\n\n const durationMs = Date.now() - ttsStartTime;\n this._bus.emit('voice:tts-end', { utterance: text, durationMs });\n\n // Only transition to idle if still in speaking state\n // (barge-in may have already changed state)\n if (this._state === 'speaking') {\n this._setState('idle');\n }\n resolve();\n };\n\n if (isWebSpeechTTS) {\n // Web Speech TTS: browser handles audio playback internally.\n // We only listen for start/end events to manage pipeline state.\n this._unsubTTSAudio = (this._tts as WebSpeechTTS).onAudio(\n (event: WebSpeechTTSAudioEvent) => {\n if (event.isFinal) {\n done();\n }\n },\n );\n (this._tts as WebSpeechTTS).speak(text);\n } else {\n // ElevenLabs TTS: audio arrives as chunks over WebSocket\n this._unsubTTSAudio = (this._tts as ElevenLabsTTS).onAudio(\n (event: TTSAudioEvent) => {\n this._handleTTSAudio(event, done);\n },\n );\n (this._tts as ElevenLabsTTS).speak(text);\n (this._tts as ElevenLabsTTS).flush();\n }\n });\n }\n\n // ────────────────────────────────────────────────────────────────────\n // stopSpeaking() — barge-in\n // ────────────────────────────────────────────────────────────────────\n\n /** Stop current TTS playback immediately (barge-in). */\n stopSpeaking(): void {\n if (this._destroyed) return;\n\n this._log('stopSpeaking() — barge-in');\n\n // Stop all active AudioBufferSourceNodes\n for (const node of this._activeSourceNodes) {\n try {\n node.stop();\n node.disconnect();\n } catch {\n // Node may already be stopped\n }\n }\n this._activeSourceNodes.clear();\n this._lastScheduledSource = null;\n\n // Clear jitter buffer\n if (this._jitterBufferTimer !== null) {\n clearTimeout(this._jitterBufferTimer);\n this._jitterBufferTimer = null;\n }\n this._playbackQueue = [];\n this._isPlaybackStarted = false;\n\n // Abort pending LLM request\n if (this._pendingLLMAbort) {\n this._pendingLLMAbort.abort();\n this._pendingLLMAbort = null;\n }\n\n // Stop Web Speech TTS playback or close ElevenLabs TTS connection\n if (this._tts instanceof WebSpeechTTS) {\n this._tts.stop();\n } else if (this._tts?.isConnected) {\n this._tts.close();\n }\n }\n\n // ────────────────────────────────────────────────────────────────────\n // onStateChange()\n // ────────────────────────────────────────────────────────────────────\n\n /** Subscribe to state changes. Returns an unsubscribe function. */\n onStateChange(callback: (state: VoiceState, previous: VoiceState) => void): () => void {\n this._stateChangeCallbacks.add(callback);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this._stateChangeCallbacks.delete(callback);\n };\n }\n\n // ────────────────────────────────────────────────────────────────────\n // onTranscript()\n // ────────────────────────────────────────────────────────────────────\n\n /** Subscribe to transcript events. Returns an unsubscribe function. */\n onTranscript(callback: (text: string, isFinal: boolean) => void): () => void {\n this._transcriptCallbacks.add(callback);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this._transcriptCallbacks.delete(callback);\n };\n }\n\n // ────────────────────────────────────────────────────────────────────\n // destroy()\n // ────────────────────────────────────────────────────────────────────\n\n /** Destroy all resources held by the pipeline. */\n async destroy(): Promise<void> {\n if (this._destroyed) return;\n this._destroyed = true;\n this._log('Destroying...');\n\n // Stop everything\n this.stopSpeaking();\n this.stopListening();\n\n // Tear down subscriptions\n this._unsubVADSpeechStart?.();\n this._unsubVADSpeechEnd?.();\n this._unsubSTTTranscript?.();\n this._unsubTTSAudio?.();\n this._unsubVADSpeechStart = null;\n this._unsubVADSpeechEnd = null;\n this._unsubSTTTranscript = null;\n this._unsubTTSAudio = null;\n\n // Destroy subsystems\n if (this._vad) {\n try {\n await this._vad.destroy();\n } catch {\n // Ignore VAD destroy errors\n }\n this._vad = null;\n }\n\n if (this._stt) {\n this._stt.destroy();\n this._stt = null;\n }\n\n if (this._tts) {\n this._tts.destroy();\n this._tts = null;\n }\n\n // Close AudioContext\n if (this._audioContext) {\n try {\n await this._audioContext.close();\n } catch {\n // Ignore close errors\n }\n this._audioContext = null;\n }\n\n // Clean up mic tracks\n this._stopMicTracks();\n\n // Clear callbacks\n this._stateChangeCallbacks.clear();\n this._transcriptCallbacks.clear();\n this._bus.removeAll();\n\n this._log('Destroyed');\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: State machine\n // ════════════════════════════════════════════════════════════════════\n\n private _setState(next: VoiceState): void {\n const prev = this._state;\n if (prev === next) return;\n\n this._state = next;\n this._log(`State: ${prev} -> ${next}`);\n\n // Emit on internal bus\n this._bus.emit('voice:state-change', { from: prev, to: next });\n\n // Notify external subscribers\n for (const cb of this._stateChangeCallbacks) {\n try {\n cb(next, prev);\n } catch (err) {\n console.error(LOG_PREFIX, 'State change callback threw:', err);\n }\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: AudioContext helpers\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Resolve the AudioContext constructor, with Safari webkitAudioContext\n * fallback. Returns null if Web Audio is not available.\n */\n private _resolveAudioContext(): typeof AudioContext | null {\n if (typeof AudioContext !== 'undefined') {\n return AudioContext;\n }\n if (typeof globalThis.webkitAudioContext !== 'undefined') {\n return globalThis.webkitAudioContext;\n }\n return null;\n }\n\n /**\n * Pre-warm the AudioContext by playing a silent buffer.\n * This forces the context into the \"running\" state and avoids a\n * noticeable delay on the first real playback.\n */\n private _prewarmAudioContext(ctx: AudioContext): void {\n try {\n const buffer = ctx.createBuffer(1, 1, ctx.sampleRate);\n const source = ctx.createBufferSource();\n source.buffer = buffer;\n source.connect(ctx.destination);\n source.start(0);\n this._log('AudioContext pre-warmed');\n } catch {\n // Non-critical — ignore\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: Mic capture → STT forwarding\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Set up a ScriptProcessorNode to capture mic audio and forward it\n * to the STT adapter when `_isForwardingToSTT` is true.\n */\n private _setupMicCapture(): void {\n if (!this._audioContext || !this._mediaStream || !this._stt) return;\n\n this._micSourceNode = this._audioContext.createMediaStreamSource(this._mediaStream);\n\n // Buffer size of 4096 at 48 kHz ≈ 85 ms of audio per callback\n const bufferSize = 4096;\n this._captureProcessor = this._audioContext.createScriptProcessor(bufferSize, 1, 1);\n\n this._captureProcessor.onaudioprocess = (event: AudioProcessingEvent) => {\n if (!this._isForwardingToSTT || !this._stt) return;\n\n const inputData = event.inputBuffer.getChannelData(0);\n // DeepgramSTT.sendAudio accepts Float32Array and converts to Int16 internally\n this._stt.sendAudio(new Float32Array(inputData));\n };\n\n this._micSourceNode.connect(this._captureProcessor);\n // ScriptProcessorNode requires connection to destination to fire events\n this._captureProcessor.connect(this._audioContext.destination);\n this._log('Mic capture pipeline set up');\n }\n\n /** Tear down the mic capture ScriptProcessorNode. */\n private _teardownMicCapture(): void {\n if (this._captureProcessor) {\n try {\n this._captureProcessor.disconnect();\n } catch {\n // Ignore\n }\n this._captureProcessor.onaudioprocess = null;\n this._captureProcessor = null;\n }\n\n if (this._micSourceNode) {\n try {\n this._micSourceNode.disconnect();\n } catch {\n // Ignore\n }\n this._micSourceNode = null;\n }\n }\n\n /** Stop all tracks on the current MediaStream. */\n private _stopMicTracks(): void {\n if (this._mediaStream) {\n for (const track of this._mediaStream.getTracks()) {\n track.stop();\n }\n this._mediaStream = null;\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: VAD event handlers\n // ════════════════════════════════════════════════════════════════════\n\n private _handleVADSpeechStart(): void {\n this._log('VAD: speech-start, current state:', this._state);\n\n if (this._state === 'speaking') {\n // Barge-in: user is speaking while TTS is playing\n if (this._isEchoDetected()) {\n this._log('Echo detected — ignoring barge-in');\n return;\n }\n\n this._log('Barge-in detected');\n this.stopSpeaking();\n // Restart listening (we keep the mic stream alive)\n this._isForwardingToSTT = true;\n this._setState('listening');\n return;\n }\n\n if (this._state === 'listening') {\n // Start forwarding audio to STT\n this._isForwardingToSTT = true;\n this._log('Started forwarding audio to STT');\n }\n }\n\n private _handleVADSpeechEnd(): void {\n this._log('VAD: speech-end, current state:', this._state);\n\n if (this._state === 'listening') {\n // Stop forwarding to STT; we wait for a final transcript\n this._isForwardingToSTT = false;\n this._log('Stopped forwarding audio to STT');\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: STT transcript handler\n // ════════════════════════════════════════════════════════════════════\n\n private _handleTranscript(event: STTTranscriptEvent): void {\n const { text, isFinal } = event;\n\n if (!text || !text.trim()) return;\n\n // Echo detection: discard transcripts that match recent TTS output\n if (isFinal && this._isTranscriptEcho(text)) {\n this._log('Echo detected — discarding transcript:', text);\n return;\n }\n\n // Notify external transcript subscribers\n this._bus.emit('voice:transcript', {\n text,\n isFinal,\n confidence: event.confidence,\n });\n\n for (const cb of this._transcriptCallbacks) {\n try {\n cb(text, isFinal);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n\n // On final transcript while listening → transition to PROCESSING\n // (The actual LLM call is driven by the consumer calling processTranscript)\n if (isFinal && this._state === 'listening') {\n this._log('Final transcript received:', text);\n this._isForwardingToSTT = false;\n // Note: we do NOT transition to PROCESSING here. The consumer is\n // responsible for calling processTranscript() which sets the state.\n // This keeps the pipeline composable — consumers can decide to\n // ignore transcripts, batch them, etc.\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: TTS audio playback\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Handle an audio chunk from ElevenLabs TTS.\n *\n * Implements a jitter buffer: we accumulate audio for JITTER_BUFFER_MS\n * before starting playback to smooth out network jitter.\n */\n private _handleTTSAudio(event: TTSAudioEvent, onDone: () => void): void {\n if (this._state !== 'speaking') {\n // State changed (e.g. barge-in) — discard audio\n return;\n }\n\n if (event.isFinal && event.audio.byteLength === 0) {\n // Final marker with no audio — flush whatever we have and finish\n this._flushJitterBuffer(onDone);\n return;\n }\n\n if (event.audio.byteLength === 0) return;\n\n // Add to jitter buffer queue\n this._playbackQueue.push(event.audio);\n\n if (!this._isPlaybackStarted) {\n // Start the jitter buffer timer on the first chunk\n if (this._jitterBufferTimer === null) {\n this._jitterBufferTimer = setTimeout(() => {\n this._jitterBufferTimer = null;\n this._startPlayback(event.isFinal ? onDone : undefined);\n }, JITTER_BUFFER_MS);\n }\n } else {\n // Playback already started — decode and schedule immediately\n this._decodeAndSchedule(event.audio, event.isFinal ? onDone : undefined);\n }\n\n if (event.isFinal) {\n // Clear the jitter buffer timer since we got the final chunk\n if (this._jitterBufferTimer !== null) {\n clearTimeout(this._jitterBufferTimer);\n this._jitterBufferTimer = null;\n this._startPlayback(onDone);\n }\n }\n }\n\n /** Flush the jitter buffer and start playback. */\n private _flushJitterBuffer(onDone: () => void): void {\n if (this._jitterBufferTimer !== null) {\n clearTimeout(this._jitterBufferTimer);\n this._jitterBufferTimer = null;\n }\n\n if (this._playbackQueue.length > 0) {\n this._startPlayback(onDone);\n } else {\n // No audio to play — done immediately\n onDone();\n }\n }\n\n /**\n * Begin playback: decode all queued chunks and schedule them.\n * If `onDone` is provided, it is called when the last chunk finishes playing.\n */\n private _startPlayback(onDone?: () => void): void {\n if (this._isPlaybackStarted) {\n // Already started — just flush the remaining queue\n if (this._playbackQueue.length > 0) {\n const remaining = this._playbackQueue.splice(0);\n const lastIdx = remaining.length - 1;\n for (let i = 0; i < remaining.length; i++) {\n this._decodeAndSchedule(\n remaining[i]!,\n i === lastIdx ? onDone : undefined,\n );\n }\n } else if (onDone) {\n // If there are active sources wait for the last one, otherwise call done now\n if (this._lastScheduledSource) {\n const prevOnEnded = this._lastScheduledSource.onended;\n this._lastScheduledSource.onended = () => {\n if (typeof prevOnEnded === 'function') {\n prevOnEnded.call(this._lastScheduledSource!, new Event('ended'));\n }\n onDone();\n };\n } else {\n onDone();\n }\n }\n return;\n }\n\n this._isPlaybackStarted = true;\n this._nextPlaybackTime = 0;\n\n const queued = this._playbackQueue.splice(0);\n const lastIdx = queued.length - 1;\n\n for (let i = 0; i < queued.length; i++) {\n this._decodeAndSchedule(\n queued[i]!,\n i === lastIdx ? onDone : undefined,\n );\n }\n }\n\n /**\n * Decode an audio chunk (mp3 from ElevenLabs) and schedule it for\n * sequential playback via AudioBufferSourceNode.\n */\n private _decodeAndSchedule(audioData: ArrayBuffer, onDone?: () => void): void {\n // Guard against multiple invocations of onDone. This can happen when\n // multiple pending decode operations reference the same callback, or\n // when both the success and error paths fire (e.g. state change\n // during decode).\n let onDoneCalled = false;\n const safeOnDone = onDone\n ? () => {\n if (onDoneCalled) return;\n onDoneCalled = true;\n onDone();\n }\n : undefined;\n\n if (!this._audioContext || this._state !== 'speaking') {\n safeOnDone?.();\n return;\n }\n\n const ctx = this._audioContext;\n\n // decodeAudioData needs a copy because it detaches the ArrayBuffer\n const copy = audioData.slice(0);\n\n ctx.decodeAudioData(\n copy,\n (decodedBuffer) => {\n if (this._state !== 'speaking' || !this._audioContext) {\n safeOnDone?.();\n return;\n }\n\n const source = ctx.createBufferSource();\n source.buffer = decodedBuffer;\n source.connect(ctx.destination);\n\n // Track active sources for barge-in cleanup\n this._activeSourceNodes.add(source);\n this._lastScheduledSource = source;\n\n source.onended = () => {\n this._activeSourceNodes.delete(source);\n if (this._lastScheduledSource === source) {\n this._lastScheduledSource = null;\n }\n\n // If this was the last source and we have onDone, call it\n if (safeOnDone) {\n safeOnDone();\n }\n };\n\n // Schedule playback sequentially\n const now = ctx.currentTime;\n const startTime = Math.max(now, this._nextPlaybackTime);\n source.start(startTime);\n this._nextPlaybackTime = startTime + decodedBuffer.duration;\n\n this._log(\n 'Scheduled audio chunk:',\n decodedBuffer.duration.toFixed(3) + 's',\n 'at',\n startTime.toFixed(3),\n );\n },\n (err) => {\n this._log('Failed to decode audio chunk:', err);\n safeOnDone?.();\n },\n );\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: Echo detection\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Check if VAD speech-start during SPEAKING state is likely echo from\n * the speaker playing TTS audio rather than genuine user speech.\n *\n * Simple heuristic: if we are still within the echo window of a recent\n * TTS utterance, treat it as potential echo.\n */\n private _isEchoDetected(): boolean {\n if (!this._lastTTSEcho) return false;\n const elapsed = Date.now() - this._lastTTSEcho.timestamp;\n // During active TTS playback, suppress barge-in only if within window\n // and the speaker is still audibly outputting. We use the echo window\n // as a conservative guard.\n return elapsed < ECHO_WINDOW_MS;\n }\n\n /**\n * Check if a transcript is an echo of recent TTS output.\n *\n * Uses word overlap: if intersection of words > 60% of max set size\n * and the transcript arrived within the echo window, discard it.\n */\n private _isTranscriptEcho(transcript: string): boolean {\n if (!this._lastTTSEcho) return false;\n\n const elapsed = Date.now() - this._lastTTSEcho.timestamp;\n if (elapsed > ECHO_WINDOW_MS) return false;\n\n const transcriptWords = new Set(this._normalizeWords(transcript));\n const ttsWords = this._lastTTSEcho.words;\n\n if (transcriptWords.size === 0 || ttsWords.size === 0) return false;\n\n // Compute intersection\n let intersectionCount = 0;\n for (const word of transcriptWords) {\n if (ttsWords.has(word)) {\n intersectionCount++;\n }\n }\n\n const maxSize = Math.max(transcriptWords.size, ttsWords.size);\n const overlap = intersectionCount / maxSize;\n\n this._log(\n 'Echo check: overlap =',\n (overlap * 100).toFixed(1) + '%,',\n 'threshold =',\n (ECHO_OVERLAP_THRESHOLD * 100).toFixed(1) + '%',\n );\n\n return overlap >= ECHO_OVERLAP_THRESHOLD;\n }\n\n /**\n * Normalize text into a set of lowercase words, stripping punctuation.\n */\n private _normalizeWords(text: string): string[] {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 0);\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: Logging\n // ════════════════════════════════════════════════════════════════════\n\n private _log(...args: unknown[]): void {\n if (this._debug) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport { WebSocketManager } from './websocket-manager.js';\nexport type { WSState, WebSocketManagerOptions } from './websocket-manager.js';\nexport { DeepgramSTT } from './deepgram-stt.js';\nexport type { DeepgramSTTOptions, STTTranscriptEvent } from './deepgram-stt.js';\nexport { ElevenLabsSTT } from './elevenlabs-stt.js';\nexport type { ElevenLabsSTTOptions } from './elevenlabs-stt.js';\nexport { ElevenLabsTTS } from './elevenlabs-tts.js';\nexport type { ElevenLabsTTSOptions, TTSAudioEvent } from './elevenlabs-tts.js';\nexport { WebSpeechSTT } from './web-speech-stt.js';\nexport type { WebSpeechSTTOptions } from './web-speech-stt.js';\nexport { WebSpeechTTS } from './web-speech-tts.js';\nexport type { WebSpeechTTSOptions, WebSpeechTTSAudioEvent } from './web-speech-tts.js';\n","/**\n * @module @guidekit/core/visual\n *\n * Visual Guidance System for the GuideKit SDK.\n * Provides spotlight overlays, tooltips, smooth scrolling, and guided tours\n * to visually direct users to page elements identified by the LLM.\n *\n * Key design decisions:\n * - Overlay lives on document.body (NOT Shadow DOM) so it can cover the entire page.\n * - Uses box-shadow cutout technique for the spotlight effect.\n * - Tracks element position via ResizeObserver + scroll listeners (NOT rAF polling).\n * - All text is set via textContent (never innerHTML) to prevent XSS.\n * - SSR-safe: every browser API is guarded behind typeof checks.\n * - Compositor-only animations (transform, opacity) for smooth 60fps.\n * - Respects prefers-reduced-motion.\n */\n\nimport { DOMScanner } from '../dom/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Visual]';\nconst DEFAULT_OVERLAY_COLOR = 'rgba(0, 0, 0, 0.5)';\nconst DEFAULT_SPOTLIGHT_COLOR = '#4a9eed';\nconst DEFAULT_ANIMATION_DURATION = 300;\nconst DEFAULT_SPOTLIGHT_PADDING = 8;\nconst AUTO_TOUR_INTERVAL_MS = 5000;\nconst TOOLTIP_ARROW_SIZE = 8;\nconst TOOLTIP_MARGIN = 12;\nconst OVERLAY_Z_INDEX = 999998;\nconst TOOLTIP_Z_INDEX = 999999;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface VisualGuidanceOptions {\n /** Color of the spotlight overlay. Default: 'rgba(0, 0, 0, 0.5)' */\n overlayColor?: string;\n /** Color of the spotlight cutout border. Default: '#4a9eed' */\n spotlightColor?: string;\n /** Animation duration in ms. Default: 300 */\n animationDuration?: number;\n /** Padding around the highlighted element in px. Default: 8 */\n spotlightPadding?: number;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n}\n\nexport interface TooltipOptions {\n text: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n}\n\nexport interface SpotlightState {\n isActive: boolean;\n selector: string | null;\n sectionId: string | null;\n tooltip: string | null;\n}\n\ntype TooltipPosition = 'top' | 'bottom' | 'left' | 'right';\n\n// ---------------------------------------------------------------------------\n// Utility: Scrollable ancestor detection\n// ---------------------------------------------------------------------------\n\n/**\n * Walk up the DOM tree and collect every ancestor that has an overflow\n * style allowing scroll (auto or scroll).\n */\nfunction getScrollableAncestors(element: Element): Element[] {\n if (typeof getComputedStyle === 'undefined') return [];\n\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n while (parent) {\n const style = getComputedStyle(parent);\n const overflow = style.overflow + style.overflowX + style.overflowY;\n if (/(auto|scroll)/.test(overflow)) {\n ancestors.push(parent);\n }\n parent = parent.parentElement;\n }\n return ancestors;\n}\n\n/**\n * Detect whether the user prefers reduced motion.\n */\nfunction prefersReducedMotion(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n// ---------------------------------------------------------------------------\n// VisualGuidance\n// ---------------------------------------------------------------------------\n\nexport class VisualGuidance {\n // Configuration\n private readonly overlayColor: string;\n private readonly spotlightColor: string;\n private readonly animationDuration: number;\n private readonly spotlightPadding: number;\n private readonly debug: boolean;\n\n // DOM elements (created lazily)\n private overlayEl: HTMLDivElement | null = null;\n private spotlightEl: HTMLDivElement | null = null;\n private tooltipEl: HTMLDivElement | null = null;\n private liveRegionEl: HTMLDivElement | null = null;\n\n // State\n private _state: SpotlightState = {\n isActive: false,\n selector: null,\n sectionId: null,\n tooltip: null,\n };\n\n // Tracking infrastructure\n private resizeObserver: ResizeObserver | null = null;\n private scrollListenerCleanups: Array<() => void> = [];\n private currentTargetElement: Element | null = null;\n\n // Tour state\n private tourSectionIds: string[] = [];\n private tourCurrentStep = -1;\n private tourMode: 'auto' | 'manual' = 'manual';\n private tourAutoTimer: ReturnType<typeof setTimeout> | null = null;\n private tourPausedByInteraction = false;\n\n // Subscribers\n private spotlightChangeCallbacks: Array<(state: SpotlightState) => void> = [];\n private tourStepCallbacks: Array<(step: number, total: number, sectionId: string) => void> = [];\n\n // DOMScanner for resolving sectionIds\n private domScanner: DOMScanner | null = null;\n\n // Track whether destroy() has been called\n private destroyed = false;\n\n constructor(options?: VisualGuidanceOptions) {\n this.overlayColor = options?.overlayColor ?? DEFAULT_OVERLAY_COLOR;\n this.spotlightColor = options?.spotlightColor ?? DEFAULT_SPOTLIGHT_COLOR;\n this.animationDuration = options?.animationDuration ?? DEFAULT_ANIMATION_DURATION;\n this.spotlightPadding = options?.spotlightPadding ?? DEFAULT_SPOTLIGHT_PADDING;\n this.debug = options?.debug ?? false;\n\n this.log('Initialised', {\n overlayColor: this.overlayColor,\n spotlightColor: this.spotlightColor,\n animationDuration: this.animationDuration,\n spotlightPadding: this.spotlightPadding,\n });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /**\n * Highlight an element by selector or sectionId.\n * Returns true if the element was found and highlighted, false otherwise.\n */\n highlight(params: {\n sectionId?: string;\n selector?: string;\n tooltip?: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n }): boolean {\n if (typeof document === 'undefined') return false;\n if (this.destroyed) return false;\n\n const { sectionId, selector, tooltip, position } = params;\n\n // Resolve the target element\n const target = this.resolveTarget(sectionId, selector);\n if (!target) {\n this.log('Target element not found', { sectionId, selector });\n return false;\n }\n\n const resolvedSelector = selector ?? this.buildSelectorForElement(target);\n\n // Dismiss any existing highlight first (without notifying to avoid flicker)\n this.cleanupTrackingInfrastructure();\n\n // Update state\n this._state = {\n isActive: true,\n selector: resolvedSelector,\n sectionId: sectionId ?? null,\n tooltip: tooltip ?? null,\n };\n\n this.currentTargetElement = target;\n\n // Check if the element has zero size (e.g., display: none)\n const rect = target.getBoundingClientRect();\n const hasSize = rect.width > 0 && rect.height > 0;\n\n if (hasSize) {\n // Create/update overlay and spotlight\n this.ensureOverlay();\n this.ensureSpotlight();\n this.positionSpotlight(rect);\n this.showOverlay();\n } else {\n this.log('Element has zero size, showing tooltip only');\n }\n\n // Show tooltip if requested\n if (tooltip) {\n this.showTooltip(target, tooltip, position ?? 'auto');\n } else {\n this.removeTooltip();\n }\n\n // Set up position tracking\n this.setupPositionTracking(target);\n\n // Announce for screen readers\n const label = sectionId ?? resolvedSelector;\n this.announce(`Highlighting ${label}`);\n\n // Notify subscribers\n this.notifySpotlightChange();\n\n this.log('Highlighted element', { sectionId, selector: resolvedSelector, tooltip });\n return true;\n }\n\n /**\n * Remove the spotlight and all associated elements.\n */\n dismissHighlight(): void {\n if (typeof document === 'undefined') return;\n\n this.cleanupTrackingInfrastructure();\n this.hideOverlay();\n this.removeTooltip();\n this.removeAriaDescribedBy();\n\n this.currentTargetElement = null;\n\n this._state = {\n isActive: false,\n selector: null,\n sectionId: null,\n tooltip: null,\n };\n\n this.notifySpotlightChange();\n this.log('Highlight dismissed');\n }\n\n /**\n * Smooth scroll to a section by its sectionId.\n */\n scrollToSection(sectionId: string, offset?: number): void {\n if (typeof document === 'undefined') return;\n\n const target = this.resolveTarget(sectionId, undefined);\n if (!target) {\n this.log('scrollToSection: section not found', { sectionId });\n return;\n }\n\n this.scrollToElement(target, offset);\n this.log('Scrolled to section', { sectionId });\n }\n\n /**\n * Smooth scroll to an element by CSS selector.\n */\n scrollToSelector(selector: string, offset?: number): void {\n if (typeof document === 'undefined') return;\n\n let target: Element | null;\n try {\n target = document.querySelector(selector);\n } catch {\n this.log('scrollToSelector: invalid selector', { selector });\n return;\n }\n\n if (!target) {\n this.log('scrollToSelector: element not found', { selector });\n return;\n }\n\n this.scrollToElement(target, offset);\n this.log('Scrolled to selector', { selector });\n }\n\n /**\n * Start a guided tour through the given section IDs.\n */\n startTour(sectionIds: string[], mode: 'auto' | 'manual' = 'manual'): void {\n if (typeof document === 'undefined') return;\n if (this.destroyed) return;\n if (sectionIds.length === 0) return;\n\n // Stop any existing tour\n this.stopTour();\n\n this.tourSectionIds = [...sectionIds];\n this.tourMode = mode;\n this.tourCurrentStep = -1;\n this.tourPausedByInteraction = false;\n\n this.log('Tour started', { steps: sectionIds.length, mode });\n\n // Advance to the first step\n this.nextTourStep();\n }\n\n /**\n * Move to the next tour step. No-op if no tour is active.\n */\n nextTourStep(): void {\n if (this.tourSectionIds.length === 0) return;\n\n // Clear any existing auto timer\n this.clearAutoTimer();\n\n const nextStep = this.tourCurrentStep + 1;\n if (nextStep >= this.tourSectionIds.length) {\n // Tour complete\n this.stopTour();\n return;\n }\n\n this.tourCurrentStep = nextStep;\n this.tourPausedByInteraction = false;\n\n this.executeTourStep();\n }\n\n /**\n * Move to the previous tour step. No-op if no tour is active or at first step.\n */\n prevTourStep(): void {\n if (this.tourSectionIds.length === 0) return;\n if (this.tourCurrentStep <= 0) return;\n\n // Clear any existing auto timer\n this.clearAutoTimer();\n\n this.tourCurrentStep -= 1;\n this.tourPausedByInteraction = false;\n\n this.executeTourStep();\n }\n\n /**\n * Stop the tour and dismiss all highlights.\n */\n stopTour(): void {\n this.clearAutoTimer();\n\n const wasActive = this.tourSectionIds.length > 0;\n\n this.tourSectionIds = [];\n this.tourCurrentStep = -1;\n this.tourPausedByInteraction = false;\n\n this.dismissHighlight();\n\n if (wasActive) {\n this.log('Tour stopped');\n }\n }\n\n /**\n * Get the current spotlight state.\n */\n get state(): SpotlightState {\n return { ...this._state };\n }\n\n /**\n * Get the current tour state, or null if no tour is active.\n */\n get tourState(): { active: boolean; step: number; total: number } | null {\n if (this.tourSectionIds.length === 0) {\n return null;\n }\n return {\n active: true,\n step: this.tourCurrentStep,\n total: this.tourSectionIds.length,\n };\n }\n\n /**\n * Subscribe to spotlight state changes.\n * Returns an unsubscribe function.\n */\n onSpotlightChange(callback: (state: SpotlightState) => void): () => void {\n this.spotlightChangeCallbacks.push(callback);\n return () => {\n const idx = this.spotlightChangeCallbacks.indexOf(callback);\n if (idx !== -1) {\n this.spotlightChangeCallbacks.splice(idx, 1);\n }\n };\n }\n\n /**\n * Subscribe to tour step events.\n * Returns an unsubscribe function.\n */\n onTourStep(callback: (step: number, total: number, sectionId: string) => void): () => void {\n this.tourStepCallbacks.push(callback);\n return () => {\n const idx = this.tourStepCallbacks.indexOf(callback);\n if (idx !== -1) {\n this.tourStepCallbacks.splice(idx, 1);\n }\n };\n }\n\n /**\n * Clean up all DOM elements, observers, and event listeners.\n * After calling destroy(), the instance is unusable.\n */\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.stopTour();\n this.dismissHighlight();\n this.cleanupTrackingInfrastructure();\n\n // Remove overlay\n if (this.overlayEl?.parentNode) {\n this.overlayEl.parentNode.removeChild(this.overlayEl);\n }\n this.overlayEl = null;\n\n // Remove spotlight\n if (this.spotlightEl?.parentNode) {\n this.spotlightEl.parentNode.removeChild(this.spotlightEl);\n }\n this.spotlightEl = null;\n\n // Remove tooltip\n this.removeTooltip();\n\n // Remove live region\n if (this.liveRegionEl?.parentNode) {\n this.liveRegionEl.parentNode.removeChild(this.liveRegionEl);\n }\n this.liveRegionEl = null;\n\n // Disconnect resize observer\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n // Clear subscriber lists\n this.spotlightChangeCallbacks = [];\n this.tourStepCallbacks = [];\n\n this.domScanner = null;\n\n this.log('Destroyed');\n }\n\n // -------------------------------------------------------------------------\n // Private: Target resolution\n // -------------------------------------------------------------------------\n\n /**\n * Resolve a target element from either a sectionId or a CSS selector.\n * If sectionId is provided, uses DOMScanner to find the section's selector.\n */\n private resolveTarget(sectionId?: string, selector?: string): Element | null {\n if (typeof document === 'undefined') return null;\n\n // Try selector first if provided\n if (selector) {\n try {\n const el = document.querySelector(selector);\n if (el) return el;\n } catch {\n this.log('Invalid selector', { selector });\n }\n }\n\n // Try sectionId via DOMScanner\n if (sectionId) {\n // Try common patterns: data-guidekit-target, id, aria-label\n const strategies = [\n `[data-guidekit-target=\"${sectionId}\"]`,\n `#${CSS.escape(sectionId)}`,\n `[aria-label=\"${sectionId}\"]`,\n ];\n\n for (const strategy of strategies) {\n try {\n const el = document.querySelector(strategy);\n if (el) return el;\n } catch {\n // Invalid selector, try next\n }\n }\n\n // Fall back to DOMScanner for a full scan\n if (!this.domScanner) {\n this.domScanner = new DOMScanner({ debug: this.debug });\n }\n const model = this.domScanner.scan();\n const section = model.sections.find((s) => s.id === sectionId);\n if (section) {\n try {\n const el = document.querySelector(section.selector);\n if (el) return el;\n } catch {\n this.log('DOMScanner selector invalid', { selector: section.selector });\n }\n }\n }\n\n return null;\n }\n\n /**\n * Build a CSS selector for an element, using the same priority hierarchy\n * as the DOMScanner.\n */\n private buildSelectorForElement(el: Element): string {\n const guideKitTarget = el.getAttribute('data-guidekit-target');\n if (guideKitTarget) return `[data-guidekit-target=\"${guideKitTarget}\"]`;\n\n const id = el.id;\n if (id) {\n try {\n const escaped = CSS.escape(id);\n if (document.querySelectorAll(`#${escaped}`).length === 1) {\n return `#${escaped}`;\n }\n } catch {\n // Fall through\n }\n }\n\n const testId = el.getAttribute('data-testid');\n if (testId) return `[data-testid=\"${testId}\"]`;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return `[aria-label=\"${ariaLabel}\"]`;\n\n // Structural path fallback\n return this.buildStructuralPath(el);\n }\n\n private buildStructuralPath(el: Element): string {\n if (typeof document === 'undefined') return '';\n\n const parts: string[] = [];\n let current: Element | null = el;\n\n while (current && current !== document.documentElement) {\n const tag = current.tagName.toLowerCase();\n\n if (tag === 'body' || tag === 'html') {\n parts.unshift(tag);\n current = current.parentElement;\n continue;\n }\n\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c) => c.tagName === current!.tagName,\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n parts.unshift(`${tag}:nth-child(${index})`);\n } else {\n parts.unshift(tag);\n }\n } else {\n parts.unshift(tag);\n }\n\n current = parent;\n }\n\n return parts.join(' > ');\n }\n\n // -------------------------------------------------------------------------\n // Private: Overlay management\n // -------------------------------------------------------------------------\n\n /**\n * Ensure the full-page overlay element exists on document.body.\n */\n private ensureOverlay(): void {\n if (typeof document === 'undefined') return;\n if (this.overlayEl) return;\n\n const overlay = document.createElement('div');\n overlay.setAttribute('aria-hidden', 'true');\n overlay.setAttribute('data-guidekit-overlay', 'true');\n overlay.style.cssText = [\n 'position: fixed',\n 'inset: 0',\n `z-index: ${OVERLAY_Z_INDEX}`,\n 'pointer-events: none',\n 'opacity: 0',\n `transition: opacity ${this.getTransitionDuration()}ms ease-out`,\n ].join('; ');\n\n document.body.appendChild(overlay);\n this.overlayEl = overlay;\n }\n\n /**\n * Ensure the spotlight (cutout) element exists on document.body.\n */\n private ensureSpotlight(): void {\n if (typeof document === 'undefined') return;\n if (this.spotlightEl) return;\n\n const spotlight = document.createElement('div');\n spotlight.setAttribute('aria-hidden', 'true');\n spotlight.setAttribute('data-guidekit-spotlight', 'true');\n\n const transitionDuration = this.getTransitionDuration();\n spotlight.style.cssText = [\n 'position: fixed',\n `z-index: ${OVERLAY_Z_INDEX}`,\n 'pointer-events: none',\n 'border-radius: 4px',\n `border: 2px solid ${this.spotlightColor}`,\n `box-shadow: 0 0 0 9999px ${this.overlayColor}`,\n 'will-change: transform, opacity',\n 'opacity: 0',\n `transition: transform ${transitionDuration}ms ease-out, opacity ${transitionDuration}ms ease-out, width ${transitionDuration}ms ease-out, height ${transitionDuration}ms ease-out`,\n ].join('; ');\n\n document.body.appendChild(spotlight);\n this.spotlightEl = spotlight;\n }\n\n /**\n * Position the spotlight element over the target's bounding rect.\n */\n private positionSpotlight(rect: DOMRect): void {\n if (!this.spotlightEl) return;\n\n const pad = this.spotlightPadding;\n const left = rect.left - pad;\n const top = rect.top - pad;\n const width = rect.width + pad * 2;\n const height = rect.height + pad * 2;\n\n this.spotlightEl.style.left = `${left}px`;\n this.spotlightEl.style.top = `${top}px`;\n this.spotlightEl.style.width = `${width}px`;\n this.spotlightEl.style.height = `${height}px`;\n }\n\n /**\n * Show the overlay and spotlight with entrance animation.\n */\n private showOverlay(): void {\n if (typeof document === 'undefined') return;\n\n // Force a reflow so the transition triggers\n if (this.overlayEl) {\n void this.overlayEl.offsetHeight;\n this.overlayEl.style.opacity = '1';\n }\n if (this.spotlightEl) {\n void this.spotlightEl.offsetHeight;\n this.spotlightEl.style.opacity = '1';\n }\n }\n\n /**\n * Hide the overlay and spotlight.\n */\n private hideOverlay(): void {\n if (this.overlayEl) {\n this.overlayEl.style.opacity = '0';\n }\n if (this.spotlightEl) {\n this.spotlightEl.style.opacity = '0';\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Tooltip management\n // -------------------------------------------------------------------------\n\n /**\n * Show a tooltip near the target element.\n */\n private showTooltip(\n target: Element,\n text: string,\n positionPref: 'top' | 'bottom' | 'left' | 'right' | 'auto',\n ): void {\n if (typeof document === 'undefined') return;\n\n // Create or reuse tooltip element\n if (!this.tooltipEl) {\n const tooltip = document.createElement('div');\n tooltip.setAttribute('role', 'tooltip');\n tooltip.setAttribute('data-guidekit-tooltip', 'true');\n\n const transitionDuration = this.getTransitionDuration();\n tooltip.style.cssText = [\n 'position: fixed',\n `z-index: ${TOOLTIP_Z_INDEX}`,\n 'pointer-events: none',\n 'background: #ffffff',\n 'color: #1a1a2e',\n 'padding: 10px 14px',\n 'border-radius: 8px',\n 'font-size: 14px',\n 'line-height: 1.4',\n 'max-width: 300px',\n 'box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15)',\n 'opacity: 0',\n `transition: opacity ${transitionDuration}ms ease-out`,\n 'font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n ].join('; ');\n\n document.body.appendChild(tooltip);\n this.tooltipEl = tooltip;\n }\n\n // Set text content (NEVER innerHTML to prevent XSS)\n this.tooltipEl.textContent = text;\n\n // Add step indicator if in a tour\n if (this.tourSectionIds.length > 0 && this.tourCurrentStep >= 0) {\n const stepText = `Step ${this.tourCurrentStep + 1} of ${this.tourSectionIds.length}`;\n this.tooltipEl.textContent = `${stepText}: ${text}`;\n }\n\n // Set aria-describedby on the target\n const tooltipId = 'guidekit-tooltip-' + Date.now();\n this.tooltipEl.id = tooltipId;\n if (target instanceof HTMLElement) {\n target.setAttribute('aria-describedby', tooltipId);\n }\n\n // Position the tooltip\n const rect = target.getBoundingClientRect();\n const position = positionPref === 'auto'\n ? this.computeAutoPosition(rect)\n : positionPref;\n\n this.positionTooltip(rect, position);\n\n // Animate in\n void this.tooltipEl.offsetHeight;\n this.tooltipEl.style.opacity = '1';\n }\n\n /**\n * Remove the tooltip element from the DOM.\n */\n private removeTooltip(): void {\n if (this.tooltipEl?.parentNode) {\n this.tooltipEl.parentNode.removeChild(this.tooltipEl);\n }\n this.tooltipEl = null;\n }\n\n /**\n * Remove aria-describedby from the current target element.\n */\n private removeAriaDescribedBy(): void {\n if (this.currentTargetElement instanceof HTMLElement) {\n this.currentTargetElement.removeAttribute('aria-describedby');\n }\n }\n\n /**\n * Compute the best auto-position for the tooltip relative to the target rect.\n * Preference order: bottom, top, right, left.\n */\n private computeAutoPosition(rect: DOMRect): TooltipPosition {\n if (typeof window === 'undefined') return 'bottom';\n\n const viewportHeight = window.innerHeight;\n const viewportWidth = window.innerWidth;\n\n const spaceBelow = viewportHeight - rect.bottom;\n const spaceAbove = rect.top;\n const spaceRight = viewportWidth - rect.right;\n const spaceLeft = rect.left;\n\n const minSpace = 80; // Minimum space needed for tooltip\n\n // Prefer bottom\n if (spaceBelow >= minSpace) return 'bottom';\n // Then top\n if (spaceAbove >= minSpace) return 'top';\n // Then right\n if (spaceRight >= minSpace) return 'right';\n // Then left\n if (spaceLeft >= minSpace) return 'left';\n\n // Default to bottom even if tight\n return 'bottom';\n }\n\n /**\n * Position the tooltip element relative to the target rect.\n */\n private positionTooltip(rect: DOMRect, position: TooltipPosition): void {\n if (!this.tooltipEl || typeof window === 'undefined') return;\n\n const pad = this.spotlightPadding;\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // We need the tooltip's dimensions. Force layout to measure.\n this.tooltipEl.style.left = '0px';\n this.tooltipEl.style.top = '0px';\n const tooltipRect = this.tooltipEl.getBoundingClientRect();\n const tw = tooltipRect.width;\n const th = tooltipRect.height;\n\n let left = 0;\n let top = 0;\n\n switch (position) {\n case 'bottom':\n left = rect.left + rect.width / 2 - tw / 2;\n top = rect.bottom + pad + TOOLTIP_ARROW_SIZE + TOOLTIP_MARGIN;\n break;\n case 'top':\n left = rect.left + rect.width / 2 - tw / 2;\n top = rect.top - pad - th - TOOLTIP_ARROW_SIZE - TOOLTIP_MARGIN;\n break;\n case 'right':\n left = rect.right + pad + TOOLTIP_ARROW_SIZE + TOOLTIP_MARGIN;\n top = rect.top + rect.height / 2 - th / 2;\n break;\n case 'left':\n left = rect.left - pad - tw - TOOLTIP_ARROW_SIZE - TOOLTIP_MARGIN;\n top = rect.top + rect.height / 2 - th / 2;\n break;\n }\n\n // Clamp within viewport\n left = Math.max(8, Math.min(left, viewportWidth - tw - 8));\n top = Math.max(8, Math.min(top, viewportHeight - th - 8));\n\n this.tooltipEl.style.left = `${left}px`;\n this.tooltipEl.style.top = `${top}px`;\n\n // Remove any existing arrow pseudo-element styling (via data attribute)\n this.tooltipEl.setAttribute('data-guidekit-position', position);\n\n // Apply arrow using a CSS trick with box-shadow on a pseudo :before\n // Since we can't use CSS stylesheets easily, we inline arrow via border trick\n this.applyTooltipArrow(position, rect);\n }\n\n /**\n * Apply an arrow on the tooltip pointing toward the target element.\n * Uses a child div with CSS border triangle technique.\n */\n private applyTooltipArrow(position: TooltipPosition, targetRect: DOMRect): void {\n if (!this.tooltipEl) return;\n\n // Remove any existing arrow\n const existingArrow = this.tooltipEl.querySelector('[data-guidekit-arrow]');\n if (existingArrow) {\n existingArrow.remove();\n }\n\n const arrow = document.createElement('div');\n arrow.setAttribute('data-guidekit-arrow', 'true');\n arrow.setAttribute('aria-hidden', 'true');\n\n const size = TOOLTIP_ARROW_SIZE;\n const baseStyle = [\n 'position: absolute',\n 'width: 0',\n 'height: 0',\n 'border-style: solid',\n ];\n\n switch (position) {\n case 'bottom':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: 0 ${size}px ${size}px ${size}px`,\n `border-color: transparent transparent #ffffff transparent`,\n `top: -${size}px`,\n `left: 50%`,\n `margin-left: -${size}px`,\n ].join('; ');\n // Adjust arrow horizontal position to point at target center\n this.adjustArrowHorizontal(arrow, targetRect, size);\n break;\n case 'top':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: ${size}px ${size}px 0 ${size}px`,\n `border-color: #ffffff transparent transparent transparent`,\n `bottom: -${size}px`,\n `left: 50%`,\n `margin-left: -${size}px`,\n ].join('; ');\n this.adjustArrowHorizontal(arrow, targetRect, size);\n break;\n case 'right':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: ${size}px ${size}px ${size}px 0`,\n `border-color: transparent #ffffff transparent transparent`,\n `left: -${size}px`,\n `top: 50%`,\n `margin-top: -${size}px`,\n ].join('; ');\n break;\n case 'left':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: ${size}px 0 ${size}px ${size}px`,\n `border-color: transparent transparent transparent #ffffff`,\n `right: -${size}px`,\n `top: 50%`,\n `margin-top: -${size}px`,\n ].join('; ');\n break;\n }\n\n this.tooltipEl.appendChild(arrow);\n }\n\n /**\n * Adjust arrow horizontal position so it points toward the target center\n * even when the tooltip is clamped to viewport edges.\n */\n private adjustArrowHorizontal(arrow: HTMLDivElement, targetRect: DOMRect, size: number): void {\n if (!this.tooltipEl) return;\n\n const tooltipRect = this.tooltipEl.getBoundingClientRect();\n const targetCenter = targetRect.left + targetRect.width / 2;\n const arrowLeft = targetCenter - tooltipRect.left;\n\n // Clamp arrow within tooltip bounds\n const minLeft = size + 4;\n const maxLeft = tooltipRect.width - size - 4;\n const clampedLeft = Math.max(minLeft, Math.min(arrowLeft, maxLeft));\n\n arrow.style.left = `${clampedLeft}px`;\n arrow.style.marginLeft = `0`;\n }\n\n // -------------------------------------------------------------------------\n // Private: Position tracking\n // -------------------------------------------------------------------------\n\n /**\n * Set up ResizeObserver and scroll listeners to track the target element\n * and update spotlight/tooltip positions.\n */\n private setupPositionTracking(target: Element): void {\n this.cleanupTrackingInfrastructure();\n\n // ResizeObserver\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => {\n this.updatePositions();\n });\n this.resizeObserver.observe(target);\n // Also observe body for layout changes\n if (typeof document !== 'undefined') {\n this.resizeObserver.observe(document.body);\n }\n }\n\n // Scroll listeners on all scrollable ancestors + window\n const scrollableAncestors = getScrollableAncestors(target);\n\n const handleScroll = (): void => {\n this.updatePositions();\n\n // In auto-tour mode, pause on user interaction\n if (this.tourMode === 'auto' && !this.tourPausedByInteraction) {\n this.tourPausedByInteraction = true;\n this.clearAutoTimer();\n // Resume after a delay\n this.tourAutoTimer = setTimeout(() => {\n this.tourPausedByInteraction = false;\n this.scheduleAutoAdvance();\n }, AUTO_TOUR_INTERVAL_MS);\n }\n };\n\n // Attach to each scrollable ancestor\n for (const ancestor of scrollableAncestors) {\n ancestor.addEventListener('scroll', handleScroll, { passive: true });\n this.scrollListenerCleanups.push(() => {\n ancestor.removeEventListener('scroll', handleScroll);\n });\n }\n\n // Always attach to window for document-level scroll\n if (typeof window !== 'undefined') {\n window.addEventListener('scroll', handleScroll, { passive: true });\n this.scrollListenerCleanups.push(() => {\n window.removeEventListener('scroll', handleScroll);\n });\n\n // Also listen for window resize\n window.addEventListener('resize', handleScroll, { passive: true });\n this.scrollListenerCleanups.push(() => {\n window.removeEventListener('resize', handleScroll);\n });\n }\n }\n\n /**\n * Remove all tracking observers and event listeners.\n */\n private cleanupTrackingInfrastructure(): void {\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n for (const cleanup of this.scrollListenerCleanups) {\n cleanup();\n }\n this.scrollListenerCleanups = [];\n }\n\n /**\n * Update spotlight and tooltip positions based on the current target\n * element's bounding rect.\n */\n private updatePositions(): void {\n if (!this.currentTargetElement) return;\n\n const rect = this.currentTargetElement.getBoundingClientRect();\n const hasSize = rect.width > 0 && rect.height > 0;\n\n if (hasSize && this.spotlightEl) {\n this.positionSpotlight(rect);\n }\n\n if (this.tooltipEl && this._state.tooltip) {\n const position = this.tooltipEl.getAttribute('data-guidekit-position') as TooltipPosition | null;\n this.positionTooltip(rect, position ?? 'bottom');\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Smooth scrolling\n // -------------------------------------------------------------------------\n\n /**\n * Scroll to an element, respecting reduced motion preferences.\n */\n private scrollToElement(target: Element, offset?: number): void {\n if (typeof window === 'undefined') return;\n\n const behavior = prefersReducedMotion() ? 'instant' as ScrollBehavior : 'smooth';\n\n if (offset !== undefined && offset !== 0) {\n // Use window.scrollTo with calculated position for header offset\n const rect = target.getBoundingClientRect();\n const scrollTop = window.pageYOffset ?? document.documentElement.scrollTop;\n const targetTop = rect.top + scrollTop - offset;\n\n window.scrollTo({\n top: targetTop,\n behavior,\n });\n } else {\n target.scrollIntoView({\n behavior,\n block: 'center',\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Tour logic\n // -------------------------------------------------------------------------\n\n /**\n * Execute the current tour step: scroll to and highlight the section.\n */\n private executeTourStep(): void {\n if (this.tourCurrentStep < 0 || this.tourCurrentStep >= this.tourSectionIds.length) {\n return;\n }\n\n const sectionId = this.tourSectionIds[this.tourCurrentStep] as string | undefined;\n if (!sectionId) return;\n\n const total = this.tourSectionIds.length;\n const step = this.tourCurrentStep;\n\n // Scroll to the section first\n this.scrollToSection(sectionId);\n\n // Slight delay to let scroll settle, then highlight\n // Use a timeout so scrollIntoView can initiate\n setTimeout(() => {\n if (this.destroyed) return;\n\n const tooltipText = `Step ${step + 1} of ${total}`;\n\n this.highlight({\n sectionId,\n tooltip: tooltipText,\n position: 'auto',\n });\n\n // Notify tour step subscribers\n for (const cb of this.tourStepCallbacks) {\n try {\n cb(step, total, sectionId);\n } catch (e) {\n this.log('Tour step callback error', { error: String(e) });\n }\n }\n\n // Schedule auto-advance if in auto mode\n if (this.tourMode === 'auto') {\n this.scheduleAutoAdvance();\n }\n }, 100);\n }\n\n /**\n * Schedule auto-advance to the next tour step.\n */\n private scheduleAutoAdvance(): void {\n this.clearAutoTimer();\n\n if (this.tourMode !== 'auto') return;\n if (this.tourPausedByInteraction) return;\n\n this.tourAutoTimer = setTimeout(() => {\n if (!this.destroyed && !this.tourPausedByInteraction) {\n this.nextTourStep();\n }\n }, AUTO_TOUR_INTERVAL_MS);\n }\n\n /**\n * Clear the auto-advance timer.\n */\n private clearAutoTimer(): void {\n if (this.tourAutoTimer !== null) {\n clearTimeout(this.tourAutoTimer);\n this.tourAutoTimer = null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Accessibility — aria-live announcements\n // -------------------------------------------------------------------------\n\n /**\n * Announce a message to screen readers via an aria-live region.\n */\n private announce(message: string): void {\n if (typeof document === 'undefined') return;\n\n if (!this.liveRegionEl) {\n const region = document.createElement('div');\n region.setAttribute('aria-live', 'assertive');\n region.setAttribute('aria-atomic', 'true');\n region.setAttribute('data-guidekit-live', 'true');\n region.style.cssText = [\n 'position: absolute',\n 'width: 1px',\n 'height: 1px',\n 'padding: 0',\n 'margin: -1px',\n 'overflow: hidden',\n 'clip: rect(0, 0, 0, 0)',\n 'white-space: nowrap',\n 'border: 0',\n ].join('; ');\n document.body.appendChild(region);\n this.liveRegionEl = region;\n }\n\n // Clear and re-set to trigger announcement\n this.liveRegionEl.textContent = '';\n // Use a microtask to ensure the DOM update is flushed before re-setting\n requestAnimationFrame(() => {\n if (this.liveRegionEl) {\n this.liveRegionEl.textContent = message;\n }\n });\n }\n\n // -------------------------------------------------------------------------\n // Private: Subscriber notifications\n // -------------------------------------------------------------------------\n\n private notifySpotlightChange(): void {\n const stateCopy = this.state;\n for (const cb of this.spotlightChangeCallbacks) {\n try {\n cb(stateCopy);\n } catch (e) {\n this.log('Spotlight change callback error', { error: String(e) });\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Utilities\n // -------------------------------------------------------------------------\n\n /**\n * Get the transition duration, respecting prefers-reduced-motion.\n */\n private getTransitionDuration(): number {\n return prefersReducedMotion() ? 0 : this.animationDuration;\n }\n\n /**\n * Debug logger.\n */\n private log(message: string, data?: Record<string, unknown>): void {\n if (!this.debug) return;\n if (typeof console !== 'undefined') {\n if (data) {\n console.log(`${LOG_PREFIX} ${message}`, data);\n } else {\n console.log(`${LOG_PREFIX} ${message}`);\n }\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – User Awareness System\n// ---------------------------------------------------------------------------\n// Monitors user behavior signals (scroll, dwell, idle, rage-click, section\n// visibility) and emits awareness events via the EventBus.\n// ---------------------------------------------------------------------------\n\nimport { EventBus } from '../bus/index.js';\n\nconst LOG_PREFIX = '[GuideKit:Awareness]';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_IDLE_TIMEOUT_MS = 60_000;\nconst DEFAULT_DWELL_TIMEOUT_MS = 8_000;\nconst DEFAULT_RAGE_CLICK_THRESHOLD = 3;\nconst DEFAULT_RAGE_CLICK_WINDOW_MS = 2_000;\nconst RAGE_CLICK_RADIUS_PX = 50;\nconst MOUSE_THROTTLE_MS = 200;\n\n/** Selectors used to discover observable sections. */\nconst SECTION_SELECTOR = [\n '[data-guidekit-target]',\n '[id]',\n 'main',\n 'section',\n 'article',\n 'aside',\n 'nav',\n 'header',\n 'footer',\n].join(', ');\n\n/** IntersectionObserver thresholds for section visibility. */\nconst IO_THRESHOLDS: number[] = [0, 0.25, 0.5, 0.75, 1.0];\n\n// ---------------------------------------------------------------------------\n// Exported types\n// ---------------------------------------------------------------------------\n\nexport interface AwarenessOptions {\n bus: EventBus;\n rootElement?: HTMLElement;\n idleTimeoutMs?: number;\n dwellTimeoutMs?: number;\n rageClickThreshold?: number;\n rageClickWindowMs?: number;\n debug?: boolean;\n}\n\nexport interface AwarenessState {\n scrollPercent: number;\n scrollDirection: 'up' | 'down' | 'none';\n focusedSectionId: string | null;\n focusedSectionDwellMs: number;\n isIdle: boolean;\n lastInteractionAt: number;\n visibleSections: Map<string, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ninterface ClickRecord {\n x: number;\n y: number;\n timestamp: number;\n target: Element;\n}\n\n// ---------------------------------------------------------------------------\n// AwarenessSystem\n// ---------------------------------------------------------------------------\n\n/**\n * Observes user interactions with the page and emits structured awareness\n * events on the shared {@link EventBus}.\n *\n * All browser API usage is gated behind `typeof window !== 'undefined'` so\n * the module can be safely imported in SSR contexts.\n */\nexport class AwarenessSystem {\n // ---- Configuration ------------------------------------------------------\n\n private readonly bus: EventBus;\n private readonly rootElement: HTMLElement | undefined;\n private readonly idleTimeoutMs: number;\n private readonly dwellTimeoutMs: number;\n private readonly rageClickThreshold: number;\n private readonly rageClickWindowMs: number;\n private readonly debugEnabled: boolean;\n\n // ---- Runtime state ------------------------------------------------------\n\n private running = false;\n\n /** AbortController whose signal is passed to every addEventListener call. */\n private abortController: AbortController | null = null;\n\n /** IntersectionObserver for section visibility tracking. */\n private sectionObserver: IntersectionObserver | null = null;\n\n /** Section id -> current visibility ratio. */\n private readonly visibleSections = new Map<string, number>();\n\n // ---- Scroll tracking ----------------------------------------------------\n\n private scrollPercent = 0;\n private scrollDirection: 'up' | 'down' | 'none' = 'none';\n private lastScrollY = 0;\n private scrollRafPending = false;\n\n // ---- Dwell detection ----------------------------------------------------\n\n private focusedSectionId: string | null = null;\n private focusedSectionSince = 0;\n private dwellTimer: ReturnType<typeof setInterval> | null = null;\n private dwellEmitted = false;\n\n // ---- Idle detection -----------------------------------------------------\n\n private lastInteractionAt = 0;\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private isIdle = false;\n\n // ---- Rage click detection -----------------------------------------------\n\n private readonly recentClicks: ClickRecord[] = [];\n\n // ---- Mouse throttle -----------------------------------------------------\n\n private lastMouseMoveAt = 0;\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options: AwarenessOptions) {\n this.bus = options.bus;\n this.rootElement = options.rootElement;\n this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.dwellTimeoutMs = options.dwellTimeoutMs ?? DEFAULT_DWELL_TIMEOUT_MS;\n this.rageClickThreshold = options.rageClickThreshold ?? DEFAULT_RAGE_CLICK_THRESHOLD;\n this.rageClickWindowMs = options.rageClickWindowMs ?? DEFAULT_RAGE_CLICK_WINDOW_MS;\n this.debugEnabled = options.debug ?? false;\n\n this.log('AwarenessSystem created');\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Begin observing user behavior. No-op if already running or in SSR. */\n start(): void {\n if (this.running) return;\n if (typeof window === 'undefined') {\n this.log('SSR environment detected — start() is a no-op');\n return;\n }\n\n this.running = true;\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n\n this.lastInteractionAt = Date.now();\n this.lastScrollY = window.scrollY;\n\n // -- Event listeners (all using the shared AbortController signal) -----\n const listenerOpts = { signal, passive: true } as const;\n\n window.addEventListener('scroll', this.handleScroll, listenerOpts);\n window.addEventListener('mousemove', this.handleMouseMove, listenerOpts);\n window.addEventListener('keydown', this.handleInteraction, listenerOpts);\n window.addEventListener('click', this.handleClick, { signal });\n window.addEventListener('touchstart', this.handleInteraction, listenerOpts);\n window.addEventListener('touchend', this.handleInteraction, listenerOpts);\n\n // -- IntersectionObserver for sections ---------------------------------\n this.initSectionObserver();\n\n // -- Idle timer --------------------------------------------------------\n this.scheduleIdleTimer();\n\n // -- Dwell check interval ---------------------------------------------\n this.dwellTimer = setInterval(this.checkDwell, 1_000);\n\n this.log('Monitoring started');\n }\n\n /** Stop all observers and listeners. */\n stop(): void {\n if (!this.running) return;\n\n this.running = false;\n\n // Abort all listeners in one call.\n this.abortController?.abort();\n this.abortController = null;\n\n // Tear down IntersectionObserver.\n if (this.sectionObserver) {\n this.sectionObserver.disconnect();\n this.sectionObserver = null;\n }\n\n // Clear timers.\n this.clearIdleTimer();\n this.clearDwellTimer();\n\n // Reset state.\n this.visibleSections.clear();\n this.recentClicks.length = 0;\n this.focusedSectionId = null;\n this.focusedSectionSince = 0;\n this.dwellEmitted = false;\n this.isIdle = false;\n this.scrollPercent = 0;\n this.scrollDirection = 'none';\n this.scrollRafPending = false;\n\n this.log('Monitoring stopped');\n }\n\n /** Alias for {@link stop}. */\n destroy(): void {\n this.stop();\n }\n\n /** Return a snapshot of the current awareness state. */\n getState(): AwarenessState {\n const now = Date.now();\n const dwellMs =\n this.focusedSectionId !== null\n ? now - this.focusedSectionSince\n : 0;\n\n return {\n scrollPercent: this.scrollPercent,\n scrollDirection: this.scrollDirection,\n focusedSectionId: this.focusedSectionId,\n focusedSectionDwellMs: dwellMs,\n isIdle: this.isIdle,\n lastInteractionAt: this.lastInteractionAt,\n visibleSections: new Map(this.visibleSections),\n };\n }\n\n // -----------------------------------------------------------------------\n // Scroll tracking\n // -----------------------------------------------------------------------\n\n private readonly handleScroll = (): void => {\n this.recordInteraction();\n\n if (this.scrollRafPending) return;\n this.scrollRafPending = true;\n\n requestAnimationFrame(() => {\n this.scrollRafPending = false;\n if (!this.running) return;\n\n const y = window.scrollY;\n const maxScroll = document.documentElement.scrollHeight - window.innerHeight;\n this.scrollPercent = maxScroll > 0 ? Math.min(1, y / maxScroll) : 0;\n\n if (y > this.lastScrollY) {\n this.scrollDirection = 'down';\n } else if (y < this.lastScrollY) {\n this.scrollDirection = 'up';\n }\n // If y === lastScrollY, keep the current direction.\n\n this.lastScrollY = y;\n });\n };\n\n // -----------------------------------------------------------------------\n // Mouse tracking (throttled)\n // -----------------------------------------------------------------------\n\n private readonly handleMouseMove = (): void => {\n const now = Date.now();\n if (now - this.lastMouseMoveAt < MOUSE_THROTTLE_MS) return;\n this.lastMouseMoveAt = now;\n\n this.recordInteraction();\n };\n\n // -----------------------------------------------------------------------\n // Click tracking & rage click detection\n // -----------------------------------------------------------------------\n\n private readonly handleClick = (e: Event): void => {\n this.recordInteraction();\n\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element | null;\n if (!target) return;\n\n const now = Date.now();\n const record: ClickRecord = {\n x: mouseEvent.clientX,\n y: mouseEvent.clientY,\n timestamp: now,\n target,\n };\n\n this.recentClicks.push(record);\n\n // Prune clicks outside the rage-click time window.\n const windowStart = now - this.rageClickWindowMs;\n while (this.recentClicks.length > 0 && this.recentClicks[0]!.timestamp < windowStart) {\n this.recentClicks.shift();\n }\n\n // Check for rage clicks: N+ clicks within the window on the same\n // element or within a small radius.\n const nearby = this.recentClicks.filter((c) => {\n const sameElement = c.target === target;\n const dx = c.x - record.x;\n const dy = c.y - record.y;\n const withinRadius = Math.sqrt(dx * dx + dy * dy) <= RAGE_CLICK_RADIUS_PX;\n return sameElement || withinRadius;\n });\n\n if (nearby.length >= this.rageClickThreshold) {\n const selector = this.buildSelector(target);\n this.bus.emit('awareness:rage-click', {\n selector,\n clicks: nearby.length,\n });\n this.log(`Rage click detected (${nearby.length} clicks) on \"${selector}\"`);\n\n // Clear clicks so we don't keep re-emitting for the same burst.\n this.recentClicks.length = 0;\n }\n };\n\n // -----------------------------------------------------------------------\n // Generic interaction handler (touch, keydown)\n // -----------------------------------------------------------------------\n\n private readonly handleInteraction = (): void => {\n this.recordInteraction();\n };\n\n // -----------------------------------------------------------------------\n // Interaction bookkeeping (shared by all handlers)\n // -----------------------------------------------------------------------\n\n private recordInteraction(): void {\n this.lastInteractionAt = Date.now();\n\n // If user was idle, mark active again and reset idle timer.\n if (this.isIdle) {\n this.isIdle = false;\n this.log('User returned from idle');\n }\n\n this.scheduleIdleTimer();\n }\n\n // -----------------------------------------------------------------------\n // Idle detection\n // -----------------------------------------------------------------------\n\n private scheduleIdleTimer(): void {\n this.clearIdleTimer();\n\n this.idleTimer = setTimeout(() => {\n if (!this.running) return;\n\n this.isIdle = true;\n const durationMs = Date.now() - this.lastInteractionAt;\n\n this.bus.emit('awareness:idle', { durationMs });\n this.log(`User idle for ${durationMs}ms`);\n }, this.idleTimeoutMs);\n }\n\n private clearIdleTimer(): void {\n if (this.idleTimer !== null) {\n clearTimeout(this.idleTimer);\n this.idleTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // Dwell detection\n // -----------------------------------------------------------------------\n\n /**\n * Periodically (every 1s) check whether the user has been focused on the\n * same section long enough to trigger a dwell event.\n */\n private readonly checkDwell = (): void => {\n if (!this.running) return;\n\n // Determine the section with the highest visibility ratio.\n let bestId: string | null = null;\n let bestRatio = 0;\n\n for (const [id, ratio] of this.visibleSections) {\n if (ratio > bestRatio) {\n bestRatio = ratio;\n bestId = id;\n }\n }\n\n // If the focused section changed, reset the dwell tracker.\n if (bestId !== this.focusedSectionId) {\n this.focusedSectionId = bestId;\n this.focusedSectionSince = Date.now();\n this.dwellEmitted = false;\n return;\n }\n\n // If we have a focused section and haven't emitted yet, check duration.\n if (this.focusedSectionId !== null && !this.dwellEmitted) {\n const dwellMs = Date.now() - this.focusedSectionSince;\n if (dwellMs >= this.dwellTimeoutMs) {\n this.dwellEmitted = true;\n this.bus.emit('awareness:dwell', {\n sectionId: this.focusedSectionId,\n durationMs: dwellMs,\n });\n this.log(`Dwell on \"${this.focusedSectionId}\" (${dwellMs}ms)`);\n }\n }\n };\n\n private clearDwellTimer(): void {\n if (this.dwellTimer !== null) {\n clearInterval(this.dwellTimer);\n this.dwellTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // IntersectionObserver — section visibility\n // -----------------------------------------------------------------------\n\n private initSectionObserver(): void {\n if (typeof IntersectionObserver === 'undefined') {\n this.log('IntersectionObserver not available — section tracking disabled');\n return;\n }\n\n this.sectionObserver = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const sectionId = this.getSectionId(entry.target);\n if (!sectionId) continue;\n\n const ratio = Math.round(entry.intersectionRatio * 100) / 100;\n const previous = this.visibleSections.get(sectionId);\n\n if (previous === ratio) continue;\n\n if (ratio === 0) {\n this.visibleSections.delete(sectionId);\n } else {\n this.visibleSections.set(sectionId, ratio);\n }\n\n this.bus.emit('awareness:section-visible', {\n sectionId,\n ratio,\n });\n }\n },\n {\n root: this.rootElement ?? null,\n threshold: IO_THRESHOLDS,\n },\n );\n\n this.observeSections();\n }\n\n /**\n * Query the DOM for observable sections and start observing them.\n */\n private observeSections(): void {\n if (!this.sectionObserver) return;\n\n const root = this.rootElement ?? document;\n const elements = root.querySelectorAll(SECTION_SELECTOR);\n\n if (elements.length === 0) {\n this.log('No observable sections found');\n return;\n }\n\n for (const el of elements) {\n this.sectionObserver.observe(el);\n }\n\n this.log(`Observing ${elements.length} section(s)`);\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n /**\n * Derive a stable string identifier for a DOM element used as a section.\n *\n * Priority: `data-guidekit-target` > `id` > tagName.\n */\n private getSectionId(el: Element): string | null {\n const guidekitTarget = el.getAttribute('data-guidekit-target');\n if (guidekitTarget) return guidekitTarget;\n\n const id = el.getAttribute('id');\n if (id) return `#${id}`;\n\n // For semantic landmarks, use the tag name (lowercase).\n const tag = el.tagName.toLowerCase();\n const landmarks = ['main', 'section', 'article', 'aside', 'nav', 'header', 'footer'];\n if (landmarks.includes(tag)) return tag;\n\n return null;\n }\n\n /**\n * Build a simple CSS selector string for an element, suitable for\n * inclusion in rage-click events.\n */\n private buildSelector(el: Element): string {\n // Prefer id.\n if (el.id) return `#${el.id}`;\n\n // data-guidekit-target\n const target = el.getAttribute('data-guidekit-target');\n if (target) return `[data-guidekit-target=\"${target}\"]`;\n\n // Construct a tag.class selector.\n const tag = el.tagName.toLowerCase();\n const classes = Array.from(el.classList)\n .slice(0, 3) // Limit to avoid absurdly long selectors\n .map((c) => `.${c}`)\n .join('');\n\n return `${tag}${classes}`;\n }\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Proactive Trigger Engine\n// ---------------------------------------------------------------------------\n// Listens to awareness events on the EventBus and decides when to\n// proactively engage the user. The engine itself never shows UI or sends\n// LLM messages — it communicates via the `onTrigger` callback so the core\n// orchestrator can decide what action to take.\n// ---------------------------------------------------------------------------\n\nimport { EventBus } from '../bus/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Proactive]';\nconst STORAGE_KEY = 'guidekit:visited';\nconst SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** Progressive dwell cooldowns in ms: 30s → 60s → 120s → stop. */\nconst DWELL_COOLDOWNS = [30_000, 60_000, 120_000];\nconst DWELL_THRESHOLD_MS = 8_000;\nconst IDLE_THRESHOLD_MS = 60_000;\nconst NAVIGATION_COOLDOWN_MS = 30_000;\nconst FORM_ABANDON_MS = 15_000;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ProactiveOptions {\n bus: EventBus;\n debug?: boolean;\n /** Callback invoked whenever a proactive trigger fires. */\n onTrigger?: (trigger: ProactiveTrigger) => void;\n}\n\nexport type ProactiveTriggerType =\n | 'greeting'\n | 'idle-help'\n | 'dwell-commentary'\n | 'navigation-commentary'\n | 'frustration'\n | 'form-abandonment';\n\nexport interface ProactiveTrigger {\n type: ProactiveTriggerType;\n sectionId?: string;\n selector?: string;\n /** Suggested context message for the LLM. */\n message?: string;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// ProactiveTriggerEngine\n// ---------------------------------------------------------------------------\n\nexport class ProactiveTriggerEngine {\n private readonly bus: EventBus;\n private readonly debug: boolean;\n private readonly onTrigger?: (trigger: ProactiveTrigger) => void;\n\n /** Collected unsubscribe functions from bus.on(). */\n private unsubs: Array<() => void> = [];\n\n /** Cooldown map: trigger key → last-fired timestamp. */\n private cooldowns = new Map<string, number>();\n\n /** Progressive dwell: sectionId → number of times triggered. */\n private dwellCounts = new Map<string, number>();\n\n /** Track forms the user started interacting with. */\n private formTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Track sections where frustration already fired (once per section). */\n private frustrationFired = new Set<string>();\n\n /** Track whether idle-help has fired on this page. */\n private idleFiredThisPage = false;\n\n private _quietMode = false;\n private started = false;\n\n constructor(options: ProactiveOptions) {\n this.bus = options.bus;\n this.debug = options.debug ?? false;\n this.onTrigger = options.onTrigger;\n }\n\n // ---- quietMode accessor -------------------------------------------------\n\n get quietMode(): boolean {\n return this._quietMode;\n }\n\n set quietMode(value: boolean) {\n this._quietMode = value;\n if (this.debug) {\n console.debug(LOG_PREFIX, `Quiet mode ${value ? 'enabled' : 'disabled'}`);\n }\n }\n\n // ---- Lifecycle -----------------------------------------------------------\n\n /** Subscribe to bus events and check for first-visit greeting. */\n start(): void {\n if (this.started) return;\n this.started = true;\n\n this.checkFirstVisitGreeting();\n\n // awareness:idle\n this.unsubs.push(\n this.bus.on('awareness:idle', (data) => {\n this.handleIdle(data.durationMs);\n }),\n );\n\n // awareness:dwell\n this.unsubs.push(\n this.bus.on('awareness:dwell', (data) => {\n this.handleDwell(data.sectionId, data.durationMs);\n }),\n );\n\n // awareness:rage-click\n this.unsubs.push(\n this.bus.on('awareness:rage-click', (data) => {\n this.handleRageClick(data.selector, data.clicks);\n }),\n );\n\n // dom:route-change — used for navigation commentary + page reset\n this.unsubs.push(\n this.bus.on('dom:route-change', (data) => {\n this.handleDomRouteChange(data.from, data.to);\n }),\n );\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Started — subscribed to awareness & dom events');\n }\n }\n\n /** Unsubscribe all bus listeners and clear internal state. */\n stop(): void {\n for (const unsub of this.unsubs) {\n unsub();\n }\n this.unsubs = [];\n\n // Clear any pending form-abandonment timers\n for (const timer of this.formTimers.values()) {\n clearTimeout(timer);\n }\n this.formTimers.clear();\n\n this.started = false;\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Stopped — all listeners removed');\n }\n }\n\n /** Alias for {@link stop}. */\n destroy(): void {\n this.stop();\n }\n\n // ---- External notifications ---------------------------------------------\n\n /**\n * Notify the engine about a route change.\n * Called from the NavigationController or externally.\n */\n onRouteChange(from: string, to: string): void {\n this.handleNavigation(from, to);\n }\n\n /**\n * Notify the engine that the user started interacting with a form.\n * If the user does not continue within {@link FORM_ABANDON_MS}, a\n * `form-abandonment` trigger fires (once per form).\n */\n onFormInteractionStart(formSelector: string): void {\n // If there is already a timer for this form, reset it\n const existing = this.formTimers.get(formSelector);\n if (existing) {\n clearTimeout(existing);\n }\n\n const timer = setTimeout(() => {\n this.formTimers.delete(formSelector);\n this.fireTrigger({\n type: 'form-abandonment',\n selector: formSelector,\n message: `User started a form (${formSelector}) but stopped interacting for ${FORM_ABANDON_MS / 1000}s. They may need help.`,\n }, `form-abandonment:${formSelector}`);\n }, FORM_ABANDON_MS);\n\n this.formTimers.set(formSelector, timer);\n\n if (this.debug) {\n console.debug(LOG_PREFIX, `Form interaction started: ${formSelector}`);\n }\n }\n\n /** Reset all cooldowns and internal tracking state (useful for testing). */\n resetCooldowns(): void {\n this.cooldowns.clear();\n this.dwellCounts.clear();\n this.frustrationFired.clear();\n this.idleFiredThisPage = false;\n\n for (const timer of this.formTimers.values()) {\n clearTimeout(timer);\n }\n this.formTimers.clear();\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'All cooldowns and state reset');\n }\n }\n\n // ---- Internal handlers ---------------------------------------------------\n\n private checkFirstVisitGreeting(): void {\n if (typeof window === 'undefined' || typeof localStorage === 'undefined') {\n return;\n }\n\n try {\n const visited = localStorage.getItem(STORAGE_KEY);\n\n if (visited === null) {\n // First visit ever — fire greeting\n localStorage.setItem(STORAGE_KEY, Date.now().toString());\n\n this.fireTrigger({\n type: 'greeting',\n message: 'First-time visitor detected. Show a visual greeting (no audio).',\n }, 'greeting');\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'First visit — greeting triggered');\n }\n return;\n }\n\n // Return visitor — check if within 7 days\n const visitedAt = parseInt(visited, 10);\n if (Number.isNaN(visitedAt)) {\n // Stored timestamp is corrupt — skip return-visitor logic\n return;\n }\n\n const elapsed = Date.now() - visitedAt;\n if (elapsed <= SEVEN_DAYS_MS && this.debug) {\n console.debug(LOG_PREFIX, 'Return visitor within 7 days — silent');\n } else if (this.debug) {\n console.debug(LOG_PREFIX, 'Return visitor after 7 days');\n }\n } catch {\n // localStorage may be unavailable (e.g. iframe sandbox)\n if (this.debug) {\n console.warn(LOG_PREFIX, 'localStorage unavailable — skipping greeting check');\n }\n }\n }\n\n private handleIdle(durationMs: number): void {\n if (durationMs < IDLE_THRESHOLD_MS) return;\n if (this.idleFiredThisPage) return;\n\n this.idleFiredThisPage = true;\n\n this.fireTrigger({\n type: 'idle-help',\n message: `User has been idle for ${Math.round(durationMs / 1000)}s. They may be stuck or unsure what to do next.`,\n }, 'idle-help');\n }\n\n private handleDwell(sectionId: string, durationMs: number): void {\n if (durationMs < DWELL_THRESHOLD_MS) return;\n\n const count = this.dwellCounts.get(sectionId) ?? 0;\n\n // After 4 dwell triggers for the same section, stop entirely\n if (count >= DWELL_COOLDOWNS.length + 1) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Dwell cap reached for section \"${sectionId}\" — suppressed`);\n }\n return;\n }\n\n // Check progressive cooldown\n if (count > 0) {\n const cooldownMs = DWELL_COOLDOWNS[Math.min(count - 1, DWELL_COOLDOWNS.length - 1)]!;\n const key = `dwell:${sectionId}`;\n const lastFired = this.cooldowns.get(key) ?? 0;\n\n if (Date.now() - lastFired < cooldownMs) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Dwell cooldown active for \"${sectionId}\" — suppressed`);\n }\n return;\n }\n }\n\n this.dwellCounts.set(sectionId, count + 1);\n\n this.fireTrigger({\n type: 'dwell-commentary',\n sectionId,\n message: `User has been dwelling on section \"${sectionId}\" for ${Math.round(durationMs / 1000)}s. They may need more context.`,\n }, `dwell:${sectionId}`);\n }\n\n private handleRageClick(selector: string, clicks: number): void {\n // Derive a \"section\" key from the selector for once-per-section tracking\n const sectionKey = selector;\n\n if (this.frustrationFired.has(sectionKey)) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Frustration already fired for \"${selector}\" — suppressed`);\n }\n return;\n }\n\n this.frustrationFired.add(sectionKey);\n\n this.fireTrigger({\n type: 'frustration',\n selector,\n message: `User rage-clicked (${clicks} clicks) on \"${selector}\". They seem frustrated — offer help.`,\n }, `frustration:${sectionKey}`);\n }\n\n private handleNavigation(from: string, to: string): void {\n // Reset per-page cooldowns on page change\n this.idleFiredThisPage = false;\n\n const key = 'navigation-commentary';\n if (this.isCooldownActive(key, NAVIGATION_COOLDOWN_MS)) {\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Navigation cooldown active — suppressed');\n }\n return;\n }\n\n this.fireTrigger({\n type: 'navigation-commentary',\n message: `User navigated from \"${from}\" to \"${to}\". Offer context about the new page.`,\n }, key);\n }\n\n /**\n * Handler for the bus `dom:route-change` event.\n * Delegates to the shared navigation logic.\n */\n private handleDomRouteChange(from: string, to: string): void {\n this.handleNavigation(from, to);\n }\n\n // ---- Trigger dispatch ----------------------------------------------------\n\n /**\n * Fire a trigger if quiet mode is off, recording the cooldown timestamp.\n */\n private fireTrigger(\n partial: Omit<ProactiveTrigger, 'timestamp'>,\n cooldownKey: string,\n ): void {\n if (this._quietMode) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Quiet mode — suppressed trigger: ${partial.type}`);\n }\n return;\n }\n\n const trigger: ProactiveTrigger = {\n ...partial,\n timestamp: Date.now(),\n };\n\n this.cooldowns.set(cooldownKey, trigger.timestamp);\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Trigger fired:', trigger.type, trigger);\n }\n\n if (this.onTrigger) {\n try {\n this.onTrigger(trigger);\n } catch (err) {\n console.error(LOG_PREFIX, 'onTrigger callback error:', err);\n }\n }\n }\n\n // ---- Cooldown helpers ----------------------------------------------------\n\n private isCooldownActive(key: string, cooldownMs: number): boolean {\n const lastFired = this.cooldowns.get(key);\n if (lastFired === undefined) return false;\n return Date.now() - lastFired < cooldownMs;\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Client-Side Rate Limiter\n// ---------------------------------------------------------------------------\n//\n// Cost-protection guardrails. These limits are trivially bypassable and exist\n// solely to:\n// 1. Protect users from unexpected costs on BYOK keys\n// 2. Prevent runaway SDK loops from burning through API quotas\n//\n// NOT a security measure — documented as \"cost protection, not security\".\n// ---------------------------------------------------------------------------\n\nimport { EventBus } from '../bus/index.js';\nimport {\n ResourceExhaustedError,\n ErrorCodes,\n} from '../errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:RateLimiter]';\n\nconst DEFAULT_MAX_LLM_CALLS_PER_MINUTE = 10;\nconst DEFAULT_MAX_STT_MINUTES_PER_SESSION = 60;\nconst DEFAULT_MAX_TTS_CHARS_PER_SESSION = 50_000;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface RateLimits {\n maxLLMCallsPerMinute?: number;\n maxSTTMinutesPerSession?: number;\n maxTTSCharsPerSession?: number;\n}\n\nexport interface RateLimiterOptions {\n bus?: EventBus;\n limits?: RateLimits;\n debug?: boolean;\n}\n\nexport interface RateLimiterState {\n llmCallsInWindow: number;\n sttMinutesUsed: number;\n ttsCharsUsed: number;\n llmWindowStart: number;\n}\n\n// ---------------------------------------------------------------------------\n// RateLimiter\n// ---------------------------------------------------------------------------\n\nexport class RateLimiter {\n private readonly bus: EventBus | null;\n private readonly debug: boolean;\n\n // Configurable limits\n private maxLLMCallsPerMinute: number;\n private maxSTTMinutesPerSession: number;\n private maxTTSCharsPerSession: number;\n\n // LLM: sliding window (timestamps of recent calls)\n private llmCallTimestamps: number[] = [];\n\n // STT: cumulative session total (milliseconds for precision)\n private sttMs = 0;\n private sttStartedAt: number | null = null;\n\n // TTS: cumulative session total (characters)\n private ttsChars = 0;\n\n constructor(options?: RateLimiterOptions) {\n this.bus = options?.bus ?? null;\n this.debug = options?.debug ?? false;\n\n const limits = options?.limits;\n this.maxLLMCallsPerMinute =\n limits?.maxLLMCallsPerMinute ?? DEFAULT_MAX_LLM_CALLS_PER_MINUTE;\n this.maxSTTMinutesPerSession =\n limits?.maxSTTMinutesPerSession ?? DEFAULT_MAX_STT_MINUTES_PER_SESSION;\n this.maxTTSCharsPerSession =\n limits?.maxTTSCharsPerSession ?? DEFAULT_MAX_TTS_CHARS_PER_SESSION;\n }\n\n // -------------------------------------------------------------------------\n // LLM rate limiting\n // -------------------------------------------------------------------------\n\n /**\n * Check whether an LLM call is allowed. If allowed, records the call.\n * Throws `ResourceExhaustedError` if the limit is exceeded.\n */\n checkLLMCall(): void {\n const now = Date.now();\n const windowStart = now - 60_000;\n\n // Prune timestamps outside the 1-minute window\n this.llmCallTimestamps = this.llmCallTimestamps.filter(\n (t) => t > windowStart,\n );\n\n if (this.llmCallTimestamps.length >= this.maxLLMCallsPerMinute) {\n const err = new ResourceExhaustedError({\n code: ErrorCodes.RATE_LIMIT_CLIENT,\n message: `LLM rate limit exceeded: ${this.maxLLMCallsPerMinute} calls per minute.`,\n suggestion: `Wait a moment before sending another message, or increase rateLimits.maxLLMCallsPerMinute.`,\n });\n this.emitError(err);\n throw err;\n }\n\n this.llmCallTimestamps.push(now);\n this.log('LLM call recorded', {\n count: this.llmCallTimestamps.length,\n max: this.maxLLMCallsPerMinute,\n });\n }\n\n // -------------------------------------------------------------------------\n // STT rate limiting\n // -------------------------------------------------------------------------\n\n /** Call when STT streaming starts. */\n sttStart(): void {\n if (this.sttStartedAt !== null) return; // already streaming\n this.sttStartedAt = Date.now();\n this.log('STT streaming started');\n }\n\n /** Call when STT streaming stops. Accumulates duration. */\n sttStop(): void {\n if (this.sttStartedAt === null) return;\n const elapsed = Date.now() - this.sttStartedAt;\n this.sttMs += elapsed;\n this.sttStartedAt = null;\n this.log('STT streaming stopped', {\n elapsedMs: elapsed,\n totalMinutes: this.sttMinutesUsed,\n });\n }\n\n /**\n * Check whether STT streaming is within limits.\n * Throws `ResourceExhaustedError` if exceeded.\n */\n checkSTT(): void {\n const totalMinutes = this.sttMinutesUsed;\n if (totalMinutes >= this.maxSTTMinutesPerSession) {\n this.sttStop(); // stop the clock\n const err = new ResourceExhaustedError({\n code: ErrorCodes.RATE_LIMIT_CLIENT,\n message: `STT session limit exceeded: ${this.maxSTTMinutesPerSession} minutes per session.`,\n suggestion: `Voice input limit reached. Use text input, or increase rateLimits.maxSTTMinutesPerSession.`,\n });\n this.emitError(err);\n throw err;\n }\n }\n\n /** Current STT minutes used (including active stream). */\n private get sttMinutesUsed(): number {\n let totalMs = this.sttMs;\n if (this.sttStartedAt !== null) {\n const activeMs = Date.now() - this.sttStartedAt;\n const maxSessionMs = this.maxSTTMinutesPerSession * 60_000;\n const maxActiveMs = maxSessionMs * 2;\n\n if (activeMs > maxActiveMs) {\n console.warn(\n `${LOG_PREFIX} STT stream running for ${Math.round(activeMs / 60_000)}min without sttStop() — ` +\n `capping at 2x session limit (${this.maxSTTMinutesPerSession * 2}min).`,\n );\n // Auto-cap: freeze the accumulated time and clear the start marker\n this.sttMs += maxActiveMs;\n this.sttStartedAt = null;\n totalMs = this.sttMs;\n } else {\n totalMs += activeMs;\n }\n }\n return totalMs / 60_000;\n }\n\n // -------------------------------------------------------------------------\n // TTS rate limiting\n // -------------------------------------------------------------------------\n\n /**\n * Record TTS character usage. Throws `ResourceExhaustedError` if limit exceeded.\n */\n checkTTS(charCount: number): void {\n if (this.ttsChars + charCount > this.maxTTSCharsPerSession) {\n const err = new ResourceExhaustedError({\n code: ErrorCodes.RATE_LIMIT_CLIENT,\n message: `TTS character limit exceeded: ${this.maxTTSCharsPerSession} characters per session.`,\n suggestion: `Voice output limit reached. Responses will be text-only, or increase rateLimits.maxTTSCharsPerSession.`,\n });\n this.emitError(err);\n throw err;\n }\n\n this.ttsChars += charCount;\n this.log('TTS chars recorded', {\n added: charCount,\n total: this.ttsChars,\n max: this.maxTTSCharsPerSession,\n });\n }\n\n // -------------------------------------------------------------------------\n // State & config\n // -------------------------------------------------------------------------\n\n /** Get the current rate limiter state for monitoring. */\n getState(): RateLimiterState {\n const now = Date.now();\n const windowStart = now - 60_000;\n return {\n llmCallsInWindow: this.llmCallTimestamps.filter((t) => t > windowStart)\n .length,\n sttMinutesUsed: Math.round(this.sttMinutesUsed * 100) / 100,\n ttsCharsUsed: this.ttsChars,\n llmWindowStart: windowStart,\n };\n }\n\n /** Update limits at runtime. */\n setLimits(limits: RateLimits): void {\n if (limits.maxLLMCallsPerMinute !== undefined) {\n this.maxLLMCallsPerMinute = limits.maxLLMCallsPerMinute;\n }\n if (limits.maxSTTMinutesPerSession !== undefined) {\n this.maxSTTMinutesPerSession = limits.maxSTTMinutesPerSession;\n }\n if (limits.maxTTSCharsPerSession !== undefined) {\n this.maxTTSCharsPerSession = limits.maxTTSCharsPerSession;\n }\n this.log('Limits updated', limits);\n }\n\n /** Reset all counters (e.g., for testing or new session). */\n reset(): void {\n this.llmCallTimestamps = [];\n this.sttMs = 0;\n this.sttStartedAt = null;\n this.ttsChars = 0;\n this.log('Counters reset');\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private emitError(err: ResourceExhaustedError): void {\n if (this.bus) {\n this.bus.emit('error', err);\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// -----------------------------------------------------------------------\n// GuideKit SDK - Internationalization (i18n) Module\n// Provides localized strings for all SDK UI elements.\n// -----------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All translatable string keys used by the SDK UI. */\nexport interface I18nStrings {\n // Widget\n widgetTitle: string;\n openAssistant: string;\n closeAssistant: string;\n closePanel: string;\n sendMessage: string;\n inputPlaceholder: string;\n listeningPlaceholder: string;\n startVoice: string;\n stopVoice: string;\n\n // Status\n statusOnline: string;\n statusConnecting: string;\n statusOffline: string;\n statusListening: string;\n statusSpeaking: string;\n statusProcessing: string;\n\n // Empty state\n emptyStateMessage: string;\n\n // Errors\n errorGeneric: string;\n errorNetwork: string;\n errorMicDenied: string;\n errorRateLimit: string;\n\n // Proactive\n greetingMessage: string;\n idleHelpMessage: string;\n\n // Voice\n voiceDegradedNotice: string;\n\n // Quiet mode\n quietModeOn: string;\n quietModeOff: string;\n}\n\nexport type SupportedLocale = 'en' | 'es' | 'fr' | 'de' | 'ja' | 'zh' | 'ar' | 'pt';\n\nexport type LocaleInput = SupportedLocale | 'auto' | I18nStrings;\n\nexport interface I18nOptions {\n locale?: LocaleInput;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in locale data\n// ---------------------------------------------------------------------------\n\nconst en: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Open assistant',\n closeAssistant: 'Close assistant',\n closePanel: 'Close assistant panel',\n sendMessage: 'Send message',\n inputPlaceholder: 'Ask a question...',\n listeningPlaceholder: 'Listening...',\n startVoice: 'Start voice input',\n stopVoice: 'Stop voice input',\n\n statusOnline: 'Online',\n statusConnecting: 'Connecting...',\n statusOffline: 'Offline',\n statusListening: 'Listening...',\n statusSpeaking: 'Speaking...',\n statusProcessing: 'Processing...',\n\n emptyStateMessage:\n 'Ask me anything about this page. I can help you navigate, understand content, and more.',\n\n errorGeneric: 'Something went wrong. Please try again.',\n errorNetwork: 'Connection lost. Reconnecting...',\n errorMicDenied:\n 'Microphone access was denied. Please enable it in your browser settings.',\n errorRateLimit: 'Too many requests. Please wait a moment.',\n\n greetingMessage: 'Hi! Need help navigating this page?',\n idleHelpMessage: 'Still here if you need help!',\n\n voiceDegradedNotice: 'Voice unavailable. Switched to text mode.',\n\n quietModeOn: 'Notifications paused',\n quietModeOff: 'Notifications resumed',\n};\n\nconst es: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Abrir asistente',\n closeAssistant: 'Cerrar asistente',\n closePanel: 'Cerrar panel del asistente',\n sendMessage: 'Enviar mensaje',\n inputPlaceholder: 'Haz una pregunta...',\n listeningPlaceholder: 'Escuchando...',\n startVoice: 'Iniciar entrada de voz',\n stopVoice: 'Detener entrada de voz',\n\n statusOnline: 'En linea',\n statusConnecting: 'Conectando...',\n statusOffline: 'Sin conexion',\n statusListening: 'Escuchando...',\n statusSpeaking: 'Hablando...',\n statusProcessing: 'Procesando...',\n\n emptyStateMessage:\n 'Preguntame lo que quieras sobre esta pagina. Puedo ayudarte a navegar, entender el contenido y mucho mas.',\n\n errorGeneric: 'Algo salio mal. Por favor, intentalo de nuevo.',\n errorNetwork: 'Se perdio la conexion. Reconectando...',\n errorMicDenied:\n 'Se denego el acceso al microfono. Activalo en la configuracion de tu navegador.',\n errorRateLimit: 'Demasiadas solicitudes. Espera un momento, por favor.',\n\n greetingMessage: 'Hola! Necesitas ayuda para navegar esta pagina?',\n idleHelpMessage: 'Sigo aqui por si necesitas ayuda.',\n\n voiceDegradedNotice: 'Voz no disponible. Se cambio al modo de texto.',\n\n quietModeOn: 'Notificaciones en pausa',\n quietModeOff: 'Notificaciones reanudadas',\n};\n\nconst fr: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: \"Ouvrir l'assistant\",\n closeAssistant: \"Fermer l'assistant\",\n closePanel: \"Fermer le panneau de l'assistant\",\n sendMessage: 'Envoyer le message',\n inputPlaceholder: 'Posez une question...',\n listeningPlaceholder: \"A l'ecoute...\",\n startVoice: 'Activer la saisie vocale',\n stopVoice: 'Arreter la saisie vocale',\n\n statusOnline: 'En ligne',\n statusConnecting: 'Connexion en cours...',\n statusOffline: 'Hors ligne',\n statusListening: \"A l'ecoute...\",\n statusSpeaking: 'En train de parler...',\n statusProcessing: 'Traitement en cours...',\n\n emptyStateMessage:\n 'Posez-moi vos questions sur cette page. Je peux vous aider a naviguer, comprendre le contenu et bien plus.',\n\n errorGeneric: \"Une erreur s'est produite. Veuillez reessayer.\",\n errorNetwork: 'Connexion perdue. Reconnexion en cours...',\n errorMicDenied:\n \"L'acces au microphone a ete refuse. Veuillez l'activer dans les parametres de votre navigateur.\",\n errorRateLimit: 'Trop de requetes. Veuillez patienter un instant.',\n\n greetingMessage: 'Bonjour ! Besoin d\\'aide pour naviguer sur cette page ?',\n idleHelpMessage: 'Je suis toujours la si vous avez besoin d\\'aide !',\n\n voiceDegradedNotice: 'Voix indisponible. Passage en mode texte.',\n\n quietModeOn: 'Notifications en pause',\n quietModeOff: 'Notifications reprises',\n};\n\nconst de: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Assistent oeffnen',\n closeAssistant: 'Assistent schliessen',\n closePanel: 'Assistenten-Panel schliessen',\n sendMessage: 'Nachricht senden',\n inputPlaceholder: 'Stelle eine Frage...',\n listeningPlaceholder: 'Hoert zu...',\n startVoice: 'Spracheingabe starten',\n stopVoice: 'Spracheingabe stoppen',\n\n statusOnline: 'Online',\n statusConnecting: 'Verbindung wird hergestellt...',\n statusOffline: 'Offline',\n statusListening: 'Hoert zu...',\n statusSpeaking: 'Spricht...',\n statusProcessing: 'Verarbeitung...',\n\n emptyStateMessage:\n 'Frag mich alles zu dieser Seite. Ich kann dir bei der Navigation helfen, Inhalte erklaeren und vieles mehr.',\n\n errorGeneric: 'Etwas ist schiefgelaufen. Bitte versuche es erneut.',\n errorNetwork: 'Verbindung verloren. Verbindung wird wiederhergestellt...',\n errorMicDenied:\n 'Mikrofonzugriff wurde verweigert. Bitte aktiviere ihn in deinen Browsereinstellungen.',\n errorRateLimit: 'Zu viele Anfragen. Bitte warte einen Moment.',\n\n greetingMessage: 'Hallo! Brauchst du Hilfe beim Navigieren auf dieser Seite?',\n idleHelpMessage: 'Ich bin noch da, falls du Hilfe brauchst!',\n\n voiceDegradedNotice: 'Sprache nicht verfuegbar. Wechsel zum Textmodus.',\n\n quietModeOn: 'Benachrichtigungen pausiert',\n quietModeOff: 'Benachrichtigungen fortgesetzt',\n};\n\nconst ja: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'アシスタントを開く',\n closeAssistant: 'アシスタントを閉じる',\n closePanel: 'アシスタントパネルを閉じる',\n sendMessage: 'メッセージを送信',\n inputPlaceholder: '質問してください...',\n listeningPlaceholder: '聞いています...',\n startVoice: '音声入力を開始',\n stopVoice: '音声入力を停止',\n\n statusOnline: 'オンライン',\n statusConnecting: '接続中...',\n statusOffline: 'オフライン',\n statusListening: '聞いています...',\n statusSpeaking: '話しています...',\n statusProcessing: '処理中...',\n\n emptyStateMessage:\n 'このページについて何でも聞いてください。ナビゲーション、コンテンツの理解など、お手伝いします。',\n\n errorGeneric: '問題が発生しました。もう一度お試しください。',\n errorNetwork: '接続が切断されました。再接続しています...',\n errorMicDenied:\n 'マイクへのアクセスが拒否されました。ブラウザの設定で有効にしてください。',\n errorRateLimit: 'リクエストが多すぎます。少々お待ちください。',\n\n greetingMessage: 'こんにちは!このページのナビゲーションでお手伝いしましょうか?',\n idleHelpMessage: 'お手伝いが必要でしたら、いつでもどうぞ!',\n\n voiceDegradedNotice: '音声が利用できません。テキストモードに切り替えました。',\n\n quietModeOn: '通知を一時停止中',\n quietModeOff: '通知を再開しました',\n};\n\nconst zh: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: '打开助手',\n closeAssistant: '关闭助手',\n closePanel: '关闭助手面板',\n sendMessage: '发送消息',\n inputPlaceholder: '请提问...',\n listeningPlaceholder: '正在聆听...',\n startVoice: '开始语音输入',\n stopVoice: '停止语音输入',\n\n statusOnline: '在线',\n statusConnecting: '连接中...',\n statusOffline: '离线',\n statusListening: '正在聆听...',\n statusSpeaking: '正在播报...',\n statusProcessing: '处理中...',\n\n emptyStateMessage:\n '关于这个页面,你可以问我任何问题。我可以帮你浏览页面、理解内容等等。',\n\n errorGeneric: '出了点问题,请重试。',\n errorNetwork: '连接已断开,正在重新连接...',\n errorMicDenied: '麦克风权限被拒绝,请在浏览器设置中开启。',\n errorRateLimit: '请求过于频繁,请稍候再试。',\n\n greetingMessage: '你好!需要帮你浏览这个页面吗?',\n idleHelpMessage: '我还在这里,随时可以帮忙!',\n\n voiceDegradedNotice: '语音不可用,已切换为文字模式。',\n\n quietModeOn: '通知已暂停',\n quietModeOff: '通知已恢复',\n};\n\nconst ar: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'فتح المساعد',\n closeAssistant: 'إغلاق المساعد',\n closePanel: 'إغلاق لوحة المساعد',\n sendMessage: 'إرسال الرسالة',\n inputPlaceholder: 'اطرح سؤالاً...',\n listeningPlaceholder: 'جارٍ الاستماع...',\n startVoice: 'بدء الإدخال الصوتي',\n stopVoice: 'إيقاف الإدخال الصوتي',\n\n statusOnline: 'متصل',\n statusConnecting: 'جارٍ الاتصال...',\n statusOffline: 'غير متصل',\n statusListening: 'جارٍ الاستماع...',\n statusSpeaking: 'جارٍ التحدث...',\n statusProcessing: 'جارٍ المعالجة...',\n\n emptyStateMessage:\n 'اسألني أي شيء عن هذه الصفحة. يمكنني مساعدتك في التنقل وفهم المحتوى والمزيد.',\n\n errorGeneric: 'حدث خطأ ما. يرجى المحاولة مرة أخرى.',\n errorNetwork: 'انقطع الاتصال. جارٍ إعادة الاتصال...',\n errorMicDenied:\n 'تم رفض الوصول إلى الميكروفون. يرجى تفعيله من إعدادات المتصفح.',\n errorRateLimit: 'طلبات كثيرة جداً. يرجى الانتظار لحظة.',\n\n greetingMessage: 'مرحباً! هل تحتاج مساعدة في تصفح هذه الصفحة؟',\n idleHelpMessage: 'ما زلت هنا إذا احتجت مساعدة!',\n\n voiceDegradedNotice: 'الصوت غير متاح. تم التبديل إلى الوضع النصي.',\n\n quietModeOn: 'الإشعارات متوقفة مؤقتاً',\n quietModeOff: 'تم استئناف الإشعارات',\n};\n\nconst pt: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Abrir assistente',\n closeAssistant: 'Fechar assistente',\n closePanel: 'Fechar painel do assistente',\n sendMessage: 'Enviar mensagem',\n inputPlaceholder: 'Faca uma pergunta...',\n listeningPlaceholder: 'Ouvindo...',\n startVoice: 'Iniciar entrada de voz',\n stopVoice: 'Parar entrada de voz',\n\n statusOnline: 'Online',\n statusConnecting: 'Conectando...',\n statusOffline: 'Offline',\n statusListening: 'Ouvindo...',\n statusSpeaking: 'Falando...',\n statusProcessing: 'Processando...',\n\n emptyStateMessage:\n 'Pergunte-me o que quiser sobre esta pagina. Posso ajudar a navegar, entender o conteudo e muito mais.',\n\n errorGeneric: 'Algo deu errado. Por favor, tente novamente.',\n errorNetwork: 'Conexao perdida. Reconectando...',\n errorMicDenied:\n 'O acesso ao microfone foi negado. Ative-o nas configuracoes do seu navegador.',\n errorRateLimit: 'Muitas solicitacoes. Aguarde um momento, por favor.',\n\n greetingMessage: 'Ola! Precisa de ajuda para navegar nesta pagina?',\n idleHelpMessage: 'Ainda estou aqui se precisar de ajuda!',\n\n voiceDegradedNotice: 'Voz indisponivel. Alternado para o modo texto.',\n\n quietModeOn: 'Notificacoes pausadas',\n quietModeOff: 'Notificacoes retomadas',\n};\n\n// ---------------------------------------------------------------------------\n// Locale registry\n// ---------------------------------------------------------------------------\n\nconst BUILTIN_LOCALES: Record<SupportedLocale, I18nStrings> = {\n en,\n es,\n fr,\n de,\n ja,\n zh,\n ar,\n pt,\n};\n\nconst SUPPORTED_LOCALE_CODES = new Set<string>(Object.keys(BUILTIN_LOCALES));\n\nconst LOG_PREFIX = '[GuideKit:I18n]';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isSupportedLocale(code: string): code is SupportedLocale {\n return SUPPORTED_LOCALE_CODES.has(code);\n}\n\nfunction isI18nStrings(input: unknown): input is I18nStrings {\n if (typeof input !== 'object' || input === null) return false;\n // Check for a handful of required keys to distinguish from other objects\n const obj = input as Record<string, unknown>;\n return (\n typeof obj.widgetTitle === 'string' &&\n typeof obj.sendMessage === 'string' &&\n typeof obj.errorGeneric === 'string'\n );\n}\n\n/**\n * Detect the user's locale from the `<html lang>` attribute.\n * SSR-safe: returns 'en' when `document` is not available.\n */\nfunction detectLocaleFromDocument(): SupportedLocale {\n if (typeof document === 'undefined') {\n return 'en';\n }\n\n const htmlLang = document.documentElement?.lang;\n if (!htmlLang) {\n return 'en';\n }\n\n const normalized = htmlLang.trim().toLowerCase();\n\n // Exact match (e.g. 'en', 'pt')\n if (isSupportedLocale(normalized)) {\n return normalized;\n }\n\n // Language prefix match (e.g. 'en-US' -> 'en', 'pt-BR' -> 'pt')\n const prefix = normalized.split('-')[0] ?? '';\n if (isSupportedLocale(prefix)) {\n return prefix;\n }\n\n return 'en';\n}\n\n// ---------------------------------------------------------------------------\n// I18n class\n// ---------------------------------------------------------------------------\n\nexport class I18n {\n private strings: I18nStrings;\n private resolvedLocale: string;\n private debug: boolean;\n\n constructor(options?: I18nOptions) {\n this.debug = options?.debug ?? false;\n const locale = options?.locale ?? 'auto';\n const { strings, resolvedLocale } = this.resolve(locale);\n this.strings = strings;\n this.resolvedLocale = resolvedLocale;\n\n if (this.debug) {\n console.debug(`${LOG_PREFIX} Initialized with locale \"${this.resolvedLocale}\"`);\n }\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Get a translated string by key. */\n t(key: keyof I18nStrings): string {\n const value = this.strings[key];\n if (value === undefined) {\n if (this.debug) {\n console.warn(`${LOG_PREFIX} Missing translation key \"${key}\"`);\n }\n // Fallback to English; in non-production show a debug marker\n return en[key] ?? (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production' ? key : `[MISSING: ${key}]`);\n }\n return value;\n }\n\n /** Get all strings for the current locale. */\n getStrings(): I18nStrings {\n return { ...this.strings };\n }\n\n /** Change the current locale at runtime. */\n setLocale(locale: LocaleInput): void {\n const { strings, resolvedLocale } = this.resolve(locale);\n this.strings = strings;\n this.resolvedLocale = resolvedLocale;\n\n if (this.debug) {\n console.debug(`${LOG_PREFIX} Locale changed to \"${this.resolvedLocale}\"`);\n }\n }\n\n /** The current resolved locale code (e.g. 'en', 'fr', or 'custom'). */\n get currentLocale(): string {\n return this.resolvedLocale;\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private resolve(locale: LocaleInput): {\n strings: I18nStrings;\n resolvedLocale: string;\n } {\n // Custom string map provided directly\n if (isI18nStrings(locale)) {\n // Merge with English defaults so partial overrides still work\n return {\n strings: { ...en, ...locale },\n resolvedLocale: 'custom',\n };\n }\n\n // Auto-detect from the document\n if (locale === 'auto') {\n const detected = detectLocaleFromDocument();\n if (this.debug) {\n console.debug(`${LOG_PREFIX} Auto-detected locale \"${detected}\"`);\n }\n return {\n strings: BUILTIN_LOCALES[detected],\n resolvedLocale: detected,\n };\n }\n\n // Explicit supported locale code\n if (isSupportedLocale(locale)) {\n return {\n strings: BUILTIN_LOCALES[locale],\n resolvedLocale: locale,\n };\n }\n\n // Unknown locale code -- fall back to English\n if (this.debug) {\n console.warn(\n `${LOG_PREFIX} Unknown locale \"${String(locale)}\", falling back to \"en\"`,\n );\n }\n return {\n strings: en,\n resolvedLocale: 'en',\n };\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Client-side Token Manager\n// ---------------------------------------------------------------------------\n//\n// Handles the full token lifecycle:\n// - Fetch token from the developer's token endpoint on init\n// - Auto-refresh at 80% of TTL\n// - BroadcastChannel multi-tab coordination with leader election\n// - localStorage fallback for browsers without BroadcastChannel\n// - Emits auth events (token-refreshed, token-refresh-failed, token-expired)\n// ---------------------------------------------------------------------------\n\nimport type { EventBus } from '../bus/index.js';\nimport { AuthenticationError, ErrorCodes } from '../errors/index.js';\n\nconst LOG_PREFIX = '[GuideKit:Auth]';\nconst REFRESH_THRESHOLD = 0.8; // Refresh at 80% of TTL\nconst MAX_RETRY_ATTEMPTS = 3;\nconst RETRY_BASE_MS = 1_000;\nconst BC_CHANNEL_NAME = 'guidekit-token';\nconst LS_KEY_PREFIX = 'guidekit-token:';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TokenData {\n token: string;\n expiresAt: number; // Unix seconds\n expiresIn: number; // Seconds from issuance\n fetchedAt: number; // Date.now() when fetched\n}\n\nexport interface TokenManagerOptions {\n tokenEndpoint: string;\n instanceId: string;\n bus: EventBus;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TokenManager\n// ---------------------------------------------------------------------------\n\nexport class TokenManager {\n private readonly endpoint: string;\n private readonly instanceId: string;\n private readonly bus: EventBus;\n private readonly debug: boolean;\n\n private _token: TokenData | null = null;\n private _refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _isLeader = false;\n private _bc: BroadcastChannel | null = null;\n private _destroyed = false;\n\n constructor(options: TokenManagerOptions) {\n this.endpoint = options.tokenEndpoint;\n this.instanceId = options.instanceId;\n this.bus = options.bus;\n this.debug = options.debug ?? false;\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Current token string, or null if not yet fetched. */\n get token(): string | null {\n return this._token?.token ?? null;\n }\n\n /** Current token data, or null if not yet fetched. */\n get tokenData(): TokenData | null {\n return this._token;\n }\n\n /** Whether this tab is the leader for token refresh. */\n get isLeader(): boolean {\n return this._isLeader;\n }\n\n /**\n * Initialize the token manager: elect leader, fetch initial token,\n * schedule auto-refresh.\n */\n async start(): Promise<void> {\n if (this._destroyed) return;\n\n this.setupBroadcastChannel();\n this.electLeader();\n\n // Try to load a cached token from localStorage first\n const cached = this.loadFromStorage();\n if (cached && !this.isExpired(cached)) {\n this._token = cached;\n this.log('Loaded cached token from localStorage');\n this.scheduleRefresh();\n return;\n }\n\n // Fetch a fresh token\n await this.fetchToken();\n }\n\n /**\n * Force a token refresh, regardless of TTL.\n */\n async refresh(): Promise<void> {\n await this.fetchToken();\n }\n\n /**\n * Clean up timers, BroadcastChannel, and release leader.\n */\n destroy(): void {\n this._destroyed = true;\n\n if (this._refreshTimer !== null) {\n clearTimeout(this._refreshTimer);\n this._refreshTimer = null;\n }\n\n if (this._bc) {\n this._bc.close();\n this._bc = null;\n }\n\n this._token = null;\n this._isLeader = false;\n }\n\n // -------------------------------------------------------------------------\n // Token fetching\n // -------------------------------------------------------------------------\n\n private async fetchToken(attempt = 1): Promise<void> {\n if (this._destroyed) return;\n\n this.log(`Fetching token (attempt ${attempt}/${MAX_RETRY_ATTEMPTS})`);\n\n try {\n const response = await fetch(this.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ instanceId: this.instanceId }),\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_INVALID_KEY,\n message: `Token endpoint returned ${response.status}: ${body}`,\n suggestion: 'Check your tokenEndpoint URL and server authentication.',\n });\n }\n // Retryable server error\n throw new Error(`Token endpoint returned ${response.status}: ${body}`);\n }\n\n const data = await response.json() as {\n token?: string;\n expiresIn?: number;\n expiresAt?: number;\n };\n\n if (!data.token || typeof data.token !== 'string') {\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_ENDPOINT_FAILED,\n message: 'Token endpoint response missing \"token\" field.',\n suggestion: 'Ensure your token endpoint returns { token, expiresIn, expiresAt }.',\n });\n }\n\n const tokenData: TokenData = {\n token: data.token,\n expiresAt: data.expiresAt ?? Math.floor(Date.now() / 1000) + (data.expiresIn ?? 900),\n expiresIn: data.expiresIn ?? 900,\n fetchedAt: Date.now(),\n };\n\n this._token = tokenData;\n this.saveToStorage(tokenData);\n this.broadcastToken(tokenData);\n this.scheduleRefresh();\n\n this.bus.emit('auth:token-refreshed', { expiresAt: tokenData.expiresAt });\n this.log(`Token fetched, expires at ${new Date(tokenData.expiresAt * 1000).toISOString()}`);\n } catch (error) {\n const remaining = MAX_RETRY_ATTEMPTS - attempt;\n\n if (remaining > 0 && !(error instanceof AuthenticationError)) {\n this.log(`Token fetch failed, retrying in ${RETRY_BASE_MS * attempt}ms`);\n this.bus.emit('auth:token-refresh-failed', {\n error: error instanceof Error ? error : new Error(String(error)),\n attemptsRemaining: remaining,\n });\n\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_BASE_MS * attempt),\n );\n return this.fetchToken(attempt + 1);\n }\n\n // All retries exhausted\n this.bus.emit('auth:token-refresh-failed', {\n error: error instanceof Error ? error : new Error(String(error)),\n attemptsRemaining: 0,\n });\n\n if (error instanceof AuthenticationError) throw error;\n\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_ENDPOINT_FAILED,\n message: `Failed to fetch token after ${MAX_RETRY_ATTEMPTS} attempts: ${error instanceof Error ? error.message : String(error)}`,\n suggestion: 'Check your tokenEndpoint URL and network connection.',\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Auto-refresh scheduling\n // -------------------------------------------------------------------------\n\n private scheduleRefresh(): void {\n if (this._destroyed || !this._token) return;\n\n // Clear existing timer\n if (this._refreshTimer !== null) {\n clearTimeout(this._refreshTimer);\n }\n\n const now = Date.now();\n const tokenAgeMs = now - this._token.fetchedAt;\n const ttlMs = this._token.expiresIn * 1000;\n const refreshAtMs = ttlMs * REFRESH_THRESHOLD;\n const delayMs = Math.max(0, refreshAtMs - tokenAgeMs);\n\n this.log(`Scheduling refresh in ${Math.round(delayMs / 1000)}s (80% of ${this._token.expiresIn}s TTL)`);\n\n this._refreshTimer = setTimeout(() => {\n if (this._destroyed) return;\n\n // Only the leader refreshes\n if (this._isLeader) {\n this.log('Leader performing scheduled refresh');\n this.fetchToken().catch((err) => {\n this.log(`Scheduled refresh failed: ${err}`);\n });\n } else {\n this.log('Not leader, skipping refresh (will receive via BroadcastChannel)');\n // Schedule another check in case we become leader\n this.scheduleExpiredCheck();\n }\n }, delayMs);\n }\n\n private scheduleExpiredCheck(): void {\n if (this._destroyed || !this._token) return;\n\n const now = Date.now();\n const expiresAtMs = this._token.expiresAt * 1000;\n const delayMs = Math.max(0, expiresAtMs - now);\n\n this._refreshTimer = setTimeout(() => {\n if (this._destroyed) return;\n if (this._token && this.isExpired(this._token)) {\n this.bus.emit('auth:token-expired', {} as Record<string, never>);\n // Try to refresh as last resort\n this.electLeader();\n if (this._isLeader) {\n this.fetchToken().catch(() => {});\n }\n }\n }, delayMs);\n }\n\n // -------------------------------------------------------------------------\n // BroadcastChannel (multi-tab coordination)\n // -------------------------------------------------------------------------\n\n private setupBroadcastChannel(): void {\n if (typeof BroadcastChannel === 'undefined') {\n // Fallback: always be leader if no BroadcastChannel\n this._isLeader = true;\n this.log('BroadcastChannel unavailable, acting as leader');\n return;\n }\n\n try {\n this._bc = new BroadcastChannel(`${BC_CHANNEL_NAME}:${this.instanceId}`);\n this._bc.onmessage = (event) => {\n const msg = event.data as { type: string; token?: TokenData; tabId?: string };\n\n if (msg.type === 'token-updated' && msg.token) {\n this.log('Received token from leader via BroadcastChannel');\n this._token = msg.token;\n this.saveToStorage(msg.token);\n this.scheduleRefresh();\n this.bus.emit('auth:token-refreshed', { expiresAt: msg.token.expiresAt });\n }\n\n if (msg.type === 'leader-election') {\n // Another tab is claiming leadership — yield if we're not already leader\n // or if their tabId is lexicographically lower (deterministic)\n if (this._isLeader && msg.tabId && msg.tabId < this._tabId) {\n this._isLeader = false;\n this.log('Yielded leadership to another tab');\n }\n }\n };\n } catch {\n this._isLeader = true;\n this.log('BroadcastChannel setup failed, acting as leader');\n }\n }\n\n private readonly _tabId = typeof crypto !== 'undefined' && crypto.randomUUID\n ? crypto.randomUUID()\n : Math.random().toString(36).slice(2);\n\n private electLeader(): void {\n // Simple leader election: broadcast our intent, wait for contestation\n // If no BroadcastChannel, we're always leader\n if (!this._bc) {\n this._isLeader = true;\n return;\n }\n\n this._isLeader = true;\n try {\n this._bc.postMessage({\n type: 'leader-election',\n tabId: this._tabId,\n });\n } catch {\n // Channel may be closed\n }\n\n this.log(`Elected as leader (tabId: ${this._tabId.slice(0, 8)}...)`);\n }\n\n private broadcastToken(tokenData: TokenData): void {\n if (!this._bc) return;\n try {\n this._bc.postMessage({\n type: 'token-updated',\n token: tokenData,\n });\n } catch {\n // Channel may be closed\n }\n }\n\n // -------------------------------------------------------------------------\n // localStorage fallback\n // -------------------------------------------------------------------------\n\n private get storageKey(): string {\n return `${LS_KEY_PREFIX}${this.instanceId}`;\n }\n\n private saveToStorage(data: TokenData): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(this.storageKey, JSON.stringify(data));\n }\n } catch {\n // localStorage may be full or unavailable (incognito, SSR)\n }\n }\n\n private loadFromStorage(): TokenData | null {\n try {\n if (typeof localStorage === 'undefined') return null;\n const raw = localStorage.getItem(this.storageKey);\n if (!raw) return null;\n return JSON.parse(raw) as TokenData;\n } catch {\n return null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private isExpired(data: TokenData): boolean {\n const nowSec = Math.floor(Date.now() / 1000);\n return nowSec >= data.expiresAt;\n }\n\n private log(message: string): void {\n if (this.debug) {\n console.debug(`${LOG_PREFIX} ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Core Orchestrator\n// ---------------------------------------------------------------------------\n//\n// The main class that wires all subsystems together. The constructor does NOT\n// call any browser APIs — everything is lazily initialized in `init()` so the\n// module is safe to import in SSR / Node environments.\n// ---------------------------------------------------------------------------\n\nimport { EventBus, createEventBus } from './bus/index.js';\nimport { ResourceManager, SingletonGuard } from './resources/index.js';\nimport { DOMScanner } from './dom/index.js';\nimport { ContextManager } from './context/index.js';\nimport { LLMOrchestrator } from './llm/index.js';\nimport { ToolExecutor } from './llm/tool-executor.js';\nimport { ConnectionManager } from './connectivity/index.js';\nimport { NavigationController } from './navigation/index.js';\nimport { VoicePipeline, type VoicePipelineOptions } from './voice/index.js';\nimport { VisualGuidance } from './visual/index.js';\nimport { AwarenessSystem } from './awareness/index.js';\nimport { ProactiveTriggerEngine } from './awareness/proactive.js';\nimport { RateLimiter } from './llm/rate-limiter.js';\nimport { I18n, type LocaleInput } from './i18n/index.js';\nimport { TokenManager } from './auth/token-manager.js';\nimport type {\n PageModel,\n AgentConfig,\n ContentMapInput,\n LLMConfig,\n STTConfig,\n TTSConfig,\n GuideKitOptions,\n ToolDefinition,\n ToolParameterSchema,\n GuideKitEvent,\n AgentState,\n GuideKitStore,\n} from './types/index.js';\nimport { GuideKitError, ConfigurationError, ErrorCodes } from './errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Default deny-list for clickElement tool\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_CLICK_DENY = [\n '[type=\"submit\"]',\n '[type=\"reset\"]',\n 'button[formaction]',\n '[data-guidekit-no-click]',\n 'form',\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a UUID, guarded for non-browser environments where\n * `crypto.randomUUID()` may not be available.\n */\nfunction generateUUID(): string {\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.randomUUID === 'function'\n ) {\n return crypto.randomUUID();\n }\n\n // Fallback: manual v4 UUID generation (RFC 4122 compliant)\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Options interface\n// ---------------------------------------------------------------------------\n\n/** Result of a health check on a single service. */\nexport interface HealthCheckStatus {\n status: 'ok' | 'degraded' | 'unavailable' | 'not-configured';\n latencyMs?: number;\n error?: string;\n}\n\n/** Full health check result. */\nexport interface HealthCheckResult {\n llm: HealthCheckStatus;\n stt: HealthCheckStatus;\n tts: HealthCheckStatus;\n mic: HealthCheckStatus;\n overall: 'ok' | 'degraded' | 'unavailable';\n}\n\n/** Context passed to onBeforeLLMCall for privacy filtering. */\nexport interface BeforeLLMCallContext {\n systemPrompt: string;\n userMessage: string;\n conversationHistory: Array<{ role: string; content: string }>;\n}\n\nexport interface GuideKitCoreOptions {\n tokenEndpoint?: string;\n stt?: STTConfig;\n tts?: TTSConfig;\n llm?: LLMConfig;\n agent?: AgentConfig;\n contentMap?: ContentMapInput;\n options?: GuideKitOptions;\n instanceId?: string;\n rootElement?: HTMLElement;\n onError?: (error: GuideKitError) => void;\n onEvent?: (event: GuideKitEvent) => void;\n onReady?: () => void;\n /**\n * Privacy hook: called before every LLM request. Return modified context\n * or throw to cancel the request. Use for custom PII scrubbing.\n */\n onBeforeLLMCall?: (context: BeforeLLMCallContext) => BeforeLLMCallContext | Promise<BeforeLLMCallContext>;\n}\n\n// ---------------------------------------------------------------------------\n// GuideKitCore\n// ---------------------------------------------------------------------------\n\nexport class GuideKitCore {\n // ---- Public readonly accessors ------------------------------------------\n\n readonly instanceId: string;\n readonly bus: EventBus;\n\n // ---- Subsystems (created lazily or on init) -----------------------------\n\n private resourceManager: ResourceManager;\n private domScanner: DOMScanner | null = null;\n private contextManager: ContextManager;\n private llmOrchestrator: LLMOrchestrator | null = null;\n private connectionManager: ConnectionManager | null = null;\n private navigationController: NavigationController | null = null;\n private voicePipeline: VoicePipeline | null = null;\n private visualGuidance: VisualGuidance | null = null;\n private toolExecutor: ToolExecutor | null = null;\n private awarenessSystem: AwarenessSystem | null = null;\n private proactiveEngine: ProactiveTriggerEngine | null = null;\n private rateLimiter: RateLimiter;\n private _i18n: I18n;\n private tokenManager: TokenManager | null = null;\n\n // ---- State --------------------------------------------------------------\n\n private _isReady = false;\n private _agentState: AgentState = { status: 'idle' };\n private _currentPageModel: PageModel | null = null;\n private readonly _options: GuideKitCoreOptions;\n private _debug: boolean;\n private _sendInFlight = false;\n private _instanceAbortController = new AbortController();\n private _initPromise: Promise<void> | null = null;\n\n // ---- Store for useSyncExternalStore -------------------------------------\n\n private storeListeners: Set<() => void> = new Set();\n private _storeSnapshot: GuideKitStore;\n\n // ---- Custom actions -----------------------------------------------------\n\n private customActions = new Map<\n string,\n {\n description: string;\n parameters: Record<string, unknown>;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n }\n >();\n\n // -------------------------------------------------------------------------\n // Constructor — NO browser APIs (SSR safe)\n // -------------------------------------------------------------------------\n\n constructor(options: GuideKitCoreOptions) {\n this._options = options;\n this.instanceId = options.instanceId ?? 'default';\n this._debug = options.options?.debug ?? false;\n\n // Create EventBus (no browser APIs)\n this.bus = createEventBus({ debug: this._debug });\n\n // Get or create ResourceManager via SingletonGuard\n this.resourceManager = SingletonGuard.acquire(\n this.instanceId,\n () => new ResourceManager(this.instanceId),\n );\n\n // Create ContextManager (no browser APIs in constructor)\n this.contextManager = new ContextManager({\n agent: options.agent,\n contentMap: options.contentMap,\n debug: this._debug,\n });\n\n // Create RateLimiter (no browser APIs)\n this.rateLimiter = new RateLimiter({\n bus: this.bus,\n limits: options.options?.rateLimits,\n debug: this._debug,\n });\n\n // Create I18n (auto-detect is SSR-safe)\n this._i18n = new I18n({\n locale: (options.options?.locale as LocaleInput) ?? 'auto',\n debug: this._debug,\n });\n\n // Initialize store snapshot\n this._storeSnapshot = this.buildSnapshot();\n\n // Wire up error handler\n if (options.onError) {\n this.bus.on('error', (err) => {\n if (err instanceof GuideKitError) {\n options.onError!(err);\n }\n });\n }\n\n // Wire up event forwarding\n if (options.onEvent) {\n this.bus.onAny((data, eventName) => {\n options.onEvent!({\n type: eventName,\n data:\n typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)\n : {},\n timestamp: Date.now(),\n });\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // init() — starts all browser-dependent subsystems\n // -------------------------------------------------------------------------\n\n async init(): Promise<void> {\n if (typeof window === 'undefined') return;\n if (this._isReady) return;\n if (this._initPromise) return this._initPromise;\n\n this._initPromise = this._doInit();\n try {\n await this._initPromise;\n } catch (err) {\n this._initPromise = null;\n throw err;\n }\n }\n\n private async _doInit(): Promise<void> {\n // Validate LLM config\n const llmConfig = this._options.llm;\n if (!llmConfig && !this._options.tokenEndpoint) {\n throw new ConfigurationError({\n code: ErrorCodes.CONFIG_MISSING_REQUIRED,\n message: 'Either tokenEndpoint or llm config must be provided.',\n suggestion:\n 'Add tokenEndpoint=\"/api/guidekit/token\" or llm={{ provider: \"gemini\", apiKey: \"...\" }} to GuideKitProvider.',\n });\n }\n\n // -- Token Manager (if tokenEndpoint is provided) -----------------------\n\n if (this._options.tokenEndpoint) {\n this.tokenManager = new TokenManager({\n tokenEndpoint: this._options.tokenEndpoint,\n instanceId: this.instanceId,\n bus: this.bus,\n debug: this._debug,\n });\n await this.tokenManager.start();\n if (!this._options.llm) {\n console.warn(\n '[GuideKit] tokenEndpoint provided without llm config. ' +\n 'The session token handles auth only — llm: { provider, apiKey } is still required ' +\n 'for LLM calls. See: https://guidekit.dev/docs/provider#token-endpoint',\n );\n }\n this.resourceManager.register({\n name: 'token-manager',\n cleanup: () => this.tokenManager?.destroy(),\n });\n }\n\n // -- DOM Scanner --------------------------------------------------------\n\n this.domScanner = new DOMScanner({\n rootElement: this._options.rootElement,\n debug: this._debug,\n });\n\n // Initial scan\n this._currentPageModel = this.domScanner.scan();\n this.bus.emit('dom:scan-complete', {\n pageModel: this._currentPageModel,\n durationMs: 0,\n });\n\n // Set up MutationObserver for auto-rescan\n const unobserve = this.domScanner.observe((model) => {\n this._currentPageModel = model;\n this.bus.emit('dom:scan-complete', {\n pageModel: model,\n durationMs: 0,\n });\n this.notifyStoreListeners();\n });\n this.resourceManager.register({\n name: 'dom-observer',\n cleanup: unobserve,\n });\n\n // -- LLM Orchestrator ---------------------------------------------------\n\n if (llmConfig) {\n this.llmOrchestrator = new LLMOrchestrator({\n config: llmConfig,\n debug: this._debug,\n onChunk: (chunk) => {\n this.bus.emit('llm:response-chunk', chunk);\n },\n onToolCall: (toolCall) => {\n this.bus.emit('llm:tool-call', toolCall);\n },\n onTokenUsage: (usage) => {\n this.bus.emit('llm:token-usage', usage);\n },\n onError: (error) => {\n this.bus.emit('error', error);\n },\n });\n }\n\n // -- ConnectionManager --------------------------------------------------\n\n this.connectionManager = new ConnectionManager({\n healthEndpoint: this._options.tokenEndpoint\n ? this._options.tokenEndpoint.replace(/\\/token$/, '/health')\n : undefined,\n debug: this._debug,\n });\n this.connectionManager.onStateChange((state, previous) => {\n this.bus.emit('connectivity:state-change', { state, previous });\n });\n this.connectionManager.start();\n this.resourceManager.register({\n name: 'connection-manager',\n cleanup: () => this.connectionManager?.stop(),\n });\n\n // -- NavigationController -----------------------------------------------\n\n this.navigationController = new NavigationController({\n debug: this._debug,\n });\n this.navigationController.onRouteChange((from, to) => {\n this.bus.emit('dom:route-change', { from, to });\n\n // Re-scan DOM on route change (allow a brief settling period)\n if (this.domScanner) {\n setTimeout(() => {\n this._currentPageModel = this.domScanner!.scan();\n this.bus.emit('dom:scan-complete', {\n pageModel: this._currentPageModel,\n durationMs: 0,\n });\n this.notifyStoreListeners();\n }, 100);\n }\n });\n this.navigationController.start();\n this.resourceManager.register({\n name: 'navigation-controller',\n cleanup: () => this.navigationController?.stop(),\n });\n\n // -- Visual Guidance System -----------------------------------------------\n\n this.visualGuidance = new VisualGuidance({\n spotlightColor: this._options.options?.spotlightColor,\n debug: this._debug,\n });\n this.resourceManager.register({\n name: 'visual-guidance',\n cleanup: () => this.visualGuidance?.destroy(),\n });\n\n // -- Awareness System ---------------------------------------------------\n\n this.awarenessSystem = new AwarenessSystem({\n bus: this.bus,\n rootElement: this._options.rootElement,\n debug: this._debug,\n });\n this.awarenessSystem.start();\n this.resourceManager.register({\n name: 'awareness-system',\n cleanup: () => this.awarenessSystem?.destroy(),\n });\n\n // -- Proactive Trigger Engine ------------------------------------------\n\n this.proactiveEngine = new ProactiveTriggerEngine({\n bus: this.bus,\n debug: this._debug,\n onTrigger: (trigger) => {\n if (this._debug) {\n console.debug('[GuideKit:Core] Proactive trigger:', trigger.type, trigger);\n }\n // Forward as a generic event for developer hooks\n this._options.onEvent?.({\n type: `proactive:${trigger.type}`,\n data: trigger as unknown as Record<string, unknown>,\n timestamp: trigger.timestamp,\n });\n },\n });\n this.proactiveEngine.start();\n this.resourceManager.register({\n name: 'proactive-engine',\n cleanup: () => this.proactiveEngine?.destroy(),\n });\n\n // -- Tool Executor (multi-turn tool calling) ----------------------------\n\n this.toolExecutor = new ToolExecutor({\n maxRounds: 5,\n debug: this._debug,\n onToolCall: (name, args) => {\n this.bus.emit('llm:tool-call', { name, arguments: args });\n },\n });\n\n this.registerBuiltinTools();\n\n // -- Voice Pipeline (lazy — only init on first startListening) ----------\n // Default to web-speech (browser-native, zero-config) when no STT/TTS\n // config is provided. Falls back gracefully in non-browser environments.\n\n {\n const sttConfig: STTConfig = this._options.stt ?? { provider: 'web-speech' };\n const ttsConfig: TTSConfig = this._options.tts ?? { provider: 'web-speech' };\n\n // Build the VoicePipeline options based on provider type\n let voiceSttConfig: VoicePipelineOptions['sttConfig'];\n let voiceTtsConfig: VoicePipelineOptions['ttsConfig'];\n\n if (sttConfig.provider === 'deepgram') {\n voiceSttConfig = {\n provider: 'deepgram',\n apiKey: sttConfig.apiKey,\n model: sttConfig.model,\n };\n } else if (sttConfig.provider === 'elevenlabs') {\n voiceSttConfig = {\n provider: 'elevenlabs',\n apiKey: sttConfig.apiKey,\n language: sttConfig.language,\n };\n } else {\n voiceSttConfig = {\n provider: 'web-speech',\n language: sttConfig.language,\n continuous: sttConfig.continuous,\n interimResults: sttConfig.interimResults,\n };\n }\n\n if (ttsConfig.provider === 'elevenlabs') {\n voiceTtsConfig = {\n provider: 'elevenlabs',\n apiKey: ttsConfig.apiKey,\n voiceId: 'voiceId' in ttsConfig ? ttsConfig.voiceId : undefined,\n };\n } else {\n voiceTtsConfig = {\n provider: 'web-speech',\n voice: ttsConfig.voice,\n rate: ttsConfig.rate,\n pitch: ttsConfig.pitch,\n language: ttsConfig.language,\n };\n }\n\n try {\n this.voicePipeline = new VoicePipeline({\n sttConfig: voiceSttConfig,\n ttsConfig: voiceTtsConfig,\n debug: this._debug,\n });\n\n // Forward voice events to the EventBus\n this.voicePipeline.onStateChange((state, previous) => {\n this.bus.emit('voice:state-change', { from: previous, to: state });\n // Map voice state to agent state\n switch (state) {\n case 'listening':\n this.setAgentState({ status: 'listening', durationMs: 0 });\n break;\n case 'speaking':\n this.setAgentState({ status: 'speaking', utterance: '' });\n break;\n case 'idle':\n if (this._agentState.status !== 'processing') {\n this.setAgentState({ status: 'idle' });\n }\n break;\n }\n });\n\n this.voicePipeline.onTranscript((text, isFinal) => {\n this.bus.emit('voice:transcript', {\n text,\n isFinal,\n confidence: 0.95,\n });\n if (isFinal && text.trim()) {\n this.voicePipeline?.processTranscript(text, (t) => this.sendText(t));\n }\n });\n\n this.resourceManager.register({\n name: 'voice-pipeline',\n cleanup: () => this.voicePipeline?.destroy(),\n });\n } catch (_err) {\n // Voice pipeline may fail in non-browser environments (SSR, jsdom)\n this.voicePipeline = null as unknown as VoicePipeline;\n if (this._debug) {\n console.debug('[GuideKit:Core] Voice pipeline unavailable in this environment');\n }\n }\n }\n\n // -- Restore session ----------------------------------------------------\n\n const session = this.contextManager.restoreSession();\n if (session && this._debug) {\n console.debug(\n '[GuideKit:Core] Restored session with',\n session.conversationHistory.length,\n 'turns',\n );\n }\n\n // -- Mark ready ---------------------------------------------------------\n\n this.resourceManager.markReady();\n this._isReady = true;\n this.notifyStoreListeners();\n this._options.onReady?.();\n\n if (this._debug) {\n console.debug('[GuideKit:Core] Initialized', {\n instanceId: this.instanceId,\n sections: this._currentPageModel?.sections.length,\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // sendText — send a text message to the LLM\n // -------------------------------------------------------------------------\n\n async sendText(message_: string): Promise<string> {\n let message = message_;\n if (!this._isReady || !this.llmOrchestrator) {\n throw new ConfigurationError({\n code: ErrorCodes.CONFIG_MISSING_REQUIRED,\n message: 'SDK not initialized or LLM not configured.',\n suggestion:\n 'Ensure init() has been called and LLM config is provided.',\n });\n }\n\n if (this._sendInFlight) {\n throw new GuideKitError({\n code: 'SEND_IN_FLIGHT',\n message: 'A message is already being processed. Wait for it to complete.',\n recoverable: true,\n suggestion: 'Await the previous sendText() call before sending another message.',\n });\n }\n this._sendInFlight = true;\n\n const maxLen = this._options.options?.maxMessageLength ?? 10_000;\n if (message_.length > maxLen) {\n throw new GuideKitError({\n code: 'INPUT_TOO_LONG',\n message: `Message exceeds maximum length of ${maxLen} characters.`,\n recoverable: true,\n suggestion: `Shorten your message to ${maxLen} characters or fewer, or increase maxMessageLength in options.`,\n });\n }\n\n // Check rate limits before proceeding\n this.rateLimiter.checkLLMCall();\n\n // Update agent state\n this.setAgentState({ status: 'processing', transcript: message });\n\n // Add user turn\n this.contextManager.addTurn({\n role: 'user',\n content: message,\n timestamp: Date.now(),\n });\n\n // Build system prompt\n let systemPrompt = this.contextManager.buildSystemPrompt(\n this._currentPageModel!,\n this.getToolDefinitions(),\n );\n\n // Privacy hook — allow developer to scrub PII before LLM call\n if (this._options.onBeforeLLMCall) {\n try {\n const ctx = await this._options.onBeforeLLMCall({\n systemPrompt,\n userMessage: message,\n conversationHistory: this.contextManager\n .getHistory()\n .map((t) => ({ role: t.role, content: t.content })),\n });\n systemPrompt = ctx.systemPrompt;\n message = ctx.userMessage;\n } catch (hookErr) {\n // Hook threw — cancel the LLM call\n this.setAgentState({ status: 'idle' });\n const err =\n hookErr instanceof GuideKitError\n ? hookErr\n : new GuideKitError({\n code: ErrorCodes.PRIVACY_HOOK_CANCELLED,\n message:\n hookErr instanceof Error\n ? hookErr.message\n : 'onBeforeLLMCall hook cancelled the request.',\n recoverable: true,\n suggestion: 'Check your onBeforeLLMCall implementation.',\n });\n this.bus.emit('error', err);\n throw err;\n }\n }\n\n const conversationId = generateUUID();\n this.bus.emit('llm:response-start', { conversationId });\n\n try {\n let responseText: string;\n let totalTokens: number;\n\n // Use multi-turn ToolExecutor if available, else single-turn\n if (this.toolExecutor) {\n const result = await this.toolExecutor.executeWithTools({\n llm: this.llmOrchestrator,\n systemPrompt,\n history: this.contextManager.getHistory().slice(0, -1),\n userMessage: message,\n tools: this.getToolDefinitions(),\n signal: this._instanceAbortController.signal,\n });\n responseText = result.text;\n totalTokens = result.totalUsage.total;\n } else {\n const result = await this.llmOrchestrator.sendMessage({\n systemPrompt,\n history: this.contextManager.getHistory().slice(0, -1),\n userMessage: message,\n tools: this.getToolDefinitions(),\n signal: this._instanceAbortController.signal,\n });\n responseText = result.text;\n totalTokens = result.usage.total;\n }\n\n // Add assistant turn\n this.contextManager.addTurn({\n role: 'assistant',\n content: responseText,\n timestamp: Date.now(),\n });\n\n // Save session\n this.contextManager.saveSession();\n\n this.bus.emit('llm:response-end', {\n conversationId,\n totalTokens,\n });\n\n this.setAgentState({ status: 'idle' });\n\n return responseText;\n } catch (error) {\n const err =\n error instanceof GuideKitError\n ? error\n : new GuideKitError({\n code: ErrorCodes.UNKNOWN,\n message:\n error instanceof Error ? error.message : 'Unknown error',\n recoverable: false,\n suggestion: 'Check the console for details.',\n });\n\n this.setAgentState({ status: 'error', error: err });\n this.bus.emit('error', err);\n throw err;\n } finally {\n this._sendInFlight = false;\n }\n }\n\n // -------------------------------------------------------------------------\n // Accessors\n // -------------------------------------------------------------------------\n\n /** Get the current page model. */\n get pageModel(): PageModel | null {\n return this._currentPageModel;\n }\n\n /** Whether the SDK has been fully initialized. */\n get isReady(): boolean {\n return this._isReady;\n }\n\n /** Current agent state. */\n get agentState(): AgentState {\n return this._agentState;\n }\n\n /** Current auth token string, or null if not using token-based auth. */\n get currentToken(): string | null {\n return this.tokenManager?.token ?? null;\n }\n\n // -------------------------------------------------------------------------\n // Store subscription (for useSyncExternalStore)\n // -------------------------------------------------------------------------\n\n subscribe(listener: () => void): () => void {\n this.storeListeners.add(listener);\n return () => {\n this.storeListeners.delete(listener);\n };\n }\n\n getSnapshot(): GuideKitStore {\n return this._storeSnapshot;\n }\n\n // -------------------------------------------------------------------------\n // Custom actions\n // -------------------------------------------------------------------------\n\n registerAction(\n actionId: string,\n action: {\n description: string;\n parameters: Record<string, unknown>;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n },\n ): void {\n this.customActions.set(actionId, action);\n }\n\n // -------------------------------------------------------------------------\n // Voice control\n // -------------------------------------------------------------------------\n\n /** Start listening for voice input. Initializes voice pipeline on first call. */\n async startListening(): Promise<void> {\n if (!this.voicePipeline) {\n if (this._debug) {\n console.debug('[GuideKit:Core] No voice pipeline configured — cannot start listening');\n }\n return;\n }\n await this.voicePipeline.init();\n await this.voicePipeline.startListening();\n }\n\n /** Stop listening for voice input. */\n stopListening(): void {\n this.voicePipeline?.stopListening();\n }\n\n /** Stop current TTS playback (barge-in). */\n stopSpeaking(): void {\n this.voicePipeline?.stopSpeaking();\n }\n\n /** Whether voice pipeline is available. */\n get hasVoice(): boolean {\n return this.voicePipeline !== null;\n }\n\n // -------------------------------------------------------------------------\n // Visual guidance (public API)\n // -------------------------------------------------------------------------\n\n /** Highlight an element by sectionId or CSS selector. */\n highlight(params: {\n sectionId?: string;\n selector?: string;\n tooltip?: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n }): boolean {\n if (!this.visualGuidance) return false;\n const result = this.visualGuidance.highlight(params);\n if (result) {\n this.bus.emit('visual:spotlight-shown', {\n selector: params.selector ?? params.sectionId ?? '',\n sectionId: params.sectionId,\n });\n }\n return result;\n }\n\n /** Dismiss the current spotlight highlight. */\n dismissHighlight(): void {\n this.visualGuidance?.dismissHighlight();\n this.bus.emit('visual:spotlight-dismissed', {});\n }\n\n /** Smooth scroll to a section. */\n scrollToSection(sectionId: string, offset?: number): void {\n this.visualGuidance?.scrollToSection(sectionId, offset);\n }\n\n /** Smooth scroll to a CSS selector. */\n scrollToSelector(selector: string, offset?: number): void {\n this.visualGuidance?.scrollToSelector(selector, offset);\n }\n\n /** Start a guided tour. */\n startTour(sectionIds: string[], mode?: 'auto' | 'manual'): void {\n this.visualGuidance?.startTour(sectionIds, mode);\n }\n\n /** Advance to next tour step. */\n nextTourStep(): void {\n this.visualGuidance?.nextTourStep();\n }\n\n /** Go back to previous tour step. */\n prevTourStep(): void {\n this.visualGuidance?.prevTourStep();\n }\n\n /** Stop the guided tour. */\n stopTour(): void {\n this.visualGuidance?.stopTour();\n }\n\n /** Navigate to a same-origin URL. */\n async navigate(href: string): Promise<boolean> {\n if (!this.navigationController) return false;\n return this.navigationController.navigate(href);\n }\n\n // -------------------------------------------------------------------------\n // Context management\n // -------------------------------------------------------------------------\n\n setPageContext(context: Record<string, unknown>): void {\n this.contextManager.setPageContext(context);\n if (this._debug) {\n console.debug('[GuideKit:Core] setPageContext', context);\n }\n }\n\n /** Get the i18n instance for localized strings. */\n get i18n(): I18n {\n return this._i18n;\n }\n\n /** Get/set quiet mode on proactive triggers. */\n get quietMode(): boolean {\n return this.proactiveEngine?.quietMode ?? false;\n }\n\n set quietMode(value: boolean) {\n if (this.proactiveEngine) {\n this.proactiveEngine.quietMode = value;\n }\n this.contextManager.quietMode = value;\n }\n\n /** Get/set user preference (voice/text). */\n get userPreference(): 'voice' | 'text' {\n return this.contextManager.userPreference;\n }\n\n set userPreference(value: 'voice' | 'text') {\n this.contextManager.userPreference = value;\n }\n\n /** Get the rate limiter for monitoring usage. */\n get rateLimiterState() {\n return this.rateLimiter.getState();\n }\n\n // -------------------------------------------------------------------------\n // Health check\n // -------------------------------------------------------------------------\n\n /**\n * Check health of all connected services.\n * Returns per-service status and an overall assessment.\n */\n async checkHealth(): Promise<HealthCheckResult> {\n const results: HealthCheckResult = {\n llm: { status: 'not-configured' },\n stt: { status: 'not-configured' },\n tts: { status: 'not-configured' },\n mic: { status: 'not-configured' },\n overall: 'ok',\n };\n\n // LLM check\n if (this.llmOrchestrator) {\n try {\n const start = Date.now();\n // Lightweight check — just verify the orchestrator is alive\n results.llm = {\n status: 'ok',\n latencyMs: Date.now() - start,\n };\n } catch (err) {\n results.llm = {\n status: 'unavailable',\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n }\n\n // STT check — report as configured only if user explicitly provided STT config\n // or if voice pipeline is active (web-speech auto-default still works on demand)\n if (this._options.stt) {\n results.stt = { status: this.voicePipeline ? 'ok' : 'degraded' };\n }\n\n // TTS check — same logic as STT\n if (this._options.tts) {\n results.tts = { status: this.voicePipeline ? 'ok' : 'degraded' };\n }\n\n // Mic check\n if (typeof navigator !== 'undefined' && navigator.mediaDevices) {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const hasMic = devices.some((d) => d.kind === 'audioinput');\n results.mic = { status: hasMic ? 'ok' : 'unavailable' };\n } catch (err) {\n results.mic = {\n status: 'unavailable',\n error: err instanceof Error ? err.message : 'Permission denied',\n };\n }\n }\n\n // Compute overall\n const statuses = [results.llm, results.stt, results.tts, results.mic];\n const configured = statuses.filter((s) => s.status !== 'not-configured');\n if (configured.some((s) => s.status === 'unavailable')) {\n results.overall = 'unavailable';\n } else if (configured.some((s) => s.status === 'degraded')) {\n results.overall = 'degraded';\n } else {\n results.overall = 'ok';\n }\n\n return results;\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n async destroy(): Promise<void> {\n this._instanceAbortController.abort();\n this.contextManager.saveSession();\n SingletonGuard.release(this.instanceId);\n this._isReady = false;\n this.notifyStoreListeners();\n\n if (this._debug) {\n console.debug('[GuideKit:Core] Destroyed instance', this.instanceId);\n }\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private setAgentState(state: AgentState): void {\n this._agentState = state;\n this.notifyStoreListeners();\n }\n\n private notifyStoreListeners(): void {\n this._storeSnapshot = this.buildSnapshot();\n for (const listener of this.storeListeners) {\n listener();\n }\n }\n\n private buildSnapshot(): GuideKitStore {\n return {\n status: {\n isReady: this._isReady,\n agentState: this._agentState,\n error:\n this._agentState.status === 'error'\n ? this._agentState.error\n : null,\n },\n voice: {\n isListening: this._agentState.status === 'listening',\n isSpeaking: this._agentState.status === 'speaking',\n },\n };\n }\n\n /**\n * Unified built-in tool specifications — single source of truth for both\n * tool definitions (sent to LLM) and handler registration.\n */\n private getBuiltinToolSpecs(): Array<ToolDefinition & { execute: (args: Record<string, unknown>) => Promise<unknown> }> {\n return [\n {\n name: 'highlight',\n description:\n 'Spotlight an element on the page to draw the user\\'s attention. Use sectionId to highlight a page section, or selector for a specific CSS selector. Optionally add a tooltip with explanation text.',\n parameters: {\n sectionId: { type: 'string', description: 'ID of the section to highlight' },\n selector: { type: 'string', description: 'CSS selector (overrides sectionId)' },\n tooltip: { type: 'string', description: 'Text to show in tooltip' },\n position: { type: 'string', enum: ['top', 'bottom', 'left', 'right', 'auto'], description: 'Tooltip position' },\n },\n required: [],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionId = args.sectionId as string | undefined;\n const selector = args.selector as string | undefined;\n const tooltip = args.tooltip as string | undefined;\n const position = args.position as 'top' | 'bottom' | 'left' | 'right' | 'auto' | undefined;\n const result = this.highlight({ sectionId, selector, tooltip, position });\n return { success: result };\n },\n },\n {\n name: 'dismissHighlight',\n description: 'Remove the current spotlight overlay.',\n parameters: {},\n required: [],\n schemaVersion: 1,\n execute: async () => {\n this.dismissHighlight();\n return { success: true };\n },\n },\n {\n name: 'scrollToSection',\n description:\n 'Smooth scroll to a section by its ID. Use offset to account for sticky headers.',\n parameters: {\n sectionId: { type: 'string', description: 'ID of the section to scroll to' },\n offset: { type: 'number', description: 'Pixel offset for sticky headers' },\n },\n required: ['sectionId'],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionId = args.sectionId as string;\n const offset = args.offset as number | undefined;\n this.scrollToSection(sectionId, offset);\n return { success: true };\n },\n },\n {\n name: 'navigate',\n description:\n 'Navigate to a different page within the same site. Only same-origin URLs are allowed.',\n parameters: {\n href: { type: 'string', description: 'URL or path to navigate to (same-origin only)' },\n },\n required: ['href'],\n schemaVersion: 1,\n execute: async (args) => {\n const href = args.href as string;\n const result = await this.navigate(href);\n return { success: result, navigatedTo: result ? href : null };\n },\n },\n {\n name: 'startTour',\n description:\n 'Start a guided tour through multiple sections in sequence.',\n parameters: {\n sectionIds: { type: 'array', items: { type: 'string' }, description: 'Section IDs in tour order' },\n mode: { type: 'string', enum: ['auto', 'manual'], description: 'auto advances automatically; manual waits for user' },\n },\n required: ['sectionIds'],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionIds = args.sectionIds as string[];\n const mode = (args.mode as 'auto' | 'manual') ?? 'manual';\n this.startTour(sectionIds, mode);\n return { success: true, steps: sectionIds.length };\n },\n },\n {\n name: 'readPageContent',\n description:\n 'Read visible text content of a section by ID, or search across all sections by keyword.',\n parameters: {\n sectionId: { type: 'string', description: 'Section ID to read' },\n query: { type: 'string', description: 'Keyword to search for across sections' },\n },\n required: [],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionId = args.sectionId as string | undefined;\n const query = args.query as string | undefined;\n const model = this._currentPageModel;\n if (!model) return { error: 'No page model available' };\n\n if (sectionId) {\n const section = model.sections.find((s) => s.id === sectionId);\n if (section) {\n const contentMapResult = await this.contextManager.getContent(sectionId);\n return {\n sectionId: section.id,\n label: section.label,\n summary: section.summary,\n contentMap: contentMapResult,\n };\n }\n return { error: `Section \"${sectionId}\" not found` };\n }\n\n if (query) {\n const queryLower = query.toLowerCase();\n const matches = model.sections.filter(\n (s) =>\n s.label?.toLowerCase().includes(queryLower) ||\n s.summary?.toLowerCase().includes(queryLower),\n );\n return {\n query,\n results: matches.slice(0, 5).map((s) => ({\n sectionId: s.id,\n label: s.label,\n snippet: s.summary?.slice(0, 200),\n })),\n };\n }\n\n return { error: 'Provide either sectionId or query' };\n },\n },\n {\n name: 'getVisibleSections',\n description:\n 'Get the list of sections currently visible in the user viewport.',\n parameters: {},\n required: [],\n schemaVersion: 1,\n execute: async () => {\n const model = this._currentPageModel;\n if (!model) return { sections: [] };\n return {\n sections: model.sections.slice(0, 10).map((s) => ({\n id: s.id,\n label: s.label,\n selector: s.selector,\n score: s.score,\n })),\n };\n },\n },\n {\n name: 'clickElement',\n description:\n 'Programmatically click an interactive element on the page.',\n parameters: {\n selector: { type: 'string', description: 'CSS selector of the element to click' },\n },\n required: ['selector'],\n schemaVersion: 1,\n execute: async (args) => {\n if (typeof document === 'undefined') return { success: false, error: 'Not in browser' };\n const selector = args.selector as string;\n\n const el = document.querySelector(selector);\n if (!el) return { success: false, error: `Element not found: ${selector}` };\n if (!(el instanceof HTMLElement)) return { success: false, error: 'Element is not clickable' };\n\n const clickableRules = this._options.options?.clickableSelectors;\n const isInDevAllowList = clickableRules?.allow?.some((pattern) => {\n try { return el.matches(pattern); } catch { return selector === pattern; }\n }) ?? false;\n\n if (!isInDevAllowList) {\n const defaultDenied = DEFAULT_CLICK_DENY.some((pattern) => {\n try { return el.matches(pattern); } catch { return false; }\n });\n if (defaultDenied) {\n return { success: false, error: `Selector \"${selector}\" matches the default deny list. Add it to clickableSelectors.allow to override.` };\n }\n }\n\n if (clickableRules?.deny?.length) {\n const denied = clickableRules.deny.some((pattern) => {\n try { return el.matches(pattern); } catch { return selector === pattern; }\n });\n if (denied) {\n return { success: false, error: `Selector \"${selector}\" is blocked by the deny list.` };\n }\n }\n\n if (clickableRules?.allow?.length && !isInDevAllowList) {\n return { success: false, error: `Selector \"${selector}\" is not in the allowed clickable selectors list.` };\n }\n\n el.click();\n return { success: true };\n },\n },\n {\n name: 'executeCustomAction',\n description:\n 'Execute a developer-registered custom action (e.g., add to cart, submit form).',\n parameters: {\n actionId: { type: 'string', description: 'ID of the custom action' },\n params: { type: 'object', description: 'Parameters for the action' },\n },\n required: ['actionId'],\n schemaVersion: 1,\n execute: async (args) => {\n const actionId = args.actionId as string;\n const params = (args.params as Record<string, unknown>) ?? {};\n const action = this.customActions.get(actionId);\n if (!action) return { error: `Unknown action: ${actionId}` };\n try {\n const result = await action.handler(params);\n return { success: true, result };\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) };\n }\n },\n },\n ];\n }\n\n /**\n * Register all built-in tool handlers with the ToolExecutor.\n * Called once during init() after VisualGuidance and all subsystems are ready.\n */\n private registerBuiltinTools(): void {\n if (!this.toolExecutor) return;\n for (const spec of this.getBuiltinToolSpecs()) {\n this.toolExecutor.registerTool({ name: spec.name, execute: spec.execute });\n }\n }\n\n private getToolDefinitions(): ToolDefinition[] {\n const builtinTools: ToolDefinition[] = this.getBuiltinToolSpecs().map(\n ({ execute: _execute, ...def }) => def,\n );\n\n // Add custom actions as individual tool definitions for better LLM discoverability\n for (const [actionId, action] of this.customActions) {\n builtinTools.push({\n name: `action_${actionId}`,\n description: action.description,\n parameters: action.parameters as Record<string, ToolParameterSchema>,\n schemaVersion: 1,\n });\n }\n\n return builtinTools;\n }\n}\n"],"mappings":"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","names":["i","env","j","A","Float16Array","Tensor","Tensor","byteLength","InferenceSession","isNode","init_wasm_utils_env","origin","isEsmImportMetaUrlHardcodedAsFileUri","getScriptSrc","scriptSrc","inferWasmPathPrefixFromScriptSrc","isSameOrigin","normalizeUrl","fallbackUrl","preload","dynamicImportDefault","embeddedWasmModule","importWasmModule","init_wasm_utils_import","wasm","initialized","initializing","aborted","isMultiThreadSupported","isSimdSupported","isRelaxedSimdSupported","initializeWebAssembly","getInstance","init_wasm_factory","allocWasmString","iterateExtraOptions","checkLastError","init_wasm_utils","setRunOptions","init_run_options","getGraphOptimzationLevel","getExecutionMode","appendDefaultOptions","appendSessionConfig","setExecutionProviders","setSessionOptions","init_session_options","tensorDataTypeStringToEnum","tensorDataTypeEnumToString","calculateTensorSizeInBytes","tensorTypeToTypedArrayConstructor","logLevelStringToEnum","isGpuBufferSupportedType","isMLTensorSupportedType","dataLocationStringToEnum","init_wasm_common","loadFile","init_wasm_utils_load_file","initOrt","initRuntime","initEp","activeSessions","getSessionInputOutputCount","getSessionInputOutputMetadata","copyFromExternalBuffer","createSession","releaseSession","prepareInputOutputTensor","run","endProfiling","init_wasm_core_impl","initializeWebAssemblyAndOrtRuntime","initializeOrtEp","init_proxy_wrapper","encodeTensorMetadata","decodeTensorMetadata","OnnxruntimeWebAssemblySessionHandler","init_session_handler_inference","backend_wasm_exports","initializeFlags","OnnxruntimeWebAssemblyBackend","wasmBackend","init_backend_wasm","version","__esmMin","URL2","filename","prefixOverride","baseUrl","absoluteUrl","blob","url","urlOverride","isMultiThreaded","isWasmOverridden","useEmbeddedModule","wasmModuleFilename","wasmModuleUrl","needPreload","flags","timeout","numThreads","multiThreadSupported","wasmPaths","wasmPrefixOverride","mjsPathOverrideFlag","mjsPathOverride","wasmPathOverrideFlag","wasmPathOverride","wasmBinaryOverride","objectUrl","ortWasmFactory","isTimeout","tasks","resolve","reject","config","fileName","inferredWasmPathPrefix","module","what","data","allocs","dataLength","dataOffset","options","prefix","seen","handler","key","value","name","message","stack","ptrSize","paramsOffset","errorCode","errorMessagePointer","errorMessage","runOptionsHandle","runOptions","tagDataOffset","keyDataOffset","valueDataOffset","e","alloc","graphOptimizationLevel","executionMode","session","ep","sessionOptionsHandle","sessionOptions","executionProviders","epName","epOptions","deviceType","webgpuOptions","epNameDataOffset","epOptionsCount","keysOffset","valuesOffset","i","logIdDataOffset","logSeverityLevel","logVerbosityLevel","optimizedModelFilePathOffset","nameOffset","type","typeProto","dateType","dimsOrSize","elementSize","size","a","b","logLevel","location","file","readFile","createReadStream","stream","chunks","chunk","response","contentLengthHeader","fileSize","reader","buffer","pages","offset","done","chunkSize","loggingLevel","env","webgpuAdapter","powerPreference","forceFallbackAdapter","sessionHandle","index","metadataOffset","elementType","dimsCount","dims","symbolicDimNameOffset","model","modelDataOffset","modelData","modelDataLength","ioBindingHandle","inputNamesUTF8Encoded","outputNamesUTF8Encoded","loadingPromises","path","provider","webnnOptions","context","gpuDevice","inputCount","outputCount","enableGraphCapture","inputNames","outputNames","inputMetadata","outputMetadata","outputPreferredLocations","shape","nameString","buf","sessionId","ioBindingState","tensor","tensorHandles","tensorNameUTF8Encoded","dataType","actualLocation","rawData","dataByteLength","gpuBuffer","registerBuffer","mlTensor","registerMLTensor","isGraphInput","isGraphOutput","tensorName","dataTypeEnum","createTemporaryTensor","uploadTensor","tensorId","dimsOffset","d","inputIndices","inputTensors","outputIndices","outputTensors","inputOutputBound","runOptionsAllocs","inputTensorHandles","outputTensorHandles","inputOutputAllocs","preAllocatedOutputs","beforeRunStack","inputValuesOffset","inputNamesOffset","outputValuesOffset","outputNamesOffset","TRACE_EVENT_BEGIN","TRACE_EVENT_END","output","outputPromises","beforeGetTensorDataStack","tensorDataOffset","keepOutputTensor","valueType","dimsLength","preferredLocation","stringData","nextOffset","maxBytesToRead","getBuffer","bufferSize","ensureTensor","isGraphInputOutputTypeSupported","result","typedArrayConstructor","v","p","profileFileName","inputs","outputs","getName","Tensor","download","dispose","pathOrBuffer","TRACE_FUNC_BEGIN","TRACE_FUNC_END","feeds","fetches","inputArray","kvp","outputArray","t","results","resultMap","__export","simd","numCpuLogicalCores","backendName","registerBackend","InferenceSession","Tensor","LOG_PREFIX","manager","withTimeout","truncate","DEFAULT_TIMEOUT_MS","emptyUsage","errorMsg","LOG_PREFIX","MAX_QUEUE_SIZE","DEFAULT_LANGUAGE","float32ToInt16","SileroVAD","lastIdx","de","pt"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/backend-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/backend.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/version.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/env-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/env.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-conversion-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-factory-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-impl-type-mapping.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-utils-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/trace.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/inference-session-impl.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/inference-session.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-conversion.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/tensor-factory.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/onnx-model.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/onnx-value.ts","../../../node_modules/.pnpm/onnxruntime-common@1.24.2/node_modules/onnxruntime-common/lib/index.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils-env.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils-import.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-factory.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/run-options.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/session-options.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-common.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-utils-load-file.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/wasm-core-impl.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/proxy-wrapper.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/wasm/session-handler-inference.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/backend-wasm.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/index.ts","../../../node_modules/.pnpm/onnxruntime-web@1.24.2/node_modules/onnxruntime-web/lib/version.ts","../../vad/src/index.ts","../src/index.ts","../../core/src/bus/index.ts","../../core/src/resources/index.ts","../../core/src/dom/index.ts","../../core/src/context/index.ts","../../core/src/errors/index.ts","../../core/src/llm/index.ts","../../core/src/llm/tool-executor.ts","../../core/src/connectivity/index.ts","../../core/src/navigation/index.ts","../../core/src/voice/websocket-manager.ts","../../core/src/voice/deepgram-stt.ts","../../core/src/voice/elevenlabs-stt.ts","../../core/src/voice/elevenlabs-tts.ts","../../core/src/voice/web-speech-stt.ts","../../core/src/voice/web-speech-tts.ts","../../core/src/voice/index.ts","../../core/src/visual/index.ts","../../core/src/awareness/index.ts","../../core/src/awareness/proactive.ts","../../core/src/llm/rate-limiter.ts","../../core/src/i18n/index.ts","../../core/src/auth/token-manager.ts","../../core/src/core.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Backend } from './backend.js';\nimport { InferenceSession } from './inference-session.js';\n\ninterface BackendInfo {\n backend: Backend;\n priority: number;\n\n initPromise?: Promise<void>;\n initialized?: boolean;\n aborted?: boolean;\n error?: string;\n}\n\nconst backends: Map<string, BackendInfo> = new Map();\nconst backendsSortedByPriority: string[] = [];\n\n/**\n * Register a backend.\n *\n * @param name - the name as a key to lookup as an execution provider.\n * @param backend - the backend object.\n * @param priority - an integer indicating the priority of the backend. Higher number means higher priority. if priority\n * < 0, it will be considered as a 'beta' version and will not be used as a fallback backend by default.\n *\n * @ignore\n */\nexport const registerBackend = (name: string, backend: Backend, priority: number): void => {\n if (backend && typeof backend.init === 'function' && typeof backend.createInferenceSessionHandler === 'function') {\n const currentBackend = backends.get(name);\n if (currentBackend === undefined) {\n backends.set(name, { backend, priority });\n } else if (currentBackend.priority > priority) {\n // same name is already registered with a higher priority. skip registeration.\n return;\n } else if (currentBackend.priority === priority) {\n if (currentBackend.backend !== backend) {\n throw new Error(`cannot register backend \"${name}\" using priority ${priority}`);\n }\n }\n\n if (priority >= 0) {\n const i = backendsSortedByPriority.indexOf(name);\n if (i !== -1) {\n backendsSortedByPriority.splice(i, 1);\n }\n\n for (let i = 0; i < backendsSortedByPriority.length; i++) {\n if (backends.get(backendsSortedByPriority[i])!.priority <= priority) {\n backendsSortedByPriority.splice(i, 0, name);\n return;\n }\n }\n backendsSortedByPriority.push(name);\n }\n return;\n }\n\n throw new TypeError('not a valid backend');\n};\n\n/**\n * Try to resolve and initialize a backend.\n *\n * @param backendName - the name of the backend.\n * @returns the backend instance if resolved and initialized successfully, or an error message if failed.\n */\nconst tryResolveAndInitializeBackend = async (backendName: string): Promise<Backend | string> => {\n const backendInfo = backends.get(backendName);\n if (!backendInfo) {\n return 'backend not found.';\n }\n\n if (backendInfo.initialized) {\n return backendInfo.backend;\n } else if (backendInfo.aborted) {\n return backendInfo.error!;\n } else {\n const isInitializing = !!backendInfo.initPromise;\n try {\n if (!isInitializing) {\n backendInfo.initPromise = backendInfo.backend.init(backendName);\n }\n await backendInfo.initPromise;\n backendInfo.initialized = true;\n return backendInfo.backend;\n } catch (e) {\n if (!isInitializing) {\n backendInfo.error = `${e}`;\n backendInfo.aborted = true;\n }\n return backendInfo.error!;\n } finally {\n delete backendInfo.initPromise;\n }\n }\n};\n\n/**\n * Resolve execution providers from the specific session options.\n *\n * @param options - the session options object.\n * @returns a promise that resolves to a tuple of an initialized backend instance and a session options object with\n * filtered EP list.\n *\n * @ignore\n */\nexport const resolveBackendAndExecutionProviders = async (\n options: InferenceSession.SessionOptions,\n): Promise<[backend: Backend, options: InferenceSession.SessionOptions]> => {\n // extract backend hints from session options\n const eps = options.executionProviders || [];\n const backendHints = eps.map((i) => (typeof i === 'string' ? i : i.name));\n const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints;\n\n // try to resolve and initialize all requested backends\n let backend: Backend | undefined;\n const errors = [];\n const availableBackendNames = new Set<string>();\n for (const backendName of backendNames) {\n const resolveResult = await tryResolveAndInitializeBackend(backendName);\n if (typeof resolveResult === 'string') {\n errors.push({ name: backendName, err: resolveResult });\n } else {\n if (!backend) {\n backend = resolveResult;\n }\n if (backend === resolveResult) {\n availableBackendNames.add(backendName);\n }\n }\n }\n\n // if no backend is available, throw error.\n if (!backend) {\n throw new Error(`no available backend found. ERR: ${errors.map((e) => `[${e.name}] ${e.err}`).join(', ')}`);\n }\n\n // for each explicitly requested backend, if it's not available, output warning message.\n for (const { name, err } of errors) {\n if (backendHints.includes(name)) {\n // eslint-disable-next-line no-console\n console.warn(\n `removing requested execution provider \"${name}\" from session options because it is not available: ${err}`,\n );\n }\n }\n\n const filteredEps = eps.filter((i) => availableBackendNames.has(typeof i === 'string' ? i : i.name));\n\n return [\n backend,\n new Proxy(options, {\n get: (target, prop) => {\n if (prop === 'executionProviders') {\n return filteredEps;\n }\n return Reflect.get(target, prop);\n },\n }),\n ];\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession } from './inference-session.js';\nimport { OnnxValue } from './onnx-value.js';\n\n/**\n * @ignore\n */\nexport declare namespace SessionHandler {\n type FeedsType = { [name: string]: OnnxValue };\n type FetchesType = { [name: string]: OnnxValue | null };\n type ReturnType = { [name: string]: OnnxValue };\n}\n\n/**\n * Represents shared SessionHandler functionality\n *\n * @ignore\n */\ninterface SessionHandler {\n dispose(): Promise<void>;\n\n readonly inputNames: readonly string[];\n readonly outputNames: readonly string[];\n\n readonly inputMetadata: readonly InferenceSession.ValueMetadata[];\n readonly outputMetadata: readonly InferenceSession.ValueMetadata[];\n}\n\n/**\n * Represent a handler instance of an inference session.\n *\n * @ignore\n */\nexport interface InferenceSessionHandler extends SessionHandler {\n startProfiling(): void;\n endProfiling(): void;\n\n run(\n feeds: SessionHandler.FeedsType,\n fetches: SessionHandler.FetchesType,\n options: InferenceSession.RunOptions,\n ): Promise<SessionHandler.ReturnType>;\n}\n\n/**\n * Represent a backend that provides implementation of model inferencing.\n *\n * @ignore\n */\nexport interface Backend {\n /**\n * Initialize the backend asynchronously. Should throw when failed.\n */\n init(backendName: string): Promise<void>;\n\n createInferenceSessionHandler(\n uriOrBuffer: string | Uint8Array,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler>;\n}\n\nexport { registerBackend } from './backend-impl.js';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// This file is generated by /js/scripts/update-version.ts\n// Do not modify file content manually.\n\nexport const version = '1.24.2';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Env } from './env.js';\nimport { version } from './version.js';\n\ntype LogLevelType = Env['logLevel'];\n\nlet logLevelValue: Required<LogLevelType> = 'warning';\n\nexport const env: Env = {\n wasm: {} as Env.WebAssemblyFlags,\n webgl: {} as Env.WebGLFlags,\n webgpu: {} as Env.WebGpuFlags,\n versions: { common: version },\n\n set logLevel(value: LogLevelType) {\n if (value === undefined) {\n return;\n }\n if (typeof value !== 'string' || ['verbose', 'info', 'warning', 'error', 'fatal'].indexOf(value) === -1) {\n throw new Error(`Unsupported logging level: ${value}`);\n }\n logLevelValue = value;\n },\n get logLevel(): Required<LogLevelType> {\n return logLevelValue;\n },\n};\n\n// set property 'logLevel' so that they can be correctly transferred to worker by `postMessage()`.\nObject.defineProperty(env, 'logLevel', { enumerable: true });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env as envImpl } from './env-impl.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\nexport declare namespace Env {\n export type WasmPathPrefix = string;\n export interface WasmFilePaths {\n /**\n * Specify the override path for the main .wasm file.\n *\n * This path should be an absolute path.\n *\n * If not modified, the filename of the .wasm file is:\n * - `ort-wasm-simd-threaded.wasm` for default build\n * - `ort-wasm-simd-threaded.jsep.wasm` for JSEP build (with WebGPU and WebNN)\n * - `ort-wasm-simd-threaded.asyncify.wasm` for WebGPU build with Asyncify (with WebNN)\n * - `ort-wasm-simd-threaded.jspi.wasm` for WebGPU build with JSPI support (with WebNN)\n */\n wasm?: URL | string;\n /**\n * Specify the override path for the main .mjs file.\n *\n * This path should be an absolute path.\n *\n * If not modified, the filename of the .mjs file is:\n * - `ort-wasm-simd-threaded.mjs` for default build\n * - `ort-wasm-simd-threaded.jsep.mjs` for JSEP build (with WebGPU and WebNN)\n * - `ort-wasm-simd-threaded.asyncify.mjs` for WebGPU build with Asyncify (with WebNN)\n * - `ort-wasm-simd-threaded.jspi.mjs` for WebGPU build with JSPI support (with WebNN)\n */\n mjs?: URL | string;\n }\n export type WasmPrefixOrFilePaths = WasmPathPrefix | WasmFilePaths;\n export interface WebAssemblyFlags {\n /**\n * set or get number of thread(s). If omitted or set to 0, number of thread(s) will be determined by system. If set\n * to 1, no worker thread will be spawned.\n *\n * This setting is available only when WebAssembly multithread feature is available in current context.\n *\n * @defaultValue `0`\n */\n numThreads?: number;\n\n /**\n * set a value indicating whether to enable SIMD.\n *\n * ONNX Runtime will perform feature detection based on the value of this property. Specifically, when the value is\n * set to:\n * - `undefined`, `true` or `\"fixed\"`: will check availability of Fixed-width SIMD.\n * - `\"relaxed\"`: will check availability of Relaxed SIMD.\n * - `false`: will not perform SIMD feature checking.\n *\n * Setting this property does not make ONNX Runtime to switch to the corresponding runtime automatically. User need\n * to set `wasmPaths` or `wasmBinary` property to load the corresponding runtime.\n *\n * This setting is available only when WebAssembly SIMD feature is available in current context.\n *\n * @defaultValue `true`\n */\n simd?: boolean | 'fixed' | 'relaxed';\n\n /**\n * set or get a boolean value indicating whether to enable trace.\n *\n * @defaultValue `false`\n *\n * @deprecated Use `env.trace` instead. If `env.trace` is set, this property will be ignored.\n */\n trace?: boolean;\n\n /**\n * Set or get a number specifying the timeout for initialization of WebAssembly backend, in milliseconds. A zero\n * value indicates no timeout is set.\n *\n * @defaultValue `0`\n */\n initTimeout?: number;\n\n /**\n * Set a custom URL prefix to the .wasm/.mjs files, or an object of overrides for both .wasm/.mjs file. The override\n * path should be an absolute path.\n */\n wasmPaths?: WasmPrefixOrFilePaths;\n\n /**\n * Set a custom buffer which contains the WebAssembly binary. If this property is set, the `wasmPaths` property will\n * be ignored.\n */\n wasmBinary?: ArrayBufferLike | Uint8Array;\n\n /**\n * Set or get a boolean value indicating whether to proxy the execution of main thread to a worker thread.\n *\n * @defaultValue `false`\n */\n proxy?: boolean;\n }\n\n export interface WebGLFlags {\n /**\n * Set or get the WebGL Context ID (webgl or webgl2).\n *\n * @defaultValue `'webgl2'`\n */\n contextId?: 'webgl' | 'webgl2';\n /**\n * Get the WebGL rendering context.\n */\n readonly context: WebGLRenderingContext;\n /**\n * Set or get the maximum batch size for matmul. 0 means to disable batching.\n *\n * @deprecated\n */\n matmulMaxBatchSize?: number;\n /**\n * Set or get the texture cache mode.\n *\n * @defaultValue `'full'`\n */\n textureCacheMode?: 'initializerOnly' | 'full';\n /**\n * Set or get the packed texture mode\n *\n * @defaultValue `false`\n */\n pack?: boolean;\n /**\n * Set or get whether enable async download.\n *\n * @defaultValue `false`\n */\n async?: boolean;\n }\n\n export interface WebGpuProfilingDataV1TensorMetadata {\n dims: readonly number[];\n dataType: string;\n }\n export interface WebGpuProfilingDataV1 {\n version: 1;\n inputsMetadata: readonly WebGpuProfilingDataV1TensorMetadata[];\n outputsMetadata: readonly WebGpuProfilingDataV1TensorMetadata[];\n kernelId: number;\n kernelType: string;\n kernelName: string;\n programName: string;\n startTime: number;\n endTime: number;\n }\n\n export type WebGpuProfilingData = WebGpuProfilingDataV1;\n\n export interface WebGpuFlags {\n /**\n * Set or get the profiling mode.\n *\n * @deprecated Use `env.webgpu.profiling.mode` instead. If `env.webgpu.profiling.mode` is set, this property will be\n * ignored.\n */\n profilingMode?: 'off' | 'default';\n /**\n * Set or get the profiling configuration.\n */\n profiling: {\n /**\n * Set or get the profiling mode.\n *\n * @defaultValue `'off'`\n */\n mode?: 'off' | 'default';\n\n /**\n * Set or get a callback function when a profiling data is received. If not set, the profiling data will be\n * printed to console.\n */\n ondata?: (data: WebGpuProfilingData) => void;\n };\n /**\n * Set or get the power preference.\n *\n * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n * used as options for `navigator.gpu.requestAdapter()`.\n *\n * See {@link https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions} for more details.\n *\n * @defaultValue `undefined`\n *\n * @deprecated Create your own GPUAdapter, use it to create a GPUDevice instance and set {@link device} property if\n * you want to use a specific power preference.\n */\n powerPreference?: 'low-power' | 'high-performance';\n /**\n * Set or get the force fallback adapter flag.\n *\n * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n * used as options for `navigator.gpu.requestAdapter()`.\n *\n * See {@link https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions} for more details.\n *\n * @defaultValue `undefined`\n *\n * @deprecated Create your own GPUAdapter, use it to create a GPUDevice instance and set {@link device} property if\n * you want to use a specific fallback option.\n */\n forceFallbackAdapter?: boolean;\n /**\n * Set or get the adapter for WebGPU.\n *\n * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n * used as the GPU adapter for the underlying WebGPU backend to create GPU device.\n *\n * If this property is not set, it will be available to get after the first WebGPU inference session is created. The\n * value will be the GPU adapter that created by the underlying WebGPU backend.\n *\n * When use with TypeScript, the type of this property is `GPUAdapter` defined in \"@webgpu/types\".\n *\n * @deprecated It is no longer recommended to use this property. The latest WebGPU spec adds `GPUDevice.adapterInfo`\n * (https://www.w3.org/TR/webgpu/#dom-gpudevice-adapterinfo), which allows to get the adapter information from the\n * device. When it's available, there is no need to set/get the {@link adapter} property.\n */\n adapter: TryGetGlobalType<'GPUAdapter'>;\n /**\n * Set or get the GPU device for WebGPU.\n *\n * There are 3 valid scenarios of accessing this property:\n * - Set a value before the first WebGPU inference session is created. The value will be used by the WebGPU backend\n * to perform calculations. If the value is not a `GPUDevice` object, an error will be thrown.\n * - Get the value before the first WebGPU inference session is created. This will try to create a new GPUDevice\n * instance. Returns a `Promise` that resolves to a `GPUDevice` object.\n * - Get the value after the first WebGPU inference session is created. Returns a resolved `Promise` to the\n * `GPUDevice` object used by the WebGPU backend.\n */\n get device(): Promise<TryGetGlobalType<'GPUDevice'>>;\n set device(value: TryGetGlobalType<'GPUDevice'>);\n /**\n * Set or get whether validate input content.\n *\n * @defaultValue `false`\n */\n validateInputContent?: boolean;\n }\n}\n\nexport interface Env {\n /**\n * set the severity level for logging.\n *\n * @defaultValue `'warning'`\n */\n logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal';\n\n /**\n * Indicate whether run in debug mode.\n *\n * @defaultValue `false`\n */\n debug?: boolean;\n\n /**\n * set or get a boolean value indicating whether to enable trace.\n *\n * @defaultValue `false`\n */\n trace?: boolean;\n\n /**\n * Get version of the current package.\n */\n readonly versions: {\n readonly common: string;\n readonly web?: string;\n readonly node?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n readonly 'react-native'?: string;\n };\n\n /**\n * Represent a set of flags for WebAssembly\n */\n readonly wasm: Env.WebAssemblyFlags;\n\n /**\n * Represent a set of flags for WebGL\n */\n readonly webgl: Env.WebGLFlags;\n\n /**\n * Represent a set of flags for WebGPU\n */\n readonly webgpu: Env.WebGpuFlags;\n\n [name: string]: unknown;\n}\n\n/**\n * Represent a set of flags as a global singleton.\n */\nexport const env: Env = envImpl;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js';\nimport { Tensor } from './tensor.js';\n\n/**\n * implementation of Tensor.toDataURL()\n */\nexport const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions): string => {\n const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : new OffscreenCanvas(1, 1);\n canvas.width = tensor.dims[3];\n canvas.height = tensor.dims[2];\n const pixels2DContext = canvas.getContext('2d') as\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D\n | null;\n\n if (pixels2DContext != null) {\n // Default values for height and width & format\n let width: number;\n let height: number;\n if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') {\n width = tensor.dims[2];\n height = tensor.dims[3];\n } else {\n // Default layout is NCWH\n width = tensor.dims[3];\n height = tensor.dims[2];\n }\n\n const inputformat = options?.format !== undefined ? options.format : 'RGB';\n\n const norm = options?.norm;\n let normMean: [number, number, number, number];\n let normBias: [number, number, number, number];\n if (norm === undefined || norm.mean === undefined) {\n normMean = [255, 255, 255, 255];\n } else {\n if (typeof norm.mean === 'number') {\n normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n } else {\n normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 0];\n if (norm.mean[3] !== undefined) {\n normMean[3] = norm.mean[3];\n }\n }\n }\n if (norm === undefined || norm.bias === undefined) {\n normBias = [0, 0, 0, 0];\n } else {\n if (typeof norm.bias === 'number') {\n normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n } else {\n normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0];\n if (norm.bias[3] !== undefined) {\n normBias[3] = norm.bias[3];\n }\n }\n }\n\n const stride = height * width;\n // Default pointer assignments\n let rTensorPointer = 0,\n gTensorPointer = stride,\n bTensorPointer = stride * 2,\n aTensorPointer = -1;\n\n // Updating the pointer assignments based on the input image format\n if (inputformat === 'RGBA') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n aTensorPointer = stride * 3;\n } else if (inputformat === 'RGB') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n } else if (inputformat === 'RBG') {\n rTensorPointer = 0;\n bTensorPointer = stride;\n gTensorPointer = stride * 2;\n }\n\n for (let i = 0; i < height; i++) {\n for (let j = 0; j < width; j++) {\n const R = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value\n const G = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value\n const B = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value\n const A = aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value\n\n pixels2DContext.fillStyle = 'rgba(' + R + ',' + G + ',' + B + ',' + A + ')';\n pixels2DContext.fillRect(j, i, 1, 1);\n }\n }\n if ('toDataURL' in canvas) {\n return canvas.toDataURL();\n } else {\n throw new Error('toDataURL is not supported');\n }\n } else {\n throw new Error('Can not access image data');\n }\n};\n\n/**\n * implementation of Tensor.toImageData()\n */\nexport const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOptions): ImageData => {\n const pixels2DContext =\n typeof document !== 'undefined'\n ? document.createElement('canvas').getContext('2d')\n : (new OffscreenCanvas(1, 1).getContext('2d') as OffscreenCanvasRenderingContext2D);\n let image: ImageData;\n if (pixels2DContext != null) {\n // Default values for height and width & format\n let width: number;\n let height: number;\n let channels: number;\n if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') {\n width = tensor.dims[2];\n height = tensor.dims[1];\n channels = tensor.dims[3];\n } else {\n // Default layout is NCWH\n width = tensor.dims[3];\n height = tensor.dims[2];\n channels = tensor.dims[1];\n }\n const inputformat = options !== undefined ? (options.format !== undefined ? options.format : 'RGB') : 'RGB';\n\n const norm = options?.norm;\n let normMean: [number, number, number, number];\n let normBias: [number, number, number, number];\n if (norm === undefined || norm.mean === undefined) {\n normMean = [255, 255, 255, 255];\n } else {\n if (typeof norm.mean === 'number') {\n normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n } else {\n normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 255];\n if (norm.mean[3] !== undefined) {\n normMean[3] = norm.mean[3];\n }\n }\n }\n if (norm === undefined || norm.bias === undefined) {\n normBias = [0, 0, 0, 0];\n } else {\n if (typeof norm.bias === 'number') {\n normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n } else {\n normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0];\n if (norm.bias[3] !== undefined) {\n normBias[3] = norm.bias[3];\n }\n }\n }\n\n const stride = height * width;\n if (options !== undefined) {\n if (\n (options.format !== undefined && channels === 4 && options.format !== 'RGBA') ||\n (channels === 3 && options.format !== 'RGB' && options.format !== 'BGR')\n ) {\n throw new Error(\"Tensor format doesn't match input tensor dims\");\n }\n }\n\n // Default pointer assignments\n const step = 4;\n let rImagePointer = 0,\n gImagePointer = 1,\n bImagePointer = 2,\n aImagePointer = 3;\n let rTensorPointer = 0,\n gTensorPointer = stride,\n bTensorPointer = stride * 2,\n aTensorPointer = -1;\n\n // Updating the pointer assignments based on the input image format\n if (inputformat === 'RGBA') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n aTensorPointer = stride * 3;\n } else if (inputformat === 'RGB') {\n rTensorPointer = 0;\n gTensorPointer = stride;\n bTensorPointer = stride * 2;\n } else if (inputformat === 'RBG') {\n rTensorPointer = 0;\n bTensorPointer = stride;\n gTensorPointer = stride * 2;\n }\n\n image = pixels2DContext.createImageData(width, height);\n\n for (\n let i = 0;\n i < height * width;\n rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++\n ) {\n image.data[rImagePointer] = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value\n image.data[gImagePointer] = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value\n image.data[bImagePointer] = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value\n image.data[aImagePointer] =\n aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value\n }\n } else {\n throw new Error('Can not access image data');\n }\n return image;\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n OptionsDimensions,\n OptionsFormat,\n OptionsNormalizationParameters,\n OptionsTensorFormat,\n OptionsTensorLayout,\n TensorFromGpuBufferOptions,\n TensorFromImageBitmapOptions,\n TensorFromImageDataOptions,\n TensorFromImageElementOptions,\n TensorFromMLTensorOptions,\n TensorFromTextureOptions,\n TensorFromUrlOptions,\n} from './tensor-factory.js';\nimport { Tensor } from './tensor-impl.js';\nimport { Tensor as TensorInterface } from './tensor.js';\n\ninterface BufferToTensorOptions\n extends OptionsDimensions,\n OptionsTensorLayout,\n OptionsNormalizationParameters,\n OptionsFormat,\n OptionsTensorFormat {}\n\n/**\n * Create a new tensor object from image object\n *\n * @param buffer - Extracted image buffer data - assuming RGBA format\n * @param imageFormat - input image configuration - required configurations height, width, format\n * @param tensorFormat - output tensor configuration - Default is RGB format\n */\nexport const bufferToTensor = (buffer: Uint8ClampedArray | undefined, options: BufferToTensorOptions): Tensor => {\n if (buffer === undefined) {\n throw new Error('Image buffer must be defined');\n }\n if (options.height === undefined || options.width === undefined) {\n throw new Error('Image height and width must be defined');\n }\n if (options.tensorLayout === 'NHWC') {\n throw new Error('NHWC Tensor layout is not supported yet');\n }\n\n const { height, width } = options;\n\n const norm = options.norm ?? { mean: 255, bias: 0 };\n let normMean: [number, number, number, number];\n let normBias: [number, number, number, number];\n\n if (typeof norm.mean === 'number') {\n normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n } else {\n normMean = [norm.mean![0], norm.mean![1], norm.mean![2], norm.mean![3] ?? 255];\n }\n\n if (typeof norm.bias === 'number') {\n normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n } else {\n normBias = [norm.bias![0], norm.bias![1], norm.bias![2], norm.bias![3] ?? 0];\n }\n\n const inputformat = options.format !== undefined ? options.format : 'RGBA';\n // default value is RGBA since imagedata and HTMLImageElement uses it\n\n const outputformat =\n options.tensorFormat !== undefined ? (options.tensorFormat !== undefined ? options.tensorFormat : 'RGB') : 'RGB';\n const stride = height * width;\n const float32Data = outputformat === 'RGBA' ? new Float32Array(stride * 4) : new Float32Array(stride * 3);\n\n // Default pointer assignments\n let step = 4,\n rImagePointer = 0,\n gImagePointer = 1,\n bImagePointer = 2,\n aImagePointer = 3;\n let rTensorPointer = 0,\n gTensorPointer = stride,\n bTensorPointer = stride * 2,\n aTensorPointer = -1;\n\n // Updating the pointer assignments based on the input image format\n if (inputformat === 'RGB') {\n step = 3;\n rImagePointer = 0;\n gImagePointer = 1;\n bImagePointer = 2;\n aImagePointer = -1;\n }\n\n // Updating the pointer assignments based on the output tensor format\n if (outputformat === 'RGBA') {\n aTensorPointer = stride * 3;\n } else if (outputformat === 'RBG') {\n rTensorPointer = 0;\n bTensorPointer = stride;\n gTensorPointer = stride * 2;\n } else if (outputformat === 'BGR') {\n bTensorPointer = 0;\n gTensorPointer = stride;\n rTensorPointer = stride * 2;\n }\n\n for (\n let i = 0;\n i < stride;\n i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step\n ) {\n float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias[0]) / normMean[0];\n float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias[1]) / normMean[1];\n float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias[2]) / normMean[2];\n if (aTensorPointer !== -1 && aImagePointer !== -1) {\n float32Data[aTensorPointer++] = (buffer[aImagePointer] + normBias[3]) / normMean[3];\n }\n }\n\n // Float32Array -> ort.Tensor\n const outputTensor =\n outputformat === 'RGBA'\n ? new Tensor('float32', float32Data, [1, 4, height, width])\n : new Tensor('float32', float32Data, [1, 3, height, width]);\n return outputTensor;\n};\n\n/**\n * implementation of Tensor.fromImage().\n */\nexport const tensorFromImage = async (\n image: ImageData | HTMLImageElement | ImageBitmap | string,\n options?:\n | TensorFromImageDataOptions\n | TensorFromImageElementOptions\n | TensorFromImageBitmapOptions\n | TensorFromUrlOptions,\n): Promise<Tensor> => {\n // checking the type of image object\n const isHTMLImageEle = typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement;\n const isImageDataEle = typeof ImageData !== 'undefined' && image instanceof ImageData;\n const isImageBitmap = typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap;\n const isString = typeof image === 'string';\n\n let data: Uint8ClampedArray | undefined;\n let bufferToTensorOptions: BufferToTensorOptions = options ?? {};\n\n const createCanvas = () => {\n if (typeof document !== 'undefined') {\n return document.createElement('canvas');\n } else if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(1, 1);\n } else {\n throw new Error('Canvas is not supported');\n }\n };\n const createCanvasContext = (canvas: HTMLCanvasElement | OffscreenCanvas) => {\n if (typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement) {\n return canvas.getContext('2d');\n } else if (canvas instanceof OffscreenCanvas) {\n return canvas.getContext('2d') as OffscreenCanvasRenderingContext2D;\n } else {\n return null;\n }\n };\n // filling and checking image configuration options\n if (isHTMLImageEle) {\n // HTMLImageElement - image object - format is RGBA by default\n const canvas = createCanvas();\n canvas.width = image.width;\n canvas.height = image.height;\n const pixels2DContext = createCanvasContext(canvas);\n\n if (pixels2DContext != null) {\n let height = image.height;\n let width = image.width;\n if (options !== undefined && options.resizedHeight !== undefined && options.resizedWidth !== undefined) {\n height = options.resizedHeight;\n width = options.resizedWidth;\n }\n\n if (options !== undefined) {\n bufferToTensorOptions = options;\n if (options.tensorFormat !== undefined) {\n throw new Error('Image input config format must be RGBA for HTMLImageElement');\n } else {\n bufferToTensorOptions.tensorFormat = 'RGBA';\n }\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n } else {\n bufferToTensorOptions.tensorFormat = 'RGBA';\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n }\n\n pixels2DContext.drawImage(image, 0, 0);\n data = pixels2DContext.getImageData(0, 0, width, height).data;\n } else {\n throw new Error('Can not access image data');\n }\n } else if (isImageDataEle) {\n let height: number;\n let width: number;\n\n if (options !== undefined && options.resizedWidth !== undefined && options.resizedHeight !== undefined) {\n height = options.resizedHeight;\n width = options.resizedWidth;\n } else {\n height = image.height;\n width = image.width;\n }\n\n if (options !== undefined) {\n bufferToTensorOptions = options;\n }\n bufferToTensorOptions.format = 'RGBA';\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n\n if (options !== undefined) {\n const tempCanvas = createCanvas();\n\n tempCanvas.width = width;\n tempCanvas.height = height;\n\n const pixels2DContext = createCanvasContext(tempCanvas);\n\n if (pixels2DContext != null) {\n pixels2DContext.putImageData(image, 0, 0);\n data = pixels2DContext.getImageData(0, 0, width, height).data;\n } else {\n throw new Error('Can not access image data');\n }\n } else {\n data = image.data;\n }\n } else if (isImageBitmap) {\n // ImageBitmap - image object - format must be provided by user\n if (options === undefined) {\n throw new Error('Please provide image config with format for Imagebitmap');\n }\n\n const canvas = createCanvas();\n canvas.width = image.width;\n canvas.height = image.height;\n const pixels2DContext = createCanvasContext(canvas);\n\n if (pixels2DContext != null) {\n const height = image.height;\n const width = image.width;\n pixels2DContext.drawImage(image, 0, 0, width, height);\n data = pixels2DContext.getImageData(0, 0, width, height).data;\n bufferToTensorOptions.height = height;\n bufferToTensorOptions.width = width;\n return bufferToTensor(data, bufferToTensorOptions);\n } else {\n throw new Error('Can not access image data');\n }\n } else if (isString) {\n return new Promise((resolve, reject) => {\n const canvas = createCanvas();\n const context = createCanvasContext(canvas);\n if (!image || !context) {\n return reject();\n }\n const newImage = new Image();\n newImage.crossOrigin = 'Anonymous';\n newImage.src = image;\n newImage.onload = () => {\n canvas.width = newImage.width;\n canvas.height = newImage.height;\n context.drawImage(newImage, 0, 0, canvas.width, canvas.height);\n const img = context.getImageData(0, 0, canvas.width, canvas.height);\n\n bufferToTensorOptions.height = canvas.height;\n bufferToTensorOptions.width = canvas.width;\n resolve(bufferToTensor(img.data, bufferToTensorOptions));\n };\n });\n } else {\n throw new Error('Input data provided is not supported - aborted tensor creation');\n }\n\n if (data !== undefined) {\n return bufferToTensor(data, bufferToTensorOptions);\n } else {\n throw new Error('Input data provided is not supported - aborted tensor creation');\n }\n};\n\n/**\n * implementation of Tensor.fromTexture().\n */\nexport const tensorFromTexture = <T extends TensorInterface.TextureDataTypes>(\n texture: TensorInterface.TextureType,\n options: TensorFromTextureOptions<T>,\n): Tensor => {\n const { width, height, download, dispose } = options;\n // Always assume RGBAF32. TODO: support different texture format\n const dims = [1, height, width, 4];\n return new Tensor({ location: 'texture', type: 'float32', texture, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromGpuBuffer().\n */\nexport const tensorFromGpuBuffer = <T extends TensorInterface.GpuBufferDataTypes>(\n gpuBuffer: TensorInterface.GpuBufferType,\n options: TensorFromGpuBufferOptions<T>,\n): Tensor => {\n const { dataType, dims, download, dispose } = options;\n return new Tensor({ location: 'gpu-buffer', type: dataType ?? 'float32', gpuBuffer, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromMLTensor().\n */\nexport const tensorFromMLTensor = <T extends TensorInterface.MLTensorDataTypes>(\n mlTensor: TensorInterface.MLTensorType,\n options: TensorFromMLTensorOptions<T>,\n): Tensor => {\n const { dataType, dims, download, dispose } = options;\n return new Tensor({ location: 'ml-tensor', type: dataType ?? 'float32', mlTensor, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromPinnedBuffer().\n */\nexport const tensorFromPinnedBuffer = <T extends TensorInterface.CpuPinnedDataTypes>(\n type: T,\n buffer: TensorInterface.DataTypeMap[T],\n dims?: readonly number[],\n): Tensor => new Tensor({ location: 'cpu-pinned', type, data: buffer, dims: dims ?? [buffer.length] });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from './tensor.js';\n\nexport type SupportedTypedArrayConstructors =\n | Float32ArrayConstructor\n | Uint8ArrayConstructor\n | Int8ArrayConstructor\n | Uint16ArrayConstructor\n | Int16ArrayConstructor\n | Int32ArrayConstructor\n | BigInt64ArrayConstructor\n | Uint8ArrayConstructor\n | Float64ArrayConstructor\n | Uint32ArrayConstructor\n | BigUint64ArrayConstructor;\nexport type SupportedTypedArray = InstanceType<SupportedTypedArrayConstructors>;\n\n// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.\nexport const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map<string, SupportedTypedArrayConstructors>([\n ['float32', Float32Array],\n ['uint8', Uint8Array],\n ['int8', Int8Array],\n ['uint16', Uint16Array],\n ['int16', Int16Array],\n ['int32', Int32Array],\n ['bool', Uint8Array],\n ['float64', Float64Array],\n ['uint32', Uint32Array],\n ['int4', Uint8Array],\n ['uint4', Uint8Array],\n]);\n\n// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.\nexport const NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = new Map<SupportedTypedArrayConstructors, Tensor.Type>([\n [Float32Array, 'float32'],\n [Uint8Array, 'uint8'],\n [Int8Array, 'int8'],\n [Uint16Array, 'uint16'],\n [Int16Array, 'int16'],\n [Int32Array, 'int32'],\n [Float64Array, 'float64'],\n [Uint32Array, 'uint32'],\n]);\n\n// the following code allows delaying execution of BigInt/Float16Array checking. This allows lazy initialization for\n// NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP and NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, which allows BigInt/Float16Array\n// polyfill if available.\nlet isTypedArrayChecked = false;\nexport const checkTypedArray = () => {\n if (!isTypedArrayChecked) {\n isTypedArrayChecked = true;\n const isBigInt64ArrayAvailable = typeof BigInt64Array !== 'undefined' && BigInt64Array.from;\n const isBigUint64ArrayAvailable = typeof BigUint64Array !== 'undefined' && BigUint64Array.from;\n\n // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any\n const Float16Array = (globalThis as any).Float16Array;\n const isFloat16ArrayAvailable = typeof Float16Array !== 'undefined' && Float16Array.from;\n\n if (isBigInt64ArrayAvailable) {\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('int64', BigInt64Array);\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigInt64Array, 'int64');\n }\n if (isBigUint64ArrayAvailable) {\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('uint64', BigUint64Array);\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigUint64Array, 'uint64');\n }\n if (isFloat16ArrayAvailable) {\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('float16', Float16Array);\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(Float16Array, 'float16');\n } else {\n // if Float16Array is not available, use 'Uint16Array' to store the data.\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('float16', Uint16Array);\n }\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n CpuPinnedConstructorParameters,\n GpuBufferConstructorParameters,\n MLTensorConstructorParameters,\n TextureConstructorParameters,\n} from './tensor-factory.js';\nimport { Tensor } from './tensor-impl.js';\n\n/**\n * calculate size from dims.\n *\n * @param dims the dims array. May be an illegal input.\n */\nexport const calculateSize = (dims: readonly unknown[]): number => {\n let size = 1;\n for (let i = 0; i < dims.length; i++) {\n const dim = dims[i];\n if (typeof dim !== 'number' || !Number.isSafeInteger(dim)) {\n throw new TypeError(`dims[${i}] must be an integer, got: ${dim}`);\n }\n if (dim < 0) {\n throw new RangeError(`dims[${i}] must be a non-negative integer, got: ${dim}`);\n }\n size *= dim;\n }\n return size;\n};\n\n/**\n * implementation of Tensor.reshape()\n */\nexport const tensorReshape = (tensor: Tensor, dims: readonly number[]): Tensor => {\n switch (tensor.location) {\n case 'cpu':\n return new Tensor(tensor.type, tensor.data, dims);\n case 'cpu-pinned':\n return new Tensor({\n location: 'cpu-pinned',\n data: tensor.data as CpuPinnedConstructorParameters['data'],\n type: tensor.type as CpuPinnedConstructorParameters['type'],\n dims,\n });\n case 'texture':\n return new Tensor({\n location: 'texture',\n texture: tensor.texture,\n type: tensor.type as TextureConstructorParameters['type'],\n dims,\n });\n case 'gpu-buffer':\n return new Tensor({\n location: 'gpu-buffer',\n gpuBuffer: tensor.gpuBuffer,\n type: tensor.type as GpuBufferConstructorParameters['type'],\n dims,\n });\n case 'ml-tensor':\n return new Tensor({\n location: 'ml-tensor',\n mlTensor: tensor.mlTensor,\n type: tensor.type as MLTensorConstructorParameters['type'],\n dims,\n });\n default:\n throw new Error(`tensorReshape: tensor location ${tensor.location} is not supported`);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { tensorToDataURL, tensorToImageData } from './tensor-conversion-impl.js';\nimport { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js';\nimport {\n tensorFromGpuBuffer,\n tensorFromImage,\n tensorFromMLTensor,\n tensorFromPinnedBuffer,\n tensorFromTexture,\n} from './tensor-factory-impl.js';\nimport {\n CpuPinnedConstructorParameters,\n GpuBufferConstructorParameters,\n MLTensorConstructorParameters,\n TensorFromGpuBufferOptions,\n TensorFromImageBitmapOptions,\n TensorFromImageDataOptions,\n TensorFromImageElementOptions,\n TensorFromMLTensorOptions,\n TensorFromTextureOptions,\n TensorFromUrlOptions,\n TextureConstructorParameters,\n} from './tensor-factory.js';\nimport {\n checkTypedArray,\n NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP,\n NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP,\n SupportedTypedArray,\n SupportedTypedArrayConstructors,\n} from './tensor-impl-type-mapping.js';\nimport { calculateSize, tensorReshape } from './tensor-utils-impl.js';\nimport { Tensor as TensorInterface } from './tensor.js';\n\n// type aliases for those exported from Tensor interface\n\ntype TensorType = TensorInterface.Type;\ntype TensorDataType = TensorInterface.DataType;\ntype TensorDataLocation = TensorInterface.DataLocation;\ntype TensorTextureType = TensorInterface.TextureType;\ntype TensorGpuBufferType = TensorInterface.GpuBufferType;\ntype TensorMLTensorType = TensorInterface.MLTensorType;\n\n/**\n * the implementation of Tensor interface.\n *\n * @ignore\n */\nexport class Tensor implements TensorInterface {\n // #region constructors\n\n /**\n * Construct a new CPU tensor object from the given type, data and dims.\n */\n constructor(\n type: TensorType,\n data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly number[] | readonly boolean[],\n dims?: readonly number[],\n );\n /**\n * Construct a new CPU tensor object from the given data and dims. Type is inferred from data.\n */\n constructor(\n data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly boolean[],\n dims?: readonly number[],\n );\n /**\n * Construct a new tensor object from the pinned CPU data with the given type and dims.\n *\n * Tensor's location will be set to 'cpu-pinned'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: CpuPinnedConstructorParameters);\n /**\n * Construct a new tensor object from the WebGL texture with the given type and dims.\n *\n * Tensor's location will be set to 'texture'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: TextureConstructorParameters);\n /**\n * Construct a new tensor object from the WebGPU buffer with the given type and dims.\n *\n * Tensor's location will be set to 'gpu-buffer'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: GpuBufferConstructorParameters);\n\n /**\n * Construct a new tensor object from the WebNN MLTensor with the given type and dims.\n *\n * Tensor's location will be set to 'ml-tensor'.\n *\n * @param params - Specify the parameters to construct the tensor.\n */\n constructor(params: MLTensorConstructorParameters);\n\n /**\n * implementation.\n */\n constructor(\n arg0:\n | TensorType\n | TensorDataType\n | Uint8ClampedArray\n | readonly string[]\n | readonly boolean[]\n | CpuPinnedConstructorParameters\n | TextureConstructorParameters\n | GpuBufferConstructorParameters\n | MLTensorConstructorParameters,\n arg1?: TensorDataType | Uint8ClampedArray | readonly number[] | readonly string[] | readonly boolean[],\n arg2?: readonly number[],\n ) {\n // perform one-time check for BigInt/Float16Array support\n checkTypedArray();\n\n let type: TensorType;\n let dims: readonly number[];\n\n if (typeof arg0 === 'object' && 'location' in arg0) {\n //\n // constructing tensor from specific location\n //\n this.dataLocation = arg0.location;\n type = arg0.type;\n dims = arg0.dims;\n switch (arg0.location) {\n case 'cpu-pinned': {\n const expectedTypedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(type);\n if (!expectedTypedArrayConstructor) {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from pinned buffer`);\n }\n if (!(arg0.data instanceof expectedTypedArrayConstructor)) {\n throw new TypeError(`buffer should be of type ${expectedTypedArrayConstructor.name}`);\n }\n this.cpuData = arg0.data;\n break;\n }\n case 'texture': {\n if (type !== 'float32') {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from texture`);\n }\n this.gpuTextureData = arg0.texture;\n this.downloader = arg0.download;\n this.disposer = arg0.dispose;\n break;\n }\n case 'gpu-buffer': {\n if (\n type !== 'float32' &&\n type !== 'float16' &&\n type !== 'int32' &&\n type !== 'int64' &&\n type !== 'uint32' &&\n type !== 'uint8' &&\n type !== 'bool' &&\n type !== 'uint4' &&\n type !== 'int4'\n ) {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from gpu buffer`);\n }\n this.gpuBufferData = arg0.gpuBuffer;\n this.downloader = arg0.download;\n this.disposer = arg0.dispose;\n break;\n }\n case 'ml-tensor': {\n if (\n type !== 'float32' &&\n type !== 'float16' &&\n type !== 'int32' &&\n type !== 'int64' &&\n type !== 'uint32' &&\n type !== 'uint64' &&\n type !== 'int8' &&\n type !== 'uint8' &&\n type !== 'bool' &&\n type !== 'uint4' &&\n type !== 'int4'\n ) {\n throw new TypeError(`unsupported type \"${type}\" to create tensor from MLTensor`);\n }\n this.mlTensorData = arg0.mlTensor;\n this.downloader = arg0.download;\n this.disposer = arg0.dispose;\n break;\n }\n default:\n throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`);\n }\n } else {\n //\n // constructing tensor of location 'cpu'\n //\n let data: TensorDataType;\n let maybeDims: typeof arg1 | typeof arg2;\n // check whether arg0 is type or data\n if (typeof arg0 === 'string') {\n //\n // Override: constructor(type, data, ...)\n //\n type = arg0;\n maybeDims = arg2;\n if (arg0 === 'string') {\n // string tensor\n if (!Array.isArray(arg1)) {\n throw new TypeError(\"A string tensor's data must be a string array.\");\n }\n // we don't check whether every element in the array is string; this is too slow. we assume it's correct and\n // error will be populated at inference\n data = arg1;\n } else {\n // numeric tensor\n const typedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(arg0);\n if (typedArrayConstructor === undefined) {\n throw new TypeError(`Unsupported tensor type: ${arg0}.`);\n }\n if (Array.isArray(arg1)) {\n if ((arg0 === 'float16' && typedArrayConstructor === Uint16Array) || arg0 === 'uint4' || arg0 === 'int4') {\n // - 'float16':\n // When no Float16Array polyfill is used, we cannot create 'float16' tensor from number array.\n //\n // Throw error here because when user try to use number array as data,\n // e.g. new Tensor('float16', [1, 2, 3, 4], dims)), it will actually call\n // Uint16Array.from(arg1) which generates wrong data.\n //\n // - 'uint4' and 'int4':\n // Uint8Array.from(arg1) will generate wrong data for 'uint4' and 'int4' tensor.\n //\n throw new TypeError(\n `Creating a ${arg0} tensor from number array is not supported. Please use ${typedArrayConstructor.name} as data.`,\n );\n } else if (arg0 === 'uint64' || arg0 === 'int64') {\n // use 'as any' here because:\n // 1. TypeScript's check on type of 'Array.isArray()' does not work with readonly arrays.\n // see https://github.com/microsoft/TypeScript/issues/17002\n // 2. TypeScript's check on union type of '(BigInt64ArrayConstructor|BigUint64ArrayConstructor).from()'\n // does not accept parameter mapFn.\n // 3. parameters of 'SupportedTypedArrayConstructors.from()' does not match the requirement of the union\n // type.\n\n // assume 'arg1' is of type \"readonly number[]|readonly bigint[]\" here.\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = (typedArrayConstructor as any).from(arg1, BigInt);\n } else {\n // assume 'arg1' is of type \"readonly number[]\" here.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = (typedArrayConstructor as any).from(arg1);\n }\n } else if (arg1 instanceof typedArrayConstructor) {\n data = arg1;\n } else if (arg1 instanceof Uint8ClampedArray) {\n if (arg0 === 'uint8') {\n data = Uint8Array.from(arg1);\n } else {\n throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`);\n }\n } else if (arg0 === 'float16' && arg1 instanceof Uint16Array && typedArrayConstructor !== Uint16Array) {\n // when Float16Array is available and data is of type Uint16Array.\n // We allow Uint16Array to be passed in as data for 'float16' tensor until Float16Array is generally\n // supported in JavaScript environment.\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = new (globalThis as any).Float16Array(arg1.buffer, arg1.byteOffset, arg1.length);\n } else {\n throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`);\n }\n }\n } else {\n //\n // Override: constructor(data, ...)\n //\n maybeDims = arg1;\n if (Array.isArray(arg0)) {\n // only boolean[] and string[] is supported\n if (arg0.length === 0) {\n throw new TypeError('Tensor type cannot be inferred from an empty array.');\n }\n const firstElementType = typeof arg0[0];\n if (firstElementType === 'string') {\n type = 'string';\n data = arg0;\n } else if (firstElementType === 'boolean') {\n type = 'bool';\n // 'arg0' is of type 'boolean[]'. Uint8Array.from(boolean[]) actually works, but typescript thinks this is\n // wrong type. We use 'as any' to make it happy.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data = Uint8Array.from(arg0 as any[]);\n } else {\n throw new TypeError(`Invalid element type of data array: ${firstElementType}.`);\n }\n } else if (arg0 instanceof Uint8ClampedArray) {\n type = 'uint8';\n data = Uint8Array.from(arg0);\n } else {\n // get tensor type from TypedArray\n const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get(\n arg0.constructor as SupportedTypedArrayConstructors,\n );\n if (mappedType === undefined) {\n throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`);\n }\n type = mappedType;\n data = arg0 as SupportedTypedArray;\n }\n }\n\n // type and data is processed, now processing dims\n if (maybeDims === undefined) {\n // assume 1-D tensor if dims omitted\n maybeDims = [data.length];\n } else if (!Array.isArray(maybeDims)) {\n throw new TypeError(\"A tensor's dims must be a number array\");\n }\n dims = maybeDims as readonly number[];\n\n this.cpuData = data;\n this.dataLocation = 'cpu';\n }\n\n // perform check on dims\n const size = calculateSize(dims);\n // if data is on CPU, check whether data length matches tensor size\n if (this.cpuData && size !== this.cpuData.length) {\n if ((type === 'uint4' || type === 'int4') && Math.ceil(size / 2) === this.cpuData.length) {\n // for (u)int4, the data length is half of the tensor size. So we check this special case when size is odd.\n } else {\n throw new Error(`Tensor's size(${size}) does not match data length(${this.cpuData.length}).`);\n }\n }\n\n this.type = type;\n this.dims = dims;\n this.size = size;\n }\n // #endregion\n\n // #region factory\n static async fromImage(\n image: ImageData | HTMLImageElement | ImageBitmap | string,\n options?:\n | TensorFromImageDataOptions\n | TensorFromImageElementOptions\n | TensorFromImageBitmapOptions\n | TensorFromUrlOptions,\n ): Promise<TensorInterface> {\n return tensorFromImage(image, options);\n }\n\n static fromTexture<T extends TensorInterface.TextureDataTypes>(\n texture: TensorTextureType,\n options: TensorFromTextureOptions<T>,\n ): TensorInterface {\n return tensorFromTexture(texture, options);\n }\n\n static fromGpuBuffer<T extends TensorInterface.GpuBufferDataTypes>(\n gpuBuffer: TensorGpuBufferType,\n options: TensorFromGpuBufferOptions<T>,\n ): TensorInterface {\n return tensorFromGpuBuffer(gpuBuffer, options);\n }\n\n static fromMLTensor<T extends TensorInterface.MLTensorDataTypes>(\n mlTensor: TensorMLTensorType,\n options: TensorFromMLTensorOptions<T>,\n ): TensorInterface {\n return tensorFromMLTensor(mlTensor, options);\n }\n\n static fromPinnedBuffer<T extends TensorInterface.CpuPinnedDataTypes>(\n type: T,\n buffer: TensorInterface.DataTypeMap[T],\n dims?: readonly number[],\n ): Tensor {\n return tensorFromPinnedBuffer(type, buffer, dims);\n }\n\n // #endregion\n\n // #region conversions\n toDataURL(options?: TensorToDataUrlOptions): string {\n return tensorToDataURL(this, options);\n }\n\n toImageData(options?: TensorToImageDataOptions): ImageData {\n return tensorToImageData(this, options);\n }\n // #endregion\n\n // #region public fields\n readonly dims: readonly number[];\n readonly type: TensorType;\n readonly size: number;\n // #endregion\n\n // #region private fields\n\n /**\n * stores the location of the data.\n */\n private dataLocation: TensorDataLocation;\n\n /**\n * stores the data on CPU, if location is 'cpu' or 'cpu-pinned'. otherwise empty.\n */\n private cpuData?: TensorDataType;\n\n /**\n * stores the underlying texture when location is 'texture'. otherwise empty.\n */\n private gpuTextureData?: TensorTextureType;\n\n /**\n * stores the underlying GPU buffer when location is 'gpu-buffer'. otherwise empty.\n */\n private gpuBufferData?: TensorGpuBufferType;\n\n /**\n * stores the underlying WebNN MLTensor when location is 'ml-tensor'. otherwise empty.\n */\n private mlTensorData?: TensorMLTensorType;\n\n /**\n * stores an optional downloader function to download data from GPU to CPU.\n */\n private downloader?(): Promise<TensorDataType>;\n\n /**\n * a flag indicating whether the data is being downloaded from GPU to CPU.\n */\n private isDownloading?: boolean;\n\n /**\n * stores an optional disposer function to dispose the underlying data.\n */\n private disposer?(): void;\n // #endregion\n\n // #region properties\n get data(): TensorDataType {\n this.ensureValid();\n if (!this.cpuData) {\n throw new Error(\n 'The data is not on CPU. Use `getData()` to download GPU data to CPU, ' +\n 'or use `texture` or `gpuBuffer` property to access the GPU data directly.',\n );\n }\n return this.cpuData;\n }\n\n get location(): TensorDataLocation {\n return this.dataLocation;\n }\n\n get texture(): TensorTextureType {\n this.ensureValid();\n if (!this.gpuTextureData) {\n throw new Error('The data is not stored as a WebGL texture.');\n }\n return this.gpuTextureData;\n }\n\n get gpuBuffer(): TensorGpuBufferType {\n this.ensureValid();\n if (!this.gpuBufferData) {\n throw new Error('The data is not stored as a WebGPU buffer.');\n }\n return this.gpuBufferData;\n }\n\n get mlTensor(): TensorMLTensorType {\n this.ensureValid();\n if (!this.mlTensorData) {\n throw new Error('The data is not stored as a WebNN MLTensor.');\n }\n return this.mlTensorData;\n }\n // #endregion\n\n // #region methods\n\n async getData(releaseData?: boolean): Promise<TensorDataType> {\n this.ensureValid();\n switch (this.dataLocation) {\n case 'cpu':\n case 'cpu-pinned':\n return this.data;\n case 'texture':\n case 'gpu-buffer':\n case 'ml-tensor': {\n if (!this.downloader) {\n throw new Error('The current tensor is not created with a specified data downloader.');\n }\n if (this.isDownloading) {\n throw new Error('The current tensor is being downloaded.');\n }\n try {\n this.isDownloading = true;\n const data = await this.downloader();\n this.downloader = undefined;\n this.dataLocation = 'cpu';\n this.cpuData = data;\n\n if (releaseData && this.disposer) {\n this.disposer();\n this.disposer = undefined;\n }\n\n return data;\n } finally {\n this.isDownloading = false;\n }\n }\n default:\n throw new Error(`cannot get data from location: ${this.dataLocation}`);\n }\n }\n\n dispose(): void {\n if (this.isDownloading) {\n throw new Error('The current tensor is being downloaded.');\n }\n\n if (this.disposer) {\n this.disposer();\n this.disposer = undefined;\n }\n this.cpuData = undefined;\n this.gpuTextureData = undefined;\n this.gpuBufferData = undefined;\n this.mlTensorData = undefined;\n this.downloader = undefined;\n this.isDownloading = undefined;\n\n this.dataLocation = 'none';\n }\n\n // #endregion\n\n // #region tensor utilities\n private ensureValid(): void {\n if (this.dataLocation === 'none') {\n throw new Error('The tensor is disposed.');\n }\n }\n\n reshape(dims: readonly number[]): TensorInterface {\n this.ensureValid();\n if (this.downloader || this.disposer) {\n throw new Error('Cannot reshape a tensor that owns GPU resource.');\n }\n return tensorReshape(this, dims);\n }\n // #endregion\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { TensorFactory } from './tensor-factory.js';\nimport { Tensor as TensorImpl } from './tensor-impl.js';\nimport { TypedTensorUtils } from './tensor-utils.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\n/* eslint-disable @typescript-eslint/no-redeclare */\n\n/**\n * represent a basic tensor with specified dimensions and data type.\n */\ninterface TypedTensorBase<T extends Tensor.Type> {\n /**\n * Get the dimensions of the tensor.\n */\n readonly dims: readonly number[];\n /**\n * Get the data type of the tensor.\n */\n readonly type: T;\n /**\n * Get the buffer data of the tensor.\n *\n * If the data is not on CPU (eg. it's in the form of WebGL texture or WebGPU buffer), throw error.\n */\n readonly data: Tensor.DataTypeMap[T];\n /**\n * Get the location of the data.\n */\n readonly location: Tensor.DataLocation;\n /**\n * Get the WebGL texture that holds the tensor data.\n *\n * If the data is not on GPU as WebGL texture, throw error.\n */\n readonly texture: Tensor.TextureType;\n /**\n * Get the WebGPU buffer that holds the tensor data.\n *\n * If the data is not on GPU as WebGPU buffer, throw error.\n */\n readonly gpuBuffer: Tensor.GpuBufferType;\n\n /**\n * Get the WebNN MLTensor that holds the tensor data.\n *\n * If the data is not in a WebNN MLTensor, throw error.\n */\n readonly mlTensor: Tensor.MLTensorType;\n\n /**\n * Get the buffer data of the tensor.\n *\n * If the data is on CPU, returns the data immediately.\n * If the data is on GPU, downloads the data and returns the promise.\n *\n * @param releaseData - whether release the data on GPU. Ignore if data is already on CPU.\n */\n getData(releaseData?: boolean): Promise<Tensor.DataTypeMap[T]>;\n\n /**\n * Dispose the tensor data.\n *\n * If the data is on CPU, remove its internal reference to the underlying data.\n * If the data is on GPU, release the data on GPU.\n *\n * After calling this function, the tensor is considered no longer valid. Its location will be set to 'none'.\n */\n dispose(): void;\n}\n\nexport declare namespace Tensor {\n interface DataTypeMap {\n float32: Float32Array;\n uint8: Uint8Array;\n int8: Int8Array;\n uint16: Uint16Array;\n int16: Int16Array;\n int32: Int32Array;\n int64: BigInt64Array;\n string: string[];\n bool: Uint8Array;\n float16: Uint16Array; // Keep using Uint16Array until we have a concrete solution for float 16.\n float64: Float64Array;\n uint32: Uint32Array;\n uint64: BigUint64Array;\n // complex64: never;\n // complex128: never;\n // bfloat16: never;\n uint4: Uint8Array;\n int4: Int8Array;\n }\n\n interface ElementTypeMap {\n float32: number;\n uint8: number;\n int8: number;\n uint16: number;\n int16: number;\n int32: number;\n int64: bigint;\n string: string;\n bool: boolean;\n float16: number; // Keep using Uint16Array until we have a concrete solution for float 16.\n float64: number;\n uint32: number;\n uint64: bigint;\n // complex64: never;\n // complex128: never;\n // bfloat16: never;\n uint4: number;\n int4: number;\n }\n\n type DataType = DataTypeMap[Type];\n type ElementType = ElementTypeMap[Type];\n\n /**\n * supported data types for constructing a tensor from a pinned CPU buffer\n */\n export type CpuPinnedDataTypes = Exclude<Tensor.Type, 'string'>;\n\n /**\n * type alias for WebGL texture\n */\n export type TextureType = WebGLTexture;\n\n /**\n * supported data types for constructing a tensor from a WebGL texture\n */\n export type TextureDataTypes = 'float32';\n\n type GpuBufferTypeFallback = { size: number; mapState: 'unmapped' | 'pending' | 'mapped' };\n /**\n * type alias for WebGPU buffer\n */\n export type GpuBufferType = TryGetGlobalType<'GPUBuffer', GpuBufferTypeFallback>;\n\n type MLTensorTypeFallback = { destroy(): void };\n /**\n * type alias for WebNN MLTensor\n *\n * The specification for WebNN's MLTensor is currently in flux.\n */\n export type MLTensorType = TryGetGlobalType<'MLTensor', MLTensorTypeFallback>;\n\n /**\n * supported data types for constructing a tensor from a WebGPU buffer\n */\n export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'bool';\n\n /**\n * supported data types for constructing a tensor from a WebNN MLTensor\n */\n export type MLTensorDataTypes =\n | 'float32'\n | 'float16'\n | 'int8'\n | 'uint8'\n | 'int32'\n | 'uint32'\n | 'int64'\n | 'uint64'\n | 'bool'\n | 'uint4'\n | 'int4';\n\n /**\n * represent where the tensor data is stored\n */\n export type DataLocation = 'none' | 'cpu' | 'cpu-pinned' | 'texture' | 'gpu-buffer' | 'ml-tensor';\n\n /**\n * represent the data type of a tensor\n */\n export type Type = keyof DataTypeMap;\n}\n\n/**\n * Represent multi-dimensional arrays to feed to or fetch from model inferencing.\n */\nexport interface TypedTensor<T extends Tensor.Type> extends TypedTensorBase<T>, TypedTensorUtils<T> {}\n/**\n * Represent multi-dimensional arrays to feed to or fetch from model inferencing.\n */\nexport interface Tensor extends TypedTensorBase<Tensor.Type>, TypedTensorUtils<Tensor.Type> {}\n\n/**\n * type TensorConstructor defines the constructors of 'Tensor' to create CPU tensor instances.\n */\nexport interface TensorConstructor extends TensorFactory {\n // #region CPU tensor - specify element type\n /**\n * Construct a new string tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (\n type: 'string',\n data: Tensor.DataTypeMap['string'] | readonly string[],\n dims?: readonly number[],\n ): TypedTensor<'string'>;\n\n /**\n * Construct a new bool tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (\n type: 'bool',\n data: Tensor.DataTypeMap['bool'] | readonly boolean[],\n dims?: readonly number[],\n ): TypedTensor<'bool'>;\n\n /**\n * Construct a new uint8 tensor object from a Uint8ClampedArray, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n /**\n * Construct a new 64-bit integer typed tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new <T extends 'uint64' | 'int64'>(\n type: T,\n data: Tensor.DataTypeMap[T] | readonly bigint[] | readonly number[],\n dims?: readonly number[],\n ): TypedTensor<T>;\n\n /**\n * Construct a new numeric tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new <T extends Exclude<Tensor.Type, 'string' | 'bool' | 'uint64' | 'int64'>>(\n type: T,\n data: Tensor.DataTypeMap[T] | readonly number[],\n dims?: readonly number[],\n ): TypedTensor<T>;\n // #endregion\n\n // #region CPU tensor - infer element types\n\n /**\n * Construct a new float32 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Float32Array, dims?: readonly number[]): TypedTensor<'float32'>;\n\n /**\n * Construct a new int8 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Int8Array, dims?: readonly number[]): TypedTensor<'int8'>;\n\n /**\n * Construct a new uint8 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n /**\n * Construct a new uint8 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n /**\n * Construct a new uint16 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint16Array, dims?: readonly number[]): TypedTensor<'uint16'>;\n\n /**\n * Construct a new int16 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Int16Array, dims?: readonly number[]): TypedTensor<'int16'>;\n\n /**\n * Construct a new int32 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Int32Array, dims?: readonly number[]): TypedTensor<'int32'>;\n\n /**\n * Construct a new int64 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: BigInt64Array, dims?: readonly number[]): TypedTensor<'int64'>;\n\n /**\n * Construct a new string tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: readonly string[], dims?: readonly number[]): TypedTensor<'string'>;\n\n /**\n * Construct a new bool tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>;\n\n /**\n * Construct a new float64 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Float64Array, dims?: readonly number[]): TypedTensor<'float64'>;\n\n /**\n * Construct a new uint32 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Uint32Array, dims?: readonly number[]): TypedTensor<'uint32'>;\n\n /**\n * Construct a new uint64 tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: BigUint64Array, dims?: readonly number[]): TypedTensor<'uint64'>;\n\n // #endregion\n\n // #region CPU tensor - fall back to non-generic tensor type declaration\n\n /**\n * Construct a new tensor object from the given type, data and dims.\n *\n * @param type - Specify the element type.\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (\n type: Tensor.Type,\n data: Tensor.DataType | readonly number[] | readonly string[] | readonly bigint[] | readonly boolean[],\n dims?: readonly number[],\n ): Tensor;\n\n /**\n * Construct a new tensor object from the given data and dims.\n *\n * @param data - Specify the CPU tensor data.\n * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n */\n new (data: Tensor.DataType, dims?: readonly number[]): Tensor;\n // #endregion\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const Tensor = TensorImpl as TensorConstructor;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env } from './env-impl.js';\n\n/**\n * @ignore\n */\nexport const TRACE = (deviceType: string, label: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n // eslint-disable-next-line no-console\n console.timeStamp(`${deviceType}::ORT::${label}`);\n};\n\nconst TRACE_FUNC = (msg: string, extraMsg?: string) => {\n const stack = new Error().stack?.split(/\\r\\n|\\r|\\n/g) || [];\n let hasTraceFunc = false;\n for (let i = 0; i < stack.length; i++) {\n if (hasTraceFunc && !stack[i].includes('TRACE_FUNC')) {\n let label = `FUNC_${msg}::${stack[i].trim().split(' ')[1]}`;\n if (extraMsg) {\n label += `::${extraMsg}`;\n }\n TRACE('CPU', label);\n return;\n }\n if (stack[i].includes('TRACE_FUNC')) {\n hasTraceFunc = true;\n }\n }\n};\n\n/**\n * @ignore\n */\nexport const TRACE_FUNC_BEGIN = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n TRACE_FUNC('BEGIN', extraMsg);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_FUNC_END = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n TRACE_FUNC('END', extraMsg);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_EVENT_BEGIN = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n // eslint-disable-next-line no-console\n console.time(`ORT::${extraMsg}`);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_EVENT_END = (extraMsg?: string) => {\n if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n return;\n }\n // eslint-disable-next-line no-console\n console.timeEnd(`ORT::${extraMsg}`);\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { resolveBackendAndExecutionProviders } from './backend-impl.js';\nimport { InferenceSessionHandler } from './backend.js';\nimport { InferenceSession as InferenceSessionInterface } from './inference-session.js';\nimport { OnnxValue } from './onnx-value.js';\nimport { Tensor } from './tensor.js';\nimport { TRACE_FUNC_BEGIN, TRACE_FUNC_END, TRACE_EVENT_BEGIN, TRACE_EVENT_END } from './trace.js';\n\ntype SessionOptions = InferenceSessionInterface.SessionOptions;\ntype RunOptions = InferenceSessionInterface.RunOptions;\ntype FeedsType = InferenceSessionInterface.FeedsType;\ntype FetchesType = InferenceSessionInterface.FetchesType;\ntype ReturnType = InferenceSessionInterface.ReturnType;\n\nexport class InferenceSession implements InferenceSessionInterface {\n private constructor(handler: InferenceSessionHandler) {\n this.handler = handler;\n }\n run(feeds: FeedsType, options?: RunOptions): Promise<ReturnType>;\n run(feeds: FeedsType, fetches: FetchesType, options?: RunOptions): Promise<ReturnType>;\n async run(feeds: FeedsType, arg1?: FetchesType | RunOptions, arg2?: RunOptions): Promise<ReturnType> {\n TRACE_FUNC_BEGIN();\n TRACE_EVENT_BEGIN('InferenceSession.run');\n const fetches: { [name: string]: OnnxValue | null } = {};\n let options: RunOptions = {};\n // check inputs\n if (typeof feeds !== 'object' || feeds === null || feeds instanceof Tensor || Array.isArray(feeds)) {\n throw new TypeError(\n \"'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.\",\n );\n }\n\n let isFetchesEmpty = true;\n // determine which override is being used\n if (typeof arg1 === 'object') {\n if (arg1 === null) {\n throw new TypeError('Unexpected argument[1]: cannot be null.');\n }\n if (arg1 instanceof Tensor) {\n throw new TypeError(\"'fetches' cannot be a Tensor\");\n }\n\n if (Array.isArray(arg1)) {\n if (arg1.length === 0) {\n throw new TypeError(\"'fetches' cannot be an empty array.\");\n }\n isFetchesEmpty = false;\n // output names\n for (const name of arg1) {\n if (typeof name !== 'string') {\n throw new TypeError(\"'fetches' must be a string array or an object.\");\n }\n if (this.outputNames.indexOf(name) === -1) {\n throw new RangeError(`'fetches' contains invalid output name: ${name}.`);\n }\n fetches[name] = null;\n }\n\n if (typeof arg2 === 'object' && arg2 !== null) {\n options = arg2;\n } else if (typeof arg2 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else {\n // decide whether arg1 is fetches or options\n // if any output name is present and its value is valid OnnxValue, we consider it fetches\n let isFetches = false;\n const arg1Keys = Object.getOwnPropertyNames(arg1);\n for (const name of this.outputNames) {\n if (arg1Keys.indexOf(name) !== -1) {\n const v = (arg1 as InferenceSessionInterface.NullableOnnxValueMapType)[name];\n if (v === null || v instanceof Tensor) {\n isFetches = true;\n isFetchesEmpty = false;\n fetches[name] = v;\n }\n }\n }\n\n if (isFetches) {\n if (typeof arg2 === 'object' && arg2 !== null) {\n options = arg2;\n } else if (typeof arg2 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else {\n options = arg1 as RunOptions;\n }\n }\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"Unexpected argument[1]: must be 'fetches' or 'options'.\");\n }\n\n // check if all inputs are in feed\n for (const name of this.inputNames) {\n if (typeof feeds[name] === 'undefined') {\n throw new Error(`input '${name}' is missing in 'feeds'.`);\n }\n }\n\n // if no fetches is specified, we use the full output names list\n if (isFetchesEmpty) {\n for (const name of this.outputNames) {\n fetches[name] = null;\n }\n }\n\n // feeds, fetches and options are prepared\n\n const results = await this.handler.run(feeds, fetches, options);\n const returnValue: { [name: string]: OnnxValue } = {};\n for (const key in results) {\n if (Object.hasOwnProperty.call(results, key)) {\n const result = results[key];\n if (result instanceof Tensor) {\n returnValue[key] = result;\n } else {\n returnValue[key] = new Tensor(result.type, result.data, result.dims);\n }\n }\n }\n TRACE_EVENT_END('InferenceSession.run');\n TRACE_FUNC_END();\n return returnValue;\n }\n\n async release(): Promise<void> {\n return this.handler.dispose();\n }\n\n static create(path: string, options?: SessionOptions): Promise<InferenceSessionInterface>;\n static create(buffer: ArrayBufferLike, options?: SessionOptions): Promise<InferenceSessionInterface>;\n static create(\n buffer: ArrayBufferLike,\n byteOffset: number,\n byteLength?: number,\n options?: SessionOptions,\n ): Promise<InferenceSessionInterface>;\n static create(buffer: Uint8Array, options?: SessionOptions): Promise<InferenceSessionInterface>;\n static async create(\n arg0: string | ArrayBufferLike | Uint8Array,\n arg1?: SessionOptions | number,\n arg2?: number,\n arg3?: SessionOptions,\n ): Promise<InferenceSessionInterface> {\n TRACE_FUNC_BEGIN();\n TRACE_EVENT_BEGIN('InferenceSession.create');\n // either load from a file or buffer\n let filePathOrUint8Array: string | Uint8Array;\n let options: SessionOptions = {};\n\n if (typeof arg0 === 'string') {\n filePathOrUint8Array = arg0;\n if (typeof arg1 === 'object' && arg1 !== null) {\n options = arg1;\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else if (arg0 instanceof Uint8Array) {\n filePathOrUint8Array = arg0;\n if (typeof arg1 === 'object' && arg1 !== null) {\n options = arg1;\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else if (\n arg0 instanceof ArrayBuffer ||\n (typeof SharedArrayBuffer !== 'undefined' && arg0 instanceof SharedArrayBuffer)\n ) {\n const buffer = arg0;\n let byteOffset = 0;\n let byteLength = arg0.byteLength;\n if (typeof arg1 === 'object' && arg1 !== null) {\n options = arg1;\n } else if (typeof arg1 === 'number') {\n byteOffset = arg1;\n if (!Number.isSafeInteger(byteOffset)) {\n throw new RangeError(\"'byteOffset' must be an integer.\");\n }\n if (byteOffset < 0 || byteOffset >= buffer.byteLength) {\n throw new RangeError(`'byteOffset' is out of range [0, ${buffer.byteLength}).`);\n }\n byteLength = arg0.byteLength - byteOffset;\n if (typeof arg2 === 'number') {\n byteLength = arg2;\n if (!Number.isSafeInteger(byteLength)) {\n throw new RangeError(\"'byteLength' must be an integer.\");\n }\n if (byteLength <= 0 || byteOffset + byteLength > buffer.byteLength) {\n throw new RangeError(`'byteLength' is out of range (0, ${buffer.byteLength - byteOffset}].`);\n }\n if (typeof arg3 === 'object' && arg3 !== null) {\n options = arg3;\n } else if (typeof arg3 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n } else if (typeof arg2 !== 'undefined') {\n throw new TypeError(\"'byteLength' must be a number.\");\n }\n } else if (typeof arg1 !== 'undefined') {\n throw new TypeError(\"'options' must be an object.\");\n }\n filePathOrUint8Array = new Uint8Array(buffer, byteOffset, byteLength);\n } else {\n throw new TypeError(\"Unexpected argument[0]: must be 'path' or 'buffer'.\");\n }\n\n // resolve backend, update session options with validated EPs, and create session handler\n const [backend, optionsWithValidatedEPs] = await resolveBackendAndExecutionProviders(options);\n const handler = await backend.createInferenceSessionHandler(filePathOrUint8Array, optionsWithValidatedEPs);\n TRACE_EVENT_END('InferenceSession.create');\n TRACE_FUNC_END();\n return new InferenceSession(handler);\n }\n\n startProfiling(): void {\n this.handler.startProfiling();\n }\n endProfiling(): void {\n this.handler.endProfiling();\n }\n\n get inputNames(): readonly string[] {\n return this.handler.inputNames;\n }\n get outputNames(): readonly string[] {\n return this.handler.outputNames;\n }\n\n get inputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] {\n return this.handler.inputMetadata;\n }\n\n get outputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] {\n return this.handler.outputMetadata;\n }\n\n private handler: InferenceSessionHandler;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession as InferenceSessionImpl } from './inference-session-impl.js';\nimport { OnnxModelOptions } from './onnx-model.js';\nimport { OnnxValue, OnnxValueDataLocation } from './onnx-value.js';\nimport type { Tensor } from './tensor.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\n/* eslint-disable @typescript-eslint/no-redeclare */\n\nexport declare namespace InferenceSession {\n // #region input/output types\n\n type OnnxValueMapType = { readonly [name: string]: OnnxValue };\n type NullableOnnxValueMapType = { readonly [name: string]: OnnxValue | null };\n\n /**\n * A feeds (model inputs) is an object that uses input names as keys and OnnxValue as corresponding values.\n */\n type FeedsType = OnnxValueMapType;\n\n /**\n * A fetches (model outputs) could be one of the following:\n *\n * - Omitted. Use model's output names definition.\n * - An array of string indicating the output names.\n * - An object that use output names as keys and OnnxValue or null as corresponding values.\n *\n * @remark\n * different from input argument, in output, OnnxValue is optional. If an OnnxValue is present it will be\n * used as a pre-allocated value by the inference engine; if omitted, inference engine will allocate buffer\n * internally.\n */\n type FetchesType = readonly string[] | NullableOnnxValueMapType;\n\n /**\n * A inferencing return type is an object that uses output names as keys and OnnxValue as corresponding values.\n */\n type ReturnType = OnnxValueMapType;\n\n // #endregion\n\n // #region session options\n\n /**\n * A set of configurations for session behavior.\n */\n export interface SessionOptions extends OnnxModelOptions {\n /**\n * An array of execution provider options.\n *\n * An execution provider option can be a string indicating the name of the execution provider,\n * or an object of corresponding type.\n */\n executionProviders?: readonly ExecutionProviderConfig[];\n\n /**\n * The intra OP threads number.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native).\n */\n intraOpNumThreads?: number;\n\n /**\n * The inter OP threads number.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native).\n */\n interOpNumThreads?: number;\n\n /**\n * The free dimension override.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n freeDimensionOverrides?: { readonly [dimensionName: string]: number };\n\n /**\n * The optimization level.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n graphOptimizationLevel?: 'disabled' | 'basic' | 'extended' | 'layout' | 'all';\n\n /**\n * Whether enable CPU memory arena.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n enableCpuMemArena?: boolean;\n\n /**\n * Whether enable memory pattern.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n enableMemPattern?: boolean;\n\n /**\n * Execution mode.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n executionMode?: 'sequential' | 'parallel';\n\n /**\n * Optimized model file path.\n *\n * If this setting is specified, the optimized model will be dumped. In browser, a blob will be created\n * with a pop-up window.\n */\n optimizedModelFilePath?: string;\n\n /**\n * Whether enable profiling.\n *\n * This setting is a placeholder for a future use.\n */\n enableProfiling?: boolean;\n\n /**\n * File prefix for profiling.\n *\n * This setting is a placeholder for a future use.\n */\n profileFilePrefix?: string;\n\n /**\n * Log ID.\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n logId?: string;\n\n /**\n * Log severity level. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/logging/severity.h\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n logSeverityLevel?: 0 | 1 | 2 | 3 | 4;\n\n /**\n * Log verbosity level.\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n */\n logVerbosityLevel?: number;\n\n /**\n * Specify string as a preferred data location for all outputs, or an object that use output names as keys and a\n * preferred data location as corresponding values.\n *\n * This setting is available only in ONNXRuntime Web for WebGL and WebGPU EP.\n */\n preferredOutputLocation?: OnnxValueDataLocation | { readonly [outputName: string]: OnnxValueDataLocation };\n\n /**\n * Whether enable graph capture.\n * This setting is available only in ONNXRuntime Web for WebGPU EP.\n */\n enableGraphCapture?: boolean;\n\n /**\n * Store configurations for a session. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/session/\n * onnxruntime_session_options_config_keys.h\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n *\n * @example\n * ```js\n * extra: {\n * session: {\n * set_denormal_as_zero: \"1\",\n * disable_prepacking: \"1\"\n * },\n * optimization: {\n * enable_gelu_approximation: \"1\"\n * }\n * }\n * ```\n */\n extra?: Record<string, unknown>;\n }\n\n // #region execution providers\n\n // Currently, we have the following backends to support execution providers:\n // Backend Node.js binding: supports 'cpu', 'dml' (win32), 'coreml' (macOS) and 'cuda' (linux).\n // Backend WebAssembly: supports 'cpu', 'wasm', 'webgpu' and 'webnn'.\n // Backend ONNX.js: supports 'webgl'.\n // Backend React Native: supports 'cpu', 'xnnpack', 'coreml' (iOS), 'nnapi' (Android).\n interface ExecutionProviderOptionMap {\n coreml: CoreMLExecutionProviderOption;\n cpu: CpuExecutionProviderOption;\n cuda: CudaExecutionProviderOption;\n dml: DmlExecutionProviderOption;\n nnapi: NnapiExecutionProviderOption;\n tensorrt: TensorRtExecutionProviderOption;\n wasm: WebAssemblyExecutionProviderOption;\n webgl: WebGLExecutionProviderOption;\n webgpu: WebGpuExecutionProviderOption;\n webnn: WebNNExecutionProviderOption;\n qnn: QnnExecutionProviderOption;\n xnnpack: XnnpackExecutionProviderOption;\n }\n\n type ExecutionProviderName = keyof ExecutionProviderOptionMap;\n type ExecutionProviderConfig =\n | ExecutionProviderOptionMap[ExecutionProviderName]\n | ExecutionProviderOption\n | ExecutionProviderName\n | string;\n\n export interface ExecutionProviderOption {\n readonly name: string;\n }\n export interface CpuExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'cpu';\n useArena?: boolean;\n }\n export interface CudaExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'cuda';\n deviceId?: number;\n }\n export interface DmlExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'dml';\n deviceId?: number;\n }\n export interface TensorRtExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'tensorrt';\n deviceId?: number;\n }\n export interface WebAssemblyExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'wasm';\n }\n export interface WebGLExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'webgl';\n // TODO: add flags\n }\n export interface XnnpackExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'xnnpack';\n }\n export interface WebGpuExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'webgpu';\n\n /**\n * Specify the preferred layout when running layout sensitive operators.\n *\n * @default 'NCHW'\n */\n preferredLayout?: 'NCHW' | 'NHWC';\n\n /**\n * Specify a list of node names that should be executed on CPU even when WebGPU EP is used.\n */\n forceCpuNodeNames?: readonly string[];\n\n /**\n * Specify the validation mode for WebGPU execution provider.\n * - 'disabled': Disable all validation.\n * When used in Node.js, disable validation may cause process crash if WebGPU errors occur. Be cautious when using\n * this mode.\n * When used in web, this mode is equivalent to 'wgpuOnly'.\n * - 'wgpuOnly': Perform WebGPU internal validation only.\n * - 'basic': Perform basic validation including WebGPU internal validation. This is the default mode.\n * - 'full': Perform full validation. This mode may have performance impact. Use it for debugging purpose.\n *\n * @default 'basic'\n */\n validationMode?: 'disabled' | 'wgpuOnly' | 'basic' | 'full';\n\n /**\n * Specify an optional WebGPU device to be used by the WebGPU execution provider.\n */\n device?: TryGetGlobalType<'GPUDevice'>;\n }\n\n // #region WebNN options\n\n interface WebNNExecutionProviderName extends ExecutionProviderOption {\n readonly name: 'webnn';\n }\n\n /**\n * Represents a set of options for creating a WebNN MLContext.\n *\n * @see https://www.w3.org/TR/webnn/#dictdef-mlcontextoptions\n */\n export interface WebNNContextOptions {\n deviceType?: 'cpu' | 'gpu' | 'npu';\n numThreads?: number;\n powerPreference?: 'default' | 'low-power' | 'high-performance';\n }\n\n /**\n * Represents a set of options for WebNN execution provider without MLContext.\n */\n export interface WebNNOptionsWithoutMLContext extends WebNNExecutionProviderName, WebNNContextOptions {\n context?: never;\n }\n\n /**\n * Represents a set of options for WebNN execution provider with MLContext.\n *\n * When MLContext is provided, the deviceType is also required so that the WebNN EP can determine the preferred\n * channel layout.\n *\n * @see https://www.w3.org/TR/webnn/#dom-ml-createcontext\n */\n export interface WebNNOptionsWithMLContext\n extends WebNNExecutionProviderName,\n Omit<WebNNContextOptions, 'deviceType'>,\n Required<Pick<WebNNContextOptions, 'deviceType'>> {\n context: TryGetGlobalType<'MLContext'>;\n }\n\n /**\n * Represents a set of options for WebNN execution provider with MLContext which is created from GPUDevice.\n *\n * @see https://www.w3.org/TR/webnn/#dom-ml-createcontext-gpudevice\n */\n export interface WebNNOptionsWebGpu extends WebNNExecutionProviderName {\n context: TryGetGlobalType<'MLContext'>;\n gpuDevice: TryGetGlobalType<'GPUDevice'>;\n }\n\n /**\n * Options for WebNN execution provider.\n */\n export type WebNNExecutionProviderOption =\n | WebNNOptionsWithoutMLContext\n | WebNNOptionsWithMLContext\n | WebNNOptionsWebGpu;\n\n // #endregion\n\n export interface QnnExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'qnn';\n /**\n * Specify the QNN backend type. E.g., 'cpu' or 'htp'.\n * Mutually exclusive with `backendPath`.\n *\n * @default 'htp'\n */\n backendType?: string;\n /**\n * Specify a path to the QNN backend library.\n * Mutually exclusive with `backendType`.\n */\n backendPath?: string;\n /**\n * Specify whether to enable HTP FP16 precision.\n *\n * @default true\n */\n enableFp16Precision?: boolean;\n }\n export interface CoreMLExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'coreml';\n /**\n * The bit flags for CoreML execution provider.\n *\n * ```\n * COREML_FLAG_USE_CPU_ONLY = 0x001\n * COREML_FLAG_ENABLE_ON_SUBGRAPH = 0x002\n * COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE = 0x004\n * COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES = 0x008\n * COREML_FLAG_CREATE_MLPROGRAM = 0x010\n * COREML_FLAG_USE_CPU_AND_GPU = 0x020\n * ```\n *\n * See include/onnxruntime/core/providers/coreml/coreml_provider_factory.h for more details.\n *\n * This flag is available only in ONNXRuntime (Node.js binding).\n */\n coreMlFlags?: number;\n /**\n * Specify whether to use CPU only in CoreML EP.\n *\n * This setting is available only in ONNXRuntime (react-native).\n */\n useCPUOnly?: boolean;\n useCPUAndGPU?: boolean;\n /**\n * Specify whether to enable CoreML EP on subgraph.\n *\n * This setting is available only in ONNXRuntime (react-native).\n */\n enableOnSubgraph?: boolean;\n /**\n * Specify whether to only enable CoreML EP for Apple devices with ANE (Apple Neural Engine).\n *\n * This setting is available only in ONNXRuntime (react-native).\n */\n onlyEnableDeviceWithANE?: boolean;\n }\n export interface NnapiExecutionProviderOption extends ExecutionProviderOption {\n readonly name: 'nnapi';\n useFP16?: boolean;\n useNCHW?: boolean;\n cpuDisabled?: boolean;\n cpuOnly?: boolean;\n }\n // #endregion\n\n // #endregion\n\n // #region run options\n\n /**\n * A set of configurations for inference run behavior\n */\n export interface RunOptions {\n /**\n * Log severity level. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/logging/severity.h\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n logSeverityLevel?: 0 | 1 | 2 | 3 | 4;\n\n /**\n * Log verbosity level.\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n */\n logVerbosityLevel?: number;\n\n /**\n * Terminate all incomplete OrtRun calls as soon as possible if true\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n */\n terminate?: boolean;\n\n /**\n * A tag for the Run() calls using this\n *\n * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n */\n tag?: string;\n\n /**\n * Set a single run configuration entry. See\n * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/session/\n * onnxruntime_run_options_config_keys.h\n *\n * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n *\n * @example\n *\n * ```js\n * extra: {\n * memory: {\n * enable_memory_arena_shrinkage: \"1\",\n * }\n * }\n * ```\n */\n extra?: Record<string, unknown>;\n }\n\n // #endregion\n\n // #region value metadata\n\n /**\n * The common part of the value metadata type for both tensor and non-tensor values.\n */\n export interface ValueMetadataBase {\n /**\n * The name of the specified input or output.\n */\n readonly name: string;\n }\n\n /**\n * Represents the metadata of a non-tensor value.\n */\n export interface NonTensorValueMetadata extends ValueMetadataBase {\n /**\n * Get a value indicating whether the value is a tensor.\n */\n readonly isTensor: false;\n }\n\n /**\n * Represents the metadata of a tensor value.\n */\n export interface TensorValueMetadata extends ValueMetadataBase {\n /**\n * Get a value indicating whether the value is a tensor.\n */\n readonly isTensor: true;\n /**\n * Get the data type of the tensor.\n */\n readonly type: Tensor.Type;\n /**\n * Get the shape of the tensor.\n *\n * If the shape is not defined, the value will an empty array. Otherwise, it will be an array representing the shape\n * of the tensor. Each element in the array can be a number or a string. If the element is a number, it represents\n * the corresponding dimension size. If the element is a string, it represents a symbolic dimension.\n */\n readonly shape: ReadonlyArray<number | string>;\n }\n\n /**\n * Represents the metadata of a value.\n */\n export type ValueMetadata = NonTensorValueMetadata | TensorValueMetadata;\n\n // #endregion\n}\n\n/**\n * Represent a runtime instance of an ONNX model.\n */\nexport interface InferenceSession {\n // #region run()\n\n /**\n * Execute the model asynchronously with the given feeds and options.\n *\n * @param feeds - Representation of the model input. See type description of `InferenceSession.InputType` for detail.\n * @param options - Optional. A set of options that controls the behavior of model inference.\n * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values.\n */\n run(feeds: InferenceSession.FeedsType, options?: InferenceSession.RunOptions): Promise<InferenceSession.ReturnType>;\n\n /**\n * Execute the model asynchronously with the given feeds, fetches and options.\n *\n * @param feeds - Representation of the model input. See type description of `InferenceSession.InputType` for detail.\n * @param fetches - Representation of the model output. See type description of `InferenceSession.OutputType` for\n * detail.\n * @param options - Optional. A set of options that controls the behavior of model inference.\n * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values.\n */\n run(\n feeds: InferenceSession.FeedsType,\n fetches: InferenceSession.FetchesType,\n options?: InferenceSession.RunOptions,\n ): Promise<InferenceSession.ReturnType>;\n\n // #endregion\n\n // #region release()\n\n /**\n * Release the inference session and the underlying resources.\n */\n release(): Promise<void>;\n\n // #endregion\n\n // #region profiling\n\n /**\n * Start profiling.\n */\n startProfiling(): void;\n\n /**\n * End profiling.\n */\n endProfiling(): void;\n\n // #endregion\n\n // #region metadata\n\n /**\n * Get input names of the loaded model.\n */\n readonly inputNames: readonly string[];\n\n /**\n * Get output names of the loaded model.\n */\n readonly outputNames: readonly string[];\n\n /**\n * Get input metadata of the loaded model.\n */\n readonly inputMetadata: readonly InferenceSession.ValueMetadata[];\n\n /**\n * Get output metadata of the loaded model.\n */\n readonly outputMetadata: readonly InferenceSession.ValueMetadata[];\n\n // #endregion\n}\n\nexport interface InferenceSessionFactory {\n // #region create()\n\n /**\n * Create a new inference session and load model asynchronously from an ONNX model file.\n *\n * @param uri - The URI or file path of the model to load.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(uri: string, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n /**\n * Create a new inference session and load model asynchronously from an array bufer.\n *\n * @param buffer - An ArrayBuffer representation of an ONNX model.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(buffer: ArrayBufferLike, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n /**\n * Create a new inference session and load model asynchronously from segment of an array bufer.\n *\n * @param buffer - An ArrayBuffer representation of an ONNX model.\n * @param byteOffset - The beginning of the specified portion of the array buffer.\n * @param byteLength - The length in bytes of the array buffer.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(\n buffer: ArrayBufferLike,\n byteOffset: number,\n byteLength?: number,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSession>;\n\n /**\n * Create a new inference session and load model asynchronously from a Uint8Array.\n *\n * @param buffer - A Uint8Array representation of an ONNX model.\n * @param options - specify configuration for creating a new inference session.\n * @returns A promise that resolves to an InferenceSession object.\n */\n create(buffer: Uint8Array, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n // #endregion\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const InferenceSession: InferenceSessionFactory = InferenceSessionImpl;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { OptionsFormat, OptionsNormalizationParameters, OptionsTensorLayout } from './tensor-factory.js';\n\nexport interface TensorToDataUrlOptions extends OptionsTensorLayout, OptionsFormat, OptionsNormalizationParameters {}\n\nexport interface TensorToImageDataOptions extends OptionsTensorLayout, OptionsFormat, OptionsNormalizationParameters {}\n\nexport interface ConversionUtils {\n /**\n * creates a DataURL instance from tensor\n *\n * @param options - An optional object representing options for creating a DataURL instance from the tensor.\n *\n * The following default settings will be applied:\n * - `format`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * @returns a DataURL string representing the image converted from tensor data\n */\n toDataURL(options?: TensorToDataUrlOptions): string;\n\n /**\n * creates an ImageData instance from tensor\n *\n * @param options - An optional object representing options for creating an ImageData instance from the tensor.\n *\n * The following default settings will be applied:\n * - `format`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * @returns an ImageData instance representing the image converted from tensor data\n */\n toImageData(options?: TensorToImageDataOptions): ImageData;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor, TypedTensor } from './tensor.js';\n\nexport type ImageFormat = 'RGB' | 'RGBA' | 'BGR' | 'RBG';\nexport type ImageTensorLayout = 'NHWC' | 'NCHW';\n\n// the following region contains type definitions for constructing tensor from a specific location.\n\n// #region types for constructing a tensor from a specific location\n\n/**\n * represent common properties of the parameter for constructing a tensor from a specific location.\n */\ninterface CommonConstructorParameters<T> extends Pick<Tensor, 'dims'> {\n /**\n * Specify the data type of the tensor.\n */\n readonly type: T;\n}\n\n/**\n * represent the parameter for constructing a tensor from a GPU resource.\n */\ninterface GpuResourceConstructorParameters<T extends Tensor.Type> {\n /**\n * an optional callback function to download data from GPU to CPU.\n *\n * If not provided, the tensor treat the GPU data as external resource.\n */\n download?(): Promise<Tensor.DataTypeMap[T]>;\n\n /**\n * an optional callback function that will be called when the tensor is disposed.\n *\n * If not provided, the tensor treat the GPU data as external resource.\n */\n dispose?(): void;\n}\n\n/**\n * represent the parameter for constructing a tensor from a pinned CPU buffer\n */\nexport interface CpuPinnedConstructorParameters<T extends Tensor.CpuPinnedDataTypes = Tensor.CpuPinnedDataTypes>\n extends CommonConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'cpu-pinned'.\n */\n readonly location: 'cpu-pinned';\n /**\n * Specify the CPU pinned buffer that holds the tensor data.\n */\n readonly data: Tensor.DataTypeMap[T];\n}\n\n/**\n * represent the parameter for constructing a tensor from a WebGL texture\n */\nexport interface TextureConstructorParameters<T extends Tensor.TextureDataTypes = Tensor.TextureDataTypes>\n extends CommonConstructorParameters<T>,\n GpuResourceConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'texture'.\n */\n readonly location: 'texture';\n /**\n * Specify the WebGL texture that holds the tensor data.\n */\n readonly texture: Tensor.TextureType;\n}\n\n/**\n * represent the parameter for constructing a tensor from a WebGPU buffer\n */\nexport interface GpuBufferConstructorParameters<T extends Tensor.GpuBufferDataTypes = Tensor.GpuBufferDataTypes>\n extends CommonConstructorParameters<T>,\n GpuResourceConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'gpu-buffer'.\n */\n readonly location: 'gpu-buffer';\n /**\n * Specify the WebGPU buffer that holds the tensor data.\n */\n readonly gpuBuffer: Tensor.GpuBufferType;\n}\n\nexport interface MLTensorConstructorParameters<T extends Tensor.MLTensorDataTypes = Tensor.MLTensorDataTypes>\n extends CommonConstructorParameters<T>,\n GpuResourceConstructorParameters<T> {\n /**\n * Specify the location of the data to be 'ml-tensor'.\n */\n readonly location: 'ml-tensor';\n\n /**\n * Specify the WebNN MLTensor that holds the tensor data.\n */\n readonly mlTensor: Tensor.MLTensorType;\n}\n\n// #endregion\n\n// the following region contains type definitions of each individual options.\n// the tensor factory functions use a composition of those options as the parameter type.\n\n// #region Options fields\n\nexport interface OptionsFormat {\n /**\n * Describes the image format represented in RGBA color space.\n */\n format?: ImageFormat;\n}\n\nexport interface OptionsTensorFormat {\n /**\n * Describes the image format of the tensor.\n *\n * NOTE: this is different from option 'format'. While option 'format' represents the original image, 'tensorFormat'\n * represents the target format of the tensor. A transpose will be performed if they are different.\n */\n tensorFormat?: ImageFormat;\n}\n\nexport interface OptionsTensorDataType {\n /**\n * Describes the data type of the tensor.\n */\n dataType?: 'float32' | 'uint8';\n}\n\nexport interface OptionsTensorLayout {\n /**\n * Describes the tensor layout when representing data of one or more image(s).\n */\n tensorLayout?: ImageTensorLayout;\n}\n\nexport interface OptionsDimensions {\n /**\n * Describes the image height in pixel\n */\n height?: number;\n /**\n * Describes the image width in pixel\n */\n width?: number;\n}\n\nexport interface OptionResizedDimensions {\n /**\n * Describes the resized height. If omitted, original height will be used.\n */\n resizedHeight?: number;\n /**\n * Describes resized width - can be accessed via tensor dimensions as well\n */\n resizedWidth?: number;\n}\n\nexport interface OptionsNormalizationParameters {\n /**\n * Describes normalization parameters when preprocessing the image as model input.\n *\n * Data element are ranged from 0 to 255.\n */\n norm?: {\n /**\n * The 'bias' value for image normalization.\n * - If omitted, use default value 0.\n * - If it's a single number, apply to each channel\n * - If it's an array of 3 or 4 numbers, apply element-wise. Number of elements need to match the number of channels\n * for the corresponding image format\n */\n bias?: number | [number, number, number] | [number, number, number, number];\n /**\n * The 'mean' value for image normalization.\n * - If omitted, use default value 255.\n * - If it's a single number, apply to each channel\n * - If it's an array of 3 or 4 numbers, apply element-wise. Number of elements need to match the number of channels\n * for the corresponding image format\n */\n mean?: number | [number, number, number] | [number, number, number, number];\n };\n}\n\n// #endregion\n\n// #region Options composition\n\nexport interface TensorFromImageDataOptions\n extends OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromImageElementOptions\n extends OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromUrlOptions\n extends OptionsDimensions,\n OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromImageBitmapOptions\n extends OptionResizedDimensions,\n OptionsTensorFormat,\n OptionsTensorLayout,\n OptionsTensorDataType,\n OptionsNormalizationParameters {}\n\nexport interface TensorFromTextureOptions<T extends Tensor.TextureDataTypes>\n extends Required<OptionsDimensions>,\n OptionsFormat,\n GpuResourceConstructorParameters<T> /* TODO: add more */ {}\n\nexport interface TensorFromGpuBufferOptions<T extends Tensor.GpuBufferDataTypes>\n extends Pick<Tensor, 'dims'>,\n GpuResourceConstructorParameters<T> {\n /**\n * Describes the data type of the tensor.\n */\n dataType?: T;\n}\n\nexport interface TensorFromMLTensorOptions<T extends Tensor.MLTensorDataTypes>\n extends Pick<Tensor, 'dims'>,\n GpuResourceConstructorParameters<T> {\n /**\n * Describes the data type of the tensor.\n */\n dataType?: T;\n}\n\n// #endregion\n\n/**\n * type TensorFactory defines the factory functions of 'Tensor' to create tensor instances from existing data or\n * resources.\n */\nexport interface TensorFactory {\n /**\n * create a tensor from an ImageData object\n *\n * @param imageData - the ImageData object to create tensor from\n * @param options - An optional object representing options for creating tensor from ImageData.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(\n imageData: ImageData,\n options?: TensorFromImageDataOptions,\n ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from a HTMLImageElement object\n *\n * @param imageElement - the HTMLImageElement object to create tensor from\n * @param options - An optional object representing options for creating tensor from HTMLImageElement.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(\n imageElement: HTMLImageElement,\n options?: TensorFromImageElementOptions,\n ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from URL\n *\n * @param urlSource - a string as a URL to the image or a data URL containing the image data.\n * @param options - An optional object representing options for creating tensor from URL.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(urlSource: string, options?: TensorFromUrlOptions): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from an ImageBitmap object\n *\n * @param bitmap - the ImageBitmap object to create tensor from\n * @param options - An optional object representing options for creating tensor from URL.\n *\n * The following default settings will be applied:\n * - `tensorFormat`: `'RGB'`\n * - `tensorLayout`: `'NCHW'`\n * - `dataType`: `'float32'`\n * @returns A promise that resolves to a tensor object\n */\n fromImage(\n bitmap: ImageBitmap,\n options: TensorFromImageBitmapOptions,\n ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n /**\n * create a tensor from a WebGL texture\n *\n * @param texture - the WebGLTexture object to create tensor from\n * @param options - An optional object representing options for creating tensor from WebGL texture.\n *\n * The options include following properties:\n * - `width`: the width of the texture. Required.\n * - `height`: the height of the texture. Required.\n * - `format`: the format of the texture. If omitted, assume 'RGBA'.\n * - `download`: an optional function to download the tensor data from GPU to CPU. If omitted, the GPU data\n * will not be able to download. Usually, this is provided by a GPU backend for the inference outputs. Users don't\n * need to provide this function.\n * - `dispose`: an optional function to dispose the tensor data on GPU. If omitted, the GPU data will not be disposed.\n * Usually, this is provided by a GPU backend for the inference outputs. Users don't need to provide this function.\n *\n * @returns a tensor object\n */\n fromTexture<T extends Tensor.TextureDataTypes = 'float32'>(\n texture: Tensor.TextureType,\n options: TensorFromTextureOptions<T>,\n ): TypedTensor<'float32'>;\n\n /**\n * create a tensor from a WebGPU buffer\n *\n * @param buffer - the GPUBuffer object to create tensor from\n * @param options - An optional object representing options for creating tensor from WebGPU buffer.\n *\n * The options include following properties:\n * - `dataType`: the data type of the tensor. If omitted, assume 'float32'.\n * - `dims`: the dimension of the tensor. Required.\n * - `download`: an optional function to download the tensor data from GPU to CPU. If omitted, the GPU data\n * will not be able to download. Usually, this is provided by a GPU backend for the inference outputs. Users don't\n * need to provide this function.\n * - `dispose`: an optional function to dispose the tensor data on GPU. If omitted, the GPU data will not be disposed.\n * Usually, this is provided by a GPU backend for the inference outputs. Users don't need to provide this function.\n *\n * @returns a tensor object\n */\n fromGpuBuffer<T extends Tensor.GpuBufferDataTypes>(\n buffer: Tensor.GpuBufferType,\n options: TensorFromGpuBufferOptions<T>,\n ): TypedTensor<T>;\n\n /**\n * create a tensor from a WebNN MLTensor\n *\n * @param tensor - the MLTensor object to create tensor from\n * @param options - An optional object representing options for creating tensor from a WebNN MLTensor.\n *\n * The options include following properties:\n * - `dataType`: the data type of the tensor. If omitted, assume 'float32'.\n * - `dims`: the dimension of the tensor. Required.\n * - `download`: an optional function to download the tensor data from the MLTensor to CPU. If omitted, the MLTensor\n * data will not be able to download. Usually, this is provided by the WebNN backend for the inference outputs.\n * Users don't need to provide this function.\n * - `dispose`: an optional function to dispose the tensor data on the WebNN MLTensor. If omitted, the MLTensor will\n * not be disposed. Usually, this is provided by the WebNN backend for the inference outputs. Users don't need to\n * provide this function.\n *\n * @returns a tensor object\n */\n fromMLTensor<T extends Tensor.MLTensorDataTypes>(\n tensor: Tensor.MLTensorType,\n options: TensorFromMLTensorOptions<T>,\n ): TypedTensor<T>;\n\n /**\n * create a tensor from a pre-allocated buffer. The buffer will be used as a pinned buffer.\n *\n * @param type - the tensor element type.\n * @param buffer - a TypedArray corresponding to the type.\n * @param dims - specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n *\n * @returns a tensor object\n */\n fromPinnedBuffer<T extends Exclude<Tensor.Type, 'string'>>(\n type: T,\n buffer: Tensor.DataTypeMap[T],\n dims?: readonly number[],\n ): TypedTensor<T>;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/**\n * A string that represents a file's URL or path.\n *\n * Path is vailable only in onnxruntime-node or onnxruntime-web running in Node.js.\n */\nexport type FileUrlOrPath = string;\n\n/**\n * A Blob object that represents a file.\n */\nexport type FileBlob = Blob;\n\n/**\n * A Uint8Array, ArrayBuffer or SharedArrayBuffer object that represents a file content.\n *\n * When it is an ArrayBuffer or SharedArrayBuffer, the whole buffer is assumed to be the file content.\n */\nexport type FileData = Uint8Array | ArrayBufferLike;\n\n/**\n * Represents a file that can be loaded by the ONNX Runtime JavaScript API.\n */\nexport type FileType = FileUrlOrPath | FileBlob | FileData;\n\n/**\n * Represents an external data file.\n */\nexport interface ExternalDataFileDescription {\n /**\n * Specify the external data file.\n */\n data: FileType;\n /**\n * Specify the file path.\n */\n path: string;\n}\n\n/**\n * Represents an external data file.\n *\n * When using a string, it should be a file URL or path that in the same directory as the model file.\n */\nexport type ExternalDataFileType = ExternalDataFileDescription | FileUrlOrPath;\n\n/**\n * Options for model loading.\n */\nexport interface OnnxModelOptions {\n /**\n * Specifying a list of files that represents the external data.\n */\n externalData?: readonly ExternalDataFileType[];\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from './tensor.js';\n\nexport type NonTensorType = never;\n\n/**\n * Type OnnxValue Represents both tensors and non-tensors value for model's inputs/outputs.\n *\n * NOTE: currently not support non-tensor\n */\nexport type OnnxValue = Tensor | NonTensorType;\n\n/**\n * Type OnnxValueDataLocation represents the location of the data of an OnnxValue.\n */\nexport type OnnxValueDataLocation = Tensor.DataLocation;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/**\n * # ONNX Runtime JavaScript API\n *\n * ONNX Runtime JavaScript API is a unified API for all JavaScript usages, including the following NPM packages:\n *\n * - [onnxruntime-node](https://www.npmjs.com/package/onnxruntime-node)\n * - [onnxruntime-web](https://www.npmjs.com/package/onnxruntime-web)\n * - [onnxruntime-react-native](https://www.npmjs.com/package/onnxruntime-react-native)\n *\n * See also:\n * - [Get Started](https://onnxruntime.ai/docs/get-started/with-javascript/)\n * - [Inference examples](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js)\n *\n * @packageDocumentation\n */\n\nexport * from './backend.js';\nexport * from './env.js';\nexport * from './inference-session.js';\nexport * from './tensor.js';\nexport * from './tensor-conversion.js';\nexport * from './tensor-factory.js';\nexport * from './trace.js';\nexport * from './onnx-model.js';\nexport * from './onnx-value.js';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nexport const isNode = !!(typeof process !== 'undefined' && process.versions && process.versions.node);\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport type { OrtWasmModule } from './wasm-types';\nimport { isNode } from './wasm-utils-env';\n\n/**\n * The origin of the current location.\n *\n * In Node.js, this is undefined.\n */\nconst origin = isNode || typeof location === 'undefined' ? undefined : location.origin;\n\n/**\n * Some bundlers (eg. Webpack) will rewrite `import.meta.url` to a file URL at compile time.\n *\n * This function checks if `import.meta.url` starts with `file:`, but using the `>` and `<` operators instead of\n * `startsWith` function so that code minimizers can remove the dead code correctly.\n *\n * For example, if we use terser to minify the following code:\n * ```js\n * if (\"file://hard-coded-filename\".startsWith(\"file:\")) {\n * console.log(1)\n * } else {\n * console.log(2)\n * }\n *\n * if (\"file://hard-coded-filename\" > \"file:\" && \"file://hard-coded-filename\" < \"file;\") {\n * console.log(3)\n * } else {\n * console.log(4)\n * }\n * ```\n *\n * The minified code will be:\n * ```js\n * \"file://hard-coded-filename\".startsWith(\"file:\")?console.log(1):console.log(2),console.log(3);\n * ```\n *\n * (use Terser 5.39.0 with default options, https://try.terser.org/)\n *\n * @returns true if the import.meta.url is hardcoded as a file URI.\n */\nexport const isEsmImportMetaUrlHardcodedAsFileUri =\n BUILD_DEFS.IS_ESM && BUILD_DEFS.ESM_IMPORT_META_URL! > 'file:' && BUILD_DEFS.ESM_IMPORT_META_URL! < 'file;';\n\nconst getScriptSrc = (): string | undefined => {\n // if Nodejs, return undefined\n if (isNode) {\n return undefined;\n }\n // if It's ESM, use import.meta.url\n if (BUILD_DEFS.IS_ESM) {\n // For ESM, if the import.meta.url is a file URL, this usually means the bundler rewrites `import.meta.url` to\n // the file path at compile time. In this case, this file path cannot be used to determine the runtime URL.\n //\n // We need to use the URL constructor like this:\n // ```js\n // new URL('actual-bundle-name.js', import.meta.url).href\n // ```\n // So that bundler can preprocess the URL correctly.\n if (isEsmImportMetaUrlHardcodedAsFileUri) {\n // if the rewritten URL is a relative path, we need to use the origin to resolve the URL.\n\n // The following is a workaround for Vite.\n //\n // Vite uses a bundler(rollup/rolldown) that does not rewrite `import.meta.url` to a file URL. So in theory, this\n // code path should not be executed in Vite. However, the bundler does not know it and it still try to load the\n // following pattern:\n // - `return new URL('filename', import.meta.url).href`\n //\n // By replacing the pattern above with the following code, we can skip the resource loading behavior:\n // - `const URL2 = URL; return new URL2('filename', import.meta.url).href;`\n //\n // And it still works in Webpack.\n const URL2 = URL;\n return new URL(new URL2(BUILD_DEFS.BUNDLE_FILENAME, BUILD_DEFS.ESM_IMPORT_META_URL).href, origin).href;\n }\n\n return BUILD_DEFS.ESM_IMPORT_META_URL;\n }\n\n return typeof document !== 'undefined'\n ? (document.currentScript as HTMLScriptElement)?.src\n : // use `self.location.href` if available\n typeof self !== 'undefined'\n ? self.location?.href\n : undefined;\n};\n\n/**\n * The classic script source URL. This is not always available in non ESModule environments.\n *\n * In Node.js, this is undefined.\n */\nexport const scriptSrc = getScriptSrc();\n\n/**\n * Infer the wasm path prefix from the script source URL.\n *\n * @returns The inferred wasm path prefix, or undefined if the script source URL is not available or is a blob URL.\n */\nexport const inferWasmPathPrefixFromScriptSrc = (): string | undefined => {\n if (scriptSrc && !scriptSrc.startsWith('blob:')) {\n return scriptSrc.substring(0, scriptSrc.lastIndexOf('/') + 1);\n }\n return undefined;\n};\n\n/**\n * Check if the given filename with prefix is from the same origin.\n */\nconst isSameOrigin = (filename: string, prefixOverride?: string) => {\n try {\n const baseUrl = prefixOverride ?? scriptSrc;\n const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename);\n return url.origin === origin;\n } catch {\n return false;\n }\n};\n\n/**\n * Normalize the inputs to an absolute URL with the given prefix override. If failed, return undefined.\n */\nconst normalizeUrl = (filename: string, prefixOverride?: string) => {\n const baseUrl = prefixOverride ?? scriptSrc;\n try {\n const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename);\n return url.href;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Create a fallback URL if an absolute URL cannot be created by the normalizeUrl function.\n */\nconst fallbackUrl = (filename: string, prefixOverride?: string) => `${prefixOverride ?? './'}${filename}`;\n\n/**\n * This helper function is used to preload a module from a URL.\n *\n * If the origin of the worker URL is different from the current origin, the worker cannot be loaded directly.\n * See discussions in https://github.com/webpack-contrib/worker-loader/issues/154\n *\n * In this case, we will fetch the worker URL and create a new Blob URL with the same origin as a workaround.\n *\n * @param absoluteUrl - The absolute URL to preload.\n *\n * @returns - A promise that resolves to a new Blob URL\n */\nconst preload = async (absoluteUrl: string): Promise<string> => {\n const response = await fetch(absoluteUrl, { credentials: 'same-origin' });\n const blob = await response.blob();\n return URL.createObjectURL(blob);\n};\n\n/**\n * This helper function is used to dynamically import a module from a URL.\n *\n * The build script has special handling for this function to ensure that the URL is not bundled into the final output.\n *\n * @param url - The URL to import.\n *\n * @returns - A promise that resolves to the default export of the module.\n */\nconst dynamicImportDefault = async <T>(url: string): Promise<T> =>\n (await import(/* webpackIgnore: true */ /* @vite-ignore */ url)).default;\n\n/**\n * The proxy worker factory imported from the proxy worker module.\n *\n * This is only available when the WebAssembly proxy is not disabled.\n */\nconst createProxyWorker: ((urlOverride?: string) => Worker) | undefined =\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n BUILD_DEFS.DISABLE_WASM_PROXY ? undefined : require('./proxy-worker/main').default;\n\n/**\n * Import the proxy worker.\n *\n * This function will perform the following steps:\n * 1. If a preload is needed, it will preload the module and return the object URL.\n * 2. Use the proxy worker factory to create the proxy worker.\n *\n * @returns - A promise that resolves to a tuple of 2 elements:\n * - The object URL of the preloaded module, or undefined if no preload is needed.\n * - The proxy worker.\n */\nexport const importProxyWorker = async (): Promise<[undefined | string, Worker]> => {\n if (!scriptSrc) {\n throw new Error('Failed to load proxy worker: cannot determine the script source URL.');\n }\n\n // If the script source is from the same origin, we can use the embedded proxy module directly.\n if (isSameOrigin(scriptSrc)) {\n return [undefined, createProxyWorker!()];\n }\n\n // Otherwise, need to preload\n const url = await preload(scriptSrc);\n return [url, createProxyWorker!(url)];\n};\n\n/**\n * The embedded WebAssembly module.\n *\n * This is only available in ESM and when embedding is not disabled.\n */\nconst embeddedWasmModule: EmscriptenModuleFactory<OrtWasmModule> | undefined =\n BUILD_DEFS.IS_ESM && BUILD_DEFS.ENABLE_BUNDLE_WASM_JS\n ? // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n require(\n !BUILD_DEFS.DISABLE_JSEP\n ? '../../dist/ort-wasm-simd-threaded.jsep.mjs'\n : BUILD_DEFS.ENABLE_JSPI\n ? '../../dist/ort-wasm-simd-threaded.jspi.mjs'\n : !BUILD_DEFS.DISABLE_WEBGPU\n ? '../../dist/ort-wasm-simd-threaded.asyncify.mjs'\n : '../../dist/ort-wasm-simd-threaded.mjs',\n ).default\n : undefined;\n\n/**\n * Import the WebAssembly module.\n *\n * This function will perform the following steps:\n * 1. If the embedded module exists and no custom URL is specified, use the embedded module.\n * 2. If a preload is needed, it will preload the module and return the object URL.\n * 3. Otherwise, it will perform a dynamic import of the module.\n *\n * @returns - A promise that resolves to a tuple of 2 elements:\n * - The object URL of the preloaded module, or undefined if no preload is needed.\n * - The default export of the module, which is a factory function to create the WebAssembly module.\n */\nexport const importWasmModule = async (\n urlOverride: string | undefined,\n prefixOverride: string | undefined,\n isMultiThreaded: boolean,\n isWasmOverridden: boolean,\n): Promise<[undefined | string, EmscriptenModuleFactory<OrtWasmModule>]> => {\n //\n // Check if we should use the embedded module.\n //\n\n // To use the embedded module, it should be available, and no URL override or prefix override should be specified.\n let useEmbeddedModule = embeddedWasmModule && !(urlOverride || prefixOverride);\n if (useEmbeddedModule) {\n if (!scriptSrc) {\n // no URL info available.\n //\n // Note: when the embedded module is available, it means the current script is ESM. Usually, in ESM, the\n // `import.meta.url` is available. But in some cases (eg. Cloudflare Workers), the value of `import.meta.url`\n // can be `null` or `undefined`. In this case, we can only load the embedded module when:\n //\n // 1. The WebAssembly module binary is overridden:\n // ```js\n // env.wasm.wasmPaths = undefined; // or not specified\n // env.wasm.wasmBinary = /* a Uint8Array containing the WebAssembly binary */;\n // ```\n //\n // 2. The \".wasm\" only is overridden.\n // ```js\n // env.wasm.wasmPaths = { wasm: /* URL of the .wasm file */ };\n // ```\n //\n if (isWasmOverridden && !isMultiThreaded) {\n useEmbeddedModule = true;\n } else {\n throw new Error('cannot determine the script source URL.');\n }\n } else {\n // if the script source is available, we can check if it is from the same origin.\n useEmbeddedModule = isSameOrigin(scriptSrc);\n }\n }\n if (useEmbeddedModule) {\n return [undefined, embeddedWasmModule!];\n } else {\n const wasmModuleFilename = !BUILD_DEFS.DISABLE_JSEP\n ? 'ort-wasm-simd-threaded.jsep.mjs'\n : BUILD_DEFS.ENABLE_JSPI\n ? 'ort-wasm-simd-threaded.jspi.mjs'\n : !BUILD_DEFS.DISABLE_WEBGPU\n ? 'ort-wasm-simd-threaded.asyncify.mjs'\n : 'ort-wasm-simd-threaded.mjs';\n const wasmModuleUrl = urlOverride ?? normalizeUrl(wasmModuleFilename, prefixOverride);\n // need to preload if all of the following conditions are met:\n // 1. not in Node.js.\n // - Node.js does not have the same origin policy for creating workers.\n // 2. multi-threaded is enabled.\n // - If multi-threaded is disabled, no worker will be created. So we don't need to preload the module.\n // 3. the absolute URL is available.\n // - If the absolute URL is failed to be created, the origin cannot be determined. In this case, we will not\n // preload the module.\n // 4. the worker URL is not from the same origin.\n // - If the worker URL is from the same origin, we can create the worker directly.\n const needPreload = !isNode && isMultiThreaded && wasmModuleUrl && !isSameOrigin(wasmModuleUrl, prefixOverride);\n const url = needPreload\n ? await preload(wasmModuleUrl)\n : (wasmModuleUrl ?? fallbackUrl(wasmModuleFilename, prefixOverride));\n return [needPreload ? url : undefined, await dynamicImportDefault<EmscriptenModuleFactory<OrtWasmModule>>(url)];\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Env } from 'onnxruntime-common';\n\nimport type { OrtWasmModule } from './wasm-types';\nimport { importWasmModule, inferWasmPathPrefixFromScriptSrc } from './wasm-utils-import';\n\nlet wasm: OrtWasmModule | undefined;\nlet initialized = false;\nlet initializing = false;\nlet aborted = false;\n\nconst isMultiThreadSupported = (): boolean => {\n // If 'SharedArrayBuffer' is not available, WebAssembly threads will not work.\n if (typeof SharedArrayBuffer === 'undefined') {\n return false;\n }\n\n try {\n // Test for transferability of SABs (for browsers. needed for Firefox)\n // https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ\n if (typeof MessageChannel !== 'undefined') {\n new MessageChannel().port1.postMessage(new SharedArrayBuffer(1));\n }\n\n // Test for WebAssembly threads capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing threaded instructions.\n return WebAssembly.validate(\n new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16,\n 2, 0, 26, 11,\n ]),\n );\n } catch {\n return false;\n }\n};\n\nconst isSimdSupported = (): boolean => {\n try {\n // Test for WebAssembly SIMD capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing SIMD instructions.\n\n // The binary data is generated from the following code by wat2wasm:\n //\n // (module\n // (type $t0 (func))\n // (func $f0 (type $t0)\n // (drop\n // (i32x4.dot_i16x8_s\n // (i8x16.splat\n // (i32.const 0))\n // (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)))))\n\n return WebAssembly.validate(\n new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0, 253, 15, 253, 12, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11,\n ]),\n );\n } catch {\n return false;\n }\n};\n\nconst isRelaxedSimdSupported = (): boolean => {\n try {\n // Test for WebAssembly Relaxed SIMD capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing Relaxed SIMD instructions.\n\n // The binary data is generated from the following code by wat2wasm:\n // (module\n // (func (result v128)\n // i32.const 1\n // i8x16.splat\n // i32.const 2\n // i8x16.splat\n // i32.const 3\n // i8x16.splat\n // i32x4.relaxed_dot_i8x16_i7x16_add_s\n // )\n // )\n return WebAssembly.validate(\n new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 19, 1, 17, 0, 65, 1, 253, 15, 65, 2, 253,\n 15, 65, 3, 253, 15, 253, 147, 2, 11,\n ]),\n );\n } catch {\n return false;\n }\n};\n\nexport const initializeWebAssembly = async (flags: Env.WebAssemblyFlags): Promise<void> => {\n if (initialized) {\n return Promise.resolve();\n }\n if (initializing) {\n throw new Error(\"multiple calls to 'initializeWebAssembly()' detected.\");\n }\n if (aborted) {\n throw new Error(\"previous call to 'initializeWebAssembly()' failed.\");\n }\n\n initializing = true;\n\n // wasm flags are already initialized\n const timeout = flags.initTimeout!;\n let numThreads = flags.numThreads!;\n\n // ensure SIMD is supported\n if (flags.simd === false) {\n // skip SIMD feature checking as it is disabled explicitly by user\n } else if (flags.simd === 'relaxed') {\n // check if relaxed SIMD is supported\n if (!isRelaxedSimdSupported()) {\n throw new Error('Relaxed WebAssembly SIMD is not supported in the current environment.');\n }\n } else if (!isSimdSupported()) {\n throw new Error('WebAssembly SIMD is not supported in the current environment.');\n }\n\n if (BUILD_DEFS.ENABLE_JSPI) {\n if (!('Suspending' in WebAssembly)) {\n throw new Error('WebAssembly JSPI is not supported in the current environment.');\n }\n }\n\n // check if multi-threading is supported\n const multiThreadSupported = isMultiThreadSupported();\n if (numThreads > 1 && !multiThreadSupported) {\n if (typeof self !== 'undefined' && !self.crossOriginIsolated) {\n // eslint-disable-next-line no-console\n console.warn(\n 'env.wasm.numThreads is set to ' +\n numThreads +\n ', but this will not work unless you enable crossOriginIsolated mode. ' +\n 'See https://web.dev/cross-origin-isolation-guide/ for more info.',\n );\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n 'WebAssembly multi-threading is not supported in the current environment. ' + 'Falling back to single-threading.',\n );\n\n // set flags.numThreads to 1 so that OrtInit() will not create a global thread pool.\n flags.numThreads = numThreads = 1;\n }\n\n const wasmPaths = flags.wasmPaths;\n const wasmPrefixOverride = typeof wasmPaths === 'string' ? wasmPaths : undefined;\n const mjsPathOverrideFlag = (wasmPaths as Env.WasmFilePaths)?.mjs;\n const mjsPathOverride = (mjsPathOverrideFlag as URL)?.href ?? mjsPathOverrideFlag;\n const wasmPathOverrideFlag = (wasmPaths as Env.WasmFilePaths)?.wasm;\n const wasmPathOverride = (wasmPathOverrideFlag as URL)?.href ?? wasmPathOverrideFlag;\n const wasmBinaryOverride = flags.wasmBinary;\n\n const [objectUrl, ortWasmFactory] = await importWasmModule(\n mjsPathOverride,\n wasmPrefixOverride,\n numThreads > 1,\n !!wasmBinaryOverride || !!wasmPathOverride,\n );\n\n let isTimeout = false;\n\n const tasks: Array<Promise<void>> = [];\n\n // promise for timeout\n if (timeout > 0) {\n tasks.push(\n new Promise((resolve) => {\n setTimeout(() => {\n isTimeout = true;\n resolve();\n }, timeout);\n }),\n );\n }\n\n // promise for module initialization\n tasks.push(\n new Promise((resolve, reject) => {\n const config: Partial<OrtWasmModule> = {\n /**\n * The number of threads. WebAssembly will create (Module.numThreads - 1) workers. If it is 1, no worker will be\n * created.\n */\n numThreads,\n };\n\n if (wasmBinaryOverride) {\n // Set a custom buffer which contains the WebAssembly binary. This will skip the wasm file fetching.\n config.wasmBinary = wasmBinaryOverride;\n } else if (wasmPathOverride || wasmPrefixOverride) {\n // A callback function to locate the WebAssembly file. The function should return the full path of the file.\n //\n // Since Emscripten 3.1.58, this function is only called for the .wasm file.\n config.locateFile = (fileName) => wasmPathOverride ?? wasmPrefixOverride + fileName;\n } else if (mjsPathOverride && mjsPathOverride.indexOf('blob:') !== 0) {\n // if mjs path is specified, use it as the base path for the .wasm file.\n config.locateFile = (fileName) => new URL(fileName, mjsPathOverride).href;\n } else if (objectUrl) {\n const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc();\n if (inferredWasmPathPrefix) {\n // if the wasm module is preloaded, use the inferred wasm path as the base path for the .wasm file.\n config.locateFile = (fileName) => inferredWasmPathPrefix + fileName;\n }\n }\n\n ortWasmFactory(config).then(\n // wasm module initialized successfully\n (module) => {\n initializing = false;\n initialized = true;\n wasm = module;\n resolve();\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl);\n }\n },\n // wasm module failed to initialize\n (what) => {\n initializing = false;\n aborted = true;\n reject(what);\n },\n );\n }),\n );\n\n await Promise.race(tasks);\n\n if (isTimeout) {\n throw new Error(`WebAssembly backend initializing failed due to timeout: ${timeout}ms`);\n }\n};\n\nexport const getInstance = (): OrtWasmModule => {\n if (initialized && wasm) {\n return wasm;\n }\n\n throw new Error('WebAssembly is not initialized yet.');\n};\n\nexport const dispose = (): void => {\n if (initialized && !initializing && !aborted) {\n // TODO: currently \"PThread.terminateAllThreads()\" is not exposed in the wasm module.\n // And this function is not yet called by any code.\n // If it is needed in the future, we should expose it in the wasm module and uncomment the following line.\n\n // wasm?.PThread?.terminateAllThreads();\n wasm = undefined;\n\n initializing = false;\n initialized = false;\n aborted = true;\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { getInstance } from './wasm-factory';\n\nexport const allocWasmString = (data: string, allocs: number[]): number => {\n const wasm = getInstance();\n\n const dataLength = wasm.lengthBytesUTF8(data) + 1;\n const dataOffset = wasm._malloc(dataLength);\n wasm.stringToUTF8(data, dataOffset, dataLength);\n allocs.push(dataOffset);\n\n return dataOffset;\n};\n\ninterface ExtraOptionsHandler {\n (name: string, value: string): void;\n}\n\nexport const iterateExtraOptions = (\n options: Record<string, unknown>,\n prefix: string,\n seen: WeakSet<Record<string, unknown>>,\n handler: ExtraOptionsHandler,\n): void => {\n if (typeof options == 'object' && options !== null) {\n if (seen.has(options)) {\n throw new Error('Circular reference in options');\n } else {\n seen.add(options);\n }\n }\n\n Object.entries(options).forEach(([key, value]) => {\n const name = prefix ? prefix + key : key;\n if (typeof value === 'object') {\n iterateExtraOptions(value as Record<string, unknown>, name + '.', seen, handler);\n } else if (typeof value === 'string' || typeof value === 'number') {\n handler(name, value.toString());\n } else if (typeof value === 'boolean') {\n handler(name, value ? '1' : '0');\n } else {\n throw new Error(`Can't handle extra config type: ${typeof value}`);\n }\n });\n};\n\n/**\n * check web assembly API's last error and throw error if any error occurred.\n * @param message a message used when an error occurred.\n */\nexport const checkLastError = (message: string): void => {\n const wasm = getInstance();\n\n const stack = wasm.stackSave();\n try {\n const ptrSize = wasm.PTR_SIZE;\n const paramsOffset = wasm.stackAlloc(2 * ptrSize);\n wasm._OrtGetLastError(paramsOffset, paramsOffset + ptrSize);\n const errorCode = Number(wasm.getValue(paramsOffset, ptrSize === 4 ? 'i32' : 'i64'));\n const errorMessagePointer = wasm.getValue(paramsOffset + ptrSize, '*');\n const errorMessage = errorMessagePointer ? wasm.UTF8ToString(errorMessagePointer) : '';\n throw new Error(`${message} ERROR_CODE: ${errorCode}, ERROR_MESSAGE: ${errorMessage}`);\n } finally {\n wasm.stackRestore(stack);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession } from 'onnxruntime-common';\n\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils';\n\nexport const setRunOptions = (options: InferenceSession.RunOptions): [number, number[]] => {\n const wasm = getInstance();\n let runOptionsHandle = 0;\n const allocs: number[] = [];\n\n const runOptions: InferenceSession.RunOptions = options || {};\n\n try {\n if (options?.logSeverityLevel === undefined) {\n runOptions.logSeverityLevel = 2; // Default to warning\n } else if (\n typeof options.logSeverityLevel !== 'number' ||\n !Number.isInteger(options.logSeverityLevel) ||\n options.logSeverityLevel < 0 ||\n options.logSeverityLevel > 4\n ) {\n throw new Error(`log severity level is not valid: ${options.logSeverityLevel}`);\n }\n\n if (options?.logVerbosityLevel === undefined) {\n runOptions.logVerbosityLevel = 0; // Default to 0\n } else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) {\n throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`);\n }\n\n if (options?.terminate === undefined) {\n runOptions.terminate = false;\n }\n\n let tagDataOffset = 0;\n if (options?.tag !== undefined) {\n tagDataOffset = allocWasmString(options.tag, allocs);\n }\n\n runOptionsHandle = wasm._OrtCreateRunOptions(\n runOptions.logSeverityLevel!,\n runOptions.logVerbosityLevel!,\n !!runOptions.terminate!,\n tagDataOffset,\n );\n if (runOptionsHandle === 0) {\n checkLastError(\"Can't create run options.\");\n }\n\n if (options?.extra !== undefined) {\n iterateExtraOptions(options.extra, '', new WeakSet<Record<string, unknown>>(), (key, value) => {\n const keyDataOffset = allocWasmString(key, allocs);\n const valueDataOffset = allocWasmString(value, allocs);\n\n if (wasm._OrtAddRunConfigEntry(runOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n checkLastError(`Can't set a run config entry: ${key} - ${value}.`);\n }\n });\n }\n\n return [runOptionsHandle, allocs];\n } catch (e) {\n if (runOptionsHandle !== 0) {\n wasm._OrtReleaseRunOptions(runOptionsHandle);\n }\n allocs.forEach((alloc) => wasm._free(alloc));\n throw e;\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport type { InferenceSession } from 'onnxruntime-common';\n\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils';\n\nconst getGraphOptimzationLevel = (graphOptimizationLevel: string | unknown): number => {\n switch (graphOptimizationLevel) {\n case 'disabled':\n return 0;\n case 'basic':\n return 1;\n case 'extended':\n return 2;\n case 'layout':\n return 3;\n case 'all':\n return 99;\n default:\n throw new Error(`unsupported graph optimization level: ${graphOptimizationLevel}`);\n }\n};\n\nconst getExecutionMode = (executionMode: 'sequential' | 'parallel'): number => {\n switch (executionMode) {\n case 'sequential':\n return 0;\n case 'parallel':\n return 1;\n default:\n throw new Error(`unsupported execution mode: ${executionMode}`);\n }\n};\n\nconst appendDefaultOptions = (options: InferenceSession.SessionOptions): void => {\n if (!options.extra) {\n options.extra = {};\n }\n if (!options.extra.session) {\n options.extra.session = {};\n }\n const session = options.extra.session as Record<string, string>;\n if (!session.use_ort_model_bytes_directly) {\n // eslint-disable-next-line camelcase\n session.use_ort_model_bytes_directly = '1';\n }\n\n // if using JSEP with WebGPU, always disable memory pattern\n if (\n options.executionProviders &&\n options.executionProviders.some((ep) => (typeof ep === 'string' ? ep : ep.name) === 'webgpu')\n ) {\n options.enableMemPattern = false;\n }\n};\n\nconst appendSessionConfig = (sessionOptionsHandle: number, key: string, value: string, allocs: number[]): void => {\n const keyDataOffset = allocWasmString(key, allocs);\n const valueDataOffset = allocWasmString(value, allocs);\n if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n checkLastError(`Can't set a session config entry: ${key} - ${value}.`);\n }\n};\n\nconst appendEpOption = (epOptions: Array<[number, number]>, key: string, value: string, allocs: number[]): void => {\n const keyDataOffset = allocWasmString(key, allocs);\n const valueDataOffset = allocWasmString(value, allocs);\n epOptions.push([keyDataOffset, valueDataOffset]);\n};\n\nconst setExecutionProviders = async (\n sessionOptionsHandle: number,\n sessionOptions: InferenceSession.SessionOptions,\n allocs: number[],\n): Promise<void> => {\n const executionProviders = sessionOptions.executionProviders!;\n for (const ep of executionProviders) {\n let epName = typeof ep === 'string' ? ep : ep.name;\n const epOptions: Array<[number, number]> = [];\n\n // check EP name\n switch (epName) {\n case 'webnn':\n epName = 'WEBNN';\n if (typeof ep !== 'string') {\n const webnnOptions = ep as InferenceSession.WebNNExecutionProviderOption;\n // const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context;\n const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType;\n if (deviceType) {\n appendSessionConfig(sessionOptionsHandle, 'deviceType', deviceType, allocs);\n }\n }\n break;\n case 'webgpu':\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n epName = 'WebGPU';\n let customDevice: GPUDevice | undefined;\n\n if (typeof ep !== 'string') {\n const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption;\n\n // set custom GPU device\n if (webgpuOptions.device) {\n if (typeof GPUDevice !== 'undefined' && webgpuOptions.device instanceof GPUDevice) {\n customDevice = webgpuOptions.device;\n } else {\n throw new Error('Invalid GPU device set in WebGPU EP options.');\n }\n }\n\n // set graph capture option from session options\n const { enableGraphCapture } = sessionOptions;\n if (typeof enableGraphCapture === 'boolean' && enableGraphCapture) {\n appendEpOption(epOptions, 'enableGraphCapture', '1', allocs);\n }\n\n // set layout option\n if (typeof webgpuOptions.preferredLayout === 'string') {\n appendEpOption(epOptions, 'preferredLayout', webgpuOptions.preferredLayout, allocs);\n }\n\n // set force CPU fallback nodes\n if (webgpuOptions.forceCpuNodeNames) {\n const names = Array.isArray(webgpuOptions.forceCpuNodeNames)\n ? webgpuOptions.forceCpuNodeNames\n : [webgpuOptions.forceCpuNodeNames];\n\n appendEpOption(epOptions, 'forceCpuNodeNames', names.join('\\n'), allocs);\n }\n\n // set validation mode\n if (webgpuOptions.validationMode) {\n appendEpOption(epOptions, 'validationMode', webgpuOptions.validationMode, allocs);\n }\n }\n\n const info = getInstance().webgpuRegisterDevice!(customDevice);\n if (info) {\n const [deviceId, instanceHandle, deviceHandle] = info;\n appendEpOption(epOptions, 'deviceId', deviceId.toString(), allocs);\n appendEpOption(epOptions, 'webgpuInstance', instanceHandle.toString(), allocs);\n appendEpOption(epOptions, 'webgpuDevice', deviceHandle.toString(), allocs);\n }\n } else {\n epName = 'JS';\n if (typeof ep !== 'string') {\n const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption;\n if (webgpuOptions?.preferredLayout) {\n if (webgpuOptions.preferredLayout !== 'NCHW' && webgpuOptions.preferredLayout !== 'NHWC') {\n throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`);\n }\n appendSessionConfig(sessionOptionsHandle, 'preferredLayout', webgpuOptions.preferredLayout, allocs);\n }\n }\n }\n break;\n case 'wasm':\n case 'cpu':\n continue;\n default:\n throw new Error(`not supported execution provider: ${epName}`);\n }\n\n const epNameDataOffset = allocWasmString(epName, allocs);\n const epOptionsCount = epOptions.length;\n let keysOffset = 0;\n let valuesOffset = 0;\n if (epOptionsCount > 0) {\n keysOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE);\n allocs.push(keysOffset);\n valuesOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE);\n allocs.push(valuesOffset);\n for (let i = 0; i < epOptionsCount; i++) {\n getInstance().setValue(keysOffset + i * getInstance().PTR_SIZE, epOptions[i][0], '*');\n getInstance().setValue(valuesOffset + i * getInstance().PTR_SIZE, epOptions[i][1], '*');\n }\n }\n if (\n (await getInstance()._OrtAppendExecutionProvider(\n sessionOptionsHandle,\n epNameDataOffset,\n keysOffset,\n valuesOffset,\n epOptionsCount,\n )) !== 0\n ) {\n checkLastError(`Can't append execution provider: ${epName}.`);\n }\n }\n};\n\nexport const setSessionOptions = async (options?: InferenceSession.SessionOptions): Promise<[number, number[]]> => {\n const wasm = getInstance();\n let sessionOptionsHandle = 0;\n const allocs: number[] = [];\n\n const sessionOptions: InferenceSession.SessionOptions = options || {};\n appendDefaultOptions(sessionOptions);\n\n try {\n const graphOptimizationLevel = getGraphOptimzationLevel(sessionOptions.graphOptimizationLevel ?? 'all');\n const executionMode = getExecutionMode(sessionOptions.executionMode ?? 'sequential');\n const logIdDataOffset =\n typeof sessionOptions.logId === 'string' ? allocWasmString(sessionOptions.logId, allocs) : 0;\n\n const logSeverityLevel = sessionOptions.logSeverityLevel ?? 2; // Default to 2 - warning\n if (!Number.isInteger(logSeverityLevel) || logSeverityLevel < 0 || logSeverityLevel > 4) {\n throw new Error(`log severity level is not valid: ${logSeverityLevel}`);\n }\n\n const logVerbosityLevel = sessionOptions.logVerbosityLevel ?? 0; // Default to 0 - verbose\n if (!Number.isInteger(logVerbosityLevel) || logVerbosityLevel < 0 || logVerbosityLevel > 4) {\n throw new Error(`log verbosity level is not valid: ${logVerbosityLevel}`);\n }\n\n const optimizedModelFilePathOffset =\n typeof sessionOptions.optimizedModelFilePath === 'string'\n ? allocWasmString(sessionOptions.optimizedModelFilePath, allocs)\n : 0;\n\n sessionOptionsHandle = wasm._OrtCreateSessionOptions(\n graphOptimizationLevel,\n !!sessionOptions.enableCpuMemArena,\n !!sessionOptions.enableMemPattern,\n executionMode,\n !!sessionOptions.enableProfiling,\n 0,\n logIdDataOffset,\n logSeverityLevel,\n logVerbosityLevel,\n optimizedModelFilePathOffset,\n );\n if (sessionOptionsHandle === 0) {\n checkLastError(\"Can't create session options.\");\n }\n\n if (sessionOptions.executionProviders) {\n await setExecutionProviders(sessionOptionsHandle, sessionOptions, allocs);\n }\n\n if (sessionOptions.enableGraphCapture !== undefined) {\n if (typeof sessionOptions.enableGraphCapture !== 'boolean') {\n throw new Error(`enableGraphCapture must be a boolean value: ${sessionOptions.enableGraphCapture}`);\n }\n appendSessionConfig(\n sessionOptionsHandle,\n 'enableGraphCapture',\n sessionOptions.enableGraphCapture.toString(),\n allocs,\n );\n }\n\n if (sessionOptions.freeDimensionOverrides) {\n for (const [name, value] of Object.entries(sessionOptions.freeDimensionOverrides)) {\n if (typeof name !== 'string') {\n throw new Error(`free dimension override name must be a string: ${name}`);\n }\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new Error(`free dimension override value must be a non-negative integer: ${value}`);\n }\n const nameOffset = allocWasmString(name, allocs);\n if (wasm._OrtAddFreeDimensionOverride(sessionOptionsHandle, nameOffset, value) !== 0) {\n checkLastError(`Can't set a free dimension override: ${name} - ${value}.`);\n }\n }\n }\n\n if (sessionOptions.extra !== undefined) {\n iterateExtraOptions(sessionOptions.extra, '', new WeakSet<Record<string, unknown>>(), (key, value) => {\n appendSessionConfig(sessionOptionsHandle, key, value, allocs);\n });\n }\n\n return [sessionOptionsHandle, allocs];\n } catch (e) {\n if (sessionOptionsHandle !== 0) {\n if (wasm._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) {\n checkLastError(\"Can't release session options.\");\n }\n }\n allocs.forEach((alloc) => wasm._free(alloc));\n throw e;\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from 'onnxruntime-common';\n\n// a dummy type declaration for Float16Array in case any polyfill is available.\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any\n const Float16Array: any;\n}\n\n// This file includes common definitions. They do NOT have dependency on the WebAssembly instance.\n\n/**\n * Copied from ONNX definition. Use this to drop dependency 'onnx_proto' to decrease compiled .js file size.\n */\nexport const enum DataType {\n undefined = 0,\n float = 1,\n uint8 = 2,\n int8 = 3,\n uint16 = 4,\n int16 = 5,\n int32 = 6,\n int64 = 7,\n string = 8,\n bool = 9,\n float16 = 10,\n double = 11,\n uint32 = 12,\n uint64 = 13,\n complex64 = 14,\n complex128 = 15,\n bfloat16 = 16,\n\n // 4-bit data-types\n uint4 = 21,\n int4 = 22,\n}\n\n/**\n * Map string tensor data to enum value\n */\nexport const tensorDataTypeStringToEnum = (type: string): DataType => {\n switch (type) {\n case 'int8':\n return DataType.int8;\n case 'uint8':\n return DataType.uint8;\n case 'bool':\n return DataType.bool;\n case 'int16':\n return DataType.int16;\n case 'uint16':\n return DataType.uint16;\n case 'int32':\n return DataType.int32;\n case 'uint32':\n return DataType.uint32;\n case 'float16':\n return DataType.float16;\n case 'float32':\n return DataType.float;\n case 'float64':\n return DataType.double;\n case 'string':\n return DataType.string;\n case 'int64':\n return DataType.int64;\n case 'uint64':\n return DataType.uint64;\n case 'int4':\n return DataType.int4;\n case 'uint4':\n return DataType.uint4;\n\n default:\n throw new Error(`unsupported data type: ${type}`);\n }\n};\n\n/**\n * Map enum value to string tensor data\n */\nexport const tensorDataTypeEnumToString = (typeProto: DataType): Tensor.Type => {\n switch (typeProto) {\n case DataType.int8:\n return 'int8';\n case DataType.uint8:\n return 'uint8';\n case DataType.bool:\n return 'bool';\n case DataType.int16:\n return 'int16';\n case DataType.uint16:\n return 'uint16';\n case DataType.int32:\n return 'int32';\n case DataType.uint32:\n return 'uint32';\n case DataType.float16:\n return 'float16';\n case DataType.float:\n return 'float32';\n case DataType.double:\n return 'float64';\n case DataType.string:\n return 'string';\n case DataType.int64:\n return 'int64';\n case DataType.uint64:\n return 'uint64';\n case DataType.int4:\n return 'int4';\n case DataType.uint4:\n return 'uint4';\n\n default:\n throw new Error(`unsupported data type: ${typeProto}`);\n }\n};\n\n/**\n * get tensor size in bytes by the given data type and dimensions\n * @returns size in integer or undefined if the data type is not supported\n */\nexport const calculateTensorSizeInBytes = (\n dateType: number,\n dimsOrSize: readonly number[] | number,\n): number | undefined => {\n const elementSize = [\n -1, // undefined = 0\n 4, // float = 1\n 1, // uint8 = 2\n 1, // int8 = 3\n 2, // uint16 = 4\n 2, // int16 = 5\n 4, // int32 = 6\n 8, // int64 = 7\n -1, // string = 8\n 1, // bool = 9\n 2, // float16 = 10\n 8, // double = 11\n 4, // uint32 = 12\n 8, // uint64 = 13\n -1, // complex64 = 14\n -1, // complex128 = 15\n -1, // bfloat16 = 16\n -1, // FLOAT8E4M3FN = 17\n -1, // FLOAT8E4M3FNUZ = 18\n -1, // FLOAT8E5M2 = 19\n -1, // FLOAT8E5M2FNUZ = 20\n 0.5, // uint4 = 21\n 0.5, // int4 = 22\n ][dateType];\n\n const size = typeof dimsOrSize === 'number' ? dimsOrSize : dimsOrSize.reduce((a, b) => a * b, 1);\n return elementSize > 0 ? Math.ceil(size * elementSize) : undefined;\n};\n\n/**\n * get typed array constructor by the given tensor type\n */\nexport const tensorTypeToTypedArrayConstructor = (\n type: Tensor.Type,\n):\n | Float32ArrayConstructor\n | Uint8ArrayConstructor\n | Int8ArrayConstructor\n | Uint16ArrayConstructor\n | Int16ArrayConstructor\n | Int32ArrayConstructor\n | BigInt64ArrayConstructor\n | Uint8ArrayConstructor\n | Float64ArrayConstructor\n | Uint32ArrayConstructor\n | BigUint64ArrayConstructor => {\n switch (type) {\n case 'float16':\n // allow Float16Array polyfill.\n return typeof Float16Array !== 'undefined' && Float16Array.from ? Float16Array : Uint16Array;\n case 'float32':\n return Float32Array;\n case 'uint8':\n return Uint8Array;\n case 'int8':\n return Int8Array;\n case 'uint16':\n return Uint16Array;\n case 'int16':\n return Int16Array;\n case 'int32':\n return Int32Array;\n case 'bool':\n return Uint8Array;\n case 'float64':\n return Float64Array;\n case 'uint32':\n return Uint32Array;\n case 'int64':\n return BigInt64Array;\n case 'uint64':\n return BigUint64Array;\n default:\n throw new Error(`unsupported type: ${type}`);\n }\n};\n\n/**\n * Map string log level to integer value\n */\nexport const logLevelStringToEnum = (logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal'): number => {\n switch (logLevel) {\n case 'verbose':\n return 0;\n case 'info':\n return 1;\n case 'warning':\n return 2;\n case 'error':\n return 3;\n case 'fatal':\n return 4;\n default:\n throw new Error(`unsupported logging level: ${logLevel}`);\n }\n};\n\n/**\n * Check whether the given tensor type is supported by GPU buffer\n */\nexport const isGpuBufferSupportedType = (type: Tensor.Type): type is Tensor.GpuBufferDataTypes =>\n type === 'float32' ||\n type === 'float16' ||\n type === 'int32' ||\n type === 'int64' ||\n type === 'uint32' ||\n type === 'uint8' ||\n type === 'bool' ||\n type === 'uint4' ||\n type === 'int4';\n\n/**\n * Check whether the given tensor type is supported by WebNN MLTensor\n */\nexport const isMLTensorSupportedType = (type: Tensor.Type): type is Tensor.MLTensorDataTypes =>\n type === 'float32' ||\n type === 'float16' ||\n type === 'int32' ||\n type === 'int64' ||\n type === 'uint32' ||\n type === 'uint64' ||\n type === 'int8' ||\n type === 'uint8' ||\n type === 'bool' ||\n type === 'uint4' ||\n type === 'int4';\n\n/**\n * Map string data location to integer value\n */\nexport const dataLocationStringToEnum = (location: Tensor.DataLocation): number => {\n switch (location) {\n case 'none':\n return 0;\n case 'cpu':\n return 1;\n case 'cpu-pinned':\n return 2;\n case 'texture':\n return 3;\n case 'gpu-buffer':\n return 4;\n case 'ml-tensor':\n return 5;\n default:\n throw new Error(`unsupported data location: ${location}`);\n }\n};\n\n/**\n * Map integer data location to string value\n */\nexport const dataLocationEnumToString = (location: number): Tensor.DataLocation | undefined =>\n (['none', 'cpu', 'cpu-pinned', 'texture', 'gpu-buffer', 'ml-tensor'] as const)[location];\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { isNode } from './wasm-utils-env';\n\n/**\n * Load a file into a Uint8Array.\n *\n * @param file - the file to load. Can be a URL/path, a Blob, an ArrayBuffer, or a Uint8Array.\n * @returns a Uint8Array containing the file data.\n */\nexport const loadFile = async (file: string | Blob | ArrayBufferLike | Uint8Array): Promise<Uint8Array> => {\n if (typeof file === 'string') {\n if (isNode) {\n // load file into ArrayBuffer in Node.js\n try {\n const { readFile } = require('node:fs/promises');\n return new Uint8Array(await readFile(file));\n } catch (e) {\n if (e.code === 'ERR_FS_FILE_TOO_LARGE') {\n // file is too large, use fs.createReadStream instead\n const { createReadStream } = require('node:fs');\n const stream = createReadStream(file);\n const chunks: Uint8Array[] = [];\n for await (const chunk of stream) {\n chunks.push(chunk);\n }\n return new Uint8Array(Buffer.concat(chunks));\n }\n throw e;\n }\n } else {\n // load file into ArrayBuffer in browsers\n const response = await fetch(file);\n if (!response.ok) {\n throw new Error(`failed to load external data file: ${file}`);\n }\n const contentLengthHeader = response.headers.get('Content-Length');\n const fileSize = contentLengthHeader ? parseInt(contentLengthHeader, 10) : 0;\n if (fileSize < 1073741824 /* 1GB */) {\n // when Content-Length header is not set, we cannot determine the file size. We assume it is small enough to\n // load into memory.\n return new Uint8Array(await response.arrayBuffer());\n } else {\n // file is too large, use stream instead\n if (!response.body) {\n throw new Error(`failed to load external data file: ${file}, no response body.`);\n }\n const reader = response.body.getReader();\n\n let buffer;\n try {\n // try to create ArrayBuffer directly\n buffer = new ArrayBuffer(fileSize);\n } catch (e) {\n if (e instanceof RangeError) {\n // use WebAssembly Memory to allocate larger ArrayBuffer\n const pages = Math.ceil(fileSize / 65536);\n buffer = new WebAssembly.Memory({ initial: pages, maximum: pages }).buffer;\n } else {\n throw e;\n }\n }\n\n let offset = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n const chunkSize = value.byteLength;\n const chunk = new Uint8Array(buffer, offset, chunkSize);\n chunk.set(value);\n offset += chunkSize;\n }\n return new Uint8Array(buffer, 0, fileSize);\n }\n }\n } else if (file instanceof Blob) {\n return new Uint8Array(await file.arrayBuffer());\n } else if (file instanceof Uint8Array) {\n return file;\n } else {\n return new Uint8Array(file);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// WebNN API currently does not have a TypeScript definition file. This file is a workaround with types generated from\n// WebNN API specification.\n// https://github.com/webmachinelearning/webnn/issues/677\n/// <reference path=\"jsep/webnn/webnn.d.ts\" />\n\nimport { Env, InferenceSession, Tensor, TRACE_EVENT_BEGIN, TRACE_EVENT_END } from 'onnxruntime-common';\n\nimport {\n SerializableInternalBuffer,\n SerializableSessionMetadata,\n SerializableTensorMetadata,\n TensorMetadata,\n} from './proxy-messages';\nimport { setRunOptions } from './run-options';\nimport { setSessionOptions } from './session-options';\nimport {\n calculateTensorSizeInBytes,\n dataLocationStringToEnum,\n isGpuBufferSupportedType,\n isMLTensorSupportedType,\n logLevelStringToEnum,\n tensorDataTypeEnumToString,\n tensorDataTypeStringToEnum,\n tensorTypeToTypedArrayConstructor,\n} from './wasm-common';\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError } from './wasm-utils';\nimport { loadFile } from './wasm-utils-load-file';\n\n// #region Initializations\n\n/**\n * There are 4 different \"initialization\" steps for ORT. They happen in different places and different time.\n *\n * 1. JavaScript initialization for onnxruntime-common and onnxruntime-web.\n * This is the first initialization step. In this step, onnxruntime-web calls onnxruntime-common's registerBackend()\n * function multiple times to register all the available backends. The backend registration is very fast. It only\n * registers the backend name with the uninitialized backend object. No heavy initialization is done in this step.\n * Refer to web/lib/index.ts for the backend registration.\n *\n * 2. WebAssembly artifact initialization.\n * This happens when any registered wasm backend is used for the first time (ie. `ort.InferenceSession.create()` is\n * called). In this step, onnxruntime-web does the followings:\n * - create a proxy worker and make sure the proxy worker is ready to receive messages, if proxy is enabled.\n * - perform feature detection, locate correct WebAssembly artifact path and call the Emscripten generated\n * JavaScript code to initialize the WebAssembly runtime.\n * - if proxy is enabled, this step happens in the proxy worker using message 'init-wasm'.\n * - downloading the 'ort-wasm{...}.wasm' file is done in this step.\n * - if multi-thread is enabled, one or more webworker will be created to initialize the PThread threadpool.\n *\n * 3. ORT environment initialization.\n * This happens after step 2. In this step, onnxruntime-web performs ONNX Runtime environment initialization.\n * Function `_OrtInit()` is called in this step.\n * - if proxy is enabled, this step happens in the proxy worker using message 'init-ort'.\n * - logging level (ort.env.logLevel) and thread number (ort.env.wasm.numThreads) are set in this step.\n *\n * 4. Session initialization.\n * This happens when `ort.InferenceSession.create()` is called. Unlike the first 3 steps (they only called once),\n * this step will be done for each session. In this step, onnxruntime-web does the followings:\n * If the parameter is a URL:\n * - download the model data from the URL.\n * - copy the model data to the WASM heap. (proxy: 'copy-from')\n * - dereference the model buffer. This step allows the original ArrayBuffer to be garbage collected.\n * - call `_OrtCreateSession()` to create the session. (proxy: 'create')\n *\n * If the parameter is a Uint8Array object:\n * - copy the model data to the WASM heap. (proxy: 'copy-from')\n * - call `_OrtCreateSession()` to create the session. (proxy: 'create')\n *\n *\n */\n\n/**\n * initialize ORT environment.\n *\n * @param numThreads SetGlobalIntraOpNumThreads(numThreads)\n * @param loggingLevel CreateEnv(static_cast<OrtLoggingLevel>(logging_level))\n */\nconst initOrt = (numThreads: number, loggingLevel: number): void => {\n const errorCode = getInstance()._OrtInit(numThreads, loggingLevel);\n if (errorCode !== 0) {\n checkLastError(\"Can't initialize onnxruntime.\");\n }\n};\n\n/**\n * initialize runtime environment.\n * @param env passed in the environment config object.\n */\nexport const initRuntime = async (env: Env): Promise<void> => {\n // init ORT\n initOrt(env.wasm.numThreads!, logLevelStringToEnum(env.logLevel));\n};\n\n/**\n * perform EP specific initialization.\n *\n * @param env\n * @param epName\n */\nexport const initEp = async (env: Env, epName: string): Promise<void> => {\n // initialize ASYNCIFY support\n getInstance().asyncInit?.();\n\n // perform WebGPU availability check ( either JSEP or WebGPU EP )\n let webgpuAdapter = env.webgpu.adapter as GPUAdapter | null;\n if (epName === 'webgpu') {\n if (typeof navigator === 'undefined' || !navigator.gpu) {\n throw new Error('WebGPU is not supported in current environment');\n }\n if (!webgpuAdapter) {\n // if adapter is not set, request a new adapter.\n const powerPreference = env.webgpu.powerPreference;\n if (powerPreference !== undefined && powerPreference !== 'low-power' && powerPreference !== 'high-performance') {\n throw new Error(`Invalid powerPreference setting: \"${powerPreference}\"`);\n }\n const forceFallbackAdapter = env.webgpu.forceFallbackAdapter;\n if (forceFallbackAdapter !== undefined && typeof forceFallbackAdapter !== 'boolean') {\n throw new Error(`Invalid forceFallbackAdapter setting: \"${forceFallbackAdapter}\"`);\n }\n webgpuAdapter = await navigator.gpu.requestAdapter({ powerPreference, forceFallbackAdapter });\n if (!webgpuAdapter) {\n throw new Error(\n 'Failed to get GPU adapter. ' +\n 'You may need to enable flag \"--enable-unsafe-webgpu\" if you are using Chrome.',\n );\n }\n } else {\n // if adapter is set, validate it.\n if (\n typeof webgpuAdapter.limits !== 'object' ||\n typeof webgpuAdapter.features !== 'object' ||\n typeof webgpuAdapter.requestDevice !== 'function'\n ) {\n throw new Error('Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.');\n }\n }\n }\n\n // perform WebNN availability check ( either JSEP or WebNN EP )\n if (epName === 'webnn') {\n if (typeof navigator === 'undefined' || !(navigator as unknown as { ml: unknown }).ml) {\n throw new Error('WebNN is not supported in current environment');\n }\n }\n\n if (!BUILD_DEFS.DISABLE_JSEP) {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const initJsep = require('./jsep/init').init;\n\n if (epName === 'webgpu') {\n await initJsep('webgpu', getInstance(), env, webgpuAdapter);\n }\n if (epName === 'webnn') {\n await initJsep('webnn', getInstance(), env);\n }\n } else {\n if (!BUILD_DEFS.DISABLE_WEBGPU && epName === 'webgpu') {\n getInstance().webgpuInit!((device) => {\n env.webgpu.device = device;\n });\n }\n if (!BUILD_DEFS.DISABLE_WEBNN && epName === 'webnn') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const backend = new (require('./jsep/backend-webnn').WebNNBackend)(env);\n getInstance().webnnInit!([\n backend,\n // webnnReserveTensorId\n () => backend.reserveTensorId(),\n // webnnReleaseTensorId,\n (tensorId: number) => backend.releaseTensorId(tensorId),\n // webnnEnsureTensor\n async (sessionId: number | undefined, tensorId: number, onnxDataType: number, shape: number[], copyOld) =>\n backend.ensureTensor(sessionId, tensorId, onnxDataType, shape, copyOld),\n // webnnUploadTensor\n (tensorId: number, data: Uint8Array) => {\n backend.uploadTensor(tensorId, data);\n },\n // webnnDownloadTensor\n async (tensorId: number, dstBuffer: ArrayBufferView | ArrayBuffer) =>\n backend.downloadTensor(tensorId, dstBuffer),\n // webnnRegisterMLContext\n (sessionId: number, mlContext: MLContext) => backend.registerMLContext(sessionId, mlContext),\n // webnnEnableTraceEvent\n !!env.trace,\n ]);\n }\n }\n};\n\n// #endregion Initializations\n\n/**\n * valid data locations for input/output tensors.\n */\ntype SupportedTensorDataLocationForInputOutput =\n | 'cpu'\n | 'cpu-pinned'\n | 'gpu-buffer'\n | 'ml-tensor'\n // Use 'ml-tensor' during inference, but output a tensor located on the CPU.\n | 'ml-tensor-cpu-output';\n\ntype IOBindingState = {\n /**\n * the handle of IO binding.\n */\n readonly handle: number;\n\n /**\n * the preferred location for each output tensor.\n *\n * value is one of 'cpu', 'cpu-pinned', 'gpu-buffer', 'ml-tensor'.\n */\n readonly outputPreferredLocations: readonly SupportedTensorDataLocationForInputOutput[];\n\n /**\n * enum value of the preferred location for each output tensor.\n */\n readonly outputPreferredLocationsEncoded: readonly number[];\n};\n\n/**\n * tuple elements are: InferenceSession ID; inputNamesUTF8Encoded; outputNamesUTF8Encoded; bindingState\n */\ntype SessionMetadata = [\n inferenceSessionId: number,\n inputNamesUTF8Encoded: number[],\n outputNamesUTF8Encoded: number[],\n bindingState: IOBindingState | null,\n enableGraphCapture: boolean,\n inputOutputBound: boolean,\n];\n\nconst activeSessions = new Map<number, SessionMetadata>();\n\n/**\n * get the input/output count of the session.\n * @param sessionHandle the handle representing the session. should be non-zero.\n * @returns a tuple including 2 numbers, representing the input count and output count.\n */\nconst getSessionInputOutputCount = (sessionHandle: number): [number, number] => {\n const wasm = getInstance();\n const stack = wasm.stackSave();\n try {\n const ptrSize = wasm.PTR_SIZE;\n const dataOffset = wasm.stackAlloc(2 * ptrSize);\n const errorCode = wasm._OrtGetInputOutputCount(sessionHandle, dataOffset, dataOffset + ptrSize);\n if (errorCode !== 0) {\n checkLastError(\"Can't get session input/output count.\");\n }\n const type = ptrSize === 4 ? 'i32' : 'i64';\n return [Number(wasm.getValue(dataOffset, type)), Number(wasm.getValue(dataOffset + ptrSize, type))];\n } finally {\n wasm.stackRestore(stack);\n }\n};\n\nconst getSessionInputOutputMetadata = (\n sessionHandle: number,\n index: number,\n): [nameOffset: number, elementType: number, dims?: Array<number | string>] => {\n const wasm = getInstance();\n const stack = wasm.stackSave();\n let metadataOffset = 0;\n try {\n const ptrSize = wasm.PTR_SIZE;\n const dataOffset = wasm.stackAlloc(2 * ptrSize);\n const errorCode = wasm._OrtGetInputOutputMetadata(sessionHandle, index, dataOffset, dataOffset + ptrSize);\n if (errorCode !== 0) {\n checkLastError(\"Can't get session input/output metadata.\");\n }\n const nameOffset = Number(wasm.getValue(dataOffset, '*'));\n metadataOffset = Number(wasm.getValue(dataOffset + ptrSize, '*'));\n // get element type\n const elementType = wasm.HEAP32[metadataOffset / 4];\n if (elementType === 0) {\n return [nameOffset, 0]; // non-tensor\n }\n\n // get dims count\n const dimsCount = wasm.HEAPU32[metadataOffset / 4 + 1];\n // get dims\n const dims: Array<number | string> = [];\n for (let i = 0; i < dimsCount; i++) {\n const symbolicDimNameOffset = Number(wasm.getValue(metadataOffset + 8 + i * ptrSize, '*'));\n dims.push(\n symbolicDimNameOffset !== 0\n ? wasm.UTF8ToString(symbolicDimNameOffset)\n : Number(wasm.getValue(metadataOffset + 8 + (i + dimsCount) * ptrSize, '*')),\n );\n }\n return [nameOffset, elementType, dims];\n } finally {\n wasm.stackRestore(stack);\n if (metadataOffset !== 0) {\n wasm._OrtFree(metadataOffset);\n }\n }\n};\n\n/**\n * allocate the memory and memcpy the external buffer.\n *\n * @param model - the external buffer containing the model data. Must not be the same buffer as the WASM heap.\n * @returns a 2-elements tuple - the pointer and size of the allocated buffer\n */\nexport const copyFromExternalBuffer = (model: Uint8Array): [number, number] => {\n const wasm = getInstance();\n const modelDataOffset = wasm._malloc(model.byteLength);\n if (modelDataOffset === 0) {\n throw new Error(`Can't create a session. failed to allocate a buffer of size ${model.byteLength}.`);\n }\n wasm.HEAPU8.set(model, modelDataOffset);\n return [modelDataOffset, model.byteLength];\n};\n\n/**\n * create an inference session from a model data buffer.\n *\n * @param modelData - either a Uint8Array object representing the model data, or a 2-elements tuple containing the\n * pointer and size of the model data buffer.\n * @param options an optional session options object.\n * @returns a 3-elements tuple containing [session handle, input names, output names]\n */\nexport const createSession = async (\n modelData: Uint8Array | SerializableInternalBuffer,\n options?: InferenceSession.SessionOptions,\n): Promise<SerializableSessionMetadata> => {\n let modelDataOffset: number, modelDataLength: number;\n const wasm = getInstance();\n\n if (Array.isArray(modelData)) {\n // if model data is an array, it must be a 2-elements tuple containing the pointer and size of the model data\n [modelDataOffset, modelDataLength] = modelData;\n } else if (modelData.buffer === wasm.HEAPU8.buffer) {\n // if model data uses the same buffer as the WASM heap, we don't need to copy it.\n [modelDataOffset, modelDataLength] = [modelData.byteOffset, modelData.byteLength];\n } else {\n // otherwise, copy the model data to the WASM heap.\n [modelDataOffset, modelDataLength] = copyFromExternalBuffer(modelData);\n }\n\n let sessionHandle = 0;\n let sessionOptionsHandle = 0;\n let ioBindingHandle = 0;\n let allocs: number[] = [];\n const inputNamesUTF8Encoded = [];\n const outputNamesUTF8Encoded = [];\n\n try {\n [sessionOptionsHandle, allocs] = await setSessionOptions(options);\n\n if (options?.externalData && wasm.mountExternalData) {\n const loadingPromises = [];\n for (const file of options.externalData) {\n const path = typeof file === 'string' ? file : file.path;\n loadingPromises.push(\n loadFile(typeof file === 'string' ? file : file.data).then((data) => {\n wasm.mountExternalData(path, data);\n }),\n );\n }\n\n // wait for all external data files to be loaded\n await Promise.all(loadingPromises);\n }\n\n for (const provider of options?.executionProviders ?? []) {\n const providerName = typeof provider === 'string' ? provider : provider.name;\n if (providerName === 'webnn') {\n wasm.shouldTransferToMLTensor = false;\n if (typeof provider !== 'string') {\n const webnnOptions = provider as InferenceSession.WebNNExecutionProviderOption;\n const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context;\n const gpuDevice = (webnnOptions as InferenceSession.WebNNOptionsWebGpu)?.gpuDevice;\n const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType;\n const powerPreference = (webnnOptions as InferenceSession.WebNNContextOptions)?.powerPreference;\n if (context) {\n wasm.currentContext = context as MLContext;\n } else if (gpuDevice) {\n wasm.currentContext = await wasm.webnnCreateMLContext!(gpuDevice);\n } else {\n wasm.currentContext = await wasm.webnnCreateMLContext!({ deviceType, powerPreference });\n }\n } else {\n wasm.currentContext = await wasm.webnnCreateMLContext!();\n }\n break;\n }\n }\n\n sessionHandle = await wasm._OrtCreateSession(modelDataOffset, modelDataLength, sessionOptionsHandle);\n wasm.webgpuOnCreateSession?.(sessionHandle);\n if (sessionHandle === 0) {\n checkLastError(\"Can't create a session.\");\n }\n\n wasm.jsepOnCreateSession?.();\n\n // clear current MLContext after session creation\n if (wasm.currentContext) {\n wasm.webnnRegisterMLContext!(sessionHandle, wasm.currentContext);\n wasm.currentContext = undefined;\n wasm.shouldTransferToMLTensor = true;\n }\n\n const [inputCount, outputCount] = getSessionInputOutputCount(sessionHandle);\n\n const enableGraphCapture = !!options?.enableGraphCapture;\n\n const inputNames = [];\n const outputNames = [];\n const inputMetadata: InferenceSession.ValueMetadata[] = [];\n const outputMetadata: InferenceSession.ValueMetadata[] = [];\n const outputPreferredLocations: SupportedTensorDataLocationForInputOutput[] = [];\n for (let i = 0; i < inputCount; i++) {\n const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i);\n if (nameOffset === 0) {\n checkLastError(\"Can't get an input name.\");\n }\n inputNamesUTF8Encoded.push(nameOffset);\n const name = wasm.UTF8ToString(nameOffset);\n inputNames.push(name);\n inputMetadata.push(\n elementType === 0\n ? { name, isTensor: false }\n : { name, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! },\n );\n }\n for (let i = 0; i < outputCount; i++) {\n const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i + inputCount);\n if (nameOffset === 0) {\n checkLastError(\"Can't get an output name.\");\n }\n outputNamesUTF8Encoded.push(nameOffset);\n const nameString = wasm.UTF8ToString(nameOffset);\n outputNames.push(nameString);\n outputMetadata.push(\n elementType === 0\n ? { name: nameString, isTensor: false }\n : { name: nameString, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! },\n );\n\n if (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) {\n if (enableGraphCapture && options?.preferredOutputLocation === undefined) {\n outputPreferredLocations.push('gpu-buffer');\n continue;\n }\n const location =\n typeof options?.preferredOutputLocation === 'string'\n ? options.preferredOutputLocation\n : (options?.preferredOutputLocation?.[nameString] ?? 'cpu');\n const isGraphOutput = wasm.webnnIsGraphOutput;\n if (location === 'cpu' && isGraphOutput && isGraphOutput(sessionHandle, nameString)) {\n outputPreferredLocations.push('ml-tensor-cpu-output');\n continue;\n }\n if (location !== 'cpu' && location !== 'cpu-pinned' && location !== 'gpu-buffer' && location !== 'ml-tensor') {\n throw new Error(`Not supported preferred output location: ${location}.`);\n }\n if (enableGraphCapture && location !== 'gpu-buffer') {\n throw new Error(\n `Not supported preferred output location: ${location}. Only 'gpu-buffer' location is supported when enableGraphCapture is true.`,\n );\n }\n outputPreferredLocations.push(location);\n }\n }\n\n // use IO binding only when at least one output is preferred to be on GPU.\n let bindingState: IOBindingState | null = null;\n if (\n (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) &&\n outputPreferredLocations.some((l) => l === 'gpu-buffer' || l === 'ml-tensor' || l === 'ml-tensor-cpu-output')\n ) {\n ioBindingHandle = wasm._OrtCreateBinding(sessionHandle);\n if (ioBindingHandle === 0) {\n checkLastError(\"Can't create IO binding.\");\n }\n\n bindingState = {\n handle: ioBindingHandle,\n outputPreferredLocations,\n outputPreferredLocationsEncoded: outputPreferredLocations\n // 'ml-tensor-cpu-output' is treated as 'ml-tensor' for the purpose of IO binding.\n .map((l) => (l === 'ml-tensor-cpu-output' ? 'ml-tensor' : l))\n .map((l) => dataLocationStringToEnum(l)),\n };\n }\n\n activeSessions.set(sessionHandle, [\n sessionHandle,\n inputNamesUTF8Encoded,\n outputNamesUTF8Encoded,\n bindingState,\n enableGraphCapture,\n false,\n ]);\n return [sessionHandle, inputNames, outputNames, inputMetadata, outputMetadata];\n } catch (e) {\n inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n\n if (ioBindingHandle !== 0) {\n if (wasm._OrtReleaseBinding(ioBindingHandle) !== 0) {\n checkLastError(\"Can't release IO binding.\");\n }\n }\n\n if (sessionHandle !== 0) {\n if (wasm._OrtReleaseSession(sessionHandle) !== 0) {\n checkLastError(\"Can't release session.\");\n }\n }\n throw e;\n } finally {\n wasm._free(modelDataOffset);\n if (sessionOptionsHandle !== 0) {\n if (wasm._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) {\n checkLastError(\"Can't release session options.\");\n }\n }\n allocs.forEach((alloc) => wasm._free(alloc));\n\n // unmount external data if necessary\n wasm.unmountExternalData?.();\n }\n};\n\nexport const releaseSession = (sessionId: number): void => {\n const wasm = getInstance();\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error(`cannot release session. invalid session id: ${sessionId}`);\n }\n const [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture] = session;\n\n if (ioBindingState) {\n if (enableGraphCapture) {\n if (wasm._OrtClearBoundOutputs(ioBindingState.handle) !== 0) {\n checkLastError(\"Can't clear bound outputs.\");\n }\n }\n if (wasm._OrtReleaseBinding(ioBindingState.handle) !== 0) {\n checkLastError(\"Can't release IO binding.\");\n }\n }\n\n wasm.jsepOnReleaseSession?.(sessionId);\n wasm.webnnOnReleaseSession?.(sessionId);\n wasm.webgpuOnReleaseSession?.(sessionId);\n\n inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n if (wasm._OrtReleaseSession(sessionHandle) !== 0) {\n checkLastError(\"Can't release session.\");\n }\n activeSessions.delete(sessionId);\n};\n\nexport const prepareInputOutputTensor = async (\n tensor: TensorMetadata | null,\n tensorHandles: number[],\n allocs: number[],\n sessionId: number,\n tensorNameUTF8Encoded: number,\n index: number,\n enableGraphCapture = false,\n): Promise<void> => {\n if (!tensor) {\n tensorHandles.push(0);\n return;\n }\n\n const wasm = getInstance();\n const ptrSize = wasm.PTR_SIZE;\n\n const dataType = tensor[0];\n const dims = tensor[1];\n const location = tensor[3];\n let actualLocation = location;\n\n let rawData: number;\n let dataByteLength: number;\n\n if (dataType === 'string' && (location === 'gpu-buffer' || location === 'ml-tensor')) {\n throw new Error('String tensor is not supported on GPU.');\n }\n\n if (enableGraphCapture && location !== 'gpu-buffer') {\n throw new Error(\n `External buffer must be provided for input/output index ${index} when enableGraphCapture is true.`,\n );\n }\n\n if (location === 'gpu-buffer') {\n const gpuBuffer = tensor[2].gpuBuffer;\n dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!;\n\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n const registerBuffer = wasm.webgpuRegisterBuffer;\n if (!registerBuffer) {\n throw new Error('Tensor location \"gpu-buffer\" is not supported without using WebGPU.');\n }\n\n rawData = registerBuffer(gpuBuffer, sessionId);\n } else {\n const registerBuffer = wasm.jsepRegisterBuffer;\n if (!registerBuffer) {\n throw new Error('Tensor location \"gpu-buffer\" is not supported without using WebGPU.');\n }\n rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength);\n }\n } else if (location === 'ml-tensor') {\n const mlTensor = tensor[2].mlTensor as MLTensor;\n dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!;\n\n const registerMLTensor = wasm.webnnRegisterMLTensor;\n if (!registerMLTensor) {\n throw new Error('Tensor location \"ml-tensor\" is not supported without using WebNN.');\n }\n rawData = registerMLTensor(sessionId, mlTensor, tensorDataTypeStringToEnum(dataType), dims);\n } else {\n const data = tensor[2];\n\n if (Array.isArray(data)) {\n // string tensor\n dataByteLength = ptrSize * data.length;\n rawData = wasm._malloc(dataByteLength);\n allocs.push(rawData);\n for (let i = 0; i < data.length; i++) {\n if (typeof data[i] !== 'string') {\n throw new TypeError(`tensor data at index ${i} is not a string`);\n }\n wasm.setValue(rawData + i * ptrSize, allocWasmString(data[i], allocs), '*');\n }\n } else {\n const isGraphInput = wasm.webnnIsGraphInput;\n const isGraphOutput = wasm.webnnIsGraphOutput;\n if (dataType !== 'string' && isGraphInput && isGraphOutput) {\n const tensorName = wasm.UTF8ToString(tensorNameUTF8Encoded);\n // Promote the tensor to 'ml-tensor' if it is a graph input.\n if (isGraphInput(sessionId, tensorName) || isGraphOutput(sessionId, tensorName)) {\n const dataTypeEnum = tensorDataTypeStringToEnum(dataType);\n dataByteLength = calculateTensorSizeInBytes(dataTypeEnum, dims)!;\n actualLocation = 'ml-tensor';\n const createTemporaryTensor = wasm.webnnCreateTemporaryTensor;\n const uploadTensor = wasm.webnnUploadTensor;\n if (!createTemporaryTensor || !uploadTensor) {\n throw new Error('Tensor location \"ml-tensor\" is not supported without using WebNN.');\n }\n const tensorId = await createTemporaryTensor(sessionId, dataTypeEnum, dims as number[]);\n uploadTensor(tensorId, new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n rawData = tensorId;\n } else {\n dataByteLength = data.byteLength;\n rawData = wasm._malloc(dataByteLength);\n allocs.push(rawData);\n wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData);\n }\n } else {\n dataByteLength = data.byteLength;\n rawData = wasm._malloc(dataByteLength);\n allocs.push(rawData);\n wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData);\n }\n }\n }\n\n const stack = wasm.stackSave();\n const dimsOffset = wasm.stackAlloc(4 * dims.length);\n try {\n dims.forEach((d, index) => wasm.setValue(dimsOffset + index * ptrSize, d, ptrSize === 4 ? 'i32' : 'i64'));\n const tensor = wasm._OrtCreateTensor(\n tensorDataTypeStringToEnum(dataType),\n rawData,\n dataByteLength,\n dimsOffset,\n dims.length,\n dataLocationStringToEnum(actualLocation),\n );\n if (tensor === 0) {\n checkLastError(`Can't create tensor for input/output. session=${sessionId}, index=${index}.`);\n }\n tensorHandles.push(tensor);\n } finally {\n wasm.stackRestore(stack);\n }\n};\n\n/**\n * perform inference run\n */\nexport const run = async (\n sessionId: number,\n inputIndices: number[],\n inputTensors: TensorMetadata[],\n outputIndices: number[],\n outputTensors: Array<TensorMetadata | null>,\n options: InferenceSession.RunOptions,\n): Promise<TensorMetadata[]> => {\n const wasm = getInstance();\n const ptrSize = wasm.PTR_SIZE;\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error(`cannot run inference. invalid session id: ${sessionId}`);\n }\n const sessionHandle = session[0];\n const inputNamesUTF8Encoded = session[1];\n const outputNamesUTF8Encoded = session[2];\n const ioBindingState = session[3];\n const enableGraphCapture = session[4];\n const inputOutputBound = session[5];\n\n const inputCount = inputIndices.length;\n const outputCount = outputIndices.length;\n\n let runOptionsHandle = 0;\n let runOptionsAllocs: number[] = [];\n\n const inputTensorHandles: number[] = [];\n const outputTensorHandles: number[] = [];\n const inputOutputAllocs: number[] = [];\n const preAllocatedOutputs: number[] = [];\n\n const beforeRunStack = wasm.stackSave();\n const inputValuesOffset = wasm.stackAlloc(inputCount * ptrSize);\n const inputNamesOffset = wasm.stackAlloc(inputCount * ptrSize);\n const outputValuesOffset = wasm.stackAlloc(outputCount * ptrSize);\n const outputNamesOffset = wasm.stackAlloc(outputCount * ptrSize);\n\n try {\n [runOptionsHandle, runOptionsAllocs] = setRunOptions(options);\n\n TRACE_EVENT_BEGIN('wasm prepareInputOutputTensor');\n // create input tensors\n for (let i = 0; i < inputCount; i++) {\n await prepareInputOutputTensor(\n inputTensors[i],\n inputTensorHandles,\n inputOutputAllocs,\n sessionId,\n inputNamesUTF8Encoded[inputIndices[i]],\n inputIndices[i],\n enableGraphCapture,\n );\n }\n\n // create output tensors\n for (let i = 0; i < outputCount; i++) {\n await prepareInputOutputTensor(\n outputTensors[i],\n outputTensorHandles,\n inputOutputAllocs,\n sessionId,\n outputNamesUTF8Encoded[outputIndices[i]],\n inputCount + outputIndices[i],\n enableGraphCapture,\n );\n }\n TRACE_EVENT_END('wasm prepareInputOutputTensor');\n\n for (let i = 0; i < inputCount; i++) {\n wasm.setValue(inputValuesOffset + i * ptrSize, inputTensorHandles[i], '*');\n wasm.setValue(inputNamesOffset + i * ptrSize, inputNamesUTF8Encoded[inputIndices[i]], '*');\n }\n for (let i = 0; i < outputCount; i++) {\n wasm.setValue(outputValuesOffset + i * ptrSize, outputTensorHandles[i], '*');\n wasm.setValue(outputNamesOffset + i * ptrSize, outputNamesUTF8Encoded[outputIndices[i]], '*');\n }\n\n if ((!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) && ioBindingState && !inputOutputBound) {\n const { handle, outputPreferredLocations, outputPreferredLocationsEncoded } = ioBindingState;\n\n if (inputNamesUTF8Encoded.length !== inputCount) {\n throw new Error(\n `input count from feeds (${inputCount}) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).`,\n );\n }\n\n TRACE_EVENT_BEGIN('wasm bindInputsOutputs');\n // process inputs\n for (let i = 0; i < inputCount; i++) {\n const index = inputIndices[i];\n const errorCode = await wasm._OrtBindInput(handle, inputNamesUTF8Encoded[index], inputTensorHandles[i]);\n if (errorCode !== 0) {\n checkLastError(`Can't bind input[${i}] for session=${sessionId}.`);\n }\n }\n\n // process pre-allocated outputs\n for (let i = 0; i < outputCount; i++) {\n const index = outputIndices[i];\n const location = outputTensors[i]?.[3]; // undefined means output is not pre-allocated.\n\n if (location) {\n // output is pre-allocated, store and bind the tensor.\n preAllocatedOutputs.push(outputTensorHandles[i]);\n const errorCode = wasm._OrtBindOutput(handle, outputNamesUTF8Encoded[index], outputTensorHandles[i], 0);\n if (errorCode !== 0) {\n checkLastError(`Can't bind pre-allocated output[${i}] for session=${sessionId}.`);\n }\n } else {\n // output is not pre-allocated. reset preferred location.\n const errorCode = wasm._OrtBindOutput(\n handle,\n outputNamesUTF8Encoded[index],\n 0,\n outputPreferredLocationsEncoded[index],\n );\n if (errorCode !== 0) {\n checkLastError(`Can't bind output[${i}] to ${outputPreferredLocations[i]} for session=${sessionId}.`);\n }\n }\n }\n TRACE_EVENT_END('wasm bindInputsOutputs');\n activeSessions.set(sessionId, [\n sessionHandle,\n inputNamesUTF8Encoded,\n outputNamesUTF8Encoded,\n ioBindingState,\n enableGraphCapture,\n true,\n ]);\n }\n\n wasm.jsepOnRunStart?.(sessionHandle);\n wasm.webnnOnRunStart?.(sessionHandle);\n\n let errorCode: number;\n if ((!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) && ioBindingState) {\n errorCode = await wasm._OrtRunWithBinding(\n sessionHandle,\n ioBindingState.handle,\n outputCount,\n outputValuesOffset,\n runOptionsHandle,\n );\n } else {\n errorCode = await wasm._OrtRun(\n sessionHandle,\n inputNamesOffset,\n inputValuesOffset,\n inputCount,\n outputNamesOffset,\n outputCount,\n outputValuesOffset,\n runOptionsHandle,\n );\n }\n\n if (errorCode !== 0) {\n checkLastError('failed to call OrtRun().');\n }\n\n const output: TensorMetadata[] = [];\n const outputPromises: Array<Promise<[number, Tensor.DataType]>> = [];\n\n TRACE_EVENT_BEGIN('wasm ProcessOutputTensor');\n for (let i = 0; i < outputCount; i++) {\n const tensor = Number(wasm.getValue(outputValuesOffset + i * ptrSize, '*'));\n // TODO: revisit this part to ensure it works for WebGPU when both pre-allocated outputs and\n // preferred location are specified.\n // Certain pre-allocated tensors may already be bound in the IO binding. e.g. the WebNN backend\n // always binds its tensor to 'ml-tensor'. In such cases, the tensor ID might change after binding,\n // but copying data for these tensors should still be avoided.\n if (tensor === outputTensorHandles[i] || preAllocatedOutputs.includes(outputTensorHandles[i])) {\n // output tensor is pre-allocated. no need to copy data.\n output.push(outputTensors[i]!);\n if (tensor !== outputTensorHandles[i]) {\n // release redundant tensor earlier.\n if (wasm._OrtReleaseTensor(tensor) !== 0) {\n checkLastError(\"Can't release tensor.\");\n }\n }\n continue;\n }\n\n const beforeGetTensorDataStack = wasm.stackSave();\n // stack allocate 4 pointer value\n const tensorDataOffset = wasm.stackAlloc(4 * ptrSize);\n\n let keepOutputTensor = false;\n let type: Tensor.Type | undefined,\n dataOffset = 0;\n try {\n const errorCode = wasm._OrtGetTensorData(\n tensor,\n tensorDataOffset,\n tensorDataOffset + ptrSize,\n tensorDataOffset + 2 * ptrSize,\n\n tensorDataOffset + 3 * ptrSize,\n );\n if (errorCode !== 0) {\n checkLastError(`Can't access output tensor data on index ${i}.`);\n }\n const valueType = ptrSize === 4 ? 'i32' : 'i64';\n const dataType = Number(wasm.getValue(tensorDataOffset, valueType));\n dataOffset = wasm.getValue(tensorDataOffset + ptrSize, '*');\n const dimsOffset = wasm.getValue(tensorDataOffset + ptrSize * 2, '*');\n const dimsLength = Number(wasm.getValue(tensorDataOffset + ptrSize * 3, valueType));\n const dims = [];\n for (let i = 0; i < dimsLength; i++) {\n dims.push(Number(wasm.getValue(dimsOffset + i * ptrSize, valueType)));\n }\n if (wasm._OrtFree(dimsOffset) !== 0) {\n checkLastError(\"Can't free memory for tensor dims.\");\n }\n const size = dims.reduce((a, b) => a * b, 1);\n type = tensorDataTypeEnumToString(dataType);\n\n const preferredLocation = ioBindingState?.outputPreferredLocations[outputIndices[i]];\n\n if (type === 'string') {\n if (preferredLocation === 'gpu-buffer' || preferredLocation === 'ml-tensor') {\n throw new Error('String tensor is not supported on GPU.');\n }\n const stringData: string[] = [];\n for (let i = 0; i < size; i++) {\n const offset = wasm.getValue(dataOffset + i * ptrSize, '*');\n const nextOffset = wasm.getValue(dataOffset + (i + 1) * ptrSize, '*');\n const maxBytesToRead = i === size - 1 ? undefined : nextOffset - offset;\n stringData.push(wasm.UTF8ToString(offset, maxBytesToRead));\n }\n output.push([type, dims, stringData, 'cpu']);\n } else {\n // If a certain output's preferred location is GPU but the tensor is empty, we still need to create a CPU\n // tensor for it. There is no mapping GPU buffer for an empty tensor.\n if (preferredLocation === 'gpu-buffer' && size > 0) {\n const getBuffer = !BUILD_DEFS.DISABLE_WEBGPU ? wasm.webgpuGetBuffer : wasm.jsepGetBuffer;\n if (!getBuffer) {\n throw new Error('preferredLocation \"gpu-buffer\" is not supported without using WebGPU.');\n }\n const gpuBuffer = getBuffer(dataOffset);\n const bufferSize = calculateTensorSizeInBytes(dataType, size);\n if (bufferSize === undefined || !isGpuBufferSupportedType(type)) {\n throw new Error(`Unsupported data type: ${type}`);\n }\n\n // do not release the tensor right now. it will be released when user calls tensor.dispose().\n keepOutputTensor = true;\n\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n wasm.webgpuRegisterBuffer!(gpuBuffer, sessionId, dataOffset);\n const downloadDataFunction = wasm.webgpuCreateDownloader!(gpuBuffer, bufferSize, sessionId);\n output.push([\n type,\n dims,\n {\n gpuBuffer,\n download: async () => {\n const arrayBuffer = await downloadDataFunction();\n const data = new (tensorTypeToTypedArrayConstructor(type!))(arrayBuffer);\n return data as Tensor.DataTypeMap[Tensor.GpuBufferDataTypes];\n },\n dispose: () => {\n if (wasm._OrtReleaseTensor(tensor) !== 0) {\n checkLastError(\"Can't release tensor.\");\n }\n },\n },\n 'gpu-buffer',\n ]);\n } else {\n output.push([\n type,\n dims,\n {\n gpuBuffer,\n download: wasm.jsepCreateDownloader!(gpuBuffer, bufferSize, type),\n dispose: () => {\n if (wasm._OrtReleaseTensor(tensor) !== 0) {\n checkLastError(\"Can't release tensor.\");\n }\n },\n },\n 'gpu-buffer',\n ]);\n }\n } else if (preferredLocation === 'ml-tensor' && size > 0) {\n const ensureTensor = wasm.webnnEnsureTensor;\n const isGraphInputOutputTypeSupported = wasm.webnnIsGraphInputOutputTypeSupported;\n if (!ensureTensor || !isGraphInputOutputTypeSupported) {\n throw new Error('preferredLocation \"ml-tensor\" is not supported without using WebNN.');\n }\n const tensorSize = calculateTensorSizeInBytes(dataType, size);\n if (tensorSize === undefined || !isMLTensorSupportedType(type)) {\n throw new Error(`Unsupported data type: ${type}`);\n }\n if (!isGraphInputOutputTypeSupported(sessionId, type, false)) {\n throw new Error(\n `preferredLocation \"ml-tensor\" for ${type} output is not supported by current WebNN Context.`,\n );\n }\n\n // If the graph has been partitioned, the output tensor may have not been created. For this reason, we use\n // ensureTensor to get/create the MLTensor. In which case, we don't need to copy the data if a new tensor\n // has been created.\n const mlTensor = await ensureTensor(sessionId, dataOffset, dataType, dims, false);\n\n // do not release the tensor right now. it will be released when user calls tensor.dispose().\n keepOutputTensor = true;\n\n output.push([\n type,\n dims,\n {\n mlTensor,\n download: wasm.webnnCreateMLTensorDownloader!(dataOffset, type),\n dispose: () => {\n wasm.webnnReleaseTensorId!(dataOffset);\n wasm._OrtReleaseTensor(tensor);\n },\n },\n 'ml-tensor',\n ]);\n } else if (preferredLocation === 'ml-tensor-cpu-output' && size > 0) {\n const data = wasm.webnnCreateMLTensorDownloader!(dataOffset, type as Tensor.MLTensorDataTypes)();\n const index = output.length;\n // Delay the data download and releasing the tensor until we can wait for all output tensors to be downloaded.\n keepOutputTensor = true;\n outputPromises.push(\n (async () => {\n const result: [number, Tensor.DataType] = [index, await data];\n wasm.webnnReleaseTensorId!(dataOffset);\n wasm._OrtReleaseTensor(tensor);\n return result;\n })(),\n );\n output.push([type, dims, [], 'cpu']);\n } else {\n const typedArrayConstructor = tensorTypeToTypedArrayConstructor(type);\n const data = new typedArrayConstructor(size);\n new Uint8Array(data.buffer, data.byteOffset, data.byteLength).set(\n wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength),\n );\n output.push([type, dims, data, 'cpu']);\n }\n }\n } finally {\n wasm.stackRestore(beforeGetTensorDataStack);\n if (type === 'string' && dataOffset) {\n wasm._free(dataOffset);\n }\n if (!keepOutputTensor) {\n wasm._OrtReleaseTensor(tensor);\n }\n }\n }\n\n if (ioBindingState && !enableGraphCapture) {\n if (wasm._OrtClearBoundOutputs(ioBindingState.handle) !== 0) {\n checkLastError(\"Can't clear bound outputs.\");\n }\n activeSessions.set(sessionId, [\n sessionHandle,\n inputNamesUTF8Encoded,\n outputNamesUTF8Encoded,\n ioBindingState,\n enableGraphCapture,\n false,\n ]);\n }\n // Wait for all output tensor data to be downloaded.\n for (const [index, data] of await Promise.all(outputPromises)) {\n output[index][2] = data;\n }\n TRACE_EVENT_END('wasm ProcessOutputTensor');\n return output;\n } finally {\n wasm.webnnOnRunEnd?.(sessionHandle);\n\n wasm.stackRestore(beforeRunStack);\n\n if (!BUILD_DEFS.DISABLE_WEBGPU) {\n inputTensors.forEach((t) => {\n if (t && t[3] === 'gpu-buffer') {\n wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer);\n }\n });\n outputTensors.forEach((t) => {\n if (t && t[3] === 'gpu-buffer') {\n wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer);\n }\n });\n }\n inputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v));\n outputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v));\n inputOutputAllocs.forEach((p) => wasm._free(p));\n\n if (runOptionsHandle !== 0) {\n wasm._OrtReleaseRunOptions(runOptionsHandle);\n }\n runOptionsAllocs.forEach((p) => wasm._free(p));\n }\n};\n\n/**\n * end profiling\n */\nexport const endProfiling = (sessionId: number): void => {\n const wasm = getInstance();\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error('invalid session id');\n }\n const sessionHandle = session[0];\n\n // profile file name is not used yet, but it must be freed.\n const profileFileName = wasm._OrtEndProfiling(sessionHandle);\n if (profileFileName === 0) {\n checkLastError(\"Can't get an profile file name.\");\n }\n wasm._OrtFree(profileFileName);\n};\n\nexport const extractTransferableBuffers = (tensors: readonly SerializableTensorMetadata[]): ArrayBufferLike[] => {\n const buffers: ArrayBufferLike[] = [];\n for (const tensor of tensors) {\n const data = tensor[2];\n if (!Array.isArray(data) && 'buffer' in data) {\n buffers.push(data.buffer);\n }\n }\n return buffers;\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env, InferenceSession } from 'onnxruntime-common';\n\nimport {\n OrtWasmMessage,\n SerializableInternalBuffer,\n SerializableSessionMetadata,\n SerializableTensorMetadata,\n TensorMetadata,\n} from './proxy-messages';\nimport * as core from './wasm-core-impl';\nimport { initializeWebAssembly } from './wasm-factory';\nimport {\n importProxyWorker,\n inferWasmPathPrefixFromScriptSrc,\n isEsmImportMetaUrlHardcodedAsFileUri,\n} from './wasm-utils-import';\n\nconst isProxy = (): boolean => !!env.wasm.proxy && typeof document !== 'undefined';\nlet proxyWorker: Worker | undefined;\nlet initializing = false;\nlet initialized = false;\nlet aborted = false;\nlet temporaryObjectUrl: string | undefined;\n\ntype PromiseCallbacks<T = void> = [resolve: (result: T) => void, reject: (reason: unknown) => void];\nlet initWasmCallbacks: PromiseCallbacks;\nconst queuedCallbacks: Map<OrtWasmMessage['type'], Array<PromiseCallbacks<unknown>>> = new Map();\n\nconst enqueueCallbacks = (type: OrtWasmMessage['type'], callbacks: PromiseCallbacks<unknown>): void => {\n const queue = queuedCallbacks.get(type);\n if (queue) {\n queue.push(callbacks);\n } else {\n queuedCallbacks.set(type, [callbacks]);\n }\n};\n\nconst ensureWorker = (): void => {\n if (initializing || !initialized || aborted || !proxyWorker) {\n throw new Error('worker not ready');\n }\n};\n\nconst onProxyWorkerMessage = (ev: MessageEvent<OrtWasmMessage>): void => {\n switch (ev.data.type) {\n case 'init-wasm':\n initializing = false;\n if (ev.data.err) {\n aborted = true;\n initWasmCallbacks[1](ev.data.err);\n } else {\n initialized = true;\n initWasmCallbacks[0]();\n }\n if (temporaryObjectUrl) {\n URL.revokeObjectURL(temporaryObjectUrl);\n temporaryObjectUrl = undefined;\n }\n break;\n case 'init-ep':\n case 'copy-from':\n case 'create':\n case 'release':\n case 'run':\n case 'end-profiling': {\n const callbacks = queuedCallbacks.get(ev.data.type)!;\n if (ev.data.err) {\n callbacks.shift();\n } else {\n callbacks.shift();\n }\n break;\n }\n default:\n }\n};\n\nexport const initializeWebAssemblyAndOrtRuntime = async (): Promise<void> => {\n if (initialized) {\n return;\n }\n if (initializing) {\n throw new Error(\"multiple calls to 'initWasm()' detected.\");\n }\n if (aborted) {\n throw new Error(\"previous call to 'initWasm()' failed.\");\n }\n\n initializing = true;\n\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n return new Promise<void>((resolve, reject) => {\n proxyWorker?.terminate();\n\n void importProxyWorker().then(([objectUrl, worker]) => {\n try {\n proxyWorker = worker;\n proxyWorker.onerror = (ev: ErrorEvent) => reject(ev);\n proxyWorker.onmessage = onProxyWorkerMessage;\n initWasmCallbacks = [resolve, reject];\n const message: OrtWasmMessage = { type: 'init-wasm', in: env };\n\n // if the proxy worker is loaded from a blob URL, we need to make sure the path information is not lost.\n //\n // when `env.wasm.wasmPaths` is not set, we need to pass the path information to the worker.\n //\n if (!BUILD_DEFS.ENABLE_BUNDLE_WASM_JS && !message.in!.wasm.wasmPaths && objectUrl) {\n // for a build not bundled the wasm JS, we need to pass the path prefix to the worker.\n // the path prefix will be used to resolve the path to both the wasm JS and the wasm file.\n const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc();\n if (inferredWasmPathPrefix) {\n message.in!.wasm.wasmPaths = inferredWasmPathPrefix;\n }\n }\n\n if (\n BUILD_DEFS.IS_ESM &&\n BUILD_DEFS.ENABLE_BUNDLE_WASM_JS &&\n !message.in!.wasm.wasmPaths &&\n (objectUrl || isEsmImportMetaUrlHardcodedAsFileUri)\n ) {\n // for a build bundled the wasm JS, if either of the following conditions is met:\n // - the proxy worker is loaded from a blob URL\n // - `import.meta.url` is a file URL, it means it is overwritten by the bundler.\n //\n // in either case, the path information is lost, we need to pass the path of the .wasm file to the worker.\n // we need to use the bundler preferred URL format:\n // new URL('filename', import.meta.url)\n // so that the bundler can handle the file using corresponding loaders.\n message.in!.wasm.wasmPaths = {\n wasm: !BUILD_DEFS.DISABLE_JSEP\n ? new URL('ort-wasm-simd-threaded.jsep.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n : BUILD_DEFS.ENABLE_JSPI\n ? new URL('ort-wasm-simd-threaded.jspi.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n : !BUILD_DEFS.DISABLE_WEBGPU\n ? new URL('ort-wasm-simd-threaded.asyncify.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n : new URL('ort-wasm-simd-threaded.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href,\n };\n }\n proxyWorker.postMessage(message);\n temporaryObjectUrl = objectUrl;\n } catch (e) {\n reject(e);\n }\n }, reject);\n });\n } else {\n try {\n await initializeWebAssembly(env.wasm);\n await core.initRuntime(env);\n initialized = true;\n } catch (e) {\n aborted = true;\n throw e;\n } finally {\n initializing = false;\n }\n }\n};\n\nexport const initializeOrtEp = async (epName: string): Promise<void> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<void>((resolve, reject) => {\n enqueueCallbacks('init-ep', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'init-ep', in: { epName, env } };\n proxyWorker!.postMessage(message);\n });\n } else {\n await core.initEp(env, epName);\n }\n};\n\nexport const copyFromExternalBuffer = async (buffer: Uint8Array): Promise<SerializableInternalBuffer> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<SerializableInternalBuffer>((resolve, reject) => {\n enqueueCallbacks('copy-from', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'copy-from', in: { buffer } };\n proxyWorker!.postMessage(message, [buffer.buffer]);\n });\n } else {\n return core.copyFromExternalBuffer(buffer);\n }\n};\n\nexport const createSession = async (\n model: SerializableInternalBuffer | Uint8Array,\n options?: InferenceSession.SessionOptions,\n): Promise<SerializableSessionMetadata> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n // check unsupported options\n if (options?.preferredOutputLocation) {\n throw new Error('session option \"preferredOutputLocation\" is not supported for proxy.');\n }\n ensureWorker();\n return new Promise<SerializableSessionMetadata>((resolve, reject) => {\n enqueueCallbacks('create', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'create', in: { model, options: { ...options } } };\n const transferable: Transferable[] = [];\n if (model instanceof Uint8Array) {\n transferable.push(model.buffer);\n }\n proxyWorker!.postMessage(message, transferable);\n });\n } else {\n return core.createSession(model, options);\n }\n};\n\nexport const releaseSession = async (sessionId: number): Promise<void> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<void>((resolve, reject) => {\n enqueueCallbacks('release', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'release', in: sessionId };\n proxyWorker!.postMessage(message);\n });\n } else {\n core.releaseSession(sessionId);\n }\n};\n\nexport const run = async (\n sessionId: number,\n inputIndices: number[],\n inputs: TensorMetadata[],\n outputIndices: number[],\n outputs: Array<TensorMetadata | null>,\n options: InferenceSession.RunOptions,\n): Promise<TensorMetadata[]> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n // check inputs location\n if (inputs.some((t) => t[3] !== 'cpu')) {\n throw new Error('input tensor on GPU is not supported for proxy.');\n }\n // check outputs location\n if (outputs.some((t) => t)) {\n throw new Error('pre-allocated output tensor is not supported for proxy.');\n }\n ensureWorker();\n return new Promise<SerializableTensorMetadata[]>((resolve, reject) => {\n enqueueCallbacks('run', [resolve, reject]);\n const serializableInputs = inputs as SerializableTensorMetadata[]; // every input is on CPU.\n const message: OrtWasmMessage = {\n type: 'run',\n in: { sessionId, inputIndices, inputs: serializableInputs, outputIndices, options },\n };\n proxyWorker!.postMessage(message, core.extractTransferableBuffers(serializableInputs));\n });\n } else {\n return core.run(sessionId, inputIndices, inputs, outputIndices, outputs, options);\n }\n};\n\nexport const endProfiling = async (sessionId: number): Promise<void> => {\n if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n ensureWorker();\n return new Promise<void>((resolve, reject) => {\n enqueueCallbacks('end-profiling', [resolve, reject]);\n const message: OrtWasmMessage = { type: 'end-profiling', in: sessionId };\n proxyWorker!.postMessage(message);\n });\n } else {\n core.endProfiling(sessionId);\n }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n InferenceSession,\n InferenceSessionHandler,\n SessionHandler,\n Tensor,\n TRACE_FUNC_BEGIN,\n TRACE_FUNC_END,\n} from 'onnxruntime-common';\n\nimport { SerializableInternalBuffer, TensorMetadata } from './proxy-messages';\nimport { copyFromExternalBuffer, createSession, endProfiling, releaseSession, run } from './proxy-wrapper';\nimport { isGpuBufferSupportedType, isMLTensorSupportedType } from './wasm-common';\nimport { isNode } from './wasm-utils-env';\nimport { loadFile } from './wasm-utils-load-file';\n\nexport const encodeTensorMetadata = (tensor: Tensor, getName: () => string): TensorMetadata => {\n switch (tensor.location) {\n case 'cpu':\n return [tensor.type, tensor.dims, tensor.data, 'cpu'];\n case 'gpu-buffer':\n return [tensor.type, tensor.dims, { gpuBuffer: tensor.gpuBuffer }, 'gpu-buffer'];\n case 'ml-tensor':\n return [tensor.type, tensor.dims, { mlTensor: tensor.mlTensor }, 'ml-tensor'];\n default:\n throw new Error(`invalid data location: ${tensor.location} for ${getName()}`);\n }\n};\n\nexport const decodeTensorMetadata = (tensor: TensorMetadata): Tensor => {\n switch (tensor[3]) {\n case 'cpu':\n return new Tensor(tensor[0], tensor[2], tensor[1]);\n case 'gpu-buffer': {\n const dataType = tensor[0];\n if (!isGpuBufferSupportedType(dataType)) {\n throw new Error(`not supported data type: ${dataType} for deserializing GPU tensor`);\n }\n const { gpuBuffer, download, dispose } = tensor[2];\n return Tensor.fromGpuBuffer(gpuBuffer, { dataType, dims: tensor[1], download, dispose });\n }\n case 'ml-tensor': {\n const dataType = tensor[0];\n if (!isMLTensorSupportedType(dataType)) {\n throw new Error(`not supported data type: ${dataType} for deserializing MLTensor tensor`);\n }\n const { mlTensor, download, dispose } = tensor[2];\n return Tensor.fromMLTensor(mlTensor, { dataType, dims: tensor[1], download, dispose });\n }\n default:\n throw new Error(`invalid data location: ${tensor[3]}`);\n }\n};\n\nexport class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHandler {\n private sessionId: number;\n\n inputNames: readonly string[];\n outputNames: readonly string[];\n inputMetadata: readonly InferenceSession.ValueMetadata[];\n outputMetadata: readonly InferenceSession.ValueMetadata[];\n\n async fetchModelAndCopyToWasmMemory(path: string): Promise<SerializableInternalBuffer> {\n // fetch model from url and move to wasm heap.\n return copyFromExternalBuffer(await loadFile(path));\n }\n\n async loadModel(pathOrBuffer: string | Uint8Array, options?: InferenceSession.SessionOptions): Promise<void> {\n TRACE_FUNC_BEGIN();\n let model: Parameters<typeof createSession>[0];\n\n if (typeof pathOrBuffer === 'string') {\n if (isNode) {\n // node\n model = await loadFile(pathOrBuffer);\n } else {\n // browser\n // fetch model and copy to wasm heap.\n model = await this.fetchModelAndCopyToWasmMemory(pathOrBuffer);\n }\n } else {\n model = pathOrBuffer;\n }\n\n [this.sessionId, this.inputNames, this.outputNames, this.inputMetadata, this.outputMetadata] = await createSession(\n model,\n options,\n );\n TRACE_FUNC_END();\n }\n\n async dispose(): Promise<void> {\n return releaseSession(this.sessionId);\n }\n\n async run(\n feeds: SessionHandler.FeedsType,\n fetches: SessionHandler.FetchesType,\n options: InferenceSession.RunOptions,\n ): Promise<SessionHandler.ReturnType> {\n TRACE_FUNC_BEGIN();\n const inputArray: Tensor[] = [];\n const inputIndices: number[] = [];\n Object.entries(feeds).forEach((kvp) => {\n const name = kvp[0];\n const tensor = kvp[1];\n const index = this.inputNames.indexOf(name);\n if (index === -1) {\n throw new Error(`invalid input '${name}'`);\n }\n inputArray.push(tensor);\n inputIndices.push(index);\n });\n\n const outputArray: Array<Tensor | null> = [];\n const outputIndices: number[] = [];\n Object.entries(fetches).forEach((kvp) => {\n const name = kvp[0];\n const tensor = kvp[1];\n const index = this.outputNames.indexOf(name);\n if (index === -1) {\n throw new Error(`invalid output '${name}'`);\n }\n outputArray.push(tensor);\n outputIndices.push(index);\n });\n\n const inputs = inputArray.map((t, i) =>\n encodeTensorMetadata(t, () => `input \"${this.inputNames[inputIndices[i]]}\"`),\n );\n const outputs = outputArray.map((t, i) =>\n t ? encodeTensorMetadata(t, () => `output \"${this.outputNames[outputIndices[i]]}\"`) : null,\n );\n\n const results = await run(this.sessionId, inputIndices, inputs, outputIndices, outputs, options);\n\n const resultMap: SessionHandler.ReturnType = {};\n for (let i = 0; i < results.length; i++) {\n resultMap[this.outputNames[outputIndices[i]]] = outputArray[i] ?? decodeTensorMetadata(results[i]);\n }\n TRACE_FUNC_END();\n return resultMap;\n }\n\n startProfiling(): void {\n // TODO: implement profiling\n }\n\n endProfiling(): void {\n void endProfiling(this.sessionId);\n }\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Backend, env, InferenceSession, InferenceSessionHandler } from 'onnxruntime-common';\n\nimport { initializeOrtEp, initializeWebAssemblyAndOrtRuntime } from './wasm/proxy-wrapper';\nimport { OnnxruntimeWebAssemblySessionHandler } from './wasm/session-handler-inference';\n\n/**\n * This function initializes all flags for WebAssembly.\n *\n * Those flags are accessible from `ort.env.wasm`. Users are allow to set those flags before the first inference session\n * being created, to override default value.\n */\nexport const initializeFlags = (): void => {\n if (typeof env.wasm.initTimeout !== 'number' || env.wasm.initTimeout < 0) {\n env.wasm.initTimeout = 0;\n }\n\n const simd = env.wasm.simd;\n if (typeof simd !== 'boolean' && simd !== undefined && simd !== 'fixed' && simd !== 'relaxed') {\n // eslint-disable-next-line no-console\n console.warn(\n `Property \"env.wasm.simd\" is set to unknown value \"${simd}\". Reset it to \\`false\\` and ignore SIMD feature checking.`,\n );\n env.wasm.simd = false;\n }\n\n if (typeof env.wasm.proxy !== 'boolean') {\n env.wasm.proxy = false;\n }\n\n if (typeof env.wasm.trace !== 'boolean') {\n env.wasm.trace = false;\n }\n\n if (typeof env.wasm.numThreads !== 'number' || !Number.isInteger(env.wasm.numThreads) || env.wasm.numThreads <= 0) {\n // The following logic only applies when `ort.env.wasm.numThreads` is not set by user. We will always honor user's\n // setting if it is provided.\n\n // Browser: when crossOriginIsolated is false, SharedArrayBuffer is not available so WebAssembly threads will not\n // work. In this case, we will set numThreads to 1.\n //\n // There is an exception: when the browser is configured to force-enable SharedArrayBuffer (e.g. Chromuim with\n // --enable-features=SharedArrayBuffer), it is possible that `self.crossOriginIsolated` is false and\n // SharedArrayBuffer is available at the same time. This is usually for testing. In this case, we will still set\n // numThreads to 1 here. If we want to enable multi-threading in test, we should set `ort.env.wasm.numThreads` to a\n // value greater than 1.\n if (typeof self !== 'undefined' && !self.crossOriginIsolated) {\n env.wasm.numThreads = 1;\n } else {\n const numCpuLogicalCores =\n typeof navigator === 'undefined' ? require('node:os').cpus().length : navigator.hardwareConcurrency;\n env.wasm.numThreads = Math.min(4, Math.ceil((numCpuLogicalCores || 1) / 2));\n }\n }\n};\n\nexport class OnnxruntimeWebAssemblyBackend implements Backend {\n /**\n * This function initializes the WebAssembly backend.\n *\n * This function will be called only once for each backend name. It will be called the first time when\n * `ort.InferenceSession.create()` is called with a registered backend name.\n *\n * @param backendName - the registered backend name.\n */\n async init(backendName: string): Promise<void> {\n // populate wasm flags\n initializeFlags();\n\n // init wasm\n await initializeWebAssemblyAndOrtRuntime();\n\n // performe EP specific initialization\n await initializeOrtEp(backendName);\n }\n createInferenceSessionHandler(\n path: string,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler>;\n createInferenceSessionHandler(\n buffer: Uint8Array,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler>;\n async createInferenceSessionHandler(\n pathOrBuffer: string | Uint8Array,\n options?: InferenceSession.SessionOptions,\n ): Promise<InferenceSessionHandler> {\n const handler = new OnnxruntimeWebAssemblySessionHandler();\n await handler.loadModel(pathOrBuffer, options);\n return handler;\n }\n}\n\nexport const wasmBackend = new OnnxruntimeWebAssemblyBackend();\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */\n\n// We use \"require\" instead of \"import\" here because import statement must be put in top level. Our current code does\n// not allow bundler to tree-shaking code as expected because some codes are treated as having side effects.\n// So we import code inside the if-clause to allow bundler remove the code safely.\n\nexport * from 'onnxruntime-common';\nimport * as ort from 'onnxruntime-common';\nexport default ort;\n\nimport { registerBackend, env } from 'onnxruntime-common';\nimport { version } from './version';\n\nif (!BUILD_DEFS.DISABLE_WEBGL) {\n const onnxjsBackend = require('./backend-onnxjs').onnxjsBackend;\n registerBackend('webgl', onnxjsBackend, -10);\n}\n\nif (!BUILD_DEFS.DISABLE_JSEP && !BUILD_DEFS.DISABLE_WEBGPU) {\n throw new Error(\n 'The current build is specified to enable both JSEP and WebGPU EP. This is not a valid configuration. ' +\n 'JSEP and WebGPU EPs cannot be enabled at the same time.',\n );\n}\n\nif (!BUILD_DEFS.DISABLE_WEBNN && BUILD_DEFS.DISABLE_JSEP && BUILD_DEFS.DISABLE_WEBGPU) {\n throw new Error(\n 'The current build is specified to enable WebNN EP without JSEP or WebGPU EP. This is not a valid configuration. ' +\n 'WebNN EP requires either JSEP or WebGPU EP to be enabled.',\n );\n}\n\nif (!BUILD_DEFS.DISABLE_WASM) {\n const wasmBackend = require('./backend-wasm').wasmBackend;\n if (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) {\n registerBackend('webgpu', wasmBackend, 5);\n }\n if (!BUILD_DEFS.DISABLE_WEBNN) {\n registerBackend('webnn', wasmBackend, 5);\n }\n registerBackend('cpu', wasmBackend, 10);\n registerBackend('wasm', wasmBackend, 10);\n}\n\nObject.defineProperty(env.versions, 'web', { value: version, enumerable: true });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// This file is generated by /js/scripts/update-version.ts\n// Do not modify file content manually.\n\nexport const version = '1.24.2';\n","// @guidekit/vad — Silero VAD ONNX model wrapper for voice activity detection\nimport * as ort from 'onnxruntime-web';\n\nexport const VAD_VERSION = '0.1.0-beta.2';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:VAD]';\n\n/** Default CDN URL for the Silero VAD ONNX model (v5). */\nconst DEFAULT_MODEL_URL =\n 'https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.20/dist/silero_vad_v5.onnx';\n\n/** Cache API key used for persisting the downloaded ONNX model. */\nconst CACHE_NAME = `guidekit-vad-v${VAD_VERSION}`;\nconst CACHE_MODEL_KEY = 'model.onnx';\n\n/** Silero VAD frame size: 512 samples at 16 kHz = 32 ms per frame. */\nconst FRAME_SIZE = 512;\n\n/** Target sample rate for VAD processing. */\nconst TARGET_SAMPLE_RATE = 16000;\n\n/** Duration (in ms) of audio collected for noise floor calibration. */\nconst CALIBRATION_DURATION_MS = 500;\n\n/** Hidden/cell state size for Silero VAD v5 LSTM. */\nconst STATE_SIZE = 128;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface VADOptions {\n /** Speech probability threshold (0-1). Default: 0.5 */\n threshold?: number;\n /** Minimum speech duration in ms to trigger start. Default: 300 */\n minSpeechDurationMs?: number;\n /** Silence duration in ms after speech to trigger end. Default: 500 */\n silenceDurationMs?: number;\n /** Sample rate. Default: 16000 */\n sampleRate?: number;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n /** Custom URL for the Silero VAD ONNX model file. */\n modelUrl?: string;\n}\n\nexport interface VADEvent {\n type: 'speech-start' | 'speech-end' | 'vad-ready';\n timestamp: number;\n /** Speech probability (0-1) at the moment of the event. */\n probability?: number;\n}\n\ntype VADEventType = VADEvent['type'];\ntype VADCallback = (event: VADEvent) => void;\n\n// ---------------------------------------------------------------------------\n// Utility: Cache API helpers\n// ---------------------------------------------------------------------------\n\nasync function loadModelFromCache(): Promise<ArrayBuffer | null> {\n if (typeof caches === 'undefined') return null;\n try {\n const cache = await caches.open(CACHE_NAME);\n const response = await cache.match(CACHE_MODEL_KEY);\n return response ? response.arrayBuffer() : null;\n } catch {\n // Cache API may be unavailable in certain contexts (e.g. opaque origins).\n return null;\n }\n}\n\nasync function saveModelToCache(data: ArrayBuffer): Promise<void> {\n if (typeof caches === 'undefined') return;\n try {\n const cache = await caches.open(CACHE_NAME);\n await cache.put(CACHE_MODEL_KEY, new Response(data));\n } catch {\n // Silently ignore cache write failures.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility: Resampler\n// ---------------------------------------------------------------------------\n\n/**\n * Simple linear-interpolation resampler from `inputRate` to `outputRate`.\n * Adequate for VAD where perceptual audio quality is irrelevant.\n */\nfunction resample(\n input: Float32Array,\n inputRate: number,\n outputRate: number,\n): Float32Array {\n if (inputRate === outputRate) return input;\n const ratio = inputRate / outputRate;\n const outputLength = Math.round(input.length / ratio);\n const output = new Float32Array(outputLength);\n for (let i = 0; i < outputLength; i++) {\n const srcIndex = i * ratio;\n const srcFloor = Math.floor(srcIndex);\n const srcCeil = Math.min(srcFloor + 1, input.length - 1);\n const frac = srcIndex - srcFloor;\n output[i] = (input[srcFloor] as number) * (1 - frac) + (input[srcCeil] as number) * frac;\n }\n return output;\n}\n\n// ---------------------------------------------------------------------------\n// SileroVAD\n// ---------------------------------------------------------------------------\n\nexport class SileroVAD {\n // Options (resolved with defaults)\n private readonly _threshold: number;\n private readonly _minSpeechDurationMs: number;\n private readonly _silenceDurationMs: number;\n private readonly _sampleRate: number;\n private readonly _debug: boolean;\n private readonly _modelUrl: string;\n\n // ONNX Runtime state\n private _session: ort.InferenceSession | null = null;\n private _h: ort.Tensor | null = null;\n private _c: ort.Tensor | null = null;\n\n // Audio pipeline\n private _audioContext: AudioContext | null = null;\n private _ownsAudioContext = false;\n private _sourceNode: MediaStreamAudioSourceNode | null = null;\n private _workletNode: AudioWorkletNode | ScriptProcessorNode | null = null;\n private _stream: MediaStream | null = null;\n\n // Frame buffer for accumulating resampled samples into FRAME_SIZE chunks\n private _frameBuffer: Float32Array = new Float32Array(0);\n private _frameBufferOffset = 0;\n\n // State tracking\n private _isReady = false;\n private _isSpeaking = false;\n private _isStarted = false;\n private _isDestroyed = false;\n\n // Duration tracking (in frames)\n private _consecutiveSpeechFrames = 0;\n private _consecutiveSilenceFrames = 0;\n private _frameDurationMs: number;\n private _minSpeechFrames: number;\n private _silenceFrames: number;\n\n // Noise floor calibration\n private _isCalibrating = false;\n private _calibrationSamples: number[] = [];\n private _calibrationFramesNeeded = 0;\n private _calibratedThreshold: number;\n\n // Event listeners\n private _listeners: Map<VADEventType, Set<VADCallback>> = new Map();\n\n // Processing lock to serialise frame inference\n private _processingPromise: Promise<void> = Promise.resolve();\n\n constructor(options?: VADOptions) {\n this._threshold = options?.threshold ?? 0.5;\n this._minSpeechDurationMs = options?.minSpeechDurationMs ?? 300;\n this._silenceDurationMs = options?.silenceDurationMs ?? 500;\n this._sampleRate = options?.sampleRate ?? TARGET_SAMPLE_RATE;\n this._debug = options?.debug ?? false;\n this._modelUrl = options?.modelUrl ?? DEFAULT_MODEL_URL;\n this._calibratedThreshold = this._threshold;\n\n // Pre-compute frame-duration-based counters\n this._frameDurationMs = (FRAME_SIZE / this._sampleRate) * 1000;\n this._minSpeechFrames = Math.ceil(this._minSpeechDurationMs / this._frameDurationMs);\n this._silenceFrames = Math.ceil(this._silenceDurationMs / this._frameDurationMs);\n\n this._log('Created with options', {\n threshold: this._threshold,\n minSpeechDurationMs: this._minSpeechDurationMs,\n silenceDurationMs: this._silenceDurationMs,\n sampleRate: this._sampleRate,\n modelUrl: this._modelUrl,\n });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Load the ONNX model. Uses Cache API for persistence across sessions. */\n async init(): Promise<void> {\n if (this._isDestroyed) {\n throw new Error(`${LOG_PREFIX} Cannot init after destroy`);\n }\n if (this._isReady) {\n this._log('Already initialised — skipping');\n return;\n }\n\n this._log('Initialising...');\n\n // 1. Attempt to load model bytes from cache, falling back to network.\n let modelBuffer = await loadModelFromCache();\n if (modelBuffer) {\n this._log('Loaded model from Cache API');\n } else {\n this._log('Fetching model from', this._modelUrl);\n const response = await fetch(this._modelUrl);\n if (!response.ok) {\n throw new Error(\n `${LOG_PREFIX} Failed to fetch model: ${response.status} ${response.statusText}`,\n );\n }\n modelBuffer = await response.arrayBuffer();\n this._log('Model fetched, size:', modelBuffer.byteLength, 'bytes');\n\n // Persist to Cache API for next time.\n await saveModelToCache(modelBuffer);\n this._log('Model saved to Cache API');\n }\n\n // 2. Create ONNX InferenceSession.\n this._session = await ort.InferenceSession.create(modelBuffer, {\n executionProviders: ['wasm'],\n graphOptimizationLevel: 'all',\n });\n\n // 3. Initialise LSTM hidden/cell state tensors (zeros).\n this._resetStates();\n\n this._isReady = true;\n this._log('Model loaded and ready');\n\n this._emit({\n type: 'vad-ready',\n timestamp: Date.now(),\n });\n }\n\n /**\n * Process a single audio frame (512 samples at 16 kHz).\n * Returns the speech probability (0-1).\n */\n async processFrame(audioData: Float32Array): Promise<number> {\n if (!this._session) {\n throw new Error(`${LOG_PREFIX} Model not loaded. Call init() first.`);\n }\n if (audioData.length !== FRAME_SIZE) {\n throw new Error(\n `${LOG_PREFIX} Expected ${FRAME_SIZE} samples, got ${audioData.length}`,\n );\n }\n\n const inputTensor = new ort.Tensor('float32', audioData, [1, FRAME_SIZE]);\n const srTensor = new ort.Tensor('int64', BigInt64Array.from([BigInt(this._sampleRate)]), [1]);\n\n const feeds: Record<string, ort.Tensor> = {\n input: inputTensor,\n sr: srTensor,\n h0: this._h!,\n c0: this._c!,\n };\n\n const results = await this._session.run(feeds);\n\n // Update LSTM hidden/cell states for the next frame.\n this._h = results['hn'] as ort.Tensor;\n this._c = results['cn'] as ort.Tensor;\n\n const probability = (results['output'] as ort.Tensor).data[0] as number;\n return probability;\n }\n\n /** Start VAD processing on a MediaStream (typically from getUserMedia). */\n start(stream: MediaStream): void {\n if (this._isDestroyed) {\n throw new Error(`${LOG_PREFIX} Cannot start after destroy`);\n }\n if (!this._isReady) {\n throw new Error(`${LOG_PREFIX} Model not loaded. Call init() first.`);\n }\n if (this._isStarted) {\n this._log('Already started — stopping previous session first');\n this.stop();\n }\n\n this._log('Starting VAD on MediaStream');\n this._stream = stream;\n this._isStarted = true;\n\n // Reset speech tracking state.\n this._isSpeaking = false;\n this._consecutiveSpeechFrames = 0;\n this._consecutiveSilenceFrames = 0;\n this._frameBuffer = new Float32Array(FRAME_SIZE);\n this._frameBufferOffset = 0;\n\n // Reset LSTM states for a fresh stream.\n this._resetStates();\n\n // Begin noise floor calibration.\n this._isCalibrating = true;\n this._calibrationSamples = [];\n this._calibrationFramesNeeded = Math.max(1, Math.floor(\n (CALIBRATION_DURATION_MS / 1000) * this._sampleRate / FRAME_SIZE,\n ));\n this._log('Calibrating noise floor for', this._calibrationFramesNeeded, 'frames');\n\n // Build the audio processing pipeline.\n this._setupAudioPipeline(stream);\n }\n\n /** Stop VAD processing and release audio resources (but keep the model). */\n stop(): void {\n if (!this._isStarted) return;\n\n this._log('Stopping VAD');\n\n // Tear down audio nodes.\n this._teardownAudioPipeline();\n\n // If we were speaking, emit speech-end.\n if (this._isSpeaking) {\n this._isSpeaking = false;\n this._emit({\n type: 'speech-end',\n timestamp: Date.now(),\n probability: 0,\n });\n }\n\n // Reset state.\n this._isStarted = false;\n this._isSpeaking = false;\n this._consecutiveSpeechFrames = 0;\n this._consecutiveSilenceFrames = 0;\n this._frameBufferOffset = 0;\n this._isCalibrating = false;\n this._calibrationSamples = [];\n this._processingPromise = Promise.resolve();\n\n this._log('VAD stopped');\n }\n\n /** Register a callback for speech-start events. Returns an unsubscribe function. */\n onSpeechStart(callback: VADCallback): () => void {\n return this._on('speech-start', callback);\n }\n\n /** Register a callback for speech-end events. Returns an unsubscribe function. */\n onSpeechEnd(callback: VADCallback): () => void {\n return this._on('speech-end', callback);\n }\n\n /** Register a callback for vad-ready events. Returns an unsubscribe function. */\n onReady(callback: VADCallback): () => void {\n return this._on('vad-ready', callback);\n }\n\n /** Whether the ONNX model is loaded and ready. */\n get isReady(): boolean {\n return this._isReady;\n }\n\n /** Whether speech is currently detected. */\n get isSpeaking(): boolean {\n return this._isSpeaking;\n }\n\n /** The MediaStream currently being processed, or null. */\n get stream(): MediaStream | null {\n return this._stream;\n }\n\n /** Release ONNX model session and all audio resources. */\n async destroy(): Promise<void> {\n if (this._isDestroyed) return;\n this._log('Destroying...');\n\n this.stop();\n\n if (this._session) {\n await this._session.release();\n this._session = null;\n }\n\n // Dispose tensors.\n this._h?.dispose();\n this._c?.dispose();\n this._h = null;\n this._c = null;\n\n this._isReady = false;\n this._isDestroyed = true;\n this._listeners.clear();\n\n this._log('Destroyed');\n }\n\n // -------------------------------------------------------------------------\n // Private: Event system\n // -------------------------------------------------------------------------\n\n private _on(type: VADEventType, callback: VADCallback): () => void {\n let set = this._listeners.get(type);\n if (!set) {\n set = new Set();\n this._listeners.set(type, set);\n }\n set.add(callback);\n return () => {\n set!.delete(callback);\n };\n }\n\n private _emit(event: VADEvent): void {\n const set = this._listeners.get(event.type);\n if (!set) return;\n for (const cb of set) {\n try {\n cb(event);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`${LOG_PREFIX} Error in ${event.type} callback:`, err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Audio pipeline\n // -------------------------------------------------------------------------\n\n private _setupAudioPipeline(stream: MediaStream): void {\n // Determine the incoming sample rate.\n const tracks = stream.getAudioTracks();\n const trackSettings = tracks[0]?.getSettings();\n const inputSampleRate = trackSettings?.sampleRate ?? 48000;\n\n this._log('Input sample rate:', inputSampleRate);\n\n // Create AudioContext at the input sample rate so we don't double-resample.\n // SSR guard: AudioContext may not exist.\n if (typeof AudioContext === 'undefined' && typeof webkitAudioContext === 'undefined') {\n throw new Error(`${LOG_PREFIX} AudioContext is not available in this environment`);\n }\n\n const AudioContextClass =\n typeof AudioContext !== 'undefined'\n ? AudioContext\n : // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (globalThis as any).webkitAudioContext as typeof AudioContext;\n\n this._audioContext = new AudioContextClass({ sampleRate: inputSampleRate });\n this._ownsAudioContext = true;\n\n this._sourceNode = this._audioContext.createMediaStreamSource(stream);\n\n // Try AudioWorklet first, fall back to ScriptProcessorNode.\n this._setupScriptProcessor(inputSampleRate);\n }\n\n /**\n * ScriptProcessorNode fallback (works everywhere, including Safari).\n * We use a buffer size of 4096 which gives ~85 ms of audio at 48 kHz.\n */\n private _setupScriptProcessor(inputSampleRate: number): void {\n if (!this._audioContext || !this._sourceNode) return;\n\n // Buffer size must be a power of 2: 256, 512, 1024, 2048, 4096, 8192, 16384.\n const bufferSize = 4096;\n const processor = this._audioContext.createScriptProcessor(bufferSize, 1, 1);\n\n processor.onaudioprocess = (event: AudioProcessingEvent) => {\n if (!this._isStarted) return;\n\n const inputData = event.inputBuffer.getChannelData(0);\n\n // Resample to target rate if needed.\n const resampled =\n inputSampleRate !== this._sampleRate\n ? resample(inputData, inputSampleRate, this._sampleRate)\n : new Float32Array(inputData);\n\n // Feed resampled audio into frame-sized chunks.\n this._feedAudio(resampled);\n };\n\n this._sourceNode.connect(processor);\n processor.connect(this._audioContext.destination);\n this._workletNode = processor;\n\n this._log('Audio pipeline set up (ScriptProcessorNode)');\n }\n\n /**\n * Accumulate resampled audio into FRAME_SIZE chunks and process each full frame.\n */\n private _feedAudio(samples: Float32Array): void {\n let offset = 0;\n\n while (offset < samples.length) {\n const remaining = FRAME_SIZE - this._frameBufferOffset;\n const available = samples.length - offset;\n const toCopy = Math.min(remaining, available);\n\n this._frameBuffer.set(\n samples.subarray(offset, offset + toCopy),\n this._frameBufferOffset,\n );\n this._frameBufferOffset += toCopy;\n offset += toCopy;\n\n if (this._frameBufferOffset === FRAME_SIZE) {\n const frame = new Float32Array(this._frameBuffer);\n this._frameBufferOffset = 0;\n\n // Serialise inference calls to avoid overlapping ONNX sessions.\n this._processingPromise = this._processingPromise.then(() =>\n this._handleFrame(frame),\n );\n }\n }\n }\n\n /**\n * Process a single FRAME_SIZE frame: run inference and update speech state.\n */\n private async _handleFrame(frame: Float32Array): Promise<void> {\n if (!this._isStarted || !this._session) return;\n\n let probability: number;\n try {\n probability = await this.processFrame(frame);\n } catch (err) {\n if (this._debug) {\n // eslint-disable-next-line no-console\n console.error(`${LOG_PREFIX} Inference error:`, err);\n }\n return;\n }\n\n // Noise floor calibration phase.\n if (this._isCalibrating) {\n this._calibrationSamples.push(probability);\n\n if (this._calibrationSamples.length >= this._calibrationFramesNeeded) {\n this._finishCalibration();\n }\n return;\n }\n\n // Speech state machine.\n const isSpeechFrame = probability >= this._calibratedThreshold;\n\n if (isSpeechFrame) {\n this._consecutiveSpeechFrames++;\n this._consecutiveSilenceFrames = 0;\n\n if (!this._isSpeaking && this._consecutiveSpeechFrames >= this._minSpeechFrames) {\n this._isSpeaking = true;\n this._log('Speech started, probability:', probability.toFixed(3));\n this._emit({\n type: 'speech-start',\n timestamp: Date.now(),\n probability,\n });\n }\n } else {\n this._consecutiveSilenceFrames++;\n // Do NOT reset _consecutiveSpeechFrames here — only reset when speech-end fires.\n\n if (this._isSpeaking && this._consecutiveSilenceFrames >= this._silenceFrames) {\n this._isSpeaking = false;\n this._consecutiveSpeechFrames = 0;\n this._log('Speech ended, probability:', probability.toFixed(3));\n this._emit({\n type: 'speech-end',\n timestamp: Date.now(),\n probability,\n });\n }\n }\n }\n\n private _finishCalibration(): void {\n if (this._calibrationSamples.length === 0) {\n this._isCalibrating = false;\n return;\n }\n\n // Compute average noise floor probability.\n const sum = this._calibrationSamples.reduce((a, b) => a + b, 0);\n const avgNoise = sum / this._calibrationSamples.length;\n\n // If the ambient noise floor is high, nudge the threshold above it.\n // We add a margin so we don't constantly trigger on background noise.\n const NOISE_MARGIN = 0.15;\n if (avgNoise + NOISE_MARGIN > this._threshold) {\n this._calibratedThreshold = Math.min(avgNoise + NOISE_MARGIN, 0.95);\n this._log(\n 'Noise floor is high. Adjusted threshold from',\n this._threshold.toFixed(3),\n 'to',\n this._calibratedThreshold.toFixed(3),\n '(avg noise:',\n avgNoise.toFixed(3) + ')',\n );\n } else {\n this._calibratedThreshold = this._threshold;\n this._log('Noise floor OK, avg:', avgNoise.toFixed(3), '— keeping threshold at', this._threshold.toFixed(3));\n }\n\n // Recompute frame counters in case threshold changed min speech behaviour.\n this._minSpeechFrames = Math.ceil(this._minSpeechDurationMs / this._frameDurationMs);\n this._silenceFrames = Math.ceil(this._silenceDurationMs / this._frameDurationMs);\n\n this._isCalibrating = false;\n this._calibrationSamples = [];\n }\n\n private _teardownAudioPipeline(): void {\n if (this._workletNode) {\n try {\n this._workletNode.disconnect();\n } catch {\n // Ignore disconnect errors.\n }\n if ('onaudioprocess' in this._workletNode) {\n (this._workletNode as ScriptProcessorNode).onaudioprocess = null;\n }\n this._workletNode = null;\n }\n\n if (this._sourceNode) {\n try {\n this._sourceNode.disconnect();\n } catch {\n // Ignore.\n }\n this._sourceNode = null;\n }\n\n if (this._audioContext && this._ownsAudioContext) {\n try {\n void this._audioContext.close();\n } catch {\n // Ignore.\n }\n this._audioContext = null;\n this._ownsAudioContext = false;\n }\n\n this._stream = null;\n }\n\n // -------------------------------------------------------------------------\n // Private: ONNX state helpers\n // -------------------------------------------------------------------------\n\n /** Reset the LSTM hidden and cell states to zeros. */\n private _resetStates(): void {\n // Dispose any existing tensors to free memory.\n this._h?.dispose();\n this._c?.dispose();\n\n const zeros = new Float32Array(2 * STATE_SIZE).fill(0);\n this._h = new ort.Tensor('float32', zeros.slice(0, STATE_SIZE), [2, 1, 64]);\n this._c = new ort.Tensor('float32', zeros.slice(STATE_SIZE), [2, 1, 64]);\n }\n\n // -------------------------------------------------------------------------\n // Private: Logging\n // -------------------------------------------------------------------------\n\n private _log(...args: unknown[]): void {\n if (!this._debug) return;\n // eslint-disable-next-line no-console\n console.log(LOG_PREFIX, ...args);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Convenience factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create and initialise a SileroVAD instance in one call.\n *\n * ```ts\n * const vad = await createVAD({ debug: true });\n * vad.onSpeechStart(() => console.log('speaking'));\n * vad.start(stream);\n * ```\n */\nexport async function createVAD(options?: VADOptions): Promise<SileroVAD> {\n const vad = new SileroVAD(options);\n await vad.init();\n return vad;\n}\n\n// Re-export the frame size constant so consumers can align their buffers.\nexport { FRAME_SIZE, TARGET_SAMPLE_RATE };\n\n// Type-only declaration for environments that provide webkitAudioContext.\ndeclare global {\n // eslint-disable-next-line no-var\n var webkitAudioContext: typeof AudioContext | undefined;\n}\n","// ---------------------------------------------------------------------------\n// @guidekit/vanilla — Non-React IIFE bundle for script-tag integration\n// ---------------------------------------------------------------------------\n//\n// Provides an imperative API for using GuideKit without React. Users include\n// the script via a <script> tag and interact with the global `GuideKit` object.\n//\n// Usage:\n// <script src=\"https://cdn.jsdelivr.net/npm/@guidekit/vanilla/dist/index.global.js\"></script>\n// <script>\n// GuideKit.init({\n// llm: { provider: 'gemini', apiKey: '...' },\n// agent: { name: 'Guide', greeting: 'Hello!' },\n// });\n// </script>\n// ---------------------------------------------------------------------------\n\nimport { GuideKitCore } from '@guidekit/core';\nimport type {\n GuideKitCoreOptions,\n AgentState,\n GuideKitEvent,\n GuideKitErrorType,\n PageModel,\n HealthCheckResult,\n I18nStrings,\n} from '@guidekit/core';\n\n// ---------------------------------------------------------------------------\n// Widget DOM (lightweight, no React — plain DOM manipulation)\n// ---------------------------------------------------------------------------\n\nconst WIDGET_CSS = /* css */ `\n :host {\n --gk-primary: #6366f1;\n --gk-primary-hover: #4f46e5;\n --gk-bg: #ffffff;\n --gk-bg-secondary: #f8fafc;\n --gk-text: #1e293b;\n --gk-text-secondary: #64748b;\n --gk-border: #e2e8f0;\n --gk-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);\n --gk-radius: 16px;\n --gk-fab-size: 56px;\n --gk-panel-width: 380px;\n --gk-panel-height: 520px;\n --gk-font: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n all: initial;\n font-family: var(--gk-font);\n position: fixed;\n z-index: 2147483647;\n bottom: 24px;\n right: 24px;\n }\n @media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n }\n .gk-fab {\n width: var(--gk-fab-size);\n height: var(--gk-fab-size);\n border-radius: 50%;\n border: none;\n background: var(--gk-primary);\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 16px rgba(99, 102, 241, 0.35);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n outline: none;\n }\n .gk-fab:hover {\n background: var(--gk-primary-hover);\n transform: scale(1.05);\n }\n .gk-fab:focus-visible {\n outline: 2px solid var(--gk-primary);\n outline-offset: 3px;\n }\n .gk-fab svg { width: 24px; height: 24px; fill: currentColor; }\n .gk-panel {\n position: absolute;\n bottom: calc(var(--gk-fab-size) + 16px);\n right: 0;\n width: var(--gk-panel-width);\n height: var(--gk-panel-height);\n background: var(--gk-bg);\n border-radius: var(--gk-radius);\n box-shadow: var(--gk-shadow);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n opacity: 0;\n transform: translateY(12px) scale(0.95);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n .gk-panel.gk-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n .gk-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--gk-border);\n flex-shrink: 0;\n }\n .gk-header-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--gk-text);\n margin: 0;\n }\n .gk-close-btn {\n width: 28px; height: 28px; border-radius: 8px;\n border: none; background: transparent; color: var(--gk-text-secondary);\n cursor: pointer; display: flex; align-items: center; justify-content: center;\n outline: none;\n }\n .gk-close-btn:hover { background: var(--gk-bg-secondary); color: var(--gk-text); }\n .gk-close-btn:focus-visible { outline: 2px solid var(--gk-primary); outline-offset: -2px; }\n .gk-close-btn svg { width: 16px; height: 16px; fill: currentColor; }\n .gk-transcript {\n flex: 1; overflow-y: auto; padding: 16px 20px;\n display: flex; flex-direction: column; gap: 12px; scroll-behavior: smooth;\n }\n .gk-empty {\n flex: 1; display: flex; flex-direction: column; align-items: center;\n justify-content: center; color: var(--gk-text-secondary); text-align: center;\n padding: 32px 16px; font-size: 13px;\n }\n .gk-msg {\n max-width: 85%; padding: 10px 14px; border-radius: 12px;\n font-size: 14px; line-height: 1.5; word-wrap: break-word; white-space: pre-wrap;\n }\n .gk-msg-user {\n align-self: flex-end; background: var(--gk-primary);\n color: #fff; border-bottom-right-radius: 4px;\n }\n .gk-msg-assistant {\n align-self: flex-start; background: var(--gk-bg-secondary);\n color: var(--gk-text); border-bottom-left-radius: 4px;\n }\n .gk-dots {\n align-self: flex-start; display: flex; gap: 4px; padding: 12px 16px;\n }\n .gk-dot {\n width: 6px; height: 6px; border-radius: 50%; background: var(--gk-text-secondary);\n animation: gk-bounce 1.4s ease-in-out infinite;\n }\n .gk-dot:nth-child(2) { animation-delay: 0.16s; }\n .gk-dot:nth-child(3) { animation-delay: 0.32s; }\n @keyframes gk-bounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-6px); }\n }\n .gk-input-area {\n display: flex; align-items: flex-end; gap: 8px;\n padding: 12px 16px; border-top: 1px solid var(--gk-border); flex-shrink: 0;\n }\n .gk-input {\n flex: 1; min-height: 40px; max-height: 120px; padding: 8px 14px;\n border: 1px solid var(--gk-border); border-radius: 12px;\n background: var(--gk-bg); color: var(--gk-text);\n font-family: var(--gk-font); font-size: 14px; line-height: 1.5;\n resize: none; outline: none;\n }\n .gk-input:focus { border-color: var(--gk-primary); box-shadow: 0 0 0 3px rgba(99,102,241,0.15); }\n .gk-send-btn {\n width: 40px; height: 40px; border-radius: 12px; border: none;\n background: var(--gk-primary); color: #fff; cursor: pointer;\n display: flex; align-items: center; justify-content: center; flex-shrink: 0;\n outline: none;\n }\n .gk-send-btn:hover:not(:disabled) { background: var(--gk-primary-hover); }\n .gk-send-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n .gk-send-btn:focus-visible { outline: 2px solid var(--gk-primary); outline-offset: 3px; }\n .gk-send-btn svg { width: 18px; height: 18px; fill: currentColor; }\n @media (hover: none) and (pointer: coarse), (max-width: 768px) {\n :host { bottom: 16px !important; right: 16px !important; }\n .gk-panel {\n position: fixed; bottom: 0; left: 0; right: 0;\n width: 100%; height: 70vh; max-height: 70vh;\n border-radius: var(--gk-radius) var(--gk-radius) 0 0;\n transform: translateY(100%);\n padding-bottom: env(safe-area-inset-bottom, 0px);\n }\n .gk-panel.gk-open { transform: translateY(0); }\n .gk-send-btn, .gk-close-btn { min-width: 44px; min-height: 44px; }\n .gk-input-area { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }\n }\n @media (forced-colors: active) {\n .gk-fab, .gk-send-btn { border: 2px solid ButtonText; }\n .gk-panel { border: 1px solid ButtonText; }\n }\n`;\n\nconst SVG_CHAT = '<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.17L4 17.17V4h16v12z\"/><path d=\"M7 9h10v2H7zm0-3h10v2H7z\"/></svg>';\nconst SVG_CLOSE = '<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/></svg>';\nconst SVG_SEND = '<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\"/></svg>';\n\n// ---------------------------------------------------------------------------\n// VanillaWidget — renders and manages the chat widget without React\n// ---------------------------------------------------------------------------\n\nclass VanillaWidget {\n private host: HTMLDivElement;\n private shadow: ShadowRoot;\n private panel!: HTMLDivElement;\n private transcript!: HTMLDivElement;\n private emptyState!: HTMLDivElement;\n private dotsEl!: HTMLDivElement;\n private input!: HTMLTextAreaElement;\n private sendBtn!: HTMLButtonElement;\n private fab!: HTMLButtonElement;\n private isOpen = false;\n private isSending = false;\n private core: GuideKitCore;\n\n constructor(core: GuideKitCore) {\n this.core = core;\n\n // Create Shadow DOM host\n this.host = document.createElement('div');\n this.host.id = 'guidekit-widget';\n this.host.style.cssText =\n 'position:fixed;z-index:2147483647;bottom:24px;right:24px;margin:0;padding:0;border:none;background:none;';\n document.body.appendChild(this.host);\n\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n // Inject styles\n const style = document.createElement('style');\n style.textContent = WIDGET_CSS;\n this.shadow.appendChild(style);\n\n this.buildDOM();\n this.bindEvents();\n }\n\n private buildDOM(): void {\n // Panel\n this.panel = document.createElement('div');\n this.panel.className = 'gk-panel';\n this.panel.setAttribute('role', 'dialog');\n this.panel.setAttribute('aria-label', 'GuideKit Assistant');\n this.panel.setAttribute('aria-hidden', 'true');\n\n // Header\n const header = document.createElement('div');\n header.className = 'gk-header';\n\n const title = document.createElement('div');\n title.className = 'gk-header-title';\n title.textContent = this.t('widgetTitle');\n header.appendChild(title);\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'gk-close-btn';\n closeBtn.setAttribute('aria-label', this.t('closePanel'));\n closeBtn.innerHTML = SVG_CLOSE;\n closeBtn.addEventListener('click', () => this.togglePanel(false));\n header.appendChild(closeBtn);\n\n this.panel.appendChild(header);\n\n // Transcript\n this.transcript = document.createElement('div');\n this.transcript.className = 'gk-transcript';\n this.transcript.setAttribute('role', 'log');\n this.transcript.setAttribute('aria-live', 'polite');\n\n this.emptyState = document.createElement('div');\n this.emptyState.className = 'gk-empty';\n this.emptyState.textContent = this.t('emptyStateMessage');\n this.transcript.appendChild(this.emptyState);\n\n // Dots indicator (hidden by default)\n this.dotsEl = document.createElement('div');\n this.dotsEl.className = 'gk-dots';\n this.dotsEl.setAttribute('role', 'status');\n this.dotsEl.setAttribute('aria-label', 'Processing');\n this.dotsEl.style.display = 'none';\n for (let i = 0; i < 3; i++) {\n const dot = document.createElement('div');\n dot.className = 'gk-dot';\n this.dotsEl.appendChild(dot);\n }\n this.transcript.appendChild(this.dotsEl);\n\n this.panel.appendChild(this.transcript);\n\n // Input area\n const inputArea = document.createElement('div');\n inputArea.className = 'gk-input-area';\n\n this.input = document.createElement('textarea');\n this.input.className = 'gk-input';\n this.input.placeholder = this.t('inputPlaceholder');\n this.input.setAttribute('aria-label', this.t('sendMessage'));\n this.input.rows = 1;\n inputArea.appendChild(this.input);\n\n this.sendBtn = document.createElement('button');\n this.sendBtn.className = 'gk-send-btn';\n this.sendBtn.setAttribute('aria-label', this.t('sendMessage'));\n this.sendBtn.innerHTML = SVG_SEND;\n inputArea.appendChild(this.sendBtn);\n\n this.panel.appendChild(inputArea);\n this.shadow.appendChild(this.panel);\n\n // FAB\n this.fab = document.createElement('button');\n this.fab.className = 'gk-fab';\n this.fab.setAttribute('aria-label', this.t('openAssistant'));\n this.fab.setAttribute('aria-expanded', 'false');\n this.fab.setAttribute('aria-haspopup', 'dialog');\n this.fab.innerHTML = SVG_CHAT;\n this.shadow.appendChild(this.fab);\n }\n\n private bindEvents(): void {\n this.fab.addEventListener('click', () => this.togglePanel(!this.isOpen));\n\n this.sendBtn.addEventListener('click', () => this.handleSend());\n\n this.input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.handleSend();\n }\n if (e.key === 'Escape') {\n this.togglePanel(false);\n this.fab.focus();\n }\n });\n }\n\n private togglePanel(open: boolean): void {\n this.isOpen = open;\n if (open) {\n this.panel.classList.add('gk-open');\n this.panel.setAttribute('aria-hidden', 'false');\n this.fab.setAttribute('aria-expanded', 'true');\n this.fab.innerHTML = SVG_CLOSE;\n this.fab.setAttribute('aria-label', this.t('closeAssistant'));\n setTimeout(() => this.input.focus(), 100);\n } else {\n this.panel.classList.remove('gk-open');\n this.panel.setAttribute('aria-hidden', 'true');\n this.fab.setAttribute('aria-expanded', 'false');\n this.fab.innerHTML = SVG_CHAT;\n this.fab.setAttribute('aria-label', this.t('openAssistant'));\n }\n }\n\n private async handleSend(): Promise<void> {\n const text = this.input.value.trim();\n if (!text || this.isSending) return;\n\n this.isSending = true;\n\n // Hide empty state\n this.emptyState.style.display = 'none';\n\n // Add user message\n this.addMessage('user', text);\n this.input.value = '';\n\n // Show processing dots\n this.dotsEl.style.display = 'flex';\n this.scrollToBottom();\n\n try {\n const response = await this.core.sendText(text);\n this.dotsEl.style.display = 'none';\n this.addMessage('assistant', response);\n } catch (err) {\n this.dotsEl.style.display = 'none';\n const msg = err instanceof Error ? err.message : 'Something went wrong.';\n this.addMessage('assistant', `Error: ${msg}`);\n } finally {\n this.isSending = false;\n }\n }\n\n private addMessage(role: 'user' | 'assistant', content: string): void {\n const el = document.createElement('div');\n el.className = `gk-msg gk-msg-${role}`;\n el.textContent = content;\n // Insert before the dots element\n this.transcript.insertBefore(el, this.dotsEl);\n this.scrollToBottom();\n }\n\n private scrollToBottom(): void {\n this.transcript.scrollTop = this.transcript.scrollHeight;\n }\n\n private t(key: string): string {\n try {\n return this.core.i18n.t(key as keyof I18nStrings) ?? key;\n } catch {\n return key;\n }\n }\n\n destroy(): void {\n this.host.remove();\n }\n}\n\n// ---------------------------------------------------------------------------\n// GuideKitVanilla — imperative wrapper around GuideKitCore\n// ---------------------------------------------------------------------------\n\nexport interface GuideKitVanillaOptions {\n tokenEndpoint?: string;\n stt?: GuideKitCoreOptions['stt'];\n tts?: GuideKitCoreOptions['tts'];\n llm?: GuideKitCoreOptions['llm'];\n agent?: GuideKitCoreOptions['agent'];\n contentMap?: GuideKitCoreOptions['contentMap'];\n options?: GuideKitCoreOptions['options'];\n instanceId?: string;\n rootElement?: HTMLElement;\n /** Disable the built-in widget UI (for headless use). */\n headless?: boolean;\n onError?: (error: GuideKitErrorType) => void;\n onEvent?: (event: GuideKitEvent) => void;\n onReady?: () => void;\n}\n\n/** Singleton state */\nlet _core: GuideKitCore | null = null;\nlet _widget: VanillaWidget | null = null;\nlet _initialized = false;\n\n/**\n * Initialize GuideKit. Must be called before any other methods.\n * Idempotent — calling multiple times is safe (returns existing instance).\n */\nexport async function init(options: GuideKitVanillaOptions): Promise<void> {\n if (_initialized && _core) return;\n\n _core = new GuideKitCore({\n tokenEndpoint: options.tokenEndpoint,\n stt: options.stt,\n tts: options.tts,\n llm: options.llm,\n agent: options.agent,\n contentMap: options.contentMap,\n options: options.options,\n instanceId: options.instanceId,\n rootElement: options.rootElement,\n onError: options.onError,\n onEvent: options.onEvent,\n onReady: options.onReady,\n });\n\n await _core.init();\n\n // Create widget unless headless\n if (!options.headless) {\n _widget = new VanillaWidget(_core);\n }\n\n _initialized = true;\n}\n\n/**\n * Send a text message to the assistant. Returns the response.\n */\nexport async function sendText(message: string): Promise<string> {\n assertInitialized();\n return _core!.sendText(message);\n}\n\n/**\n * Highlight an element on the page.\n */\nexport function highlight(params: {\n sectionId?: string;\n selector?: string;\n tooltip?: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n}): boolean {\n assertInitialized();\n return _core!.highlight(params);\n}\n\n/** Dismiss the current spotlight highlight. */\nexport function dismissHighlight(): void {\n assertInitialized();\n _core!.dismissHighlight();\n}\n\n/** Smooth scroll to a section by ID. */\nexport function scrollToSection(sectionId: string, offset?: number): void {\n assertInitialized();\n _core!.scrollToSection(sectionId, offset);\n}\n\n/** Start a guided tour. */\nexport function startTour(sectionIds: string[], mode?: 'auto' | 'manual'): void {\n assertInitialized();\n _core!.startTour(sectionIds, mode);\n}\n\n/** Stop the current tour. */\nexport function stopTour(): void {\n assertInitialized();\n _core!.stopTour();\n}\n\n/** Navigate to a URL (same-origin only). */\nexport async function navigate(href: string): Promise<boolean> {\n assertInitialized();\n return _core!.navigate(href);\n}\n\n/** Set developer page context for the LLM. */\nexport function setPageContext(context: Record<string, unknown>): void {\n assertInitialized();\n _core!.setPageContext(context);\n}\n\n/** Register a custom action the LLM can invoke. */\nexport function registerAction(\n actionId: string,\n action: {\n description: string;\n parameters: Record<string, unknown>;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n },\n): void {\n assertInitialized();\n _core!.registerAction(actionId, action);\n}\n\n/** Start voice input. */\nexport async function startListening(): Promise<void> {\n assertInitialized();\n await _core!.startListening();\n}\n\n/** Stop voice input. */\nexport function stopListening(): void {\n assertInitialized();\n _core!.stopListening();\n}\n\n/** Get current agent state. */\nexport function getAgentState(): AgentState {\n assertInitialized();\n return _core!.agentState;\n}\n\n/** Get current page model. */\nexport function getPageModel(): PageModel | null {\n assertInitialized();\n return _core!.pageModel;\n}\n\n/** Whether the SDK is ready. */\nexport function isReady(): boolean {\n return _core?.isReady ?? false;\n}\n\n/** Get/set quiet mode. */\nexport function getQuietMode(): boolean {\n assertInitialized();\n return _core!.quietMode;\n}\n\nexport function setQuietMode(value: boolean): void {\n assertInitialized();\n _core!.quietMode = value;\n}\n\n/** Check health of all connected services. */\nexport async function checkHealth(): Promise<HealthCheckResult> {\n assertInitialized();\n return _core!.checkHealth();\n}\n\n/** Destroy the instance and clean up. */\nexport async function destroy(): Promise<void> {\n if (_widget) {\n _widget.destroy();\n _widget = null;\n }\n if (_core) {\n await _core.destroy();\n _core = null;\n }\n _initialized = false;\n}\n\n/** Get the underlying GuideKitCore instance (escape hatch). */\nexport function getCore(): GuideKitCore | null {\n return _core;\n}\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nfunction assertInitialized(): void {\n if (!_core || !_initialized) {\n throw new Error(\n 'GuideKit not initialized. Call GuideKit.init({...}) first.',\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Version\n// ---------------------------------------------------------------------------\n\nexport const VERSION = '0.1.0-beta.2';\n","// ---------------------------------------------------------------------------\n// GuideKit SDK - Typed EventBus\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical map of every event in the GuideKit system.\n *\n * Keys use a `namespace:name` convention (except the top-level `error` event).\n * Values are the payload types that accompany each event.\n */\nexport interface EventMap {\n // -- DOM events -----------------------------------------------------------\n 'dom:scan-complete': { pageModel: unknown; durationMs: number };\n 'dom:mutation-detected': { mutations: number; debounced: boolean };\n 'dom:route-change': { from: string; to: string };\n\n // -- LLM events -----------------------------------------------------------\n 'llm:response-start': { conversationId: string };\n 'llm:response-chunk': { text: string; done: boolean };\n 'llm:response-end': { conversationId: string; totalTokens: number };\n 'llm:tool-call': { name: string; arguments: Record<string, unknown> };\n 'llm:token-usage': { prompt: number; completion: number; total: number };\n\n // -- Voice events ---------------------------------------------------------\n 'voice:state-change': { from: string; to: string };\n 'voice:transcript': { text: string; isFinal: boolean; confidence: number };\n 'voice:tts-start': { utterance: string };\n 'voice:tts-end': { utterance: string; durationMs: number };\n 'voice:degraded': { reason: string; fallback: 'text' };\n\n // -- Auth events ----------------------------------------------------------\n 'auth:token-refreshed': { expiresAt: number };\n 'auth:token-refresh-failed': { error: Error; attemptsRemaining: number };\n 'auth:token-expired': Record<string, never>;\n\n // -- Connectivity events --------------------------------------------------\n 'connectivity:state-change': {\n state: 'online' | 'degraded' | 'offline';\n previous: 'online' | 'degraded' | 'offline';\n };\n\n // -- Awareness events -----------------------------------------------------\n 'awareness:dwell': { sectionId: string; durationMs: number };\n 'awareness:idle': { durationMs: number };\n 'awareness:rage-click': { selector: string; clicks: number };\n 'awareness:section-visible': { sectionId: string; ratio: number };\n\n // -- Visual events --------------------------------------------------------\n 'visual:spotlight-shown': { selector: string; sectionId?: string };\n 'visual:spotlight-dismissed': Record<string, never>;\n 'visual:tour-step': {\n stepIndex: number;\n totalSteps: number;\n sectionId: string;\n };\n\n // -- Top-level error event ------------------------------------------------\n error: Error;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helper types\n// ---------------------------------------------------------------------------\n\n/** Handler for a concrete, known event key. */\ntype TypedHandler<K extends keyof EventMap> = (data: EventMap[K]) => void;\n\n/** Handler for a wildcard (namespace) subscription. */\ntype WildcardHandler = (data: unknown, eventName: string) => void;\n\n/** Discriminated wrapper so we can store both kinds in one map. */\ntype StoredHandler =\n | { kind: 'typed'; fn: TypedHandler<any> }\n | { kind: 'wildcard'; fn: WildcardHandler };\n\n// ---------------------------------------------------------------------------\n// EventBus\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Bus]';\n\nexport class EventBus {\n /** Per-event listeners. Wildcard keys end with `:*`. */\n private readonly listeners = new Map<string, StoredHandler[]>();\n\n /** Listeners registered via `onAny`. */\n private readonly anyListeners: WildcardHandler[] = [];\n\n /** When true, every `emit` is logged to the console. */\n private readonly debug: boolean;\n\n constructor(options?: { debug?: boolean }) {\n this.debug = options?.debug ?? false;\n }\n\n // ---- on (specific event) ------------------------------------------------\n\n /**\n * Subscribe to a specific typed event.\n *\n * @returns An unsubscribe function.\n */\n on<K extends keyof EventMap>(\n event: K,\n handler: (data: EventMap[K]) => void,\n ): () => void;\n\n /**\n * Subscribe to a namespace wildcard (e.g. `'dom:*'`).\n * The handler receives `(data, eventName)`.\n *\n * @returns An unsubscribe function.\n */\n on(\n event: `${string}:*`,\n handler: (data: unknown, eventName: string) => void,\n ): () => void;\n\n /** Unified implementation. */\n on(event: string, handler: (...args: any[]) => void): () => void {\n const isWildcard = event.endsWith(':*');\n const stored: StoredHandler = isWildcard\n ? { kind: 'wildcard', fn: handler as WildcardHandler }\n : { kind: 'typed', fn: handler as TypedHandler<any> };\n\n let list = this.listeners.get(event);\n if (!list) {\n list = [];\n this.listeners.set(event, list);\n }\n list.push(stored);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n const arr = this.listeners.get(event);\n if (!arr) return;\n const idx = arr.indexOf(stored);\n if (idx !== -1) arr.splice(idx, 1);\n if (arr.length === 0) this.listeners.delete(event);\n };\n }\n\n // ---- onAny --------------------------------------------------------------\n\n /**\n * Subscribe to **every** event emitted on the bus.\n *\n * @returns An unsubscribe function.\n */\n onAny(handler: (data: unknown, eventName: string) => void): () => void {\n this.anyListeners.push(handler);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n const idx = this.anyListeners.indexOf(handler);\n if (idx !== -1) this.anyListeners.splice(idx, 1);\n };\n }\n\n // ---- emit ---------------------------------------------------------------\n\n /**\n * Emit a typed event.\n *\n * Handlers are invoked synchronously in registration order. If a handler\n * throws, the error is logged and remaining handlers still execute.\n */\n emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void {\n if (this.debug) {\n console.log(LOG_PREFIX, event, data);\n }\n\n const eventKey = event as string;\n\n // 1. Exact-match listeners\n const exact = this.listeners.get(eventKey);\n if (exact) {\n // Snapshot to avoid issues if a handler adds/removes listeners\n const snapshot = exact.slice();\n for (const entry of snapshot) {\n this.invokeSafe(entry.fn, data, eventKey);\n }\n }\n\n // 2. Namespace wildcard listeners (e.g. \"dom:*\" matches \"dom:scan-complete\")\n const colonIdx = eventKey.indexOf(':');\n if (colonIdx !== -1) {\n const ns = eventKey.slice(0, colonIdx);\n const wildcardKey = `${ns}:*`;\n const wildcardList = this.listeners.get(wildcardKey);\n if (wildcardList) {\n const snapshot = wildcardList.slice();\n for (const entry of snapshot) {\n this.invokeSafe(entry.fn, data, eventKey);\n }\n }\n }\n\n // 3. `onAny` listeners\n if (this.anyListeners.length > 0) {\n const snapshot = this.anyListeners.slice();\n for (const fn of snapshot) {\n this.invokeSafe(fn, data, eventKey);\n }\n }\n }\n\n // ---- once ---------------------------------------------------------------\n\n /**\n * Subscribe to a specific event, automatically unsubscribing after the\n * first invocation.\n *\n * @returns An unsubscribe function (also cancels a not-yet-fired listener).\n */\n once<K extends keyof EventMap>(\n event: K,\n handler: (data: EventMap[K]) => void,\n ): () => void {\n const unsub = this.on(event, ((data: EventMap[K]) => {\n unsub();\n handler(data);\n }) as any);\n return unsub;\n }\n\n // ---- removeAll ----------------------------------------------------------\n\n /** Remove **all** listeners from the bus. */\n removeAll(): void {\n this.listeners.clear();\n this.anyListeners.length = 0;\n }\n\n // ---- listenerCount ------------------------------------------------------\n\n /**\n * Return the number of registered listeners.\n *\n * - If `event` is provided, returns the count for that specific event key\n * (including wildcard keys like `'dom:*'`).\n * - If omitted, returns the total across all events plus `onAny` listeners.\n */\n listenerCount(event?: string): number {\n if (event !== undefined) {\n return this.listeners.get(event)?.length ?? 0;\n }\n\n let total = this.anyListeners.length;\n for (const list of this.listeners.values()) {\n total += list.length;\n }\n return total;\n }\n\n // ---- private helpers ----------------------------------------------------\n\n /**\n * Invoke a handler inside a try/catch so one misbehaving handler never\n * prevents the remaining handlers from executing.\n */\n private invokeSafe(fn: (...args: any[]) => void, ...args: any[]): void {\n try {\n fn(...args);\n } catch (err) {\n console.error(\n LOG_PREFIX,\n 'Handler threw an error:',\n err,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new {@link EventBus} instance.\n *\n * ```ts\n * const bus = createEventBus({ debug: true });\n * const unsub = bus.on('dom:scan-complete', (data) => {\n * console.log(data.pageModel, data.durationMs);\n * });\n * bus.emit('dom:scan-complete', { pageModel: {}, durationMs: 42 });\n * unsub();\n * ```\n */\nexport function createEventBus(options?: { debug?: boolean }): EventBus {\n return new EventBus(options);\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Resource Lifecycle Manager\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Resources]';\n\n/** Timeout in milliseconds for each resource cleanup operation. */\nconst CLEANUP_TIMEOUT_MS = 2_000;\n\n// ---------------------------------------------------------------------------\n// Resource interface\n// ---------------------------------------------------------------------------\n\n/**\n * A disposable resource that the SDK tracks for deterministic cleanup.\n * Each resource has a unique name and a cleanup function that may be async.\n */\nexport interface Resource {\n name: string;\n cleanup: () => void | Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// ResourceManager\n// ---------------------------------------------------------------------------\n\n/** Lifecycle states for a ResourceManager instance. */\nexport type ResourceManagerState =\n | 'initializing'\n | 'ready'\n | 'tearing_down'\n | 'torn_down';\n\n/**\n * Manages the lifecycle of SDK resources (AbortControllers, event listeners,\n * WebSocket connections, etc.) and ensures deterministic cleanup on unmount.\n *\n * Resources are cleaned up sequentially — order matters because later\n * resources may depend on earlier ones still being alive during their own\n * cleanup phase.\n */\nexport class ResourceManager {\n readonly instanceId: string;\n\n private _state: ResourceManagerState = 'initializing';\n private readonly _resources: Map<string, Resource> = new Map();\n private _destroyPromise: Promise<void> | null = null;\n private _destroyCancelled = false;\n\n constructor(instanceId?: string) {\n this.instanceId = instanceId ?? generateId();\n debug(`Created ResourceManager \"${this.instanceId}\"`);\n }\n\n // -------------------------------------------------------------------------\n // State\n // -------------------------------------------------------------------------\n\n /** Current lifecycle state. */\n get state(): ResourceManagerState {\n return this._state;\n }\n\n /** Number of currently registered resources. */\n get resourceCount(): number {\n return this._resources.size;\n }\n\n // -------------------------------------------------------------------------\n // Registration\n // -------------------------------------------------------------------------\n\n /**\n * Register a resource for cleanup tracking.\n *\n * @throws If the manager has already been torn down.\n */\n register(resource: Resource): void {\n if (this._state === 'torn_down') {\n throw new Error(\n `${LOG_PREFIX} Cannot register resource \"${resource.name}\" — manager is torn down`,\n );\n }\n\n if (this._resources.has(resource.name)) {\n debug(\n `Replacing existing resource \"${resource.name}\" in \"${this.instanceId}\"`,\n );\n }\n\n this._resources.set(resource.name, resource);\n debug(\n `Registered \"${resource.name}\" in \"${this.instanceId}\" (total: ${this._resources.size})`,\n );\n }\n\n /**\n * Unregister a specific resource by name without invoking its cleanup.\n */\n unregister(name: string): void {\n const deleted = this._resources.delete(name);\n if (deleted) {\n debug(\n `Unregistered \"${name}\" from \"${this.instanceId}\" (total: ${this._resources.size})`,\n );\n }\n }\n\n // -------------------------------------------------------------------------\n // AbortController helper\n // -------------------------------------------------------------------------\n\n /**\n * Create a tracked AbortController. On destroy, its `abort()` method will\n * be called automatically.\n */\n createAbortController(name: string): AbortController {\n const controller = new AbortController();\n\n this.register({\n name,\n cleanup: () => {\n if (!controller.signal.aborted) {\n controller.abort();\n }\n },\n });\n\n return controller;\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle transitions\n // -------------------------------------------------------------------------\n\n /** Transition from `initializing` to `ready`. */\n markReady(): void {\n if (this._state === 'initializing') {\n this._state = 'ready';\n debug(`\"${this.instanceId}\" is now ready`);\n }\n }\n\n /**\n * Destroy all registered resources sequentially.\n *\n * Each resource gets up to {@link CLEANUP_TIMEOUT_MS}ms to complete.\n * If cleanup exceeds the timeout a warning is logged and the manager\n * proceeds to the next resource.\n *\n * After all resources are processed the state transitions to `torn_down`.\n * Calling `destroy()` multiple times returns the same promise.\n */\n async destroy(): Promise<void> {\n // Idempotent — return existing promise if already running / finished.\n if (this._destroyPromise) {\n return this._destroyPromise;\n }\n\n this._state = 'tearing_down';\n this._destroyCancelled = false;\n\n debug(\n `Destroying \"${this.instanceId}\" (${this._resources.size} resource(s))`,\n );\n\n this._destroyPromise = this._performDestroy();\n return this._destroyPromise;\n }\n\n /**\n * Cancel a pending destroy, transitioning back to `ready`.\n *\n * This exists to support React 18 StrictMode which unmounts then\n * immediately re-mounts components. If the re-mount arrives while\n * teardown is still in progress, cancelling prevents resource loss.\n *\n * @returns `true` if teardown was pending and has been cancelled.\n * `false` if already torn down or not currently tearing down.\n */\n cancelDestroy(): boolean {\n if (this._state !== 'tearing_down') {\n return false;\n }\n\n debug(`Cancelling destroy for \"${this.instanceId}\"`);\n this._destroyCancelled = true;\n this._state = 'ready';\n this._destroyPromise = null;\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Internal\n // -------------------------------------------------------------------------\n\n /** Sequential cleanup with per-resource timeout. */\n private async _performDestroy(): Promise<void> {\n // Snapshot the resource names so we iterate a stable list.\n const names = Array.from(this._resources.keys());\n\n for (const name of names) {\n // If cancelDestroy() was called mid-teardown, bail out early.\n if (this._destroyCancelled) {\n debug(\n `Destroy cancelled mid-teardown for \"${this.instanceId}\" — stopping cleanup`,\n );\n return;\n }\n\n const resource = this._resources.get(name);\n if (!resource) {\n continue;\n }\n\n try {\n /**\n * Cleanup timeout: logs warning but resolves promise regardless.\n * Resources may leak if cleanup takes longer than the timeout period.\n */\n await withTimeout(resource.cleanup(), CLEANUP_TIMEOUT_MS, () => {\n console.warn(\n `${LOG_PREFIX} Cleanup timeout for \"${name}\" (${CLEANUP_TIMEOUT_MS}ms)`,\n );\n });\n } catch (err) {\n console.warn(\n `${LOG_PREFIX} Cleanup error for \"${name}\":`,\n err,\n );\n }\n\n this._resources.delete(name);\n }\n\n // Only transition to torn_down if we were not cancelled.\n if (!this._destroyCancelled) {\n this._state = 'torn_down';\n debug(`\"${this.instanceId}\" is now torn down`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SingletonGuard – ref-counted singleton map\n// ---------------------------------------------------------------------------\n\ninterface GuardEntry {\n manager: ResourceManager;\n refCount: number;\n pendingDestroyTimer: ReturnType<typeof setTimeout> | null;\n}\n\n/**\n * Ref-counted singleton guard keyed by `instanceId`.\n *\n * - `acquire()` increments the ref count (or creates the manager).\n * - `release()` decrements the ref count. When it reaches 0 a\n * `setTimeout(0)` is scheduled to allow React StrictMode re-mount to\n * reclaim the instance before it is destroyed.\n * - If a mount arrives during `TEARING_DOWN`, the teardown is cancelled\n * and the manager transitions back to `READY`.\n */\nexport class SingletonGuard {\n private static readonly _entries: Map<string, GuardEntry> = new Map();\n\n /**\n * Acquire (or create) a ResourceManager for the given instanceId.\n *\n * @param instanceId Unique identifier for the singleton slot.\n * @param factory Called to create a fresh ResourceManager when none\n * exists or the previous one has been torn down.\n */\n static acquire(\n instanceId: string,\n factory: () => ResourceManager,\n ): ResourceManager {\n const existing = SingletonGuard._entries.get(instanceId);\n\n if (existing) {\n // Cancel any pending deferred destruction.\n if (existing.pendingDestroyTimer !== null) {\n clearTimeout(existing.pendingDestroyTimer);\n existing.pendingDestroyTimer = null;\n debug(`Cleared pending destroy timer for \"${instanceId}\"`);\n }\n\n // If the manager is mid-teardown, cancel it.\n if (existing.manager.state === 'tearing_down') {\n const cancelled = existing.manager.cancelDestroy();\n if (cancelled) {\n debug(\n `Re-acquired \"${instanceId}\" — cancelled in-flight teardown`,\n );\n }\n }\n\n // If the previous manager was fully torn down, replace it.\n if (existing.manager.state === 'torn_down') {\n debug(\n `Previous manager for \"${instanceId}\" is torn down — creating new one`,\n );\n const manager = factory();\n SingletonGuard._entries.set(instanceId, {\n manager,\n refCount: 1,\n pendingDestroyTimer: null,\n });\n return manager;\n }\n\n existing.refCount += 1;\n debug(\n `Acquired \"${instanceId}\" (refCount: ${existing.refCount})`,\n );\n return existing.manager;\n }\n\n // First acquisition — create a new entry.\n const manager = factory();\n SingletonGuard._entries.set(instanceId, {\n manager,\n refCount: 1,\n pendingDestroyTimer: null,\n });\n debug(`Created new singleton for \"${instanceId}\"`);\n return manager;\n }\n\n /**\n * Release a reference to the manager. When the ref count drops to 0 a\n * `setTimeout(0)` delay is introduced before destruction so that React\n * StrictMode's synchronous re-mount can reclaim the instance.\n */\n static release(instanceId: string): void {\n const entry = SingletonGuard._entries.get(instanceId);\n if (!entry) {\n debug(`Release called for unknown instanceId \"${instanceId}\"`);\n return;\n }\n\n entry.refCount = Math.max(0, entry.refCount - 1);\n debug(`Released \"${instanceId}\" (refCount: ${entry.refCount})`);\n\n if (entry.refCount === 0) {\n // Defer destruction so StrictMode re-mount can reclaim.\n entry.pendingDestroyTimer = setTimeout(() => {\n entry.pendingDestroyTimer = null;\n\n // Double-check nobody re-acquired in the meantime.\n if (entry.refCount > 0) {\n return;\n }\n\n debug(`Destroying singleton \"${instanceId}\" (refCount is 0)`);\n entry.manager.destroy().then(() => {\n // Only remove from the map if it is still the same entry and\n // the manager successfully tore down.\n if (\n SingletonGuard._entries.get(instanceId) === entry &&\n entry.manager.state === 'torn_down'\n ) {\n SingletonGuard._entries.delete(instanceId);\n debug(`Removed singleton entry for \"${instanceId}\"`);\n }\n });\n }, 0);\n }\n }\n\n /**\n * Retrieve a manager by instanceId without affecting the ref count.\n * Returns `undefined` if no manager exists for the given id.\n */\n static get(instanceId: string): ResourceManager | undefined {\n return SingletonGuard._entries.get(instanceId)?.manager;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Race a (possibly async) operation against a timeout.\n * If the timeout wins, `onTimeout` is called and the function resolves\n * (it does **not** reject — the next resource should still be processed).\n */\nfunction withTimeout(\n work: void | Promise<void>,\n ms: number,\n onTimeout: () => void,\n): Promise<void> {\n // Synchronous cleanup — no timeout needed.\n if (!(work instanceof Promise)) {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve) => {\n let settled = false;\n\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n onTimeout();\n resolve();\n }\n }, ms);\n\n work.then(\n () => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n resolve();\n }\n },\n (err) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n // Re-throw so the caller's catch block can log it.\n // We wrap in a rejected promise to keep the signature clean.\n resolve(Promise.reject(err));\n }\n },\n );\n });\n}\n\n/** Simple random ID generator (no crypto dependency required). */\nfunction generateId(): string {\n return `gk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/** Conditional debug logging — only logs when globalThis has a truthy `__GUIDEKIT_DEBUG__` flag. */\nfunction debug(...args: unknown[]): void {\n if (\n typeof globalThis !== 'undefined' &&\n (globalThis as Record<string, unknown>).__GUIDEKIT_DEBUG__\n ) {\n console.debug(LOG_PREFIX, ...args);\n }\n}\n","/**\n * @module @guidekit/core/dom\n *\n * DOM intelligence engine for the GuideKit SDK.\n * Scans the current page and builds a structured PageModel that serves as\n * grounding context for the LLM on every turn.\n *\n * Key design decisions:\n * - SSR-safe: every browser API is guarded behind `typeof document/window`.\n * - Privacy-first: password fields and PII patterns are never captured.\n * - Budget-constrained: hard limits on node count and tree depth prevent\n * runaway scans on large pages.\n * - Mutation-resilient: MutationObserver is throttled and circuit-broken.\n */\n\nimport type {\n PageModel,\n PageSection,\n NavItem,\n InteractiveElement,\n FormSummary,\n FormField,\n OverlayElement,\n ScanMetadata,\n} from '../types/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_MAX_NODES = 5000;\nconst DEFAULT_MAX_SECTIONS = 20;\nconst DEFAULT_MAX_DEPTH = 15;\n\nconst MUTATION_DEBOUNCE_MS = 500;\nconst MUTATION_CIRCUIT_BREAKER_THRESHOLD = 100; // mutations per second\nconst CIRCUIT_BREAKER_COOLDOWN_MS = 2000;\nconst MIN_RESCAN_INTERVAL_MS = 2000;\n\nconst LOG_PREFIX = '[GuideKit:DOM]';\n\n/** Semantic tags that qualify as sections without additional attributes. */\nconst SECTION_TAGS = new Set([\n 'SECTION',\n 'ARTICLE',\n 'MAIN',\n 'ASIDE',\n 'HEADER',\n 'FOOTER',\n 'NAV',\n]);\n\n/** Tags that map to landmark roles for scoring. */\nconst LANDMARK_TAG_MAP: Record<string, string> = {\n HEADER: 'banner',\n FOOTER: 'contentinfo',\n NAV: 'navigation',\n MAIN: 'main',\n ASIDE: 'complementary',\n};\n\n/** Interactive element selectors. */\nconst INTERACTIVE_SELECTOR =\n 'button, a[href], input, select, textarea, [role=\"button\"], [role=\"link\"], [tabindex]';\n\n/** Tags whose text value must never be captured. */\nconst SENSITIVE_INPUT_TYPES = new Set(['password', 'tel', 'email']);\n\n/** PII regex patterns stripped from text content. */\nconst PII_PATTERNS: RegExp[] = [\n // Email addresses\n /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g,\n // US phone numbers (various formats)\n /(\\+?1[-.\\s]?)?(\\(?\\d{3}\\)?[-.\\s]?)?\\d{3}[-.\\s]?\\d{4}/g,\n // SSN\n /\\b\\d{3}[-]?\\d{2}[-]?\\d{4}\\b/g,\n // Credit card numbers (basic)\n /\\b(?:\\d[ -]*?){13,19}\\b/g,\n];\n\n// ---------------------------------------------------------------------------\n// Utility helpers\n// ---------------------------------------------------------------------------\n\n/** Simple string hash (djb2). */\nfunction djb2Hash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/** Strip PII from a string. */\nfunction stripPII(text: string): string {\n let result = text;\n for (const pattern of PII_PATTERNS) {\n // Reset lastIndex for global regexps that are reused\n pattern.lastIndex = 0;\n result = result.replace(pattern, '[REDACTED]');\n }\n return result;\n}\n\n/** Truncate a string to a max length, adding ellipsis if needed. */\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max).trimEnd() + '\\u2026';\n}\n\n/** Collapse whitespace in a string. */\nfunction collapseWhitespace(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n\n/** Get visible text content from an element, limited in length. */\nfunction getTextContent(el: Element, maxLen: number = 200): string {\n const raw = el.textContent ?? '';\n return stripPII(truncate(collapseWhitespace(raw), maxLen));\n}\n\n/** Check whether an element is visible in the layout sense (not IntersectionObserver). */\nfunction isElementVisible(el: Element): boolean {\n if (typeof window === 'undefined') return false;\n const style = window.getComputedStyle(el);\n return (\n style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0'\n );\n}\n\n/** Get an accessible label for an element. */\nfunction getAccessibleLabel(el: Element): string {\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n const ariaLabelledBy = el.getAttribute('aria-labelledby');\n if (ariaLabelledBy && typeof document !== 'undefined') {\n const labelEl = document.getElementById(ariaLabelledBy);\n if (labelEl) return collapseWhitespace(labelEl.textContent ?? '');\n }\n\n return '';\n}\n\n/** Request idle callback with fallback. */\nfunction scheduleIdle(cb: () => void): void {\n if (typeof window !== 'undefined' && 'requestIdleCallback' in window) {\n (window as unknown as { requestIdleCallback: (cb: () => void) => void }).requestIdleCallback(cb);\n } else if (typeof setTimeout !== 'undefined') {\n setTimeout(cb, 0);\n } else {\n cb();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Selector builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build a stable CSS selector for an element following the priority hierarchy:\n * 1. data-guidekit-target\n * 2. id\n * 3. data-testid\n * 4. aria-label\n * 5. Structural path fallback\n */\nfunction buildSelector(el: Element): string {\n // 1. GuideKit target (highest priority)\n const guideKitTarget = el.getAttribute('data-guidekit-target');\n if (guideKitTarget) {\n return `[data-guidekit-target=\"${guideKitTarget}\"]`;\n }\n\n // 2. ID\n const id = el.id;\n if (id && typeof document !== 'undefined') {\n // Verify uniqueness\n try {\n const matches = document.querySelectorAll(`#${CSS.escape(id)}`);\n if (matches.length === 1) {\n return `#${CSS.escape(id)}`;\n }\n } catch {\n // CSS.escape may not be available; fall through\n }\n }\n\n // 3. data-testid\n const testId = el.getAttribute('data-testid');\n if (testId) {\n return `[data-testid=\"${testId}\"]`;\n }\n\n // 4. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) {\n return `[aria-label=\"${ariaLabel}\"]`;\n }\n\n // 5. Structural path fallback\n return buildStructuralPath(el);\n}\n\n/** Build a structural CSS selector path from root to the element. */\nfunction buildStructuralPath(el: Element): string {\n const parts: string[] = [];\n let current: Element | null = el;\n\n while (current && current !== document.documentElement) {\n const tag = current.tagName.toLowerCase();\n\n if (tag === 'body' || tag === 'html') {\n parts.unshift(tag);\n current = current.parentElement;\n continue;\n }\n\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c) => c.tagName === current!.tagName,\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n parts.unshift(`${tag}:nth-child(${index})`);\n } else {\n parts.unshift(tag);\n }\n } else {\n parts.unshift(tag);\n }\n\n current = parent;\n }\n\n return parts.join(' > ');\n}\n\n// ---------------------------------------------------------------------------\n// Section ID generation\n// ---------------------------------------------------------------------------\n\nlet sectionCounter = 0;\n\nfunction generateSectionId(el: Element): string {\n const guideKitTarget = el.getAttribute('data-guidekit-target');\n if (guideKitTarget) return guideKitTarget;\n\n const id = el.id;\n if (id) return id;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) {\n return ariaLabel\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n }\n\n sectionCounter += 1;\n return `section-${sectionCounter}`;\n}\n\n// ---------------------------------------------------------------------------\n// DOMScanner\n// ---------------------------------------------------------------------------\n\nexport interface DOMScannerOptions {\n rootElement?: HTMLElement;\n debug?: boolean;\n maxNodes?: number;\n maxSections?: number;\n maxDepth?: number;\n}\n\nexport class DOMScanner {\n private readonly root: HTMLElement | null;\n private readonly debug: boolean;\n private readonly maxNodes: number;\n private readonly maxSections: number;\n private readonly maxDepth: number;\n\n private cachedModel: PageModel | null = null;\n\n // Visibility tracking (updated via IntersectionObserver)\n private visibilityMap: Map<Element, number> = new Map();\n\n // MutationObserver state\n private observer: MutationObserver | null = null;\n private mutationCount = 0;\n private mutationWindowStart = 0;\n private circuitBroken = false;\n private circuitBrokenTimer: ReturnType<typeof setTimeout> | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private lastScanTime = 0;\n\n constructor(options?: DOMScannerOptions) {\n const isBrowser =\n typeof document !== 'undefined' && typeof window !== 'undefined';\n\n this.root = options?.rootElement ?? (isBrowser ? document.body : null);\n this.debug = options?.debug ?? false;\n this.maxNodes = options?.maxNodes ?? DEFAULT_MAX_NODES;\n this.maxSections = options?.maxSections ?? DEFAULT_MAX_SECTIONS;\n this.maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;\n\n this.log('Initialised', {\n root: this.root?.tagName,\n maxNodes: this.maxNodes,\n maxSections: this.maxSections,\n maxDepth: this.maxDepth,\n });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Perform a full scan and return a PageModel. */\n scan(): PageModel {\n if (typeof document === 'undefined' || typeof window === 'undefined') {\n this.log('SSR environment detected, returning empty model');\n return this.emptyModel();\n }\n\n if (!this.root) {\n this.log('No root element available, returning empty model');\n return this.emptyModel();\n }\n\n this.log('Starting scan');\n const startTime = performance.now();\n\n // Reset section counter per scan\n sectionCounter = 0;\n\n let nodesScanned = 0;\n let budgetExhausted = false;\n\n // Phase 1: Walk DOM and collect candidate section elements\n const candidateSections: Array<{ el: Element; depth: number }> = [];\n const allElements: Element[] = [];\n\n const walker = document.createTreeWalker(\n this.root,\n NodeFilter.SHOW_ELEMENT,\n {\n acceptNode: (node: Node): number => {\n const el = node as Element;\n\n // Skip guidekit-ignore subtrees\n if (el.hasAttribute('data-guidekit-ignore')) {\n return NodeFilter.FILTER_REJECT;\n }\n\n // Budget check\n if (nodesScanned >= this.maxNodes) {\n budgetExhausted = true;\n return NodeFilter.FILTER_REJECT;\n }\n\n nodesScanned++;\n return NodeFilter.FILTER_ACCEPT;\n },\n },\n );\n\n // Walk the tree\n let currentNode = walker.nextNode();\n while (currentNode) {\n const el = currentNode as Element;\n allElements.push(el);\n\n // Check if this is a candidate section\n const depth = this.getDepth(el);\n if (depth <= this.maxDepth && this.isSectionCandidate(el)) {\n candidateSections.push({ el, depth });\n }\n\n currentNode = walker.nextNode();\n }\n\n this.log(`Walked ${nodesScanned} nodes, found ${candidateSections.length} section candidates`);\n\n // Phase 2: Extract page data\n const sections = this.extractSections(candidateSections);\n const navigation = this.extractNavigation();\n const interactiveElements = this.extractInteractiveElements();\n const forms = this.extractForms();\n const activeOverlays = this.extractOverlays();\n const meta = this.extractMeta();\n\n const scanMetadata: ScanMetadata = {\n totalSectionsFound: candidateSections.length,\n sectionsIncluded: sections.length,\n totalNodesScanned: nodesScanned,\n scanBudgetExhausted: budgetExhausted,\n };\n\n const model: PageModel = {\n url: window.location.href,\n title: document.title ?? '',\n meta,\n sections,\n navigation,\n interactiveElements,\n forms,\n activeOverlays,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n orientation:\n window.innerWidth >= window.innerHeight ? 'landscape' : 'portrait',\n },\n allSectionsSummary: sections.map(\n (s) => `[${s.label}] ${s.summary}`,\n ),\n hash: '',\n timestamp: Date.now(),\n scanMetadata,\n };\n\n // Generate hash from key model content\n model.hash = this.generateHash(model);\n\n this.cachedModel = model;\n\n const elapsed = (performance.now() - startTime).toFixed(1);\n this.log(`Scan complete in ${elapsed}ms`, {\n sections: sections.length,\n navItems: navigation.length,\n interactive: interactiveElements.length,\n forms: forms.length,\n overlays: activeOverlays.length,\n nodesScanned,\n budgetExhausted,\n });\n\n return model;\n }\n\n /**\n * Set up a MutationObserver that rescans on DOM changes.\n * Returns a cleanup function to disconnect the observer.\n */\n observe(callback: (model: PageModel) => void): () => void {\n if (typeof MutationObserver === 'undefined' || !this.root) {\n this.log('MutationObserver not available or no root');\n return () => {};\n }\n\n this.log('Starting observation');\n\n const handleMutations = (_mutations: MutationRecord[]) => {\n const now = Date.now();\n\n // --- Circuit breaker ---\n if (now - this.mutationWindowStart > 1000) {\n // New one-second window\n this.mutationCount = _mutations.length;\n this.mutationWindowStart = now;\n } else {\n this.mutationCount += _mutations.length;\n }\n\n if (this.mutationCount > MUTATION_CIRCUIT_BREAKER_THRESHOLD) {\n if (!this.circuitBroken) {\n this.circuitBroken = true;\n this.log('Circuit breaker tripped — pausing observation');\n\n // Disconnect temporarily\n this.observer?.disconnect();\n\n this.circuitBrokenTimer = setTimeout(() => {\n this.circuitBroken = false;\n this.mutationCount = 0;\n this.log('Circuit breaker reset — resuming observation');\n this.startObserving();\n this.triggerRescan(callback);\n }, CIRCUIT_BREAKER_COOLDOWN_MS);\n }\n return;\n }\n\n // --- Debounce ---\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n }\n\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.triggerRescan(callback);\n }, MUTATION_DEBOUNCE_MS);\n };\n\n this.observer = new MutationObserver(handleMutations);\n this.startObserving();\n\n // Return cleanup function\n return () => {\n this.log('Stopping observation');\n this.cleanup();\n };\n }\n\n /** Update visibility data from an IntersectionObserver. */\n updateVisibility(entries: IntersectionObserverEntry[]): void {\n for (const entry of entries) {\n this.visibilityMap.set(entry.target, entry.intersectionRatio);\n }\n }\n\n /** Get the current cached page model. */\n get currentModel(): PageModel | null {\n return this.cachedModel;\n }\n\n // -------------------------------------------------------------------------\n // Private: Observation helpers\n // -------------------------------------------------------------------------\n\n private startObserving(): void {\n if (!this.observer || !this.root) return;\n\n this.observer.observe(this.root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\n 'class',\n 'style',\n 'hidden',\n 'aria-hidden',\n 'aria-label',\n 'role',\n 'data-guidekit-target',\n 'data-guidekit-ignore',\n 'disabled',\n ],\n });\n }\n\n private triggerRescan(callback: (model: PageModel) => void): void {\n const now = Date.now();\n if (now - this.lastScanTime < MIN_RESCAN_INTERVAL_MS) {\n this.log('Rescan throttled');\n return;\n }\n\n this.lastScanTime = now;\n\n scheduleIdle(() => {\n const model = this.scan();\n callback(model);\n });\n }\n\n private cleanup(): void {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n if (this.circuitBrokenTimer !== null) {\n clearTimeout(this.circuitBrokenTimer);\n this.circuitBrokenTimer = null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Section extraction\n // -------------------------------------------------------------------------\n\n private isSectionCandidate(el: Element): boolean {\n const tag = el.tagName;\n\n // Semantic section tags\n if (SECTION_TAGS.has(tag)) return true;\n\n // Divs or other elements with role, aria-label, or id\n if (\n el.getAttribute('role') ||\n el.getAttribute('aria-label') ||\n el.id\n ) {\n return true;\n }\n\n return false;\n }\n\n private extractSections(\n candidates: Array<{ el: Element; depth: number }>,\n ): PageSection[] {\n const scored: PageSection[] = [];\n\n for (const { el, depth } of candidates) {\n const section = this.buildPageSection(el, depth);\n scored.push(section);\n }\n\n // Sort by score descending\n scored.sort((a, b) => b.score - a.score);\n\n // Take top N\n return scored.slice(0, this.maxSections);\n }\n\n private buildPageSection(el: Element, depth: number): PageSection {\n const tag = el.tagName;\n const selector = buildSelector(el);\n\n // Determine label\n const label = this.getSectionLabel(el);\n\n // Get summary from first ~100 chars of text\n const summary = getTextContent(el, 100);\n\n // Check visibility\n const visRatio = this.visibilityMap.get(el) ?? 0;\n const isVisible = visRatio > 0 || this.isInViewport(el);\n\n // Check for interactive elements\n const hasInteractive =\n el.querySelector(INTERACTIVE_SELECTOR) !== null;\n\n // Determine landmark\n const landmark = this.getLandmark(el);\n\n // Has heading?\n const hasHeading = el.querySelector('h1, h2, h3, h4, h5, h6') !== null;\n\n // Score\n const score = this.scoreSection({\n isVisible,\n hasInteractive,\n landmark,\n hasHeading,\n depth,\n el,\n });\n\n return {\n id: generateSectionId(el),\n selector,\n tagName: tag.toLowerCase(),\n label,\n summary,\n isVisible,\n visibilityRatio: visRatio,\n score,\n landmark: landmark ?? undefined,\n hasInteractiveElements: hasInteractive,\n depth,\n };\n }\n\n private getSectionLabel(el: Element): string {\n // 1. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n // 2. First heading\n const heading = el.querySelector('h1, h2, h3, h4, h5, h6');\n if (heading) {\n const text = collapseWhitespace(heading.textContent ?? '');\n if (text) return stripPII(truncate(text, 80));\n }\n\n // 3. id as fallback\n if (el.id) return el.id;\n\n // 4. Tag name\n return el.tagName.toLowerCase();\n }\n\n private getLandmark(el: Element): string | null {\n // Explicit role\n const role = el.getAttribute('role');\n if (role) return role;\n\n // Implicit landmark via tag\n const implicit = LANDMARK_TAG_MAP[el.tagName];\n if (implicit) return implicit;\n\n // section/article with aria-label count as landmarks\n if (\n (el.tagName === 'SECTION' || el.tagName === 'ARTICLE') &&\n el.getAttribute('aria-label')\n ) {\n return el.tagName === 'SECTION' ? 'region' : 'article';\n }\n\n return null;\n }\n\n private scoreSection(params: {\n isVisible: boolean;\n hasInteractive: boolean;\n landmark: string | null;\n hasHeading: boolean;\n depth: number;\n el: Element;\n }): number {\n let score = 0;\n\n if (params.isVisible) score += 100;\n if (params.hasInteractive) score += 20;\n if (params.landmark) score += 15;\n\n // Near scroll position\n if (typeof window !== 'undefined') {\n const rect = params.el.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n if (\n rect.top >= -viewportHeight &&\n rect.top <= viewportHeight * 2\n ) {\n score += 10;\n }\n }\n\n if (params.hasHeading) score += 5;\n\n // Depth penalty\n score -= params.depth * 2;\n\n return score;\n }\n\n // -------------------------------------------------------------------------\n // Private: Navigation extraction\n // -------------------------------------------------------------------------\n\n private extractNavigation(): NavItem[] {\n if (typeof document === 'undefined') return [];\n\n const navElements = this.root?.querySelectorAll('nav') ?? [];\n const items: NavItem[] = [];\n\n navElements.forEach((nav) => {\n if (nav.hasAttribute('data-guidekit-ignore')) return;\n\n const links = nav.querySelectorAll('a[href]');\n links.forEach((link) => {\n const anchor = link as HTMLAnchorElement;\n const label = collapseWhitespace(anchor.textContent ?? '');\n if (!label) return;\n\n const href = anchor.getAttribute('href') ?? '';\n const isCurrent =\n anchor.getAttribute('aria-current') === 'page' ||\n anchor.classList.contains('active') ||\n (typeof window !== 'undefined' && anchor.href === window.location.href);\n\n items.push({\n label: stripPII(truncate(label, 60)),\n href,\n isCurrent,\n selector: buildSelector(anchor),\n });\n });\n });\n\n return items;\n }\n\n // -------------------------------------------------------------------------\n // Private: Interactive elements extraction\n // -------------------------------------------------------------------------\n\n private extractInteractiveElements(): InteractiveElement[] {\n if (typeof document === 'undefined' || !this.root) return [];\n\n const elements = this.root.querySelectorAll(INTERACTIVE_SELECTOR);\n const result: InteractiveElement[] = [];\n\n elements.forEach((el) => {\n // Skip elements inside ignored subtrees\n if (el.closest('[data-guidekit-ignore]')) return;\n\n const htmlEl = el as HTMLElement;\n const tag = el.tagName.toLowerCase();\n const type = el.getAttribute('type') ?? undefined;\n\n // Skip sensitive input types — never capture their labels from value/placeholder\n const isSensitive =\n tag === 'input' && SENSITIVE_INPUT_TYPES.has(type ?? '');\n\n // Get label\n let label = getAccessibleLabel(el);\n if (!label && !isSensitive) {\n label = collapseWhitespace(el.textContent ?? '');\n }\n if (!label) {\n const placeholder = el.getAttribute('placeholder');\n if (placeholder && !isSensitive) {\n label = placeholder;\n }\n }\n if (!label && el.getAttribute('title')) {\n label = el.getAttribute('title') ?? '';\n }\n if (!label && isSensitive) {\n label = type ?? 'input';\n }\n label = stripPII(truncate(label, 60));\n\n const role = el.getAttribute('role') ?? undefined;\n const isDisabled =\n htmlEl.hasAttribute('disabled') ||\n htmlEl.getAttribute('aria-disabled') === 'true';\n const guideKitTarget =\n el.getAttribute('data-guidekit-target') ?? undefined;\n\n result.push({\n selector: buildSelector(el),\n tagName: tag,\n type,\n label,\n role,\n isDisabled,\n guideKitTarget,\n });\n });\n\n return result;\n }\n\n // -------------------------------------------------------------------------\n // Private: Form extraction\n // -------------------------------------------------------------------------\n\n private extractForms(): FormSummary[] {\n if (typeof document === 'undefined' || !this.root) return [];\n\n const formElements = this.root.querySelectorAll('form');\n const result: FormSummary[] = [];\n\n formElements.forEach((form) => {\n if (form.closest('[data-guidekit-ignore]')) return;\n\n const fields = this.extractFormFields(form);\n const hasValidationErrors = fields.some((f) => f.hasError);\n\n result.push({\n selector: buildSelector(form),\n id: form.id || undefined,\n action: form.action || undefined,\n fields,\n hasValidationErrors,\n });\n });\n\n return result;\n }\n\n private extractFormFields(form: HTMLFormElement): FormField[] {\n const fields: FormField[] = [];\n const fieldElements = form.querySelectorAll(\n 'input, select, textarea',\n );\n\n fieldElements.forEach((el) => {\n const input = el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n const name = input.name || input.id || '';\n const type =\n el.tagName === 'SELECT'\n ? 'select'\n : el.tagName === 'TEXTAREA'\n ? 'textarea'\n : (el as HTMLInputElement).type || 'text';\n\n // Find label\n let label = '';\n if (input.id && typeof document !== 'undefined') {\n const labelEl = document.querySelector(\n `label[for=\"${CSS.escape(input.id)}\"]`,\n );\n if (labelEl) {\n label = collapseWhitespace(labelEl.textContent ?? '');\n }\n }\n if (!label) {\n // Check for wrapping label\n const parentLabel = input.closest('label');\n if (parentLabel) {\n label = collapseWhitespace(parentLabel.textContent ?? '');\n }\n }\n if (!label) {\n label = getAccessibleLabel(el);\n }\n if (!label) {\n const placeholder = el.getAttribute('placeholder');\n label = placeholder ?? name;\n }\n label = stripPII(truncate(label, 60));\n\n // Required?\n const isRequired =\n input.hasAttribute('required') ||\n input.getAttribute('aria-required') === 'true';\n\n // Validation error\n const hasError =\n input.getAttribute('aria-invalid') === 'true' ||\n (input instanceof HTMLInputElement && !input.validity.valid && input.value !== '');\n\n let errorMessage: string | undefined;\n const errorId = input.getAttribute('aria-errormessage') ?? input.getAttribute('aria-describedby');\n if (hasError && errorId && typeof document !== 'undefined') {\n const errorEl = document.getElementById(errorId);\n if (errorEl) {\n errorMessage = collapseWhitespace(errorEl.textContent ?? '');\n }\n }\n if (hasError && !errorMessage && input instanceof HTMLInputElement) {\n errorMessage = input.validationMessage || undefined;\n }\n\n fields.push({\n selector: buildSelector(el),\n name,\n type,\n label,\n isRequired,\n hasError,\n errorMessage,\n });\n });\n\n return fields;\n }\n\n // -------------------------------------------------------------------------\n // Private: Overlay detection\n // -------------------------------------------------------------------------\n\n private extractOverlays(): OverlayElement[] {\n if (typeof document === 'undefined' || typeof window === 'undefined' || !this.root) {\n return [];\n }\n\n const result: OverlayElement[] = [];\n\n // 1. Elements with explicit dialog roles\n const dialogElements = this.root.querySelectorAll(\n '[role=\"dialog\"], [role=\"alertdialog\"], dialog',\n );\n dialogElements.forEach((el) => {\n if (el.closest('[data-guidekit-ignore]')) return;\n const label = getAccessibleLabel(el) || getTextContent(el, 40) || 'dialog';\n result.push({\n selector: buildSelector(el),\n type: 'modal',\n label: stripPII(label),\n isVisible: isElementVisible(el),\n });\n });\n\n // 2. Common modal patterns: high z-index + fixed/absolute positioning\n const allElements = this.root.querySelectorAll('*');\n const seen = new Set<Element>(dialogElements);\n\n allElements.forEach((el) => {\n if (seen.has(el)) return;\n if (el.closest('[data-guidekit-ignore]')) return;\n\n const style = window.getComputedStyle(el);\n const position = style.position;\n const zIndex = parseInt(style.zIndex, 10) || 0;\n\n if (\n (position === 'fixed' || position === 'absolute') &&\n !Number.isNaN(zIndex) &&\n zIndex >= 1000\n ) {\n const visible = isElementVisible(el);\n if (!visible) return;\n\n // Determine overlay type heuristically\n const overlayType = this.classifyOverlay(el, style);\n if (!overlayType) return;\n\n const label =\n getAccessibleLabel(el) || getTextContent(el, 40) || overlayType;\n\n result.push({\n selector: buildSelector(el),\n type: overlayType,\n label: stripPII(label),\n isVisible: visible,\n });\n }\n });\n\n return result;\n }\n\n private classifyOverlay(\n el: Element,\n style: CSSStyleDeclaration,\n ): OverlayElement['type'] | null {\n const role = el.getAttribute('role');\n if (role === 'dialog' || role === 'alertdialog') return 'modal';\n if (role === 'menu' || role === 'listbox') return 'dropdown';\n\n // Check class names for hints\n const className = el.className?.toString?.() ?? '';\n const lower = className.toLowerCase();\n\n if (lower.includes('modal') || lower.includes('dialog')) return 'modal';\n if (lower.includes('drawer') || lower.includes('sidebar')) return 'drawer';\n if (\n lower.includes('dropdown') ||\n lower.includes('menu') ||\n lower.includes('popover')\n )\n return 'dropdown';\n\n // Fixed elements covering large area are likely modals\n const width = parseFloat(style.width);\n const height = parseFloat(style.height);\n if (\n typeof window !== 'undefined' &&\n !Number.isNaN(width) &&\n !Number.isNaN(height) &&\n width > window.innerWidth * 0.5 &&\n height > window.innerHeight * 0.5\n ) {\n return 'modal';\n }\n\n // Small positioned element is likely a popover\n if (!Number.isNaN(width) && width < 400) return 'popover';\n\n return null;\n }\n\n // -------------------------------------------------------------------------\n // Private: Meta extraction\n // -------------------------------------------------------------------------\n\n private extractMeta(): PageModel['meta'] {\n if (typeof document === 'undefined') {\n return { description: '', h1: null, language: 'en' };\n }\n\n const descMeta = document.querySelector('meta[name=\"description\"]');\n const description = descMeta?.getAttribute('content') ?? '';\n\n const h1El = document.querySelector('h1');\n const h1 = h1El ? stripPII(collapseWhitespace(h1El.textContent ?? '')) : null;\n\n const language =\n document.documentElement.getAttribute('lang') ?? 'en';\n\n return {\n description: stripPII(description),\n h1,\n language,\n };\n }\n\n // -------------------------------------------------------------------------\n // Private: Helpers\n // -------------------------------------------------------------------------\n\n private getDepth(el: Element): number {\n let depth = 0;\n let current: Element | null = el;\n const root = this.root;\n\n while (current && current !== root && depth < this.maxDepth + 1) {\n current = current.parentElement;\n depth++;\n }\n\n return depth;\n }\n\n private isInViewport(el: Element): boolean {\n if (typeof window === 'undefined') return false;\n try {\n const rect = el.getBoundingClientRect();\n return (\n rect.top < window.innerHeight &&\n rect.bottom > 0 &&\n rect.left < window.innerWidth &&\n rect.right > 0\n );\n } catch {\n return false;\n }\n }\n\n private generateHash(model: PageModel): string {\n // Hash key structural content for change detection\n const content = [\n model.url,\n model.title,\n model.meta.h1 ?? '',\n model.sections.map((s) => `${s.id}:${s.label}`).join(','),\n model.navigation.map((n) => n.href).join(','),\n model.interactiveElements.length.toString(),\n model.forms.length.toString(),\n model.activeOverlays.length.toString(),\n ].join('|');\n\n return djb2Hash(content);\n }\n\n private emptyModel(): PageModel {\n return {\n url: typeof window !== 'undefined' ? window.location.href : '',\n title: typeof document !== 'undefined' ? document.title ?? '' : '',\n meta: { description: '', h1: null, language: 'en' },\n sections: [],\n navigation: [],\n interactiveElements: [],\n forms: [],\n activeOverlays: [],\n viewport: { width: 0, height: 0, orientation: 'portrait' },\n allSectionsSummary: [],\n hash: '',\n timestamp: Date.now(),\n scanMetadata: {\n totalSectionsFound: 0,\n sectionsIncluded: 0,\n totalNodesScanned: 0,\n scanBudgetExhausted: false,\n },\n };\n }\n\n private log(message: string, data?: Record<string, unknown>): void {\n if (!this.debug) return;\n if (typeof console !== 'undefined') {\n if (data) {\n console.log(`${LOG_PREFIX} ${message}`, data);\n } else {\n console.log(`${LOG_PREFIX} ${message}`);\n }\n }\n }\n}\n","/**\n * @module @guidekit/core/context\n *\n * Context manager for the GuideKit SDK.\n * Assembles the LLM system prompt from the current page model, manages\n * conversation history with automatic eviction, resolves content-map entries,\n * and persists session state across page navigations via sessionStorage.\n */\n\nimport type {\n PageModel,\n ConversationTurn,\n ContentMapInput,\n ContentMap,\n ContentMapEntry,\n AgentConfig,\n ToolDefinition,\n SessionState,\n} from '../types/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst SESSION_STORAGE_KEY = 'guidekit:session';\nconst DEFAULT_MAX_TURNS = 20;\nconst DEFAULT_MAX_SESSION_SIZE_BYTES = 50_000; // 50 KB\nconst DEFAULT_TOKEN_BUDGET = 6_000; // ~1 500 tokens\nconst CONTENT_MAP_TIMEOUT_MS = 2_000;\nconst CONTENT_CACHE_TTL_MS = 30_000; // 30 seconds\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Measure byte-length of a string in UTF-8. */\nfunction byteLength(str: string): number {\n if (typeof TextEncoder !== 'undefined') {\n return new TextEncoder().encode(str).byteLength;\n }\n // Fallback for environments without TextEncoder (unlikely in modern runtimes)\n let bytes = 0;\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n if (code <= 0x7f) bytes += 1;\n else if (code <= 0x7ff) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdfff) {\n bytes += 4;\n i++; // surrogate pair\n } else bytes += 3;\n }\n return bytes;\n}\n\n/** Race a promise against a timeout, returning `null` on timeout. */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T | null> {\n return new Promise<T | null>((resolve) => {\n let settled = false;\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n resolve(null);\n }\n }, ms);\n\n promise\n .then((value) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n resolve(value);\n }\n })\n .catch(() => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n resolve(null);\n }\n });\n });\n}\n\n/** Check whether sessionStorage is available (SSR-safe). */\nfunction hasSessionStorage(): boolean {\n try {\n return (\n typeof window !== 'undefined' &&\n typeof window.sessionStorage !== 'undefined'\n );\n } catch {\n // In some environments, accessing sessionStorage itself can throw (e.g. sandboxed iframes).\n return false;\n }\n}\n\n/** Truncate a string to a maximum character count, appending an ellipsis if trimmed. */\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + '\\u2026';\n}\n\n// ---------------------------------------------------------------------------\n// Content cache entry\n// ---------------------------------------------------------------------------\n\ninterface CachedContent {\n entry: ContentMapEntry | null;\n expiresAt: number;\n}\n\n// ---------------------------------------------------------------------------\n// ContextManager\n// ---------------------------------------------------------------------------\n\nexport interface ContextManagerOptions {\n agent?: AgentConfig;\n contentMap?: ContentMapInput;\n maxTurns?: number;\n maxSessionSizeBytes?: number;\n tokenBudget?: number;\n debug?: boolean;\n}\n\nexport class ContextManager {\n private agent: AgentConfig;\n private contentMap: ContentMapInput | undefined;\n private maxTurns: number;\n private maxSessionSizeBytes: number;\n private tokenBudget: number;\n private debug: boolean;\n\n private history: ConversationTurn[] = [];\n private contentCache: Map<string, CachedContent> = new Map();\n\n // Session preferences (persisted across navigations)\n private _userPreference: 'voice' | 'text' = 'text';\n private _quietMode = false;\n private _pageContext: Record<string, unknown> = {};\n\n constructor(options?: ContextManagerOptions) {\n this.agent = options?.agent ?? {};\n this.contentMap = options?.contentMap;\n this.maxTurns = options?.maxTurns ?? DEFAULT_MAX_TURNS;\n this.maxSessionSizeBytes =\n options?.maxSessionSizeBytes ?? DEFAULT_MAX_SESSION_SIZE_BYTES;\n this.tokenBudget = options?.tokenBudget ?? DEFAULT_TOKEN_BUDGET;\n this.debug = options?.debug ?? false;\n }\n\n // -------------------------------------------------------------------------\n // System prompt\n // -------------------------------------------------------------------------\n\n /**\n * Build the full system prompt from the current page model and available\n * tools. The output is capped at `tokenBudget` characters so it fits\n * comfortably inside the LLM context window alongside conversation history.\n */\n buildSystemPrompt(pageModel: PageModel, tools: ToolDefinition[]): string {\n const parts: string[] = [];\n\n // -- Role ----------------------------------------------------------------\n parts.push(this.buildRoleSection());\n\n // -- Current Page --------------------------------------------------------\n parts.push(this.buildCurrentPageSection(pageModel));\n\n // -- Page Sections -------------------------------------------------------\n parts.push(this.buildPageSectionsSection(pageModel));\n\n // -- Navigation ----------------------------------------------------------\n if (pageModel.navigation.length > 0) {\n parts.push(this.buildNavigationSection(pageModel));\n }\n\n // -- Interactive Elements ------------------------------------------------\n if (pageModel.interactiveElements.length > 0) {\n parts.push(this.buildInteractiveElementsSection(pageModel));\n }\n\n // -- Forms ---------------------------------------------------------------\n if (pageModel.forms.length > 0) {\n parts.push(this.buildFormsSection(pageModel));\n }\n\n // -- User Viewport -------------------------------------------------------\n parts.push(this.buildViewportSection(pageModel));\n\n // -- Available Actions ---------------------------------------------------\n if (tools.length > 0) {\n parts.push(this.buildToolsSection(tools));\n }\n\n // -- Developer Context ---------------------------------------------------\n const pageCtxKeys = Object.keys(this._pageContext);\n if (pageCtxKeys.length > 0) {\n parts.push(this.buildPageContextSection());\n }\n\n // -- Guidelines ----------------------------------------------------------\n parts.push(this.buildGuidelinesSection());\n\n // Join and enforce budget\n let prompt = parts.join('\\n\\n');\n if (prompt.length > this.tokenBudget) {\n prompt = this.trimPromptToBudget(prompt, pageModel, tools);\n }\n\n return prompt;\n }\n\n // -------------------------------------------------------------------------\n // Conversation history\n // -------------------------------------------------------------------------\n\n /** Append a turn to the conversation history, enforcing size constraints. */\n addTurn(turn: ConversationTurn): void {\n this.history.push(turn);\n this.enforceHistoryLimits();\n }\n\n /** Return a copy of the current conversation history. */\n getHistory(): ConversationTurn[] {\n return this.history.slice();\n }\n\n /** Clear all conversation history. */\n clearHistory(): void {\n this.history = [];\n }\n\n // -------------------------------------------------------------------------\n // Content map\n // -------------------------------------------------------------------------\n\n /**\n * Resolve a `ContentMapEntry` for the given `sectionId`.\n *\n * - Static maps are looked up directly.\n * - Function-based maps are called with a 2-second timeout.\n * - Results are cached for 30 seconds per section ID.\n */\n async getContent(sectionId: string): Promise<ContentMapEntry | null> {\n // Check cache first\n const cached = this.contentCache.get(sectionId);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.entry;\n }\n\n if (this.contentMap === undefined) {\n return null;\n }\n\n let entry: ContentMapEntry | null;\n\n if (typeof this.contentMap === 'function') {\n try {\n const result = this.contentMap(sectionId);\n if (result instanceof Promise) {\n entry = await withTimeout(result, CONTENT_MAP_TIMEOUT_MS);\n } else {\n entry = result;\n }\n } catch (err) {\n this.log('Content map function threw for sectionId:', sectionId, err);\n entry = null;\n }\n } else {\n // Static Record<string, ContentMapEntry>\n entry = (this.contentMap as ContentMap)[sectionId] ?? null;\n }\n\n // Cache the result\n this.contentCache.set(sectionId, {\n entry,\n expiresAt: Date.now() + CONTENT_CACHE_TTL_MS,\n });\n\n return entry;\n }\n\n /** Replace the content map used for section lookups. Clears the cache. */\n setContentMap(contentMap: ContentMapInput): void {\n this.contentMap = contentMap;\n this.contentCache.clear();\n }\n\n // -------------------------------------------------------------------------\n // Session preferences\n // -------------------------------------------------------------------------\n\n get userPreference(): 'voice' | 'text' {\n return this._userPreference;\n }\n\n set userPreference(value: 'voice' | 'text') {\n this._userPreference = value;\n }\n\n get quietMode(): boolean {\n return this._quietMode;\n }\n\n set quietMode(value: boolean) {\n this._quietMode = value;\n }\n\n // -------------------------------------------------------------------------\n // Page context (dynamic context injection)\n // -------------------------------------------------------------------------\n\n /** Set developer-supplied page context (merged into system prompt). */\n setPageContext(context: Record<string, unknown>): void {\n this._pageContext = { ...this._pageContext, ...context };\n this.log('Page context updated', Object.keys(context));\n }\n\n /** Get the current page context. */\n getPageContext(): Record<string, unknown> {\n return { ...this._pageContext };\n }\n\n /** Clear all page context. */\n clearPageContext(): void {\n this._pageContext = {};\n }\n\n // -------------------------------------------------------------------------\n // Session persistence\n // -------------------------------------------------------------------------\n\n /** Persist the current session state to `sessionStorage`. */\n saveSession(): void {\n if (!hasSessionStorage()) return;\n\n const state = this.getSessionState();\n try {\n window.sessionStorage.setItem(\n SESSION_STORAGE_KEY,\n JSON.stringify(state),\n );\n } catch (err) {\n this.log('Failed to save session:', err);\n }\n }\n\n /** Restore a previously persisted session from `sessionStorage`. */\n restoreSession(): SessionState | null {\n if (!hasSessionStorage()) return null;\n\n try {\n const raw = window.sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) return null;\n\n const state = JSON.parse(raw) as SessionState;\n\n // Validate minimal shape\n if (\n !Array.isArray(state.conversationHistory) ||\n typeof state.currentUrl !== 'string'\n ) {\n this.log('Invalid session state, discarding.');\n return null;\n }\n\n // Restore conversation history\n this.history = state.conversationHistory;\n this.enforceHistoryLimits();\n\n // Restore preferences\n if (state.userPreference === 'voice' || state.userPreference === 'text') {\n this._userPreference = state.userPreference;\n }\n if (typeof state.quietMode === 'boolean') {\n this._quietMode = state.quietMode;\n }\n\n return state;\n } catch (err) {\n this.log('Failed to restore session:', err);\n return null;\n }\n }\n\n /** Build the current session state snapshot. */\n getSessionState(): SessionState {\n const serialised = JSON.stringify(this.history);\n const currentUrl =\n typeof window !== 'undefined' ? window.location.href : '';\n\n return {\n conversationHistory: this.history,\n currentUrl,\n agentStatus: 'idle',\n userPreference: this._userPreference,\n quietMode: this._quietMode,\n totalSizeBytes: byteLength(serialised),\n };\n }\n\n // -------------------------------------------------------------------------\n // Private — prompt section builders\n // -------------------------------------------------------------------------\n\n private buildRoleSection(): string {\n const name = this.agent.name || 'GuideKit';\n const personality =\n this.agent.personality ||\n 'You help users understand and navigate the site.';\n return `# Role\\nYou are ${name}, an AI guide embedded on this website.\\n${personality}`;\n }\n\n private buildCurrentPageSection(pageModel: PageModel): string {\n const lines = ['# Current Page'];\n lines.push(`URL: ${pageModel.url}`);\n lines.push(`Title: ${pageModel.title}`);\n if (pageModel.meta.description) {\n lines.push(`Description: ${pageModel.meta.description}`);\n }\n lines.push(`Language: ${pageModel.meta.language}`);\n return lines.join('\\n');\n }\n\n private buildPageSectionsSection(pageModel: PageModel): string {\n const { sectionsIncluded, totalSectionsFound } = pageModel.scanMetadata;\n const lines = [\n `# Page Sections (${sectionsIncluded} of ${totalSectionsFound})`,\n ];\n\n for (const section of pageModel.sections) {\n const vis = section.isVisible ? 'visible' : 'hidden';\n lines.push(\n `- [${section.id}] ${section.label}: ${truncate(section.summary, 120)} (${vis})`,\n );\n }\n\n if (sectionsIncluded < totalSectionsFound) {\n lines.push(\n `\\nNote: You see ${sectionsIncluded} of ${totalSectionsFound} sections. Use readPageContent to access more.`,\n );\n }\n\n return lines.join('\\n');\n }\n\n private buildNavigationSection(pageModel: PageModel): string {\n const lines = ['# Navigation'];\n for (const nav of pageModel.navigation) {\n const current = nav.isCurrent ? ' (current)' : '';\n lines.push(`- ${nav.label}: ${nav.href}${current}`);\n }\n return lines.join('\\n');\n }\n\n private buildInteractiveElementsSection(pageModel: PageModel): string {\n const lines = ['# Interactive Elements'];\n for (const el of pageModel.interactiveElements) {\n const disabled = el.isDisabled ? ' [disabled]' : '';\n lines.push(\n `- ${el.tagName}${el.type ? `[${el.type}]` : ''}: ${el.label}${disabled} (${el.selector})`,\n );\n }\n return lines.join('\\n');\n }\n\n private buildFormsSection(pageModel: PageModel): string {\n const lines = ['# Forms'];\n for (const form of pageModel.forms) {\n const formId = form.id ? ` id=\"${form.id}\"` : '';\n const errors = form.hasValidationErrors ? ' [has errors]' : '';\n lines.push(`- <form${formId}>${errors}`);\n for (const field of form.fields) {\n const req = field.isRequired ? ' *' : '';\n const err = field.hasError\n ? ` [error: ${field.errorMessage || 'invalid'}]`\n : '';\n lines.push(\n ` - ${field.label || field.name} (${field.type})${req}${err}`,\n );\n }\n }\n return lines.join('\\n');\n }\n\n private buildViewportSection(pageModel: PageModel): string {\n const { width, height, orientation } = pageModel.viewport;\n return `# User Viewport\\n${width}x${height}, ${orientation}`;\n }\n\n private buildToolsSection(tools: ToolDefinition[]): string {\n const lines = ['# Available Actions'];\n for (const tool of tools) {\n lines.push(`- ${tool.name}: ${tool.description}`);\n }\n return lines.join('\\n');\n }\n\n private buildPageContextSection(): string {\n const lines = ['# Developer Context'];\n for (const [key, value] of Object.entries(this._pageContext)) {\n const valStr =\n typeof value === 'string'\n ? value\n : JSON.stringify(value);\n lines.push(`- ${key}: ${truncate(String(valStr), 200)}`);\n }\n return lines.join('\\n');\n }\n\n private buildGuidelinesSection(): string {\n return [\n '# Guidelines',\n '- Always reference specific sections by their ID when guiding users',\n '- Use highlight() to point at elements you are discussing',\n '- Use scrollToSection() before highlighting offscreen elements',\n '- Never make up information not present in the page context',\n '- If asked about content you cannot see, use readPageContent to access it',\n '- Keep responses concise — 2-3 sentences unless the user asks for detail',\n ].join('\\n');\n }\n\n // -------------------------------------------------------------------------\n // Private — prompt trimming\n // -------------------------------------------------------------------------\n\n /**\n * When the assembled prompt exceeds the budget, progressively trim\n * lower-priority sections to fit.\n */\n private trimPromptToBudget(\n _fullPrompt: string,\n pageModel: PageModel,\n tools: ToolDefinition[],\n ): string {\n // Rebuild with trimming strategies applied in priority order:\n // 1. Truncate interactive elements list\n // 2. Truncate navigation list\n // 3. Truncate forms\n // 4. Truncate page sections\n\n const essentialParts: string[] = [\n this.buildRoleSection(),\n this.buildCurrentPageSection(pageModel),\n this.buildViewportSection(pageModel),\n this.buildGuidelinesSection(),\n ];\n\n if (tools.length > 0) {\n essentialParts.push(this.buildToolsSection(tools));\n }\n\n const essentialLength = essentialParts.reduce(\n (sum, p) => sum + p.length + 2,\n 0,\n );\n let remaining = this.tokenBudget - essentialLength;\n\n const optionalSections: string[] = [];\n\n // Page sections — highest priority optional section\n const sectionsStr = this.buildPageSectionsSection(pageModel);\n if (sectionsStr.length <= remaining) {\n optionalSections.push(sectionsStr);\n remaining -= sectionsStr.length + 2;\n } else if (remaining > 100) {\n optionalSections.push(truncate(sectionsStr, remaining));\n remaining = 0;\n }\n\n // Navigation\n if (remaining > 0 && pageModel.navigation.length > 0) {\n const navStr = this.buildNavigationSection(pageModel);\n if (navStr.length <= remaining) {\n optionalSections.push(navStr);\n remaining -= navStr.length + 2;\n } else if (remaining > 80) {\n optionalSections.push(truncate(navStr, remaining));\n remaining = 0;\n }\n }\n\n // Forms\n if (remaining > 0 && pageModel.forms.length > 0) {\n const formsStr = this.buildFormsSection(pageModel);\n if (formsStr.length <= remaining) {\n optionalSections.push(formsStr);\n remaining -= formsStr.length + 2;\n } else if (remaining > 80) {\n optionalSections.push(truncate(formsStr, remaining));\n remaining = 0;\n }\n }\n\n // Interactive elements\n if (remaining > 0 && pageModel.interactiveElements.length > 0) {\n const ieStr = this.buildInteractiveElementsSection(pageModel);\n if (ieStr.length <= remaining) {\n optionalSections.push(ieStr);\n } else if (remaining > 80) {\n optionalSections.push(truncate(ieStr, remaining));\n }\n }\n\n // Insert optional sections after current-page and before viewport\n const result = [\n essentialParts[0], // Role\n essentialParts[1], // Current Page\n ...optionalSections,\n essentialParts[2], // Viewport\n ...essentialParts.slice(3), // Tools + Guidelines\n ];\n\n return result.join('\\n\\n');\n }\n\n // -------------------------------------------------------------------------\n // Private — history management\n // -------------------------------------------------------------------------\n\n /**\n * Enforce `maxTurns` and `maxSessionSizeBytes` constraints on the\n * conversation history. When the history approaches 80% of `maxTurns`,\n * the oldest turns are summarised into a single recap turn.\n */\n private enforceHistoryLimits(): void {\n // -- Summarise when near capacity (>80% of maxTurns) --------------------\n const summariseThreshold = Math.floor(this.maxTurns * 0.8);\n if (this.history.length > summariseThreshold) {\n this.summariseOldestTurns();\n }\n\n // -- Hard cap on turn count ---------------------------------------------\n while (this.history.length > this.maxTurns) {\n this.history.shift();\n }\n\n // -- Enforce byte-size limit --------------------------------------------\n this.enforceByteLimit();\n }\n\n /**\n * Compress the oldest half of turns into a single recap turn so the\n * context window is used more efficiently.\n */\n private summariseOldestTurns(): void {\n if (this.history.length < 4) return; // Not enough to summarise\n\n const splitIndex = Math.floor(this.history.length / 2);\n const oldTurns = this.history.slice(0, splitIndex);\n const recentTurns = this.history.slice(splitIndex);\n\n // Build a compact recap from the old turns\n const recapLines: string[] = [];\n for (const turn of oldTurns) {\n const role = turn.role === 'user' ? 'User' : 'Assistant';\n recapLines.push(`${role}: ${truncate(turn.content, 150)}`);\n }\n\n const recapTurn: ConversationTurn = {\n role: 'assistant',\n content: `[Conversation recap]\\n${recapLines.join('\\n')}`,\n timestamp: oldTurns[oldTurns.length - 1]!.timestamp,\n };\n\n this.history = [recapTurn, ...recentTurns];\n }\n\n /** Evict oldest turns until the serialised history fits within the byte budget. */\n private enforceByteLimit(): void {\n while (this.history.length > 1) {\n const serialised = JSON.stringify(this.history);\n if (byteLength(serialised) <= this.maxSessionSizeBytes) break;\n this.history.shift();\n }\n }\n\n // -------------------------------------------------------------------------\n // Private — debug logging\n // -------------------------------------------------------------------------\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.debug('[GuideKit:ContextManager]', ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Error Hierarchy\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical error codes emitted by the SDK.\n * Keyed as `DOMAIN_DETAIL` so consumers can match on prefixes or exact values.\n */\nexport const ErrorCodes = {\n // Auth\n AUTH_INVALID_KEY: 'AUTH_INVALID_KEY',\n AUTH_EXPIRED_TOKEN: 'AUTH_EXPIRED_TOKEN',\n AUTH_TOKEN_REFRESH_FAILED: 'AUTH_TOKEN_REFRESH_FAILED',\n AUTH_ENDPOINT_FAILED: 'AUTH_ENDPOINT_FAILED',\n\n // Config\n CONFIG_INVALID_PROVIDER: 'CONFIG_INVALID_PROVIDER',\n CONFIG_MISSING_REQUIRED: 'CONFIG_MISSING_REQUIRED',\n\n // Init\n INIT_SHADOW_DOM_FAILED: 'INIT_SHADOW_DOM_FAILED',\n INIT_BROWSER_UNSUPPORTED: 'INIT_BROWSER_UNSUPPORTED',\n\n // Rate limit\n RATE_LIMIT_PROVIDER: 'RATE_LIMIT_PROVIDER',\n RATE_LIMIT_CLIENT: 'RATE_LIMIT_CLIENT',\n\n // Resources\n RESOURCE_EXHAUSTED_LLM: 'RESOURCE_EXHAUSTED_LLM',\n RESOURCE_EXHAUSTED_STT: 'RESOURCE_EXHAUSTED_STT',\n RESOURCE_EXHAUSTED_TTS: 'RESOURCE_EXHAUSTED_TTS',\n\n // Permission\n PERMISSION_MIC_DENIED: 'PERMISSION_MIC_DENIED',\n PERMISSION_MIC_UNAVAILABLE: 'PERMISSION_MIC_UNAVAILABLE',\n\n // Network\n NETWORK_WEBSOCKET_FAILED: 'NETWORK_WEBSOCKET_FAILED',\n NETWORK_CONNECTION_LOST: 'NETWORK_CONNECTION_LOST',\n NETWORK_TIMEOUT: 'NETWORK_TIMEOUT',\n\n // Timeout\n TIMEOUT_STT_CONNECT: 'TIMEOUT_STT_CONNECT',\n TIMEOUT_LLM_RESPONSE: 'TIMEOUT_LLM_RESPONSE',\n TIMEOUT_TTS_CONNECT: 'TIMEOUT_TTS_CONNECT',\n TIMEOUT_TTS_FIRST_AUDIO: 'TIMEOUT_TTS_FIRST_AUDIO',\n\n // Browser\n BROWSER_NO_WEB_AUDIO: 'BROWSER_NO_WEB_AUDIO',\n BROWSER_NO_WASM: 'BROWSER_NO_WASM',\n VAD_PACKAGE_MISSING: 'VAD_PACKAGE_MISSING',\n\n // Content\n CONTENT_FILTER_TRIGGERED: 'CONTENT_FILTER_TRIGGERED',\n\n // Privacy\n PRIVACY_HOOK_CANCELLED: 'PRIVACY_HOOK_CANCELLED',\n\n // General\n UNKNOWN: 'UNKNOWN',\n} as const;\n\n/** Union of every known error code string. */\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n// ---------------------------------------------------------------------------\n// Provider type\n// ---------------------------------------------------------------------------\n\nexport type Provider = 'deepgram' | 'elevenlabs' | 'gemini' | 'openai' | 'web-speech' | (string & {});\n\n// ---------------------------------------------------------------------------\n// Base options shared by every error constructor\n// ---------------------------------------------------------------------------\n\nexport interface GuideKitErrorOptions {\n code: string;\n message: string;\n provider?: Provider;\n recoverable: boolean;\n suggestion: string;\n docsUrl?: string;\n cause?: Error;\n}\n\n// ---------------------------------------------------------------------------\n// Base error class\n// ---------------------------------------------------------------------------\n\n/**\n * Root error for every failure surfaced by the GuideKit SDK.\n *\n * Every instance carries structured metadata so UI layers can present\n * actionable feedback without parsing message strings.\n */\nexport class GuideKitError extends Error {\n readonly code: string;\n readonly provider?: Provider;\n readonly recoverable: boolean;\n readonly suggestion: string;\n readonly docsUrl: string;\n\n constructor(options: GuideKitErrorOptions) {\n super(options.message, { cause: options.cause });\n\n // Fix the prototype chain so `instanceof` works correctly when\n // compiling to ES5 or when subclassing built-in Error.\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = 'GuideKitError';\n this.code = options.code;\n this.provider = options.provider;\n this.recoverable = options.recoverable;\n this.suggestion = options.suggestion;\n this.docsUrl =\n options.docsUrl ?? `https://guidekit.dev/docs/error-codes#${options.code}`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Specific error subclasses\n// ---------------------------------------------------------------------------\n\n/** Wrong or expired API key / token. */\nexport class AuthenticationError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'AuthenticationError';\n }\n}\n\n/** Invalid provider configuration supplied at init time. */\nexport class ConfigurationError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'ConfigurationError';\n }\n}\n\n/** SDK startup failure (Shadow DOM creation, browser too old, etc.). */\nexport class InitializationError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'InitializationError';\n }\n}\n\n/** Provider-side rate limit hit. Includes a retry hint. */\nexport class RateLimitError extends GuideKitError {\n readonly retryAfterMs: number;\n\n constructor(\n options: GuideKitErrorOptions & { retryAfterMs: number },\n ) {\n super({ ...options, recoverable: true });\n this.name = 'RateLimitError';\n this.retryAfterMs = options.retryAfterMs;\n }\n}\n\n/** Client-side cost / usage limits exhausted. */\nexport class ResourceExhaustedError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'ResourceExhaustedError';\n }\n}\n\n/** Microphone permission denied or device not available. */\nexport class PermissionError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'PermissionError';\n }\n}\n\n/** WebSocket dropped, HTTP connection failed, etc. */\nexport class NetworkError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: true, ...options });\n this.name = 'NetworkError';\n }\n}\n\n/** An operation exceeded its deadline. */\nexport class TimeoutError extends GuideKitError {\n readonly operationName: string;\n readonly timeoutMs: number;\n\n constructor(\n options: GuideKitErrorOptions & {\n operationName: string;\n timeoutMs: number;\n },\n ) {\n super({ ...options, recoverable: true });\n this.name = 'TimeoutError';\n this.operationName = options.operationName;\n this.timeoutMs = options.timeoutMs;\n }\n}\n\n/** Missing browser capability (Web Audio, WASM, VAD). */\nexport class BrowserSupportError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'BrowserSupportError';\n }\n}\n\n/** LLM safety / content filter triggered. */\nexport class ContentFilterError extends GuideKitError {\n constructor(\n options: Omit<GuideKitErrorOptions, 'recoverable'> & {\n recoverable?: boolean;\n },\n ) {\n super({ recoverable: false, ...options });\n this.name = 'ContentFilterError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type guard\n// ---------------------------------------------------------------------------\n\n/**\n * Narrows an unknown caught value to `GuideKitError`.\n *\n * ```ts\n * try { ... } catch (err) {\n * if (isGuideKitError(err)) {\n * console.log(err.code, err.suggestion);\n * }\n * }\n * ```\n */\nexport function isGuideKitError(error: unknown): error is GuideKitError {\n return error instanceof GuideKitError;\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – LLM Orchestrator & Gemini Adapter\n// ---------------------------------------------------------------------------\n\nimport type {\n LLMConfig,\n LLMProviderAdapter,\n ToolDefinition,\n ToolCall,\n TextChunk,\n ConversationTurn,\n} from '../types/index.js';\n\nimport {\n AuthenticationError,\n RateLimitError,\n NetworkError,\n TimeoutError,\n ContentFilterError,\n ErrorCodes,\n} from '../errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_GEMINI_MODEL = 'gemini-2.5-flash';\nconst DEFAULT_TIMEOUT_MS = 15_000;\nconst GEMINI_BASE_URL =\n 'https://generativelanguage.googleapis.com/v1beta/models';\n\n/**\n * Gemini safety categories with their corresponding enum names.\n * We apply `BLOCK_ONLY_HIGH` to every category by default so the model\n * is usable for general-purpose assistance without over-blocking.\n */\nconst DEFAULT_SAFETY_SETTINGS = [\n { category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_ONLY_HIGH' },\n { category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_ONLY_HIGH' },\n { category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT', threshold: 'BLOCK_ONLY_HIGH' },\n { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' },\n];\n\n// ---------------------------------------------------------------------------\n// Token usage helper\n// ---------------------------------------------------------------------------\n\ninterface TokenUsage {\n prompt: number;\n completion: number;\n total: number;\n}\n\nfunction emptyUsage(): TokenUsage {\n return { prompt: 0, completion: 0, total: 0 };\n}\n\n// ---------------------------------------------------------------------------\n// GeminiAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Adapter that translates between GuideKit's internal types and the\n * Gemini REST API wire format. Handles streaming via SSE, tool formatting,\n * and response parsing.\n */\nexport class GeminiAdapter implements LLMProviderAdapter {\n private readonly apiKey: string;\n private readonly model: string;\n\n /**\n * Token usage extracted from the most recent `parseResponse` call.\n * Updated as each SSE chunk is parsed; the final value reflects the\n * cumulative usage metadata sent by Gemini (typically in the last chunk).\n */\n private _lastUsage: TokenUsage = emptyUsage();\n\n constructor(config: Extract<LLMConfig, { provider: 'gemini' }>) {\n this.apiKey = config.apiKey;\n this.model = config.model ?? DEFAULT_GEMINI_MODEL;\n }\n\n /** Token usage from the most recent parseResponse call. */\n get lastUsage(): TokenUsage {\n return this._lastUsage;\n }\n\n // -----------------------------------------------------------------------\n // LLMProviderAdapter implementation\n // -----------------------------------------------------------------------\n\n /**\n * Convert GuideKit tool definitions into Gemini's `functionDeclarations`\n * format, wrapped inside a `tools` array.\n */\n formatTools(tools: ToolDefinition[]): unknown {\n if (tools.length === 0) return undefined;\n\n return [\n {\n functionDeclarations: tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: { ...tool.parameters },\n required: tool.required ?? [],\n },\n })),\n },\n ];\n }\n\n /**\n * Convert an array of `ConversationTurn` objects into Gemini's `contents`\n * array with `role: 'user' | 'model'`.\n */\n formatConversation(\n history: ConversationTurn[],\n ): Array<{ role: string; parts: Array<{ text: string }> }> {\n return history.map((turn) => ({\n role: turn.role === 'assistant' ? 'model' : 'user',\n parts: [{ text: turn.content }],\n }));\n }\n\n /**\n * Parse a Gemini SSE streaming response into an async iterable of\n * `TextChunk` and `ToolCall` objects.\n *\n * The Gemini `streamGenerateContent?alt=sse` endpoint sends each chunk\n * as a JSON object prefixed by `data: `. We parse line-by-line, extract\n * text parts and function call parts, and yield the appropriate types.\n *\n * This method also:\n * - Detects content filtering and throws `ContentFilterError`.\n * - Tracks token usage (accessible via `lastUsage` after iteration).\n */\n async *parseResponse(\n stream: ReadableStream<Uint8Array>,\n ): AsyncIterable<TextChunk | ToolCall> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n this._lastUsage = emptyUsage();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n // Keep the last (possibly incomplete) line in the buffer.\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // SSE lines that are not data payloads.\n if (!trimmed.startsWith('data:')) continue;\n\n const jsonStr = trimmed.slice(5).trim();\n if (jsonStr === '' || jsonStr === '[DONE]') continue;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(jsonStr) as Record<string, unknown>;\n } catch {\n // Malformed JSON chunk – skip silently.\n continue;\n }\n\n // Check for content filtering — throws if blocked.\n if (this.isContentFiltered(parsed)) {\n throw new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message: 'Response was blocked by provider content safety filter.',\n provider: 'gemini',\n suggestion: 'Rephrase your question or adjust safety settings.',\n });\n }\n\n // Track token usage (usually present in the last chunk).\n const chunkUsage = this.extractUsage(parsed);\n if (chunkUsage) {\n this._lastUsage = chunkUsage;\n }\n\n yield* this.extractChunks(parsed);\n }\n }\n\n // Flush any remaining data in the buffer.\n if (buffer.trim().startsWith('data:')) {\n const jsonStr = buffer.trim().slice(5).trim();\n if (jsonStr !== '' && jsonStr !== '[DONE]') {\n try {\n const parsed = JSON.parse(jsonStr) as Record<string, unknown>;\n\n if (this.isContentFiltered(parsed)) {\n throw new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message: 'Response was blocked by provider content safety filter.',\n provider: 'gemini',\n suggestion: 'Rephrase your question or adjust safety settings.',\n });\n }\n\n const chunkUsage = this.extractUsage(parsed);\n if (chunkUsage) {\n this._lastUsage = chunkUsage;\n }\n\n yield* this.extractChunks(parsed);\n } catch (error: unknown) {\n // Re-throw ContentFilterError, ignore other parse errors.\n if (error instanceof ContentFilterError) throw error;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Format a tool result so it can be sent back to Gemini as a\n * `functionResponse` part.\n */\n formatToolResult(\n callId: string,\n result: unknown,\n ): {\n role: string;\n parts: Array<{\n functionResponse: { name: string; response: { result: unknown } };\n }>;\n } {\n return {\n role: 'function',\n parts: [\n {\n functionResponse: {\n name: callId,\n response: { result },\n },\n },\n ],\n };\n }\n\n // -----------------------------------------------------------------------\n // Streaming request\n // -----------------------------------------------------------------------\n\n /**\n * Build and execute a streaming request to the Gemini API.\n * Returns the raw `ReadableStream` for the response body together with\n * the raw Response object.\n *\n * Note: The Gemini API key is passed as a URL query parameter (`key=`).\n * This is inherent to the Gemini REST SSE endpoint design; the key is\n * transmitted over HTTPS so it remains encrypted in transit. (H3)\n */\n async streamRequest(params: {\n systemPrompt: string;\n contents: unknown;\n userMessage?: string;\n tools?: unknown;\n signal?: AbortSignal;\n timeoutMs?: number;\n }): Promise<{\n stream: ReadableStream<Uint8Array>;\n response: Response;\n }> {\n // Build the full contents array: formatted history + the new user message.\n const contentsArray = params.contents as Array<unknown>;\n const fullContents = params.userMessage\n ? [...contentsArray, { role: 'user', parts: [{ text: params.userMessage }] }]\n : contentsArray;\n\n const url = `${GEMINI_BASE_URL}/${this.model}:streamGenerateContent?alt=sse&key=${this.apiKey}`;\n\n const body: Record<string, unknown> = {\n systemInstruction: {\n parts: [{ text: params.systemPrompt }],\n },\n contents: fullContents,\n safetySettings: DEFAULT_SAFETY_SETTINGS,\n generationConfig: {\n temperature: 0.7,\n topP: 0.95,\n topK: 40,\n },\n };\n\n if (params.tools) {\n body.tools = params.tools;\n }\n\n const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const controller = new AbortController();\n\n // Combine the external signal with our timeout signal.\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n if (params.signal) {\n // If the caller aborts, propagate to our controller.\n params.signal.addEventListener(\n 'abort',\n () => controller.abort(params.signal!.reason),\n { once: true },\n );\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n\n if (\n error instanceof DOMException &&\n error.name === 'AbortError'\n ) {\n // Distinguish caller abort from timeout.\n if (params.signal?.aborted) {\n throw error; // Re-throw caller abort as-is.\n }\n throw new TimeoutError({\n code: ErrorCodes.TIMEOUT_LLM_RESPONSE,\n message: `Gemini request timed out after ${timeoutMs}ms`,\n provider: 'gemini',\n recoverable: true,\n suggestion: 'Try again or increase the timeout.',\n operationName: 'gemini.streamGenerateContent',\n timeoutMs,\n });\n }\n\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `Failed to connect to Gemini API: ${(error as Error).message}`,\n provider: 'gemini',\n suggestion:\n 'Check your network connection and try again.',\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n clearTimeout(timeoutId);\n\n // Handle HTTP-level errors.\n if (!response.ok) {\n await this.handleHttpError(response);\n }\n\n if (!response.body) {\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: 'Gemini response body is null – streaming unavailable.',\n provider: 'gemini',\n suggestion: 'Retry the request.',\n });\n }\n\n return { stream: response.body, response };\n }\n\n // -----------------------------------------------------------------------\n // Public helpers (LLMProviderAdapter interface)\n // -----------------------------------------------------------------------\n\n /**\n * Extract `TextChunk` and `ToolCall` items from a single parsed Gemini\n * SSE JSON object.\n */\n private *extractChunks(\n parsed: Record<string, unknown>,\n ): Generator<TextChunk | ToolCall> {\n const candidates = parsed.candidates as\n | Array<Record<string, unknown>>\n | undefined;\n\n if (!candidates || candidates.length === 0) return;\n\n for (const candidate of candidates) {\n const content = candidate.content as\n | { parts?: Array<Record<string, unknown>> }\n | undefined;\n\n if (!content?.parts) continue;\n\n const finishReason = candidate.finishReason as string | undefined;\n const isDone =\n finishReason === 'STOP' || finishReason === 'MAX_TOKENS';\n\n for (const part of content.parts) {\n // Text part\n if (typeof part.text === 'string') {\n const textChunk: TextChunk = {\n text: part.text,\n done: isDone,\n };\n yield textChunk;\n }\n\n // Function call part\n if (part.functionCall) {\n const fc = part.functionCall as {\n name: string;\n args?: Record<string, unknown>;\n };\n const toolCall: ToolCall = {\n id: fc.name,\n name: fc.name,\n arguments: fc.args ?? {},\n };\n yield toolCall;\n }\n }\n }\n }\n\n /**\n * Extract token usage from a parsed Gemini response chunk.\n * Returns `null` if no usage metadata is present.\n */\n extractUsage(parsed: Record<string, unknown>): TokenUsage | null {\n const meta = parsed.usageMetadata as\n | {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n }\n | undefined;\n\n if (!meta) return null;\n\n return {\n prompt: meta.promptTokenCount ?? 0,\n completion: meta.candidatesTokenCount ?? 0,\n total: meta.totalTokenCount ?? 0,\n };\n }\n\n /**\n * Check whether a parsed Gemini chunk indicates the response was\n * blocked by a safety filter.\n */\n isContentFiltered(parsed: Record<string, unknown>): boolean {\n const candidates = parsed.candidates as\n | Array<Record<string, unknown>>\n | undefined;\n\n if (!candidates || candidates.length === 0) {\n // If there is a promptFeedback.blockReason the response was blocked\n // before generation even started.\n const feedback = parsed.promptFeedback as\n | { blockReason?: string }\n | undefined;\n return feedback?.blockReason != null;\n }\n\n return candidates.some(\n (c) =>\n c.finishReason === 'SAFETY' ||\n c.finishReason === 'BLOCKED_REASON' ||\n c.finishReason === 'OTHER',\n );\n }\n\n /**\n * Translate an HTTP error response from Gemini into the appropriate\n * GuideKit error class.\n */\n private async handleHttpError(response: Response): Promise<never> {\n let errorBody = '';\n try {\n errorBody = await response.text();\n } catch {\n // Ignore read failure.\n }\n\n const status = response.status;\n\n if (status === 401 || status === 403) {\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_INVALID_KEY,\n message: `Gemini API authentication failed (${status}): ${errorBody}`,\n provider: 'gemini',\n suggestion:\n 'Verify your Gemini API key is correct and has not expired.',\n });\n }\n\n if (status === 429) {\n const retryAfterHeader = response.headers.get('retry-after');\n const retryAfterMs = retryAfterHeader\n ? parseInt(retryAfterHeader, 10) * 1000\n : 60_000;\n\n throw new RateLimitError({\n code: ErrorCodes.RATE_LIMIT_PROVIDER,\n message: `Gemini API rate limit exceeded (429): ${errorBody}`,\n provider: 'gemini',\n recoverable: true,\n suggestion: `Rate limited by Gemini. Retry after ${Math.ceil(retryAfterMs / 1000)}s.`,\n retryAfterMs,\n });\n }\n\n if (status >= 500) {\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `Gemini API server error (${status}): ${errorBody}`,\n provider: 'gemini',\n suggestion:\n 'The Gemini API is experiencing issues. Please try again later.',\n });\n }\n\n // Fallback for other 4xx errors.\n throw new NetworkError({\n code: ErrorCodes.NETWORK_CONNECTION_LOST,\n message: `Gemini API request failed (${status}): ${errorBody}`,\n provider: 'gemini',\n suggestion: 'Check the request parameters and try again.',\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// LLMOrchestrator\n// ---------------------------------------------------------------------------\n\n/** Callback options accepted by `LLMOrchestrator`. */\ninterface OrchestratorCallbacks {\n onChunk?: (chunk: TextChunk) => void;\n onToolCall?: (toolCall: ToolCall) => void;\n onTokenUsage?: (usage: TokenUsage) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * High-level orchestrator that manages LLM interactions for the GuideKit SDK.\n *\n * Responsibilities:\n * - Owns the active `LLMProviderAdapter`.\n * - Streams responses from the provider, emitting callbacks for text chunks,\n * tool calls, and token usage.\n * - Handles content filter retries: if the initial response is blocked, it\n * retries once with a stripped-down prompt (no tools).\n * - Surfaces all errors through the SDK error hierarchy.\n *\n * The orchestrator is fully adapter-agnostic: all provider-specific logic\n * (SSE parsing, content filter detection, usage extraction) lives in the\n * adapter implementations.\n */\nexport class LLMOrchestrator {\n private _adapter: LLMProviderAdapter;\n private _config: LLMConfig;\n private readonly debug: boolean;\n private readonly callbacks: OrchestratorCallbacks;\n\n constructor(options: {\n config: LLMConfig;\n debug?: boolean;\n onChunk?: (chunk: TextChunk) => void;\n onToolCall?: (toolCall: ToolCall) => void;\n onTokenUsage?: (usage: TokenUsage) => void;\n onError?: (error: Error) => void;\n }) {\n this._config = options.config;\n this.debug = options.debug ?? false;\n this.callbacks = {\n onChunk: options.onChunk,\n onToolCall: options.onToolCall,\n onTokenUsage: options.onTokenUsage,\n onError: options.onError,\n };\n this._adapter = this.createAdapter(options.config);\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Send a message and stream the response from the LLM.\n *\n * Accumulates text and tool calls from the stream, invoking callbacks\n * as chunks arrive, and returns the complete result once the stream ends.\n */\n async sendMessage(params: {\n systemPrompt: string;\n history: ConversationTurn[];\n userMessage: string;\n tools?: ToolDefinition[];\n signal?: AbortSignal;\n }): Promise<{\n text: string;\n toolCalls: ToolCall[];\n usage: TokenUsage;\n }> {\n try {\n return await this.executeStream(params, /* isRetry */ false);\n } catch (error: unknown) {\n if (error instanceof ContentFilterError) {\n // Retry once without tools (simplified prompt).\n this.log('Content filter triggered – retrying without tools');\n try {\n return await this.executeStream(\n { ...params, tools: undefined },\n /* isRetry */ true,\n );\n } catch (_retryError: unknown) {\n const cfError = new ContentFilterError({\n code: ErrorCodes.CONTENT_FILTER_TRIGGERED,\n message:\n 'Response blocked by content safety filter after retry.',\n provider: this.providerName,\n suggestion:\n 'Rephrase your question or adjust safety settings.',\n });\n this.callbacks.onError?.(cfError);\n throw cfError;\n }\n }\n\n // For non-content-filter errors, notify and re-throw.\n if (error instanceof Error) {\n this.callbacks.onError?.(error);\n }\n throw error;\n }\n }\n\n /**\n * Hot-swap the LLM configuration. Creates a new adapter for the\n * updated provider/model.\n */\n updateConfig(config: LLMConfig): void {\n this._config = config;\n this._adapter = this.createAdapter(config);\n const label = 'provider' in config ? config.provider : 'custom adapter';\n this.log(`Config updated: ${label}`);\n }\n\n /** Get the current provider adapter. */\n get adapter(): LLMProviderAdapter {\n return this._adapter;\n }\n\n // -----------------------------------------------------------------------\n // Internal helpers\n // -----------------------------------------------------------------------\n\n /**\n * Execute a streaming LLM request and collect the results.\n *\n * This method is fully adapter-agnostic: it delegates streaming,\n * response parsing, content-filter detection, and usage extraction\n * entirely to the active `LLMProviderAdapter`. No provider-specific\n * SSE parsing lives in the orchestrator.\n */\n private async executeStream(\n params: {\n systemPrompt: string;\n history: ConversationTurn[];\n userMessage: string;\n tools?: ToolDefinition[];\n signal?: AbortSignal;\n },\n _isRetry: boolean,\n ): Promise<{\n text: string;\n toolCalls: ToolCall[];\n usage: TokenUsage;\n }> {\n const adapter = this._adapter;\n\n // Format conversation history via the adapter.\n const historyContents = adapter.formatConversation(params.history);\n\n // Format tools if provided.\n const tools =\n params.tools && params.tools.length > 0\n ? adapter.formatTools(params.tools)\n : undefined;\n\n // Execute the streaming request via the adapter.\n // The adapter's streamRequest accepts the formatted history as `contents`\n // and appends the user message internally using `userMessage`.\n const { stream } = await adapter.streamRequest({\n systemPrompt: params.systemPrompt,\n contents: historyContents,\n userMessage: params.userMessage,\n tools,\n signal: params.signal,\n });\n\n // Parse the stream using the adapter's parseResponse.\n // Content filter detection and usage tracking are handled within\n // the adapter's parseResponse — a ContentFilterError will propagate\n // up naturally from the async iteration.\n let fullText = '';\n const toolCalls: ToolCall[] = [];\n\n for await (const item of adapter.parseResponse(stream)) {\n if ('name' in item && 'arguments' in item) {\n // ToolCall\n const toolCall = item as ToolCall;\n toolCalls.push(toolCall);\n this.callbacks.onToolCall?.(toolCall);\n } else {\n // TextChunk\n const chunk = item as TextChunk;\n if (chunk.text) {\n fullText += chunk.text;\n }\n this.callbacks.onChunk?.(chunk);\n }\n }\n\n // Always emit a final \"done\" chunk to signal stream completion,\n // regardless of whether text was received (M3 fix).\n this.callbacks.onChunk?.({ text: '', done: true });\n\n // Retrieve token usage from the adapter. The adapter tracks usage\n // internally during parseResponse via the `lastUsage` property.\n let usage: TokenUsage = emptyUsage();\n if ('lastUsage' in adapter) {\n usage = (adapter as unknown as { lastUsage: TokenUsage }).lastUsage;\n }\n\n // Report token usage.\n if (usage.total > 0) {\n this.callbacks.onTokenUsage?.(usage);\n }\n\n this.log(\n `Response complete: ${fullText.length} chars, ` +\n `${toolCalls.length} tool calls, ` +\n `${usage.total} tokens`,\n );\n\n return { text: fullText, toolCalls, usage };\n }\n\n /**\n * Create the appropriate adapter for the given config.\n *\n * Built-in providers:\n * - `'gemini'` — uses the bundled `GeminiAdapter`.\n *\n * Custom adapters:\n * - Pass `{ adapter: myAdapter }` to use any `LLMProviderAdapter`.\n * Example: `llm: { adapter: myCustomAdapter }`\n */\n private createAdapter(config: LLMConfig): LLMProviderAdapter {\n // Custom adapter — pass-through.\n if ('adapter' in config) {\n return config.adapter;\n }\n\n // Built-in providers.\n switch (config.provider) {\n case 'gemini':\n return new GeminiAdapter(config);\n default:\n throw new Error(\n `LLM provider \"${(config as { provider: string }).provider}\" is not yet supported. ` +\n 'Use { adapter: yourAdapter } for custom providers.',\n );\n }\n }\n\n /** Convenience accessor for the current provider name. */\n private get providerName(): string | undefined {\n if ('provider' in this._config) return this._config.provider;\n return undefined;\n }\n\n /** Log a debug message if debug mode is enabled. */\n private log(message: string): void {\n if (this.debug) {\n console.debug(`[GuideKit:LLM] ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Multi-Turn Tool Executor\n// ---------------------------------------------------------------------------\n//\n// Implements a multi-turn tool execution loop that sits between the\n// LLMOrchestrator and callers. When the LLM returns tool calls, this\n// executor runs them, feeds results back, and repeats until the LLM\n// produces a text-only response or the round limit is reached.\n// ---------------------------------------------------------------------------\n\nimport type {\n ToolDefinition,\n ToolCall,\n ConversationTurn,\n} from '../types/index.js';\nimport type { LLMOrchestrator } from './index.js';\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\n/**\n * A registered handler for a specific tool. The `name` must match the tool\n * definition's `name` field exactly.\n */\nexport interface ToolHandler {\n name: string;\n execute: (args: Record<string, unknown>) => Promise<unknown>;\n}\n\n/** Options for configuring the ToolExecutor. */\nexport interface ToolExecutorOptions {\n /** Max number of tool call rounds before forcing text response. Default: 5 */\n maxRounds?: number;\n /** Enable debug logging. */\n debug?: boolean;\n /** Called when a tool is about to be executed. */\n onToolCall?: (name: string, args: Record<string, unknown>) => void;\n /** Called when a tool execution completes. */\n onToolResult?: (name: string, result: unknown, durationMs: number) => void;\n /** Called when a tool execution fails. */\n onToolError?: (name: string, error: Error) => void;\n}\n\n/** A single executed tool call with its outcome. */\nexport interface ToolCallRecord {\n name: string;\n args: Record<string, unknown>;\n result: unknown;\n durationMs: number;\n error?: string;\n}\n\n/** Aggregated token usage across all rounds. */\nexport interface AggregatedUsage {\n prompt: number;\n completion: number;\n total: number;\n}\n\n/** The complete result of a multi-turn tool execution session. */\nexport interface ToolExecutionResult {\n /** The final text response from the LLM. */\n text: string;\n /** All tool calls that were executed across every round. */\n toolCallsExecuted: ToolCallRecord[];\n /** Accumulated token usage across all LLM calls. */\n totalUsage: AggregatedUsage;\n /** Number of LLM round-trips performed. */\n rounds: number;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types for tool-augmented conversation turns\n// ---------------------------------------------------------------------------\n\n/**\n * Internally, the tool executor needs richer turn types than the public\n * `ConversationTurn` (which only supports 'user' | 'assistant'). These\n * extended types carry tool call metadata and tool results so that each\n * LLM provider adapter can format them correctly.\n */\ninterface AssistantToolCallTurn {\n role: 'assistant';\n content: string;\n toolCalls: Array<{ id: string; name: string; args: Record<string, unknown> }>;\n timestamp: number;\n}\n\ninterface ToolResultTurn {\n role: 'tool';\n content: string;\n toolCallId: string;\n toolName: string;\n timestamp: number;\n}\n\n/**\n * A conversation turn that may be a standard turn, an assistant turn\n * with tool calls, or a tool result turn.\n */\ntype InternalTurn = ConversationTurn | AssistantToolCallTurn | ToolResultTurn;\n\n// ---------------------------------------------------------------------------\n// ToolExecutor\n// ---------------------------------------------------------------------------\n\n/**\n * Manages multi-turn LLM interactions involving tool calls.\n *\n * Flow:\n * 1. Send the user message to the LLM along with available tool definitions.\n * 2. If the LLM response includes tool calls, execute them in parallel.\n * 3. Feed tool results back to the LLM as additional conversation context.\n * 4. Repeat until the LLM produces a text-only response or `maxRounds`\n * is exceeded.\n */\nexport class ToolExecutor {\n private readonly maxRounds: number;\n private readonly debugEnabled: boolean;\n private readonly handlers = new Map<string, ToolHandler>();\n\n // Callbacks\n private readonly onToolCallCb?: (name: string, args: Record<string, unknown>) => void;\n private readonly onToolResultCb?: (name: string, result: unknown, durationMs: number) => void;\n private readonly onToolErrorCb?: (name: string, error: Error) => void;\n\n constructor(options?: ToolExecutorOptions) {\n this.maxRounds = options?.maxRounds ?? 5;\n this.debugEnabled = options?.debug ?? false;\n this.onToolCallCb = options?.onToolCall;\n this.onToolResultCb = options?.onToolResult;\n this.onToolErrorCb = options?.onToolError;\n }\n\n // -----------------------------------------------------------------------\n // Tool registration\n // -----------------------------------------------------------------------\n\n /** Register a tool handler. Overwrites any existing handler with the same name. */\n registerTool(handler: ToolHandler): void {\n this.handlers.set(handler.name, handler);\n this.log(`Registered tool: ${handler.name}`);\n }\n\n /** Unregister a tool by name. No-op if the tool is not registered. */\n unregisterTool(name: string): void {\n const deleted = this.handlers.delete(name);\n if (deleted) {\n this.log(`Unregistered tool: ${name}`);\n }\n }\n\n /** Check whether a tool handler is registered. */\n hasTool(name: string): boolean {\n return this.handlers.has(name);\n }\n\n /**\n * Build `ToolDefinition[]` from all registered handlers.\n *\n * Since `ToolHandler` only carries `name` and `execute`, the returned\n * definitions have empty descriptions and parameters. Callers that need\n * richer definitions should maintain their own `ToolDefinition[]` and\n * pass them directly to `executeWithTools`.\n */\n getToolDefinitions(): ToolDefinition[] {\n const definitions: ToolDefinition[] = [];\n for (const handler of this.handlers.values()) {\n definitions.push({\n name: handler.name,\n description: '',\n parameters: {},\n schemaVersion: 1,\n });\n }\n return definitions;\n }\n\n // -----------------------------------------------------------------------\n // Multi-turn execution loop\n // -----------------------------------------------------------------------\n\n /**\n * Execute a multi-turn conversation with tool calls.\n *\n * The method sends the initial user message to the LLM. If the LLM\n * responds with tool calls, each call is executed in parallel, the\n * results are appended to the conversation, and the updated context\n * is sent back to the LLM. This loop repeats until:\n *\n * - The LLM returns a text-only response (no tool calls), or\n * - `maxRounds` consecutive tool-calling rounds have been exhausted.\n *\n * When `maxRounds` is exceeded the executor returns whatever text the\n * LLM has produced so far (which may be empty).\n */\n async executeWithTools(params: {\n llm: LLMOrchestrator;\n systemPrompt: string;\n history: ConversationTurn[];\n userMessage: string;\n tools: ToolDefinition[];\n signal?: AbortSignal;\n }): Promise<ToolExecutionResult> {\n const { llm, systemPrompt, userMessage, tools, signal } = params;\n\n // Accumulate results across rounds.\n const allToolCalls: ToolCallRecord[] = [];\n const totalUsage: AggregatedUsage = { prompt: 0, completion: 0, total: 0 };\n let rounds = 0;\n let finalText = '';\n\n // Build the running conversation. We start with the caller-supplied\n // history and progressively append assistant / tool turns as the\n // loop executes. The initial history uses the standard ConversationTurn\n // type; tool-related turns use our internal extended types.\n const internalHistory: InternalTurn[] = [...params.history];\n\n // The user message for the *first* round. On subsequent rounds the\n // LLM is called with an empty user message because the new context\n // is conveyed through the tool result turns appended to the history.\n let currentUserMessage = userMessage;\n\n while (rounds < this.maxRounds) {\n // Check for abort before each round.\n if (signal?.aborted) {\n this.log('Aborted before round ' + (rounds + 1));\n break;\n }\n\n rounds++;\n this.log(`--- Round ${rounds} ---`);\n\n // Convert internal history to standard ConversationTurn[] for the\n // LLMOrchestrator, which only understands 'user' | 'assistant' roles.\n const llmHistory = this.flattenHistory(internalHistory);\n\n // Send to LLM.\n const response = await llm.sendMessage({\n systemPrompt,\n history: llmHistory,\n userMessage: currentUserMessage,\n tools,\n signal,\n });\n\n // Accumulate token usage.\n totalUsage.prompt += response.usage.prompt;\n totalUsage.completion += response.usage.completion;\n totalUsage.total += response.usage.total;\n\n // Capture any text the LLM produced alongside tool calls.\n if (response.text) {\n finalText = response.text;\n }\n\n // If there are no tool calls, we are done.\n if (response.toolCalls.length === 0) {\n this.log(`Round ${rounds}: text-only response, finishing loop`);\n break;\n }\n\n this.log(\n `Round ${rounds}: ${response.toolCalls.length} tool call(s) received`,\n );\n\n // Record the assistant turn with its tool calls.\n const assistantTurn: AssistantToolCallTurn = {\n role: 'assistant',\n content: response.text,\n toolCalls: response.toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: tc.arguments,\n })),\n timestamp: Date.now(),\n };\n internalHistory.push(assistantTurn);\n\n // Execute all tool calls from this round in parallel.\n const toolResults = await this.executeToolCallsInParallel(\n response.toolCalls,\n signal,\n );\n\n // Append each tool result as a separate turn and record it.\n for (const tr of toolResults) {\n allToolCalls.push(tr.record);\n\n const resultTurn: ToolResultTurn = {\n role: 'tool',\n content: JSON.stringify(\n tr.record.error != null\n ? { error: tr.record.error }\n : tr.record.result,\n ),\n toolCallId: tr.toolCallId,\n toolName: tr.record.name,\n timestamp: Date.now(),\n };\n internalHistory.push(resultTurn);\n }\n\n // On subsequent rounds the new context is carried by the tool\n // result turns, so we send an empty user message.\n currentUserMessage = '';\n\n // Check abort again before looping.\n if (signal?.aborted) {\n this.log('Aborted after tool execution in round ' + rounds);\n break;\n }\n }\n\n if (rounds >= this.maxRounds) {\n this.log(\n `Max rounds (${this.maxRounds}) reached. Returning current text.`,\n );\n }\n\n this.log(\n `Execution complete: ${rounds} round(s), ` +\n `${allToolCalls.length} tool call(s), ` +\n `${totalUsage.total} total tokens`,\n );\n\n return {\n text: finalText,\n toolCallsExecuted: allToolCalls,\n totalUsage,\n rounds,\n };\n }\n\n // -----------------------------------------------------------------------\n // Private: execute a single tool call\n // -----------------------------------------------------------------------\n\n /**\n * Execute a single tool call by looking up the registered handler and\n * invoking it. Returns the result, any error message, and the wall-clock\n * duration in milliseconds.\n */\n private async executeTool(\n toolCall: ToolCall,\n ): Promise<{ result: unknown; error?: string; durationMs: number }> {\n const handler = this.handlers.get(toolCall.name);\n\n if (!handler) {\n const errorMsg = `Unknown tool: ${toolCall.name}`;\n this.log(errorMsg);\n return { result: undefined, error: errorMsg, durationMs: 0 };\n }\n\n this.onToolCallCb?.(toolCall.name, toolCall.arguments);\n\n const startTime = performance.now();\n\n try {\n const result = await handler.execute(toolCall.arguments);\n const durationMs = Math.round(performance.now() - startTime);\n\n this.onToolResultCb?.(toolCall.name, result, durationMs);\n this.log(\n `Tool \"${toolCall.name}\" completed in ${durationMs}ms`,\n );\n\n return { result, durationMs };\n } catch (err: unknown) {\n const durationMs = Math.round(performance.now() - startTime);\n const error = err instanceof Error ? err : new Error(String(err));\n\n this.onToolErrorCb?.(toolCall.name, error);\n this.log(\n `Tool \"${toolCall.name}\" failed after ${durationMs}ms: ${error.message}`,\n );\n\n return { result: undefined, error: error.message, durationMs };\n }\n }\n\n // -----------------------------------------------------------------------\n // Private: execute tool calls in parallel\n // -----------------------------------------------------------------------\n\n /**\n * Execute an array of tool calls concurrently. If the abort signal fires\n * mid-execution, already-started calls run to completion but the results\n * of all settled calls are still returned.\n */\n private async executeToolCallsInParallel(\n toolCalls: ToolCall[],\n signal?: AbortSignal,\n ): Promise<\n Array<{\n toolCallId: string;\n record: ToolCallRecord;\n }>\n > {\n // If already aborted, skip execution entirely.\n if (signal?.aborted) {\n return toolCalls.map((tc) => ({\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: undefined,\n durationMs: 0,\n error: 'Execution aborted',\n },\n }));\n }\n\n const settled = await Promise.allSettled(\n toolCalls.map(async (tc) => {\n // Check abort before starting each call. Already-queued microtasks\n // will still run, but this avoids starting new work when possible.\n if (signal?.aborted) {\n return {\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: undefined,\n durationMs: 0,\n error: 'Execution aborted',\n } satisfies ToolCallRecord,\n };\n }\n\n const outcome = await this.executeTool(tc);\n\n return {\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: outcome.result,\n durationMs: outcome.durationMs,\n ...(outcome.error != null ? { error: outcome.error } : {}),\n } satisfies ToolCallRecord,\n };\n }),\n );\n\n // Collect results. Rejected promises are converted to error records.\n return settled.map((s, i) => {\n if (s.status === 'fulfilled') {\n return s.value;\n }\n\n // This branch should be unreachable because executeTool catches all\n // errors, but we handle it defensively.\n const tc = toolCalls[i];\n if (!tc) {\n const errorMsg =\n s.reason instanceof Error ? s.reason.message : String(s.reason);\n return {\n toolCallId: `unknown-${i}`,\n record: {\n name: 'unknown',\n args: {},\n result: undefined,\n durationMs: 0,\n error: errorMsg,\n },\n };\n }\n const errorMsg =\n s.reason instanceof Error ? s.reason.message : String(s.reason);\n\n return {\n toolCallId: tc.id,\n record: {\n name: tc.name,\n args: tc.arguments,\n result: undefined,\n durationMs: 0,\n error: errorMsg,\n },\n };\n });\n }\n\n // -----------------------------------------------------------------------\n // Private: flatten internal history for the LLMOrchestrator\n // -----------------------------------------------------------------------\n\n /**\n * Convert the internal turn representation (which includes 'tool' roles\n * and assistant turns with tool call metadata) into the flat\n * `ConversationTurn[]` that `LLMOrchestrator.sendMessage` expects.\n *\n * Strategy:\n * - Standard `ConversationTurn` objects pass through unchanged.\n * - `AssistantToolCallTurn` objects are converted to an assistant turn\n * whose content describes the tool calls that were made.\n * - `ToolResultTurn` objects are converted to user turns that report\n * the tool results so the LLM can incorporate them.\n *\n * This approach works with any LLM provider since it only uses the\n * 'user' | 'assistant' role discriminator.\n */\n private flattenHistory(turns: InternalTurn[]): ConversationTurn[] {\n const flat: ConversationTurn[] = [];\n\n for (const turn of turns) {\n if (this.isToolResultTurn(turn)) {\n // Encode tool results as user turns so the LLM sees them as\n // new information to process.\n flat.push({\n role: 'user',\n content: `[Tool result for \"${turn.toolName}\" (id: ${turn.toolCallId})]: ${turn.content}`,\n timestamp: turn.timestamp,\n });\n } else if (this.isAssistantToolCallTurn(turn)) {\n // Encode the assistant's tool call request as an assistant turn.\n const callDescriptions = turn.toolCalls\n .map(\n (tc) =>\n `[Calling tool \"${tc.name}\" (id: ${tc.id}) with args: ${JSON.stringify(tc.args)}]`,\n )\n .join('\\n');\n\n const content = turn.content\n ? `${turn.content}\\n\\n${callDescriptions}`\n : callDescriptions;\n\n flat.push({\n role: 'assistant',\n content,\n timestamp: turn.timestamp,\n });\n } else {\n // Standard ConversationTurn — pass through.\n flat.push(turn);\n }\n }\n\n return flat;\n }\n\n // -----------------------------------------------------------------------\n // Type guards\n // -----------------------------------------------------------------------\n\n private isToolResultTurn(turn: InternalTurn): turn is ToolResultTurn {\n return (turn as ToolResultTurn).role === 'tool';\n }\n\n private isAssistantToolCallTurn(\n turn: InternalTurn,\n ): turn is AssistantToolCallTurn {\n return (\n turn.role === 'assistant' &&\n Array.isArray((turn as AssistantToolCallTurn).toolCalls)\n );\n }\n\n // -----------------------------------------------------------------------\n // Debug logging\n // -----------------------------------------------------------------------\n\n private log(message: string): void {\n if (this.debugEnabled) {\n console.debug(`[GuideKit:ToolExecutor] ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Network Connectivity Manager\n// ---------------------------------------------------------------------------\n\nimport type { ConnectionState } from '../types/index.js';\n\nconst LOG_PREFIX = '[GuideKit:Connectivity]';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Maximum number of messages held in the offline queue. */\nconst MAX_QUEUE_SIZE = 5;\n\n/** Number of recent pings used to compute rolling average latency. */\nconst ROLLING_WINDOW = 3;\n\n/** Latency threshold (ms) above which the connection is considered degraded. */\nconst DEGRADED_THRESHOLD_MS = 2_000;\n\n/** Ping intervals per state (ms). */\nconst PING_INTERVALS: Record<ConnectionState, number> = {\n online: 30_000,\n degraded: 5_000,\n offline: 10_000,\n};\n\n/** Timeout applied to each health-check fetch (ms). */\nconst PING_TIMEOUT_MS = 5_000;\n\n// ---------------------------------------------------------------------------\n// QueuedMessage\n// ---------------------------------------------------------------------------\n\n/** A message held for replay once connectivity is restored. */\nexport interface QueuedMessage {\n content: string;\n timestamp: number;\n pageUrl: string;\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface ConnectionManagerOptions {\n /** Server endpoint for lightweight health-check pings. */\n healthEndpoint?: string;\n /** When `true`, diagnostic messages are logged to the console. */\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// State-change subscriber\n// ---------------------------------------------------------------------------\n\ntype StateChangeCallback = (\n state: ConnectionState,\n previous: ConnectionState,\n) => void;\n\n// ---------------------------------------------------------------------------\n// ConnectionManager\n// ---------------------------------------------------------------------------\n\n/**\n * Monitors network connectivity and exposes a reactive {@link ConnectionState}.\n *\n * Strategy:\n * 1. Listen to `window.online` / `window.offline` events (coarse signal).\n * 2. Periodically ping the configured `healthEndpoint` (fine-grained signal).\n * 3. Compute a rolling average of the last {@link ROLLING_WINDOW} ping\n * latencies to detect degraded connections (> {@link DEGRADED_THRESHOLD_MS}).\n * 4. When fully offline (`navigator.onLine === false`), suspend pinging and\n * wait for the browser's `online` event before resuming.\n *\n * All browser APIs are gated behind `typeof window !== 'undefined'` so the\n * class can be safely imported (though not meaningfully used) in SSR contexts.\n */\nexport class ConnectionManager {\n // ---- Configuration ------------------------------------------------------\n\n private readonly healthEndpoint: string | undefined;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state -----------------------------------------------------\n\n private _state: ConnectionState = 'online';\n private _running = false;\n\n /** Rolling window of recent ping latencies (ms). */\n private readonly pingLatencies: number[] = [];\n\n /** Queued messages awaiting replay on reconnect. */\n private readonly messageQueue: QueuedMessage[] = [];\n\n /** Registered state-change subscribers. */\n private readonly subscribers: Set<StateChangeCallback> = new Set();\n\n /** Timer handle for the periodic ping loop. */\n private pingTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Bound event handlers (stored for deterministic removal). */\n private readonly handleOnline: () => void;\n private readonly handleOffline: () => void;\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options?: ConnectionManagerOptions) {\n this.healthEndpoint = options?.healthEndpoint;\n this.debugEnabled = options?.debug ?? false;\n\n // Pre-bind handlers so we can add/remove the exact same references.\n this.handleOnline = this.onBrowserOnline.bind(this);\n this.handleOffline = this.onBrowserOffline.bind(this);\n\n this.log('ConnectionManager created');\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Current connection state. */\n get state(): ConnectionState {\n return this._state;\n }\n\n /**\n * Start monitoring connectivity.\n *\n * Attaches browser event listeners and begins the periodic ping loop.\n * Calling `start()` when already running is a no-op.\n */\n start(): void {\n if (this._running) {\n return;\n }\n\n this._running = true;\n this.log('Monitoring started');\n\n if (typeof window !== 'undefined') {\n window.addEventListener('online', this.handleOnline);\n window.addEventListener('offline', this.handleOffline);\n\n // Seed initial state from the browser.\n if (!navigator.onLine) {\n this.transition('offline');\n }\n }\n\n this.schedulePing();\n }\n\n /**\n * Stop monitoring connectivity.\n *\n * Removes all event listeners, clears timers, and resets internal state.\n */\n stop(): void {\n if (!this._running) {\n return;\n }\n\n this._running = false;\n this.log('Monitoring stopped');\n\n if (typeof window !== 'undefined') {\n window.removeEventListener('online', this.handleOnline);\n window.removeEventListener('offline', this.handleOffline);\n }\n\n this.clearPingTimer();\n this.pingLatencies.length = 0;\n }\n\n /**\n * Subscribe to connection state changes.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onStateChange(callback: StateChangeCallback): () => void {\n this.subscribers.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.subscribers.delete(callback);\n };\n }\n\n /**\n * Queue a message for replay once the connection is restored.\n *\n * The queue is capped at {@link MAX_QUEUE_SIZE} messages. When the cap is\n * exceeded the oldest message is discarded.\n */\n queueMessage(message: QueuedMessage): void {\n if (this.messageQueue.length >= MAX_QUEUE_SIZE) {\n const discarded = this.messageQueue.shift();\n this.log('Queue full — discarded oldest message', discarded);\n }\n\n this.messageQueue.push(message);\n this.log(`Message queued (${this.messageQueue.length}/${MAX_QUEUE_SIZE})`);\n }\n\n /**\n * Drain the message queue and return its contents.\n *\n * Messages whose `pageUrl` no longer matches the current browser URL are\n * silently discarded (the user has navigated away since queueing).\n */\n drainQueue(): QueuedMessage[] {\n const currentUrl = this.getCurrentUrl();\n const valid: QueuedMessage[] = [];\n\n for (const msg of this.messageQueue) {\n if (msg.pageUrl === currentUrl) {\n valid.push(msg);\n } else {\n this.log('Discarded stale message (URL changed)', msg.pageUrl);\n }\n }\n\n this.messageQueue.length = 0;\n this.log(`Drained ${valid.length} message(s)`);\n return valid;\n }\n\n /**\n * Force an immediate connectivity check.\n *\n * @returns The updated {@link ConnectionState} after the check completes.\n */\n async checkNow(): Promise<ConnectionState> {\n // If the browser reports offline, skip the network request entirely.\n if (typeof window !== 'undefined' && !navigator.onLine) {\n this.transition('offline');\n return this._state;\n }\n\n await this.ping();\n return this._state;\n }\n\n // -----------------------------------------------------------------------\n // Browser event handlers\n // -----------------------------------------------------------------------\n\n private onBrowserOnline(): void {\n this.log('Browser \"online\" event received');\n\n // Reset latency history — the previous measurements are stale.\n this.pingLatencies.length = 0;\n\n // Optimistically assume online; the next ping will refine the state.\n this.transition('online');\n\n // Resume pinging if we are still in monitoring mode.\n if (this._running) {\n this.schedulePing();\n }\n }\n\n private onBrowserOffline(): void {\n this.log('Browser \"offline\" event received');\n this.transition('offline');\n\n // Suspend pinging — no point hitting the network when the browser\n // itself says we are offline. We will resume via `handleOnline`.\n this.clearPingTimer();\n }\n\n // -----------------------------------------------------------------------\n // Ping logic\n // -----------------------------------------------------------------------\n\n /**\n * Execute a single health-check ping and update state accordingly.\n */\n private async ping(): Promise<void> {\n if (!this.healthEndpoint) {\n // Without an endpoint we can only rely on navigator.onLine.\n if (typeof window !== 'undefined') {\n this.transition(navigator.onLine ? 'online' : 'offline');\n }\n return;\n }\n\n const start = Date.now();\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), PING_TIMEOUT_MS);\n\n try {\n await fetch(this.healthEndpoint, {\n method: 'HEAD',\n mode: 'no-cors',\n cache: 'no-store',\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeout);\n }\n\n const latency = Date.now() - start;\n this.recordLatency(latency);\n this.log(`Ping OK (${latency}ms)`);\n\n // Evaluate rolling average to decide between online / degraded.\n const avg = this.rollingAverage();\n if (avg > DEGRADED_THRESHOLD_MS) {\n this.transition('degraded');\n } else {\n this.transition('online');\n }\n } catch {\n this.log('Ping failed');\n\n // A failed ping when navigator reports offline is a clear offline.\n if (typeof window !== 'undefined' && !navigator.onLine) {\n this.transition('offline');\n } else {\n // Network may still be up, but the endpoint is unreachable —\n // treat as degraded rather than outright offline.\n this.transition('degraded');\n }\n }\n }\n\n /**\n * Record a latency sample, keeping only the last {@link ROLLING_WINDOW}\n * entries.\n */\n private recordLatency(ms: number): void {\n this.pingLatencies.push(ms);\n if (this.pingLatencies.length > ROLLING_WINDOW) {\n this.pingLatencies.shift();\n }\n }\n\n /** Compute the arithmetic mean of recorded latencies. */\n private rollingAverage(): number {\n if (this.pingLatencies.length === 0) return 0;\n\n let sum = 0;\n for (const v of this.pingLatencies) {\n sum += v;\n }\n return sum / this.pingLatencies.length;\n }\n\n // -----------------------------------------------------------------------\n // Ping scheduling\n // -----------------------------------------------------------------------\n\n /**\n * Schedule the next ping according to the current state's interval.\n *\n * When in the `offline` state, pinging is suspended entirely — the\n * manager waits for the browser's `online` event to resume.\n */\n private schedulePing(): void {\n this.clearPingTimer();\n\n if (!this._running) {\n return;\n }\n\n // While offline, do not ping. The browser `online` event will resume.\n if (this._state === 'offline') {\n return;\n }\n\n const interval = PING_INTERVALS[this._state];\n\n this.pingTimer = setTimeout(async () => {\n if (!this._running) return;\n\n await this.ping();\n\n // Schedule the next iteration (interval may have changed due to\n // a state transition during the ping).\n this.schedulePing();\n }, interval);\n }\n\n private clearPingTimer(): void {\n if (this.pingTimer !== null) {\n clearTimeout(this.pingTimer);\n this.pingTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // State transitions\n // -----------------------------------------------------------------------\n\n /**\n * Transition to a new state, notifying subscribers if the state actually\n * changed.\n */\n private transition(next: ConnectionState): void {\n const previous = this._state;\n if (previous === next) {\n return;\n }\n\n this._state = next;\n this.log(`State: ${previous} -> ${next}`);\n\n // Notify subscribers. Errors in callbacks are caught so one bad\n // subscriber does not prevent the rest from being notified.\n for (const cb of this.subscribers) {\n try {\n cb(next, previous);\n } catch (err) {\n console.error(LOG_PREFIX, 'Subscriber threw an error:', err);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n /** Return the current page URL, or an empty string in SSR contexts. */\n private getCurrentUrl(): string {\n if (typeof window !== 'undefined') {\n return window.location.href;\n }\n return '';\n }\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Navigation Controller\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Nav]';\n\nexport interface NavigationControllerOptions {\n debug?: boolean;\n /** Developer-provided router for guaranteed SPA navigation. */\n router?: {\n push: (href: string) => void | Promise<void>;\n };\n}\n\n/**\n * Manages SPA navigation detection and programmatic routing.\n *\n * - Prefers the Navigation API (Chrome 102+) where available.\n * - Falls back to `popstate` + periodic URL polling (200ms).\n * - Developer can pass a `router` prop for guaranteed SPA nav.\n */\nexport class NavigationController {\n private readonly debug: boolean;\n private readonly router?: { push: (href: string) => void | Promise<void> };\n\n private currentUrl: string = '';\n private pollingTimer: ReturnType<typeof setInterval> | null = null;\n private callbacks: Array<(from: string, to: string) => void> = [];\n private cleanups: Array<() => void> = [];\n\n constructor(options?: NavigationControllerOptions) {\n this.debug = options?.debug ?? false;\n this.router = options?.router;\n }\n\n /** Start listening for navigation events. */\n start(): void {\n if (typeof window === 'undefined') return;\n\n this.currentUrl = window.location.href;\n\n // Prefer Navigation API\n if ('navigation' in window && typeof (window as any).navigation?.addEventListener === 'function') {\n const nav = (window as any).navigation;\n const handler = (event: any) => {\n const to = event.destination?.url ?? window.location.href;\n this.handleRouteChange(to);\n };\n nav.addEventListener('navigate', handler);\n this.cleanups.push(() => nav.removeEventListener('navigate', handler));\n\n if (this.debug) console.debug(LOG_PREFIX, 'Using Navigation API');\n } else {\n // Fallback: popstate + polling\n const popHandler = () => {\n this.handleRouteChange(window.location.href);\n };\n window.addEventListener('popstate', popHandler);\n this.cleanups.push(() => window.removeEventListener('popstate', popHandler));\n\n // Poll every 200ms for pushState changes\n this.pollingTimer = setInterval(() => {\n if (window.location.href !== this.currentUrl) {\n this.handleRouteChange(window.location.href);\n }\n }, 200);\n\n if (this.debug) console.debug(LOG_PREFIX, 'Using popstate + URL polling fallback');\n }\n }\n\n /** Stop listening for navigation events. */\n stop(): void {\n for (const cleanup of this.cleanups) {\n cleanup();\n }\n this.cleanups = [];\n\n if (this.pollingTimer !== null) {\n clearInterval(this.pollingTimer);\n this.pollingTimer = null;\n }\n }\n\n /**\n * Subscribe to route changes.\n * @returns Unsubscribe function.\n */\n onRouteChange(callback: (from: string, to: string) => void): () => void {\n this.callbacks.push(callback);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n const idx = this.callbacks.indexOf(callback);\n if (idx !== -1) this.callbacks.splice(idx, 1);\n };\n }\n\n /**\n * Programmatically navigate to a URL.\n * Validates same-origin before navigating.\n */\n async navigate(href: string): Promise<boolean> {\n if (typeof window === 'undefined') return false;\n\n // Same-origin validation\n try {\n const target = new URL(href, window.location.origin);\n if (target.origin !== window.location.origin) {\n if (this.debug) console.warn(LOG_PREFIX, 'Blocked cross-origin navigation to', href);\n return false;\n }\n href = target.href;\n } catch {\n if (this.debug) console.warn(LOG_PREFIX, 'Invalid URL:', href);\n return false;\n }\n\n // Use developer-provided router if available\n if (this.router) {\n await this.router.push(href);\n return true;\n }\n\n // Fallback: update location\n window.location.href = href;\n return true;\n }\n\n /** Get the current URL. */\n get url(): string {\n if (typeof window === 'undefined') return '';\n return window.location.href;\n }\n\n private handleRouteChange(newUrl: string): void {\n if (newUrl === this.currentUrl) return;\n\n const from = this.currentUrl;\n this.currentUrl = newUrl;\n\n if (this.debug) console.debug(LOG_PREFIX, `Route change: ${from} → ${newUrl}`);\n\n for (const callback of this.callbacks.slice()) {\n try {\n callback(from, newUrl);\n } catch (err) {\n console.error(LOG_PREFIX, 'Route change handler error:', err);\n }\n }\n }\n}\n","// ----------------------------------------------------------------------------\n// WebSocket Connection Manager for STT/TTS\n// Manages WebSocket connections with automatic reconnection, exponential\n// backoff, send queueing, and SSR safety.\n// ----------------------------------------------------------------------------\n\nexport type WSState =\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'failed'\n | 'suspended';\n\nexport interface WebSocketManagerOptions {\n url: string | (() => string | Promise<string>);\n /** Max reconnection attempts before entering FAILED state. Default: 5 */\n maxReconnectAttempts?: number;\n /** Initial reconnect delay in ms. Default: 1000 */\n initialDelay?: number;\n /** Max reconnect delay in ms. Default: 30000 */\n maxDelay?: number;\n /** Connection timeout in ms. Default: 5000 */\n connectTimeoutMs?: number;\n /** Protocols to pass to WebSocket constructor */\n protocols?: string | string[];\n /** Debug logging */\n debug?: boolean;\n /** Label for logging (e.g., 'STT', 'TTS') */\n label?: string;\n}\n\ntype MessagePayload = string | ArrayBuffer | Blob;\n\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;\nconst DEFAULT_INITIAL_DELAY = 1000;\nconst DEFAULT_MAX_DELAY = 30_000;\nconst DEFAULT_CONNECT_TIMEOUT_MS = 5000;\nconst MAX_QUEUE_SIZE = 50;\n\ninterface ListenerRefs {\n onOpen: () => void;\n onClose: (e: CloseEvent) => void;\n onError: (e: Event) => void;\n onMessage: (e: MessageEvent) => void;\n}\n\nexport class WebSocketManager {\n // ── Options (resolved with defaults) ────────────────────────────────\n private readonly _url: string | (() => string | Promise<string>);\n private readonly _maxReconnectAttempts: number;\n private readonly _initialDelay: number;\n private readonly _maxDelay: number;\n private readonly _connectTimeoutMs: number;\n private readonly _protocols: string | string[] | undefined;\n private readonly _debug: boolean;\n private readonly _label: string;\n\n // ── Internal state ──────────────────────────────────────────────────\n private _state: WSState = 'disconnected';\n private _socket: WebSocket | null = null;\n private _reconnectAttempts = 0;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _connectTimer: ReturnType<typeof setTimeout> | null = null;\n private _destroyed = false;\n\n // ── Listener references (for proper cleanup) ──────────────────────\n private _listenerRefs = new WeakMap<WebSocket, ListenerRefs>();\n\n // ── Send queue ──────────────────────────────────────────────────────\n private _queue: MessagePayload[] = [];\n\n // ── Event listeners ─────────────────────────────────────────────────\n private _onOpenCallbacks: Set<() => void> = new Set();\n private _onCloseCallbacks: Set<(code: number, reason: string) => void> = new Set();\n private _onMessageCallbacks: Set<(data: MessageEvent) => void> = new Set();\n private _onErrorCallbacks: Set<(error: Event) => void> = new Set();\n private _onStateChangeCallbacks: Set<(state: WSState, previous: WSState) => void> = new Set();\n\n // ── Constructor ─────────────────────────────────────────────────────\n\n constructor(options: WebSocketManagerOptions) {\n this._url = options.url;\n this._maxReconnectAttempts = options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n this._initialDelay = options.initialDelay ?? DEFAULT_INITIAL_DELAY;\n this._maxDelay = options.maxDelay ?? DEFAULT_MAX_DELAY;\n this._connectTimeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;\n this._protocols = options.protocols;\n this._debug = options.debug ?? false;\n this._label = options.label ?? 'WS';\n }\n\n // ── Public getters ──────────────────────────────────────────────────\n\n /** Current connection state */\n get state(): WSState {\n return this._state;\n }\n\n /** The underlying WebSocket (null if not connected) */\n get socket(): WebSocket | null {\n return this._socket;\n }\n\n // ── Connection lifecycle ────────────────────────────────────────────\n\n /** Connect to the WebSocket server */\n async connect(): Promise<void> {\n if (this._destroyed) {\n this._log('Cannot connect — manager is destroyed');\n return;\n }\n\n // SSR guard\n if (typeof WebSocket === 'undefined') {\n this._log('WebSocket is not available in this environment');\n return;\n }\n\n // If already connected or connecting, no-op\n if (this._state === 'connected' || this._state === 'connecting') {\n this._log(`Already in state \"${this._state}\", ignoring connect()`);\n return;\n }\n\n // A manual connect() call from FAILED state resets the attempt counter\n if (this._state === 'failed') {\n this._reconnectAttempts = 0;\n }\n\n this._setState('connecting');\n await this._attemptConnection();\n }\n\n /** Gracefully close the connection */\n close(code?: number, reason?: string): void {\n this._log('close() called');\n this._clearTimers();\n this._reconnectAttempts = 0;\n\n if (this._socket) {\n // Remove listeners before closing to prevent the close handler from\n // triggering reconnection logic.\n this._detachSocketListeners(this._socket);\n try {\n this._socket.close(code ?? 1000, reason ?? 'Client closed');\n } catch {\n // Socket may already be closed; ignore.\n }\n this._socket = null;\n }\n\n this._setState('disconnected');\n }\n\n /**\n * Send data through the WebSocket.\n * - If state is `connecting` or `reconnecting`, the message is queued.\n * - If state is `connected`, the message is sent immediately.\n * - If state is `failed` or `suspended`, an error is thrown.\n * - If state is `disconnected`, the message is queued (a reconnect may follow).\n */\n send(data: MessagePayload): void {\n if (this._state === 'failed') {\n throw new Error(\n `[GuideKit:WS:${this._label}] Cannot send — connection is in FAILED state. Call connect() to retry.`,\n );\n }\n\n if (this._state === 'suspended') {\n throw new Error(\n `[GuideKit:WS:${this._label}] Cannot send — connection is SUSPENDED. Call resume() first.`,\n );\n }\n\n if (this._state === 'connected' && this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(data);\n return;\n }\n\n // Queue the message for later delivery\n this._enqueue(data);\n }\n\n // ── Suspend / Resume ────────────────────────────────────────────────\n\n /** Suspend reconnection (e.g., during confirmed offline). No reconnection attempts. */\n suspend(): void {\n if (this._state === 'failed' || this._state === 'suspended') {\n this._log(`suspend() ignored — already in \"${this._state}\"`);\n return;\n }\n\n this._log('Suspending');\n this._clearTimers();\n\n // If there is an active socket, close it\n if (this._socket) {\n this._detachSocketListeners(this._socket);\n try {\n this._socket.close(1000, 'Suspended');\n } catch {\n // ignore\n }\n this._socket = null;\n }\n\n this._setState('suspended');\n }\n\n /** Resume from suspended state. Triggers reconnection. */\n resume(): void {\n if (this._state !== 'suspended') {\n this._log(`resume() ignored — not in SUSPENDED state (current: \"${this._state}\")`);\n return;\n }\n\n this._log('Resuming');\n this._reconnectAttempts = 0;\n this._setState('reconnecting');\n this._scheduleReconnect();\n }\n\n // ── Event registration ──────────────────────────────────────────────\n\n /** Register an onOpen handler. Returns an unsubscribe function. */\n onOpen(callback: () => void): () => void {\n this._onOpenCallbacks.add(callback);\n return () => {\n this._onOpenCallbacks.delete(callback);\n };\n }\n\n /** Register an onClose handler. Returns an unsubscribe function. */\n onClose(callback: (code: number, reason: string) => void): () => void {\n this._onCloseCallbacks.add(callback);\n return () => {\n this._onCloseCallbacks.delete(callback);\n };\n }\n\n /** Register an onMessage handler. Returns an unsubscribe function. */\n onMessage(callback: (data: MessageEvent) => void): () => void {\n this._onMessageCallbacks.add(callback);\n return () => {\n this._onMessageCallbacks.delete(callback);\n };\n }\n\n /** Register an onError handler. Returns an unsubscribe function. */\n onError(callback: (error: Event) => void): () => void {\n this._onErrorCallbacks.add(callback);\n return () => {\n this._onErrorCallbacks.delete(callback);\n };\n }\n\n /** Register a state change handler. Returns an unsubscribe function. */\n onStateChange(callback: (state: WSState, previous: WSState) => void): () => void {\n this._onStateChangeCallbacks.add(callback);\n return () => {\n this._onStateChangeCallbacks.delete(callback);\n };\n }\n\n // ── Destroy ─────────────────────────────────────────────────────────\n\n /** Destroy the manager and clean up all resources */\n destroy(): void {\n if (this._destroyed) return;\n this._destroyed = true;\n this._log('Destroying');\n\n this.close();\n this._queue = [];\n this._onOpenCallbacks.clear();\n this._onCloseCallbacks.clear();\n this._onMessageCallbacks.clear();\n this._onErrorCallbacks.clear();\n this._onStateChangeCallbacks.clear();\n }\n\n // ── Private: Connection logic ───────────────────────────────────────\n\n private async _resolveUrl(): Promise<string> {\n if (typeof this._url === 'function') {\n return await this._url();\n }\n return this._url;\n }\n\n private async _attemptConnection(): Promise<void> {\n // SSR guard\n if (typeof WebSocket === 'undefined') return;\n\n let url: string;\n try {\n url = await this._resolveUrl();\n } catch (err) {\n this._log(`URL resolution failed: ${err}`);\n this._handleConnectionFailure();\n return;\n }\n\n this._log(`Connecting to ${url}`);\n\n let ws: WebSocket;\n try {\n ws = this._protocols ? new WebSocket(url, this._protocols) : new WebSocket(url);\n } catch (err) {\n this._log(`WebSocket constructor threw: ${err}`);\n this._handleConnectionFailure();\n return;\n }\n\n // Binary type: arraybuffer is generally more useful than blob\n ws.binaryType = 'arraybuffer';\n\n this._socket = ws;\n\n // ── Connection timeout ──────────────────────────────────────────\n this._connectTimer = setTimeout(() => {\n if (ws.readyState === WebSocket.CONNECTING) {\n this._log('Connection timed out');\n // Force-close the socket; the close handler will trigger reconnection.\n ws.close();\n }\n }, this._connectTimeoutMs);\n\n // ── Socket event handlers ───────────────────────────────────────\n const onOpen = () => {\n this._clearConnectTimer();\n this._reconnectAttempts = 0;\n this._setState('connected');\n this._log('Connected');\n\n // Notify listeners\n for (const cb of this._onOpenCallbacks) {\n try {\n cb();\n } catch {\n // Swallow listener errors\n }\n }\n\n // Flush queued messages\n this._flushQueue();\n };\n\n const onClose = (event: CloseEvent) => {\n this._clearConnectTimer();\n this._log(`Socket closed — code=${event.code} reason=\"${event.reason}\"`);\n\n // Notify close listeners\n for (const cb of this._onCloseCallbacks) {\n try {\n cb(event.code, event.reason);\n } catch {\n // Swallow listener errors\n }\n }\n\n // Clean up this socket reference if it is the current one\n if (this._socket === ws) {\n this._socket = null;\n }\n\n // Only attempt reconnection if the manager hasn't been destroyed or\n // intentionally closed (state would be 'disconnected' in that case).\n if (\n !this._destroyed &&\n this._state !== 'disconnected' &&\n this._state !== 'suspended' &&\n this._state !== 'failed'\n ) {\n this._setState('disconnected');\n this._handleConnectionFailure();\n }\n };\n\n const onError = (event: Event) => {\n this._log('Socket error');\n for (const cb of this._onErrorCallbacks) {\n try {\n cb(event);\n } catch {\n // Swallow listener errors\n }\n }\n // The `close` event will follow the `error` event, so reconnection\n // logic is handled there.\n };\n\n const onMessage = (event: MessageEvent) => {\n for (const cb of this._onMessageCallbacks) {\n try {\n cb(event);\n } catch {\n // Swallow listener errors\n }\n }\n };\n\n ws.addEventListener('open', onOpen);\n ws.addEventListener('close', onClose);\n ws.addEventListener('error', onError);\n ws.addEventListener('message', onMessage);\n\n // Store references for later removal\n this._listenerRefs.set(ws, { onOpen, onClose, onError, onMessage });\n }\n\n private _detachSocketListeners(ws: WebSocket): void {\n const listeners = this._listenerRefs.get(ws);\n if (!listeners) return;\n ws.removeEventListener('open', listeners.onOpen);\n ws.removeEventListener('close', listeners.onClose);\n ws.removeEventListener('error', listeners.onError);\n ws.removeEventListener('message', listeners.onMessage);\n this._listenerRefs.delete(ws);\n }\n\n // ── Private: Reconnection ───────────────────────────────────────────\n\n private _handleConnectionFailure(): void {\n if (this._destroyed || this._state === 'suspended') return;\n\n this._reconnectAttempts++;\n\n if (this._reconnectAttempts > this._maxReconnectAttempts) {\n this._log(\n `Max reconnect attempts (${this._maxReconnectAttempts}) reached — entering FAILED state`,\n );\n this._setState('failed');\n return;\n }\n\n this._setState('reconnecting');\n this._scheduleReconnect();\n }\n\n private _scheduleReconnect(): void {\n if (this._destroyed) return;\n\n const delay = this._calculateBackoff(this._reconnectAttempts - 1);\n this._log(`Reconnecting in ${delay}ms (attempt ${this._reconnectAttempts}/${this._maxReconnectAttempts})`);\n\n this._reconnectTimer = setTimeout(async () => {\n this._reconnectTimer = null;\n if (this._destroyed || this._state === 'suspended' || this._state === 'failed') return;\n\n this._setState('connecting');\n await this._attemptConnection();\n }, delay);\n }\n\n /**\n * Exponential backoff with jitter.\n * delay = initialDelay * 2^attempt, capped at maxDelay, with +/-25% jitter.\n */\n private _calculateBackoff(attempt: number): number {\n const exponential = this._initialDelay * Math.pow(2, attempt);\n const capped = Math.min(exponential, this._maxDelay);\n // Jitter: random value between 0.75 and 1.25 of the capped delay\n const jitter = 0.75 + Math.random() * 0.5;\n return Math.round(capped * jitter);\n }\n\n // ── Private: Send queue ─────────────────────────────────────────────\n\n private _enqueue(data: MessagePayload): void {\n if (this._queue.length >= MAX_QUEUE_SIZE) {\n this._log('Send queue full — dropping oldest message');\n this._queue.shift();\n }\n this._queue.push(data);\n }\n\n private _flushQueue(): void {\n if (\n this._queue.length === 0 ||\n !this._socket ||\n this._socket.readyState !== WebSocket.OPEN\n ) {\n return;\n }\n\n this._log(`Flushing ${this._queue.length} queued message(s)`);\n const pending = this._queue.slice();\n this._queue = [];\n\n for (const msg of pending) {\n try {\n this._socket.send(msg);\n } catch (err) {\n this._log(`Failed to send queued message: ${err}`);\n // Re-queue remaining messages on failure\n // The current message is lost but remaining ones are preserved.\n break;\n }\n }\n }\n\n // ── Private: State management ───────────────────────────────────────\n\n private _setState(next: WSState): void {\n const prev = this._state;\n if (prev === next) return;\n\n this._state = next;\n this._log(`State: ${prev} -> ${next}`);\n\n for (const cb of this._onStateChangeCallbacks) {\n try {\n cb(next, prev);\n } catch {\n // Swallow listener errors\n }\n }\n }\n\n // ── Private: Timer management ───────────────────────────────────────\n\n private _clearTimers(): void {\n this._clearConnectTimer();\n this._clearReconnectTimer();\n }\n\n private _clearConnectTimer(): void {\n if (this._connectTimer !== null) {\n clearTimeout(this._connectTimer);\n this._connectTimer = null;\n }\n }\n\n private _clearReconnectTimer(): void {\n if (this._reconnectTimer !== null) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n\n // ── Private: Logging ────────────────────────────────────────────────\n\n private _log(message: string): void {\n if (this._debug) {\n console.log(`[GuideKit:WS:${this._label}] ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Deepgram Nova Real-Time Speech-to-Text Adapter\n// ---------------------------------------------------------------------------\n//\n// Streams microphone audio to Deepgram over a WebSocket and emits interim /\n// final transcript events. Designed for browser use; all browser-only APIs are\n// guarded behind `typeof window` checks so the module is safe to import at\n// build time in SSR environments.\n// ---------------------------------------------------------------------------\n\nimport { WebSocketManager } from './websocket-manager.js';\nimport type { STTTranscriptEvent } from '../types/index.js';\n\n// Re-export the shared type for consumers that only import from this module\nexport type { STTTranscriptEvent };\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:STT]';\n\n/** Interval (ms) between KeepAlive messages sent to Deepgram. */\nconst KEEPALIVE_INTERVAL_MS = 10_000;\n\n/** Default Deepgram model. */\nconst DEFAULT_MODEL = 'nova-3';\n\n/** Default language. */\nconst DEFAULT_LANGUAGE = 'en';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface DeepgramSTTOptions {\n apiKey: string;\n model?: 'nova-2' | 'nova-3';\n language?: string;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert Float32Array PCM samples (range -1..1) to Int16Array (linear16).\n * Deepgram expects linear16 encoded audio frames.\n */\nfunction float32ToInt16(float32: Float32Array): Int16Array {\n const int16 = new Int16Array(float32.length);\n for (let i = 0; i < float32.length; i++) {\n // Clamp to [-1, 1] then scale to Int16 range.\n const s = Math.max(-1, Math.min(1, float32[i]!));\n int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n return int16;\n}\n\n// ---------------------------------------------------------------------------\n// DeepgramSTT\n// ---------------------------------------------------------------------------\n\nexport class DeepgramSTT {\n // ---- Configuration ------------------------------------------------------\n\n private readonly apiKey: string;\n private readonly model: 'nova-2' | 'nova-3';\n private readonly language: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state -----------------------------------------------------\n\n private wsManager: WebSocketManager | null = null;\n private keepAliveTimer: ReturnType<typeof setInterval> | null = null;\n private _connected = false;\n private _suspended = false;\n\n /** Registered transcript callbacks. */\n private readonly transcriptCallbacks: Set<(event: STTTranscriptEvent) => void> =\n new Set();\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options: DeepgramSTTOptions) {\n this.apiKey = options.apiKey;\n this.model = options.model ?? DEFAULT_MODEL;\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.debugEnabled = options.debug ?? false;\n\n this.log('DeepgramSTT created', {\n model: this.model,\n language: this.language,\n });\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Whether the WebSocket is currently connected and ready. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Open a WebSocket connection to Deepgram's real-time STT endpoint.\n *\n * Resolves once the connection is established and the socket is ready to\n * receive audio frames. Rejects if the connection cannot be established.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof WebSocket === 'undefined') {\n this.log('WebSocket API not available (SSR?) — cannot connect');\n return;\n }\n\n const url = this.buildUrl();\n this.log('Connecting to', url.replace(this.apiKey, '***'));\n\n this.wsManager = new WebSocketManager({\n url,\n protocols: [],\n debug: this.debugEnabled,\n label: 'Deepgram-STT',\n });\n\n this.wsManager.onOpen(() => {\n this._connected = true;\n this.startKeepAlive();\n this.log('Connected');\n });\n this.wsManager.onMessage((event: MessageEvent) => {\n this.handleMessage(event);\n });\n this.wsManager.onClose((code: number, reason: string) => {\n this.log('Connection closed', { code, reason });\n this.cleanup();\n });\n this.wsManager.onError((event: Event) => {\n this.log('WebSocket error', event);\n });\n\n return this.wsManager.connect();\n }\n\n /**\n * Send audio data to Deepgram for transcription.\n *\n * Accepts either `Float32Array` (Web Audio API output) or `Int16Array`\n * (already encoded as linear16). Float32 data is automatically converted\n * to Int16 before sending.\n */\n sendAudio(audioData: Float32Array | Int16Array): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n return;\n }\n\n let buffer: ArrayBuffer;\n if (audioData instanceof Float32Array) {\n buffer = float32ToInt16(audioData).buffer as ArrayBuffer;\n } else {\n buffer = audioData.buffer as ArrayBuffer;\n }\n\n this.wsManager.send(buffer);\n }\n\n /**\n * Register a callback to receive transcript events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onTranscript(callback: (event: STTTranscriptEvent) => void): () => void {\n this.transcriptCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.transcriptCallbacks.delete(callback);\n };\n }\n\n /**\n * Gracefully close the connection.\n *\n * Sends a `CloseStream` message to Deepgram so the server can finalise\n * any pending transcription before the socket is torn down.\n */\n close(): void {\n if (!this._connected || !this.wsManager) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Sending CloseStream and closing');\n this.stopKeepAlive();\n\n try {\n this.wsManager.send(JSON.stringify({ type: 'CloseStream' }));\n } catch {\n // Socket may already be closing — ignore.\n }\n\n this.wsManager.close();\n this.cleanup();\n }\n\n /** Force-destroy the connection without a graceful handshake. */\n destroy(): void {\n this.log('Destroying');\n this.stopKeepAlive();\n\n if (this.wsManager) {\n this.wsManager.destroy();\n this.wsManager = null;\n }\n\n this.cleanup();\n this.transcriptCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Stops the keepalive timer and marks the adapter as suspended so that\n * incoming `sendAudio` calls are silently dropped. The WebSocket itself\n * is left open; Deepgram will close it after an inactivity timeout if\n * the network truly went away.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this.stopKeepAlive();\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`. If the underlying connection is\n * still alive, the keepalive timer is restarted. If the connection was\n * lost while suspended, callers should `close()` / `destroy()` and\n * create a new instance.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this.log('Resumed');\n\n if (this._connected && this.wsManager) {\n this.startKeepAlive();\n }\n }\n\n // -----------------------------------------------------------------------\n // Message handling\n // -----------------------------------------------------------------------\n\n /**\n * Parse incoming Deepgram JSON messages and emit transcript events.\n *\n * Deepgram sends `Results` messages with the following shape:\n * ```json\n * {\n * \"type\": \"Results\",\n * \"channel\": {\n * \"alternatives\": [{ \"transcript\": \"...\", \"confidence\": 0.97 }]\n * },\n * \"is_final\": true,\n * \"speech_final\": true\n * }\n * ```\n */\n private handleMessage(event: MessageEvent): void {\n // Binary messages are not expected — ignore.\n if (typeof event.data !== 'string') {\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n this.log('Failed to parse message', event.data);\n return;\n }\n\n const type = parsed['type'] as string | undefined;\n\n if (type === 'Results') {\n this.handleResultsMessage(parsed);\n } else if (type === 'Metadata') {\n this.log('Received metadata', parsed);\n } else if (type === 'Error') {\n this.log('Deepgram error', parsed);\n } else {\n this.log('Unknown message type', type, parsed);\n }\n }\n\n /**\n * Extract transcript data from a `Results` message and notify subscribers.\n */\n private handleResultsMessage(parsed: Record<string, unknown>): void {\n const channel = parsed['channel'] as\n | { alternatives?: { transcript?: string; confidence?: number }[] }\n | undefined;\n\n const alternatives = channel?.alternatives;\n if (!alternatives || alternatives.length === 0) {\n return;\n }\n\n const best = alternatives[0];\n if (!best) return;\n const transcript = best.transcript ?? '';\n const confidence = best.confidence ?? 0;\n\n // Deepgram sends empty transcripts for silence — skip those.\n if (transcript.trim() === '') {\n return;\n }\n\n const isFinal =\n (parsed['is_final'] === true) && (parsed['speech_final'] === true);\n\n const transcriptEvent: STTTranscriptEvent = {\n text: transcript,\n isFinal,\n confidence,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final transcript:' : 'Interim transcript:',\n transcript,\n `(${(confidence * 100).toFixed(1)}%)`,\n );\n\n this.emitTranscript(transcriptEvent);\n }\n\n // -----------------------------------------------------------------------\n // Keepalive\n // -----------------------------------------------------------------------\n\n /** Start the periodic KeepAlive heartbeat. */\n private startKeepAlive(): void {\n this.stopKeepAlive();\n\n this.keepAliveTimer = setInterval(() => {\n if (this._connected && this.wsManager && !this._suspended) {\n try {\n this.wsManager.send(JSON.stringify({ type: 'KeepAlive' }));\n this.log('Sent KeepAlive');\n } catch {\n this.log('Failed to send KeepAlive');\n }\n }\n }, KEEPALIVE_INTERVAL_MS);\n }\n\n /** Stop the KeepAlive heartbeat. */\n private stopKeepAlive(): void {\n if (this.keepAliveTimer !== null) {\n clearInterval(this.keepAliveTimer);\n this.keepAliveTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // Subscriber notification\n // -----------------------------------------------------------------------\n\n /**\n * Emit a transcript event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitTranscript(event: STTTranscriptEvent): void {\n for (const cb of this.transcriptCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // URL building\n // -----------------------------------------------------------------------\n\n /** Build the Deepgram streaming endpoint URL with query parameters. */\n private buildUrl(): string {\n // NOTE: API key in WebSocket URL is inherent to Deepgram's WS protocol.\n // This is a known limitation — keys should only be session-scoped tokens.\n const params = new URLSearchParams({\n model: this.model,\n language: this.language,\n punctuate: 'true',\n interim_results: 'true',\n endpointing: '300',\n token: this.apiKey,\n });\n\n return `wss://api.deepgram.com/v1/listen?${params.toString()}`;\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n this.stopKeepAlive();\n }\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – ElevenLabs Real-Time Speech-to-Text Adapter\n// ---------------------------------------------------------------------------\n//\n// Streams microphone audio to ElevenLabs over a WebSocket using JSON messages\n// with base64-encoded PCM audio. Emits interim / final transcript events.\n//\n// Protocol:\n// - Send: { type: 'input_audio_chunk', audio: <base64>, sample_rate: 16000 }\n// - Receive: { type: 'partial_transcript', result: { text, confidence } }\n// { type: 'committed_transcript', result: { text, confidence } }\n// - Close: send { type: 'commit_audio' } before closing socket\n// ---------------------------------------------------------------------------\n\nimport { WebSocketManager } from './websocket-manager.js';\nimport type { STTTranscriptEvent } from '../types/index.js';\n\n// Re-export the shared type for consumers that only import from this module\nexport type { STTTranscriptEvent };\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:ElevenLabs-STT]';\n\nconst ELEVENLABS_STT_ENDPOINT =\n 'wss://api.elevenlabs.io/v1/speech-to-text/realtime';\n\nconst DEFAULT_LANGUAGE = 'en';\nconst INACTIVITY_TIMEOUT_S = 30;\nconst SAMPLE_RATE = 16_000;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ElevenLabsSTTOptions {\n apiKey: string;\n language?: string;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert Float32Array PCM samples (range -1..1) to Int16Array (linear16).\n */\nfunction float32ToInt16(float32: Float32Array): Int16Array {\n const int16 = new Int16Array(float32.length);\n for (let i = 0; i < float32.length; i++) {\n const s = Math.max(-1, Math.min(1, float32[i]!));\n int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n return int16;\n}\n\n/**\n * Encode an Int16Array as a base64 string.\n * Uses chunked encoding to avoid stack overflow on large buffers.\n */\nfunction int16ToBase64(int16: Int16Array): string {\n const bytes = new Uint8Array(int16.buffer);\n // Replace character-by-character loop with chunked encoding\n const CHUNK_SIZE = 8192;\n let binary = '';\n for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {\n const chunk = bytes.subarray(i, i + CHUNK_SIZE);\n binary += String.fromCharCode(...chunk);\n }\n return btoa(binary);\n}\n\n// ---------------------------------------------------------------------------\n// ElevenLabsSTT\n// ---------------------------------------------------------------------------\n\nexport class ElevenLabsSTT {\n // ---- Configuration -------------------------------------------------------\n\n private readonly apiKey: string;\n private readonly language: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state ------------------------------------------------------\n\n private wsManager: WebSocketManager | null = null;\n private _connected = false;\n private _suspended = false;\n\n /** Registered transcript callbacks. */\n private readonly transcriptCallbacks: Set<(event: STTTranscriptEvent) => void> =\n new Set();\n\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(options: ElevenLabsSTTOptions) {\n this.apiKey = options.apiKey;\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.debugEnabled = options.debug ?? false;\n\n this.log('ElevenLabsSTT created', { language: this.language });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Whether the WebSocket is currently connected and ready. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Open a WebSocket connection to ElevenLabs' real-time STT endpoint.\n *\n * Resolves once the connection is established and the socket is ready to\n * receive audio frames. Rejects if the connection cannot be established.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n if (typeof WebSocket === 'undefined') {\n this.log('WebSocket API not available (SSR?) — cannot connect');\n return;\n }\n\n const url = this.buildUrl();\n this.log('Connecting to', url.replace(this.apiKey, '***'));\n\n this.wsManager = new WebSocketManager({\n url,\n protocols: [],\n debug: this.debugEnabled,\n label: 'ElevenLabs-STT',\n });\n\n this.wsManager.onOpen(() => {\n this._connected = true;\n this.log('Connected');\n });\n this.wsManager.onMessage((event: MessageEvent) => {\n this.handleMessage(event);\n });\n this.wsManager.onClose((code: number, reason: string) => {\n this.log('Connection closed', { code, reason });\n this.cleanup();\n });\n this.wsManager.onError((event: Event) => {\n this.log('WebSocket error', event);\n });\n\n return this.wsManager.connect();\n }\n\n /**\n * Send audio data to ElevenLabs for transcription.\n *\n * Accepts either `Float32Array` (Web Audio API output) or `Int16Array`\n * (already encoded as linear16). Float32 data is automatically converted\n * to Int16 before encoding. Audio is sent as a base64-encoded JSON message.\n */\n sendAudio(audioData: Float32Array | Int16Array): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n return;\n }\n\n const int16 =\n audioData instanceof Float32Array ? float32ToInt16(audioData) : audioData;\n\n const base64 = int16ToBase64(int16);\n\n this.wsManager.send(\n JSON.stringify({\n type: 'input_audio_chunk',\n audio: base64,\n sample_rate: SAMPLE_RATE,\n }),\n );\n }\n\n /**\n * Register a callback to receive transcript events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onTranscript(callback: (event: STTTranscriptEvent) => void): () => void {\n this.transcriptCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.transcriptCallbacks.delete(callback);\n };\n }\n\n /**\n * Gracefully close the connection.\n *\n * Sends a `commit_audio` message so ElevenLabs can finalise any pending\n * transcription before the socket is torn down.\n */\n close(): void {\n if (!this._connected || !this.wsManager) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Sending commit_audio and closing');\n\n try {\n this.wsManager.send(JSON.stringify({ type: 'commit_audio' }));\n } catch {\n // Socket may already be closing — ignore.\n }\n\n this.wsManager.close();\n this.cleanup();\n }\n\n /** Force-destroy the connection without a graceful handshake. */\n destroy(): void {\n this.log('Destroying');\n\n if (this.wsManager) {\n this.wsManager.destroy();\n this.wsManager = null;\n }\n\n this.cleanup();\n this.transcriptCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Marks the adapter as suspended so that incoming `sendAudio` calls are\n * silently dropped. The WebSocket itself is left open.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this.log('Resumed');\n }\n\n // -------------------------------------------------------------------------\n // Message handling\n // -------------------------------------------------------------------------\n\n /**\n * Parse incoming ElevenLabs JSON messages and emit transcript events.\n *\n * ElevenLabs sends two transcript message types:\n * - `partial_transcript`: interim result, `isFinal = false`\n * - `committed_transcript`: final result, `isFinal = true`\n */\n private handleMessage(event: MessageEvent): void {\n if (typeof event.data !== 'string') {\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n this.log('Failed to parse message', event.data);\n return;\n }\n\n const type = parsed['type'] as string | undefined;\n\n if (type === 'committed_transcript' || type === 'partial_transcript') {\n this.handleTranscriptMessage(parsed, type === 'committed_transcript');\n } else {\n this.log('Received message', type, parsed);\n }\n }\n\n /**\n * Extract transcript data from a transcript message and notify subscribers.\n */\n private handleTranscriptMessage(\n parsed: Record<string, unknown>,\n isFinal: boolean,\n ): void {\n const result = parsed['result'] as\n | { text?: string; confidence?: number }\n | undefined;\n\n const text = result?.text ?? '';\n const confidence = result?.confidence ?? 0;\n\n if (text.trim() === '') {\n return;\n }\n\n const transcriptEvent: STTTranscriptEvent = {\n text,\n isFinal,\n confidence,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final transcript:' : 'Interim transcript:',\n text,\n `(${(confidence * 100).toFixed(1)}%)`,\n );\n\n this.emitTranscript(transcriptEvent);\n }\n\n // -------------------------------------------------------------------------\n // Subscriber notification\n // -------------------------------------------------------------------------\n\n /**\n * Emit a transcript event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitTranscript(event: STTTranscriptEvent): void {\n for (const cb of this.transcriptCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // URL building\n // -------------------------------------------------------------------------\n\n /** Build the ElevenLabs streaming STT endpoint URL with auth query params. */\n private buildUrl(): string {\n const params = new URLSearchParams({\n xi_api_key: this.apiKey,\n language: this.language,\n inactivity_timeout: String(INACTIVITY_TIMEOUT_S),\n });\n\n return `${ELEVENLABS_STT_ENDPOINT}?${params.toString()}`;\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n }\n\n // -------------------------------------------------------------------------\n // Logging\n // -------------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – ElevenLabs Real-Time Text-to-Speech Adapter\n// ---------------------------------------------------------------------------\n//\n// Streams text to ElevenLabs over a WebSocket and receives audio chunks in\n// real time. Designed for browser use; all browser-only APIs are guarded\n// behind `typeof window` checks so the module is safe to import at build\n// time in SSR environments.\n// ---------------------------------------------------------------------------\n\nimport { WebSocketManager } from './websocket-manager.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:TTS]';\n\n/** Default ElevenLabs voice ID (Rachel). */\nconst DEFAULT_VOICE_ID = '21m00Tcm4TlvDq8ikWAM';\n\n/** Default model — ElevenLabs Flash v2.5 for lowest latency. */\nconst DEFAULT_MODEL_ID = 'eleven_flash_v2_5';\n\n/** Default voice stability setting (0–1). */\nconst DEFAULT_STABILITY = 0.5;\n\n/** Default similarity boost setting (0–1). */\nconst DEFAULT_SIMILARITY_BOOST = 0.75;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ElevenLabsTTSOptions {\n apiKey: string;\n voiceId?: string;\n modelId?: string;\n debug?: boolean;\n}\n\nexport interface TTSAudioEvent {\n audio: ArrayBuffer;\n /** Whether this is the final chunk for the current utterance. */\n isFinal: boolean;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Decode a base64-encoded string into an `ArrayBuffer`.\n *\n * Uses the native `atob` function available in browsers. In SSR contexts\n * the adapter will never reach this code path because `connect()` is\n * guarded by a WebSocket availability check.\n */\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = atob(base64);\n const length = binaryString.length;\n const bytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n// ---------------------------------------------------------------------------\n// ElevenLabsTTS\n// ---------------------------------------------------------------------------\n\nexport class ElevenLabsTTS {\n // ---- Configuration ------------------------------------------------------\n\n private readonly apiKey: string;\n private readonly voiceId: string;\n private readonly modelId: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state -----------------------------------------------------\n\n private wsManager: WebSocketManager | null = null;\n private _connected = false;\n private _suspended = false;\n\n /**\n * Whether the BOS (beginning-of-stream) handshake has been sent for the\n * current WebSocket session. ElevenLabs requires the first message to\n * contain voice settings and the API key before any text chunks.\n */\n private bosSent = false;\n\n /** Registered audio-event callbacks. */\n private readonly audioCallbacks: Set<(event: TTSAudioEvent) => void> =\n new Set();\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options: ElevenLabsTTSOptions) {\n this.apiKey = options.apiKey;\n this.voiceId = options.voiceId ?? DEFAULT_VOICE_ID;\n this.modelId = options.modelId ?? DEFAULT_MODEL_ID;\n this.debugEnabled = options.debug ?? false;\n\n this.log('ElevenLabsTTS created', {\n voiceId: this.voiceId,\n modelId: this.modelId,\n });\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Whether the WebSocket is currently connected and ready. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Open a WebSocket connection to the ElevenLabs streaming TTS endpoint.\n *\n * Resolves once the connection is established and the BOS handshake has\n * been sent. Rejects if the connection cannot be established.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof WebSocket === 'undefined') {\n this.log('WebSocket API not available (SSR?) — cannot connect');\n return;\n }\n\n const url = this.buildUrl();\n this.log('Connecting to', url);\n\n this.wsManager = new WebSocketManager({\n url,\n protocols: [],\n debug: this.debugEnabled,\n label: 'ElevenLabs-TTS',\n });\n\n this.wsManager.onOpen(() => {\n this._connected = true;\n this.sendBOS();\n this.log('Connected and BOS sent');\n });\n this.wsManager.onMessage((event: MessageEvent) => {\n this.handleMessage(event);\n });\n this.wsManager.onClose((code: number, reason: string) => {\n this.log('Connection closed', { code, reason });\n this.cleanup();\n });\n this.wsManager.onError((event: Event) => {\n this.log('WebSocket error', event);\n });\n\n return this.wsManager.connect();\n }\n\n /**\n * Send text to be synthesised into speech.\n *\n * May be called multiple times to stream text incrementally. Each call\n * sends a text chunk with `try_trigger_generation: true` so ElevenLabs\n * can begin synthesising as soon as it has enough context.\n *\n * Call {@link flush} when the complete utterance has been sent.\n */\n speak(text: string): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n this.log('Cannot speak — not connected or suspended');\n return;\n }\n\n if (!text) {\n return;\n }\n\n const message = JSON.stringify({\n text,\n try_trigger_generation: true,\n });\n\n this.log('Sending text chunk:', text.slice(0, 80) + (text.length > 80 ? '...' : ''));\n this.wsManager.send(message);\n }\n\n /**\n * Signal the end of text input for the current utterance.\n *\n * Sends the EOS (end-of-stream) marker to ElevenLabs. The server will\n * flush any remaining audio and send a final chunk with `isFinal: true`.\n */\n flush(): void {\n if (!this._connected || !this.wsManager || this._suspended) {\n this.log('Cannot flush — not connected or suspended');\n return;\n }\n\n const message = JSON.stringify({ text: '' });\n this.log('Sending EOS (flush)');\n this.wsManager.send(message);\n }\n\n /**\n * Register a callback to receive audio output events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onAudio(callback: (event: TTSAudioEvent) => void): () => void {\n this.audioCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.audioCallbacks.delete(callback);\n };\n }\n\n /** Gracefully close the connection by sending EOS then closing. */\n close(): void {\n if (!this._connected || !this.wsManager) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Closing connection');\n\n // Send EOS to let the server finalise any pending audio.\n try {\n this.wsManager.send(JSON.stringify({ text: '' }));\n } catch {\n // Socket may already be closing — ignore.\n }\n\n this.wsManager.close();\n this.cleanup();\n }\n\n /** Force-destroy the connection without a graceful handshake. */\n destroy(): void {\n this.log('Destroying');\n\n if (this.wsManager) {\n this.wsManager.destroy();\n this.wsManager = null;\n }\n\n this.cleanup();\n this.audioCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Marks the adapter as suspended so that calls to `speak()` and `flush()`\n * are silently dropped. The WebSocket itself is left open; ElevenLabs\n * will close it after an inactivity timeout if the network went away.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`. If the underlying connection is\n * still alive, the adapter returns to normal operation. If the connection\n * was lost while suspended, callers should `close()` / `destroy()` and\n * create a new instance.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this.log('Resumed');\n }\n\n // -----------------------------------------------------------------------\n // BOS handshake\n // -----------------------------------------------------------------------\n\n /**\n * Send the BOS (beginning-of-stream) message.\n *\n * This must be the very first message on a new WebSocket session. It\n * carries the API key and voice settings.\n */\n private sendBOS(): void {\n if (!this.wsManager || this.bosSent) {\n return;\n }\n\n const bos = JSON.stringify({\n text: ' ',\n voice_settings: {\n stability: DEFAULT_STABILITY,\n similarity_boost: DEFAULT_SIMILARITY_BOOST,\n },\n xi_api_key: this.apiKey,\n });\n\n this.wsManager.send(bos);\n this.bosSent = true;\n this.log('BOS handshake sent');\n }\n\n // -----------------------------------------------------------------------\n // Message handling\n // -----------------------------------------------------------------------\n\n /**\n * Parse incoming ElevenLabs JSON messages and emit audio events.\n *\n * ElevenLabs sends messages with the following shape:\n * ```json\n * { \"audio\": \"base64encoded...\", \"isFinal\": false }\n * ```\n *\n * When `isFinal` is `true`, the server has finished synthesising the\n * current utterance (i.e. after EOS was sent).\n */\n private handleMessage(event: MessageEvent): void {\n // Binary messages are not expected from ElevenLabs — ignore.\n if (typeof event.data !== 'string') {\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n this.log('Failed to parse message', event.data);\n return;\n }\n\n // Handle error responses from ElevenLabs.\n if (parsed['error'] !== undefined) {\n this.log('ElevenLabs error:', parsed['error']);\n return;\n }\n\n // Handle alignment / metadata messages (no audio payload).\n if (parsed['audio'] === undefined || parsed['audio'] === null) {\n this.log('Non-audio message received', parsed);\n return;\n }\n\n const audioBase64 = parsed['audio'] as string;\n const isFinal = parsed['isFinal'] === true;\n\n // Skip empty audio chunks.\n if (!audioBase64 || audioBase64.length === 0) {\n if (isFinal) {\n // Emit a final event even without audio so consumers know the\n // utterance has ended.\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n }\n return;\n }\n\n let audioBuffer: ArrayBuffer;\n try {\n audioBuffer = base64ToArrayBuffer(audioBase64);\n } catch (err) {\n this.log('Failed to decode base64 audio', err);\n return;\n }\n\n const audioEvent: TTSAudioEvent = {\n audio: audioBuffer,\n isFinal,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final audio chunk:' : 'Audio chunk:',\n `${audioBuffer.byteLength} bytes`,\n );\n\n this.emitAudio(audioEvent);\n }\n\n // -----------------------------------------------------------------------\n // Subscriber notification\n // -----------------------------------------------------------------------\n\n /**\n * Emit an audio event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitAudio(event: TTSAudioEvent): void {\n for (const cb of this.audioCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Audio callback threw:', err);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // URL building\n // -----------------------------------------------------------------------\n\n /** Build the ElevenLabs streaming TTS endpoint URL. */\n private buildUrl(): string {\n const params = new URLSearchParams({\n model_id: this.modelId,\n });\n\n return `wss://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(this.voiceId)}/stream-input?${params.toString()}`;\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n this.bosSent = false;\n }\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Web Speech API Speech-to-Text Adapter\n// ---------------------------------------------------------------------------\n//\n// Browser-native SpeechRecognition adapter that requires no API keys or\n// external services. Uses the Web Speech API (SpeechRecognition) available\n// in most modern browsers. Designed as the zero-config default when no STT\n// provider is explicitly configured.\n//\n// SSR safe: all browser APIs are guarded behind `typeof window` checks so\n// the module is safe to import at build time in SSR environments.\n// ---------------------------------------------------------------------------\n\nimport type { STTTranscriptEvent } from '../types/index.js';\n\n// Re-export the shared type for consumers that only import from this module\nexport type { STTTranscriptEvent };\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:WebSpeech-STT]';\n\n/** Default language for speech recognition. */\nconst DEFAULT_LANGUAGE = 'en-US';\n\n// ---------------------------------------------------------------------------\n// Browser type declarations\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal type declarations for the Web Speech API SpeechRecognition\n * interface. These cover the subset used by this adapter. Full type\n * definitions are available in lib.dom.d.ts but may not be present in\n * all TS configurations.\n */\ninterface SpeechRecognitionEvent {\n readonly resultIndex: number;\n readonly results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionResultList {\n readonly length: number;\n item(index: number): SpeechRecognitionResult;\n [index: number]: SpeechRecognitionResult;\n}\n\ninterface SpeechRecognitionResult {\n readonly length: number;\n readonly isFinal: boolean;\n item(index: number): SpeechRecognitionAlternative;\n [index: number]: SpeechRecognitionAlternative;\n}\n\ninterface SpeechRecognitionAlternative {\n readonly transcript: string;\n readonly confidence: number;\n}\n\ninterface SpeechRecognitionErrorEvent {\n readonly error: string;\n readonly message: string;\n}\n\ninterface SpeechRecognitionInstance extends EventTarget {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n maxAlternatives: number;\n onresult: ((event: SpeechRecognitionEvent) => void) | null;\n onerror: ((event: SpeechRecognitionErrorEvent) => void) | null;\n onend: (() => void) | null;\n onstart: (() => void) | null;\n start(): void;\n stop(): void;\n abort(): void;\n}\n\ninterface SpeechRecognitionConstructor {\n new (): SpeechRecognitionInstance;\n}\n\n// Extend globalThis for webkit-prefixed SpeechRecognition\ndeclare global {\n // eslint-disable-next-line no-var\n var webkitSpeechRecognition: SpeechRecognitionConstructor | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface WebSpeechSTTOptions {\n language?: string;\n continuous?: boolean;\n interimResults?: boolean;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// WebSpeechSTT\n// ---------------------------------------------------------------------------\n\nexport class WebSpeechSTT {\n // ---- Configuration -------------------------------------------------------\n\n private readonly language: string;\n private readonly continuous: boolean;\n private readonly interimResultsEnabled: boolean;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state ------------------------------------------------------\n\n private recognition: SpeechRecognitionInstance | null = null;\n private _connected = false;\n private _suspended = false;\n\n /**\n * Whether we intentionally stopped recognition. Used to distinguish\n * between intentional stop and unexpected end (for auto-restart in\n * continuous mode).\n */\n private _intentionalStop = false;\n\n /** Registered transcript callbacks. */\n private readonly transcriptCallbacks: Set<(event: STTTranscriptEvent) => void> =\n new Set();\n\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(options: WebSpeechSTTOptions = {}) {\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.continuous = options.continuous ?? true;\n this.interimResultsEnabled = options.interimResults ?? true;\n this.debugEnabled = options.debug ?? false;\n\n this.log('WebSpeechSTT created', {\n language: this.language,\n continuous: this.continuous,\n interimResults: this.interimResultsEnabled,\n });\n }\n\n // -------------------------------------------------------------------------\n // Static methods\n // -------------------------------------------------------------------------\n\n /**\n * Check whether the Web Speech API SpeechRecognition is supported in the\n * current environment. Safe to call in SSR (returns false).\n */\n static isSupported(): boolean {\n if (typeof window === 'undefined') return false;\n return (\n typeof (window as unknown as Record<string, unknown>)['SpeechRecognition'] !== 'undefined' ||\n typeof globalThis.webkitSpeechRecognition !== 'undefined'\n );\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Whether recognition is currently active and connected. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Start speech recognition.\n *\n * Creates the SpeechRecognition instance and begins listening. Resolves\n * once the recognition session has started. Rejects if the API is not\n * supported or the browser denies permission.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined') {\n this.log('SSR environment detected — cannot connect');\n return;\n }\n\n const SpeechRecognitionClass = this.resolveSpeechRecognition();\n if (!SpeechRecognitionClass) {\n throw new Error(\n 'Web Speech API (SpeechRecognition) is not supported in this browser.',\n );\n }\n\n this.recognition = new SpeechRecognitionClass();\n this.recognition.lang = this.language;\n this.recognition.continuous = this.continuous;\n this.recognition.interimResults = this.interimResultsEnabled;\n this.recognition.maxAlternatives = 1;\n\n // Wire event handlers\n this.recognition.onstart = () => {\n this._connected = true;\n this._intentionalStop = false;\n this.log('Recognition started');\n };\n\n this.recognition.onresult = (event: SpeechRecognitionEvent) => {\n this.handleResult(event);\n };\n\n this.recognition.onerror = (event: SpeechRecognitionErrorEvent) => {\n this.handleError(event);\n };\n\n this.recognition.onend = () => {\n this.log('Recognition ended');\n const wasConnected = this._connected;\n this._connected = false;\n\n // In continuous mode, auto-restart if not intentionally stopped\n // and we were previously connected (not an error during startup).\n if (\n this.continuous &&\n !this._intentionalStop &&\n !this._suspended &&\n wasConnected\n ) {\n this.log('Auto-restarting continuous recognition');\n try {\n this.recognition?.start();\n } catch {\n this.log('Failed to auto-restart recognition');\n }\n }\n };\n\n // Start recognition\n return new Promise<void>((resolve, reject) => {\n const onStart = (): void => {\n cleanup();\n resolve();\n };\n\n const onError = (event: SpeechRecognitionErrorEvent): void => {\n cleanup();\n reject(new Error(`SpeechRecognition error: ${event.error} — ${event.message}`));\n };\n\n const cleanup = (): void => {\n if (this.recognition) {\n // Remove the one-shot listeners (keep the persistent ones)\n this.recognition.removeEventListener('start', onStart as unknown as EventListener);\n this.recognition.removeEventListener('error', onError as unknown as EventListener);\n }\n };\n\n this.recognition!.addEventListener('start', onStart as unknown as EventListener, { once: true });\n this.recognition!.addEventListener('error', onError as unknown as EventListener, { once: true });\n\n try {\n this.recognition!.start();\n } catch (err) {\n cleanup();\n reject(err);\n }\n });\n }\n\n /**\n * Send audio data. No-op for Web Speech API since it captures audio\n * directly from the microphone via the browser's internal pipeline.\n *\n * Provided for interface compatibility with WebSocket-based STT adapters\n * (DeepgramSTT, ElevenLabsSTT).\n */\n sendAudio(_audioData: Float32Array | Int16Array): void {\n // Web Speech API manages its own audio capture — nothing to do here.\n }\n\n /**\n * Register a callback to receive transcript events.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onTranscript(callback: (event: STTTranscriptEvent) => void): () => void {\n this.transcriptCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.transcriptCallbacks.delete(callback);\n };\n }\n\n /**\n * Gracefully stop recognition.\n *\n * Calls `stop()` on the SpeechRecognition instance which allows it to\n * deliver any pending final results before ending.\n */\n close(): void {\n if (!this.recognition) {\n this.log('Not connected — nothing to close');\n return;\n }\n\n this.log('Closing recognition');\n this._intentionalStop = true;\n\n try {\n this.recognition.stop();\n } catch {\n // Recognition may already be stopped\n }\n\n this.cleanup();\n }\n\n /** Force-destroy the recognition without waiting for pending results. */\n destroy(): void {\n this.log('Destroying');\n this._intentionalStop = true;\n\n if (this.recognition) {\n try {\n this.recognition.abort();\n } catch {\n // Recognition may already be stopped\n }\n this.recognition.onresult = null;\n this.recognition.onerror = null;\n this.recognition.onend = null;\n this.recognition.onstart = null;\n this.recognition = null;\n }\n\n this.cleanup();\n this.transcriptCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Stops recognition and marks the adapter as suspended so that auto-restart\n * does not trigger.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n this._intentionalStop = true;\n\n if (this.recognition && this._connected) {\n try {\n this.recognition.stop();\n } catch {\n // Ignore\n }\n }\n\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`. Restarts recognition if it was\n * running before suspension.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n this._intentionalStop = false;\n this.log('Resumed');\n\n // Restart recognition if we have an instance\n if (this.recognition && !this._connected) {\n try {\n this.recognition.start();\n } catch {\n this.log('Failed to restart recognition after resume');\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Result handling\n // -------------------------------------------------------------------------\n\n /**\n * Handle SpeechRecognition result events.\n *\n * The `results` property is a SpeechRecognitionResultList containing all\n * results accumulated during this recognition session. We only process\n * results from `resultIndex` onward to avoid re-emitting old results.\n */\n private handleResult(event: SpeechRecognitionEvent): void {\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n if (!result) continue;\n\n const alternative = result[0];\n if (!alternative) continue;\n\n const transcript = alternative.transcript;\n if (!transcript || transcript.trim() === '') continue;\n\n const isFinal = result.isFinal;\n // Web Speech API confidence is 0 for interim results in some browsers\n const confidence = alternative.confidence > 0 ? alternative.confidence : 0.85;\n\n const transcriptEvent: STTTranscriptEvent = {\n text: transcript,\n isFinal,\n confidence,\n timestamp: Date.now(),\n };\n\n this.log(\n isFinal ? 'Final transcript:' : 'Interim transcript:',\n transcript,\n `(${(confidence * 100).toFixed(1)}%)`,\n );\n\n this.emitTranscript(transcriptEvent);\n }\n }\n\n // -------------------------------------------------------------------------\n // Error handling\n // -------------------------------------------------------------------------\n\n /**\n * Handle SpeechRecognition errors.\n *\n * Some errors are recoverable (e.g. `no-speech`) and some are fatal\n * (e.g. `not-allowed`). For recoverable errors in continuous mode,\n * recognition will auto-restart via the `onend` handler.\n */\n private handleError(event: SpeechRecognitionErrorEvent): void {\n const errorType = event.error;\n\n this.log('Recognition error:', errorType, event.message);\n\n // 'no-speech' and 'aborted' are common non-fatal errors\n // In continuous mode, the onend handler will auto-restart\n if (errorType === 'no-speech' || errorType === 'aborted') {\n this.log('Non-fatal error — will recover');\n return;\n }\n\n // 'network' errors may be transient\n if (errorType === 'network') {\n this.log('Network error — recognition may auto-restart');\n return;\n }\n\n // Fatal errors: 'not-allowed', 'service-not-allowed', 'language-not-supported'\n // For these, mark as intentionally stopped to prevent auto-restart\n if (\n errorType === 'not-allowed' ||\n errorType === 'service-not-allowed' ||\n errorType === 'language-not-supported'\n ) {\n this._intentionalStop = true;\n this.log('Fatal recognition error — stopping');\n }\n }\n\n // -------------------------------------------------------------------------\n // Subscriber notification\n // -------------------------------------------------------------------------\n\n /**\n * Emit a transcript event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitTranscript(event: STTTranscriptEvent): void {\n for (const cb of this.transcriptCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // SpeechRecognition resolution\n // -------------------------------------------------------------------------\n\n /**\n * Resolve the SpeechRecognition constructor, with the webkit-prefixed\n * fallback. Returns null if not available.\n */\n private resolveSpeechRecognition(): SpeechRecognitionConstructor | null {\n if (typeof window === 'undefined') return null;\n\n const win = window as unknown as Record<string, unknown>;\n if (typeof win['SpeechRecognition'] !== 'undefined') {\n return win['SpeechRecognition'] as SpeechRecognitionConstructor;\n }\n if (typeof globalThis.webkitSpeechRecognition !== 'undefined') {\n return globalThis.webkitSpeechRecognition;\n }\n return null;\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n /** Reset internal state after disconnection. */\n private cleanup(): void {\n this._connected = false;\n }\n\n // -------------------------------------------------------------------------\n // Logging\n // -------------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Web Speech API Text-to-Speech Adapter\n// ---------------------------------------------------------------------------\n//\n// Browser-native SpeechSynthesis adapter that requires no API keys or\n// external services. Uses the Web Speech API (SpeechSynthesis) available\n// in all modern browsers. Designed as the zero-config default when no TTS\n// provider is explicitly configured.\n//\n// Unlike the WebSocket-based ElevenLabsTTS adapter, this adapter does not\n// stream audio chunks. Instead it uses the browser's built-in speech\n// synthesis engine and returns a Promise from speak() that resolves when\n// the utterance completes.\n//\n// SSR safe: all browser APIs are guarded behind `typeof window` checks so\n// the module is safe to import at build time in SSR environments.\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:WebSpeech-TTS]';\n\n/** Default speech rate (1.0 is normal speed). */\nconst DEFAULT_RATE = 1.0;\n\n/** Default pitch (1.0 is normal pitch). */\nconst DEFAULT_PITCH = 1.0;\n\n/** Default language. */\nconst DEFAULT_LANGUAGE = 'en-US';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface WebSpeechTTSOptions {\n voice?: string;\n rate?: number;\n pitch?: number;\n language?: string;\n debug?: boolean;\n}\n\n/**\n * Audio event compatible with the TTSAudioEvent shape used by\n * VoicePipeline for ElevenLabs TTS. Web Speech API does not produce\n * raw audio buffers, so we emit events with empty buffers and use\n * isFinal to signal utterance completion.\n */\nexport interface WebSpeechTTSAudioEvent {\n audio: ArrayBuffer;\n isFinal: boolean;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// WebSpeechTTS\n// ---------------------------------------------------------------------------\n\nexport class WebSpeechTTS {\n // ---- Configuration -------------------------------------------------------\n\n private readonly voiceName: string | null;\n private readonly rate: number;\n private readonly pitch: number;\n private readonly language: string;\n private readonly debugEnabled: boolean;\n\n // ---- Internal state ------------------------------------------------------\n\n private _connected = false;\n private _suspended = false;\n\n /** Cached voice object resolved from voiceName. */\n private _resolvedVoice: SpeechSynthesisVoice | null = null;\n\n /** Whether voices have been loaded (they load async in some browsers). */\n private _voicesLoaded = false;\n\n /** Registered audio-event callbacks. */\n private readonly audioCallbacks: Set<(event: WebSpeechTTSAudioEvent) => void> =\n new Set();\n\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(options: WebSpeechTTSOptions = {}) {\n this.voiceName = options.voice ?? null;\n this.rate = options.rate ?? DEFAULT_RATE;\n this.pitch = options.pitch ?? DEFAULT_PITCH;\n this.language = options.language ?? DEFAULT_LANGUAGE;\n this.debugEnabled = options.debug ?? false;\n\n this.log('WebSpeechTTS created', {\n voice: this.voiceName,\n rate: this.rate,\n pitch: this.pitch,\n language: this.language,\n });\n }\n\n // -------------------------------------------------------------------------\n // Static methods\n // -------------------------------------------------------------------------\n\n /**\n * Check whether the Web Speech API SpeechSynthesis is supported in the\n * current environment. Safe to call in SSR (returns false).\n */\n static isSupported(): boolean {\n if (typeof window === 'undefined') return false;\n return typeof window.speechSynthesis !== 'undefined';\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Whether the adapter is connected (ready for speech). */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Initialize the adapter.\n *\n * Loads available voices and resolves the requested voice name. Voice\n * loading is async in some browsers (notably Chrome) so we wait for\n * the `voiceschanged` event if needed.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n this.log('Already connected — skipping');\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n this.log('SpeechSynthesis not available — cannot connect');\n return;\n }\n\n // Load voices\n await this.loadVoices();\n\n // Resolve the requested voice\n if (this.voiceName) {\n this._resolvedVoice = this.findVoice(this.voiceName);\n if (this._resolvedVoice) {\n this.log('Resolved voice:', this._resolvedVoice.name);\n } else {\n this.log('Requested voice not found:', this.voiceName, '— using browser default');\n }\n }\n\n this._connected = true;\n this.log('Connected');\n }\n\n /**\n * Speak the given text using the browser's speech synthesis engine.\n *\n * Returns a Promise that resolves when the utterance completes or is\n * cancelled. Rejects if an error occurs during synthesis.\n *\n * Also emits audio events to registered callbacks for VoicePipeline\n * compatibility.\n */\n speak(text: string): void {\n if (!this._connected || this._suspended) {\n this.log('Cannot speak — not connected or suspended');\n return;\n }\n\n if (!text || !text.trim()) {\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n return;\n }\n\n const synth = window.speechSynthesis;\n const utterance = new SpeechSynthesisUtterance(text);\n\n // Apply settings\n utterance.lang = this.language;\n utterance.rate = this.rate;\n utterance.pitch = this.pitch;\n\n if (this._resolvedVoice) {\n utterance.voice = this._resolvedVoice;\n }\n\n\n\n utterance.onstart = () => {\n this.log('Utterance started:', text.slice(0, 80) + (text.length > 80 ? '...' : ''));\n // Emit a non-final event to signal playback has started\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: false,\n timestamp: Date.now(),\n });\n };\n\n utterance.onend = () => {\n \n this.log('Utterance ended');\n // Emit final event to signal completion\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n };\n\n utterance.onerror = (event: SpeechSynthesisErrorEvent) => {\n \n // 'canceled' is not a real error — it occurs when stop() is called\n if (event.error === 'canceled') {\n this.log('Utterance cancelled');\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n return;\n }\n this.log('Utterance error:', event.error);\n // Still emit final to unblock the pipeline\n this.emitAudio({\n audio: new ArrayBuffer(0),\n isFinal: true,\n timestamp: Date.now(),\n });\n };\n\n this.log('Speaking:', text.slice(0, 80) + (text.length > 80 ? '...' : ''));\n synth.speak(utterance);\n }\n\n /**\n * Flush / finalize the current utterance.\n *\n * No-op for Web Speech API since each speak() call is a complete\n * utterance. Provided for interface compatibility with ElevenLabsTTS.\n */\n flush(): void {\n // Web Speech API utterances are self-contained — nothing to flush.\n }\n\n /**\n * Register a callback to receive audio output events.\n *\n * For Web Speech API, these events have empty audio buffers and are\n * used to signal utterance start/end for VoicePipeline state management.\n *\n * @returns An unsubscribe function. Calling it more than once is safe.\n */\n onAudio(callback: (event: WebSpeechTTSAudioEvent) => void): () => void {\n this.audioCallbacks.add(callback);\n\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this.audioCallbacks.delete(callback);\n };\n }\n\n /** Stop current speech synthesis and cancel any queued utterances. */\n stop(): void {\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n return;\n }\n\n this.log('Stopping speech synthesis');\n window.speechSynthesis.cancel();\n\n }\n\n /** Gracefully close the adapter. */\n close(): void {\n this.log('Closing');\n this.stop();\n this.cleanup();\n }\n\n /** Force-destroy the adapter. */\n destroy(): void {\n this.log('Destroying');\n this.stop();\n this.cleanup();\n this.audioCallbacks.clear();\n }\n\n /**\n * Suspend the adapter (e.g. when the device goes offline).\n *\n * Pauses any active speech synthesis and marks the adapter as suspended.\n */\n suspend(): void {\n if (this._suspended) return;\n\n this._suspended = true;\n\n if (typeof window !== 'undefined' && typeof window.speechSynthesis !== 'undefined') {\n window.speechSynthesis.pause();\n }\n\n this.log('Suspended');\n }\n\n /**\n * Resume after a prior `suspend()`.\n */\n resume(): void {\n if (!this._suspended) return;\n\n this._suspended = false;\n\n if (typeof window !== 'undefined' && typeof window.speechSynthesis !== 'undefined') {\n window.speechSynthesis.resume();\n }\n\n this.log('Resumed');\n }\n\n // -------------------------------------------------------------------------\n // Voice loading\n // -------------------------------------------------------------------------\n\n /**\n * Load available voices from the browser.\n *\n * In Chrome and some other browsers, voices load asynchronously after\n * the page loads. We wait for the `voiceschanged` event with a timeout.\n */\n private async loadVoices(): Promise<void> {\n if (this._voicesLoaded) return;\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') return;\n\n const synth = window.speechSynthesis;\n let voices = synth.getVoices();\n\n if (voices.length > 0) {\n this._voicesLoaded = true;\n this.log('Voices loaded:', voices.length, 'available');\n return;\n }\n\n // Wait for voiceschanged event (Chrome loads voices async)\n await new Promise<void>((resolve) => {\n const onVoicesChanged = (): void => {\n synth.removeEventListener('voiceschanged', onVoicesChanged);\n clearTimeout(timeout);\n voices = synth.getVoices();\n this._voicesLoaded = true;\n this.log('Voices loaded (async):', voices.length, 'available');\n resolve();\n };\n\n // Timeout after 2 seconds — some browsers never fire voiceschanged\n const timeout = setTimeout(() => {\n synth.removeEventListener('voiceschanged', onVoicesChanged);\n this._voicesLoaded = true;\n this.log('Voices loading timed out — proceeding with defaults');\n resolve();\n }, 2_000);\n\n synth.addEventListener('voiceschanged', onVoicesChanged);\n });\n }\n\n /**\n * Find a voice by name (case-insensitive partial match).\n */\n private findVoice(name: string): SpeechSynthesisVoice | null {\n if (typeof window === 'undefined' || typeof window.speechSynthesis === 'undefined') {\n return null;\n }\n\n const voices = window.speechSynthesis.getVoices();\n const lowerName = name.toLowerCase();\n\n // Try exact match first\n const exact = voices.find((v) => v.name.toLowerCase() === lowerName);\n if (exact) return exact;\n\n // Try partial match\n const partial = voices.find((v) => v.name.toLowerCase().includes(lowerName));\n if (partial) return partial;\n\n // Try matching by language if voice name looks like a language code\n if (lowerName.includes('-') || lowerName.length <= 5) {\n const langMatch = voices.find((v) => v.lang.toLowerCase().startsWith(lowerName));\n if (langMatch) return langMatch;\n }\n\n return null;\n }\n\n // -------------------------------------------------------------------------\n // Subscriber notification\n // -------------------------------------------------------------------------\n\n /**\n * Emit an audio event to all registered callbacks.\n *\n * Errors thrown by individual callbacks are caught and logged so one\n * misbehaving subscriber does not prevent others from receiving the event.\n */\n private emitAudio(event: WebSpeechTTSAudioEvent): void {\n for (const cb of this.audioCallbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(LOG_PREFIX, 'Audio callback threw:', err);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n /** Reset internal state. */\n private cleanup(): void {\n this._connected = false;\n\n }\n\n // -------------------------------------------------------------------------\n // Logging\n // -------------------------------------------------------------------------\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Voice Pipeline (Phase 1b)\n// ---------------------------------------------------------------------------\n//\n// Orchestrates the full voice flow: Mic → VAD → STT → LLM → TTS → Speaker.\n//\n// Half-duplex state machine:\n// IDLE ──startListening()──► LISTENING\n// LISTENING ──final transcript──► PROCESSING\n// PROCESSING ──LLM response──► SPEAKING\n// SPEAKING ──TTS done──► IDLE\n// SPEAKING ──barge-in──► LISTENING\n// Any ──error──► ERROR\n// ERROR ──startListening()──► LISTENING\n//\n// SSR safe: all browser APIs are guarded behind `typeof window` checks.\n// AudioContext is only created in init() which must be called after a user\n// gesture to satisfy browser autoplay policies.\n// ---------------------------------------------------------------------------\n\nimport { EventBus, createEventBus } from '../bus/index.js';\nimport { BrowserSupportError, ErrorCodes, PermissionError } from '../errors/index.js';\nimport { DeepgramSTT } from './deepgram-stt.js';\nimport { ElevenLabsSTT } from './elevenlabs-stt.js';\nimport { ElevenLabsTTS } from './elevenlabs-tts.js';\nimport { WebSpeechSTT } from './web-speech-stt.js';\nimport { WebSpeechTTS } from './web-speech-tts.js';\n\nimport type { STTTranscriptEvent } from '../types/index.js';\nimport type { TTSAudioEvent } from './elevenlabs-tts.js';\nimport type { WebSpeechTTSAudioEvent } from './web-speech-tts.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Voice]';\n\n/** Jitter buffer: accumulate this many ms of audio before starting playback. */\nconst JITTER_BUFFER_MS = 150;\n\n/** Echo detection: discard transcript if >60% word overlap within this window. */\nconst ECHO_WINDOW_MS = 3_000;\n\n/** Echo detection: minimum word overlap ratio to classify as echo. */\nconst ECHO_OVERLAP_THRESHOLD = 0.6;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type VoiceState = 'idle' | 'listening' | 'processing' | 'speaking' | 'error';\n\nexport interface VoicePipelineOptions {\n sttConfig:\n | { provider: 'deepgram'; apiKey: string; model?: 'nova-2' | 'nova-3' }\n | { provider: 'elevenlabs'; apiKey: string; language?: string }\n | { provider: 'web-speech'; language?: string; continuous?: boolean; interimResults?: boolean };\n ttsConfig:\n | { provider: 'elevenlabs'; apiKey: string; voiceId?: string; modelId?: string }\n | { provider: 'web-speech'; voice?: string; rate?: number; pitch?: number; language?: string };\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Type declarations for environments with webkitAudioContext\n// ---------------------------------------------------------------------------\n\ndeclare global {\n // eslint-disable-next-line no-var\n var webkitAudioContext: typeof AudioContext | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internals: VAD interface (dynamically imported from @guidekit/vad)\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal interface mirroring the public API of SileroVAD from @guidekit/vad.\n * Declared here so we can type the dynamically imported instance without a\n * hard compile-time dependency.\n */\ninterface VADInstance {\n init(): Promise<void>;\n start(stream: MediaStream): void;\n stop(): void;\n destroy(): Promise<void>;\n onSpeechStart(cb: (event: { type: string; timestamp: number; probability?: number }) => void): () => void;\n onSpeechEnd(cb: (event: { type: string; timestamp: number; probability?: number }) => void): () => void;\n readonly isSpeaking: boolean;\n readonly isReady: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Internals: Echo tracker\n// ---------------------------------------------------------------------------\n\ninterface EchoRecord {\n words: Set<string>;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// VoicePipeline\n// ---------------------------------------------------------------------------\n\nexport class VoicePipeline {\n // ── Configuration ────────────────────────────────────────────────────\n private readonly _sttConfig: VoicePipelineOptions['sttConfig'];\n private readonly _ttsConfig: VoicePipelineOptions['ttsConfig'];\n private readonly _debug: boolean;\n\n // ── State ────────────────────────────────────────────────────────────\n private _state: VoiceState = 'idle';\n private _destroyed = false;\n\n // ── EventBus (internal, for voice-specific events) ──────────────────\n private readonly _bus: EventBus;\n\n // ── Audio pipeline components ────────────────────────────────────────\n private _audioContext: AudioContext | null = null;\n private _mediaStream: MediaStream | null = null;\n private _vad: VADInstance | null = null;\n private _stt: DeepgramSTT | ElevenLabsSTT | WebSpeechSTT | null = null;\n private _tts: ElevenLabsTTS | WebSpeechTTS | null = null;\n\n // ── Audio capture (mic → ScriptProcessor → STT) ─────────────────────\n private _micSourceNode: MediaStreamAudioSourceNode | null = null;\n private _captureProcessor: ScriptProcessorNode | null = null;\n private _isForwardingToSTT = false;\n\n // ── TTS playback ────────────────────────────────────────────────────\n private _playbackQueue: ArrayBuffer[] = [];\n private _jitterBufferTimer: ReturnType<typeof setTimeout> | null = null;\n private _isPlaybackStarted = false;\n private _nextPlaybackTime = 0;\n private _activeSourceNodes: Set<AudioBufferSourceNode> = new Set();\n private _lastScheduledSource: AudioBufferSourceNode | null = null;\n\n // ── Echo detection ──────────────────────────────────────────────────\n private _lastTTSEcho: EchoRecord | null = null;\n\n // ── Barge-in / abort ────────────────────────────────────────────────\n private _pendingLLMAbort: AbortController | null = null;\n\n // ── Subscriber management ───────────────────────────────────────────\n private readonly _stateChangeCallbacks: Set<(state: VoiceState, previous: VoiceState) => void> = new Set();\n private readonly _transcriptCallbacks: Set<(text: string, isFinal: boolean) => void> = new Set();\n\n // ── Cleanup handles ─────────────────────────────────────────────────\n private _unsubVADSpeechStart: (() => void) | null = null;\n private _unsubVADSpeechEnd: (() => void) | null = null;\n private _unsubSTTTranscript: (() => void) | null = null;\n private _unsubTTSAudio: (() => void) | null = null;\n\n // ────────────────────────────────────────────────────────────────────\n // Constructor\n // ────────────────────────────────────────────────────────────────────\n\n constructor(options: VoicePipelineOptions) {\n this._sttConfig = options.sttConfig;\n this._ttsConfig = options.ttsConfig;\n this._debug = options.debug ?? false;\n this._bus = createEventBus({ debug: this._debug });\n\n this._log('VoicePipeline created');\n }\n\n // ────────────────────────────────────────────────────────────────────\n // Public getters\n // ────────────────────────────────────────────────────────────────────\n\n /** Current pipeline state. */\n get state(): VoiceState {\n return this._state;\n }\n\n // ────────────────────────────────────────────────────────────────────\n // init() — call after user gesture\n // ────────────────────────────────────────────────────────────────────\n\n /**\n * Initialize AudioContext, VAD model, and STT/TTS connections.\n *\n * **Must be called in response to a user gesture** (click / tap) to\n * satisfy browser autoplay policies.\n */\n async init(): Promise<void> {\n if (this._destroyed) {\n this._log('Cannot init — pipeline is destroyed');\n return;\n }\n\n // SSR guard\n if (typeof window === 'undefined') {\n this._log('SSR environment detected — skipping init');\n return;\n }\n\n if (this._audioContext) {\n this._log('Already initialized — skipping');\n return;\n }\n\n this._log('Initializing...');\n\n // ── 1. Create AudioContext ───────────────────────────────────────\n const AudioContextClass = this._resolveAudioContext();\n if (!AudioContextClass) {\n throw new BrowserSupportError({\n code: ErrorCodes.BROWSER_NO_WEB_AUDIO,\n message: 'Web Audio API is not supported in this browser.',\n suggestion: 'Use a modern browser such as Chrome, Firefox, or Safari.',\n });\n }\n\n this._audioContext = new AudioContextClass();\n this._log('AudioContext created, sampleRate:', this._audioContext.sampleRate);\n\n // Pre-warm the AudioContext with a silent buffer to avoid first-play delay\n this._prewarmAudioContext(this._audioContext);\n\n // ── 2. Load VAD model ───────────────────────────────────────────\n try {\n const vadModule = await import('@guidekit/vad');\n const SileroVAD = vadModule.SileroVAD;\n this._vad = new SileroVAD({ debug: this._debug }) as unknown as VADInstance;\n await this._vad.init();\n this._log('VAD model loaded');\n } catch (err) {\n throw new BrowserSupportError({\n code: ErrorCodes.VAD_PACKAGE_MISSING,\n message:\n 'Failed to load @guidekit/vad. Ensure the package is installed.',\n suggestion:\n 'Run: npm install @guidekit/vad — or check that WASM is supported.',\n cause: err instanceof Error ? err : undefined,\n });\n }\n\n // ── 3. Create STT adapter ───────────────────────────────────────\n if (this._sttConfig.provider === 'deepgram') {\n this._stt = new DeepgramSTT({\n apiKey: this._sttConfig.apiKey,\n model: this._sttConfig.model,\n debug: this._debug,\n });\n } else if (this._sttConfig.provider === 'elevenlabs') {\n this._stt = new ElevenLabsSTT({\n apiKey: this._sttConfig.apiKey,\n language: this._sttConfig.language,\n debug: this._debug,\n });\n } else {\n // web-speech provider (browser-native, zero-config)\n this._stt = new WebSpeechSTT({\n language: this._sttConfig.language,\n continuous: this._sttConfig.continuous,\n interimResults: this._sttConfig.interimResults,\n debug: this._debug,\n });\n }\n\n // ── 4. Create TTS adapter ───────────────────────────────────────\n if (this._ttsConfig.provider === 'elevenlabs') {\n this._tts = new ElevenLabsTTS({\n apiKey: this._ttsConfig.apiKey,\n voiceId: this._ttsConfig.voiceId,\n modelId: 'modelId' in this._ttsConfig ? this._ttsConfig.modelId : undefined,\n debug: this._debug,\n });\n } else {\n // web-speech provider (browser-native, zero-config)\n this._tts = new WebSpeechTTS({\n voice: this._ttsConfig.voice,\n rate: this._ttsConfig.rate,\n pitch: this._ttsConfig.pitch,\n language: this._ttsConfig.language,\n debug: this._debug,\n });\n }\n\n this._log('Initialization complete');\n }\n\n // ────────────────────────────────────────────────────────────────────\n // startListening()\n // ────────────────────────────────────────────────────────────────────\n\n /**\n * Start listening: activate microphone, begin VAD + STT pipeline.\n *\n * Valid from: IDLE, ERROR, SPEAKING (barge-in path calls this internally).\n */\n async startListening(): Promise<void> {\n if (this._destroyed) return;\n\n if (!this._audioContext || !this._vad || !this._stt) {\n throw new BrowserSupportError({\n code: ErrorCodes.BROWSER_NO_WEB_AUDIO,\n message: 'Voice pipeline not initialized. Call init() first.',\n suggestion: 'Ensure init() is called after a user gesture before startListening().',\n });\n }\n\n // Resume AudioContext if it was suspended (browser policy)\n if (this._audioContext.state === 'suspended') {\n try {\n await this._audioContext.resume();\n } catch {\n // Ignore resume errors — the context may auto-resume on interaction\n }\n }\n\n // ── Get mic access ──────────────────────────────────────────────\n try {\n this._mediaStream = await navigator.mediaDevices.getUserMedia({\n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n },\n });\n this._log('Microphone access granted');\n } catch (err) {\n const isNotAllowed =\n err instanceof DOMException &&\n (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError');\n\n if (isNotAllowed) {\n const permErr = new PermissionError({\n code: ErrorCodes.PERMISSION_MIC_DENIED,\n message: 'Microphone permission was denied by the user.',\n suggestion: 'Allow microphone access in your browser settings and try again.',\n });\n this._setState('error');\n this._bus.emit('error', permErr);\n throw permErr;\n }\n\n const unavailErr = new PermissionError({\n code: ErrorCodes.PERMISSION_MIC_UNAVAILABLE,\n message: 'No microphone device available.',\n suggestion: 'Connect a microphone and try again.',\n cause: err instanceof Error ? err : undefined,\n });\n this._setState('error');\n this._bus.emit('error', unavailErr);\n throw unavailErr;\n }\n\n // ── Connect STT ─────────────────────────────────────────────────\n try {\n await this._stt.connect();\n this._log('STT connected');\n } catch (_err) {\n this._log('STT connection failed — degrading to text mode');\n this._bus.emit('voice:degraded', { reason: 'STT connection failed', fallback: 'text' });\n this._stopMicTracks();\n this._setState('error');\n return;\n }\n\n // ── Wire STT transcript events ──────────────────────────────────\n this._unsubSTTTranscript?.();\n this._unsubSTTTranscript = this._stt.onTranscript((event: STTTranscriptEvent) => {\n this._handleTranscript(event);\n });\n\n // ── Set up mic → ScriptProcessor for STT forwarding ─────────────\n this._setupMicCapture();\n\n // ── Start VAD on the MediaStream ────────────────────────────────\n this._unsubVADSpeechStart?.();\n this._unsubVADSpeechEnd?.();\n\n this._unsubVADSpeechStart = this._vad.onSpeechStart(() => {\n this._handleVADSpeechStart();\n });\n this._unsubVADSpeechEnd = this._vad.onSpeechEnd(() => {\n this._handleVADSpeechEnd();\n });\n\n this._vad.start(this._mediaStream);\n this._log('VAD started');\n\n // ── Transition state ────────────────────────────────────────────\n this._setState('listening');\n }\n\n // ────────────────────────────────────────────────────────────────────\n // stopListening()\n // ────────────────────────────────────────────────────────────────────\n\n /** Stop listening: deactivate mic and VAD. */\n stopListening(): void {\n if (this._destroyed) return;\n\n this._log('stopListening()');\n this._isForwardingToSTT = false;\n this._teardownMicCapture();\n this._vad?.stop();\n this._stt?.close();\n this._stopMicTracks();\n\n if (this._state === 'listening') {\n this._setState('idle');\n }\n }\n\n // ────────────────────────────────────────────────────────────────────\n // processTranscript()\n // ────────────────────────────────────────────────────────────────────\n\n /**\n * Process a transcript through an LLM callback and speak the response.\n *\n * @param text - The user's transcript text.\n * @param sendToLLM - Async callback that sends text to the LLM and returns the response.\n */\n async processTranscript(\n text: string,\n sendToLLM: (text: string) => Promise<string>,\n ): Promise<void> {\n if (this._destroyed) return;\n\n this._setState('processing');\n\n // Set up abort controller for barge-in\n this._pendingLLMAbort = new AbortController();\n const signal = this._pendingLLMAbort.signal;\n\n let response: string;\n try {\n response = await sendToLLM(text);\n\n // Check if aborted during LLM call (barge-in)\n if (signal.aborted) {\n this._log('LLM response discarded (barge-in during processing)');\n return;\n }\n } catch (err) {\n if (signal.aborted) {\n this._log('LLM call aborted (barge-in)');\n return;\n }\n this._log('LLM call failed:', err);\n this._setState('error');\n return;\n } finally {\n this._pendingLLMAbort = null;\n }\n\n // Speak the response\n if (response && response.trim()) {\n await this.speak(response);\n } else {\n this._setState('idle');\n }\n }\n\n // ────────────────────────────────────────────────────────────────────\n // speak()\n // ────────────────────────────────────────────────────────────────────\n\n /** Speak text via TTS (ElevenLabs or Web Speech API). */\n async speak(text: string): Promise<void> {\n if (this._destroyed || !text.trim()) return;\n\n // Web Speech TTS does not require AudioContext for playback\n const isWebSpeechTTS = this._tts instanceof WebSpeechTTS;\n if (!this._tts || (!this._audioContext && !isWebSpeechTTS)) {\n this._log('TTS or AudioContext not available — cannot speak');\n this._bus.emit('voice:degraded', { reason: 'TTS not available', fallback: 'text' });\n this._setState('idle');\n return;\n }\n\n this._setState('speaking');\n // Record echo info for later detection\n this._lastTTSEcho = {\n words: new Set(this._normalizeWords(text)),\n timestamp: Date.now(),\n };\n\n this._bus.emit('voice:tts-start', { utterance: text });\n\n // Connect TTS if needed\n try {\n if (!this._tts.isConnected) {\n await this._tts.connect();\n this._log('TTS connected');\n }\n } catch (_err) {\n this._log('TTS connection failed — degrading to text mode');\n this._bus.emit('voice:degraded', { reason: 'TTS connection failed', fallback: 'text' });\n this._bus.emit('voice:tts-end', { utterance: text, durationMs: 0 });\n this._setState('idle');\n return;\n }\n\n // Reset playback state\n this._playbackQueue = [];\n this._isPlaybackStarted = false;\n this._nextPlaybackTime = 0;\n this._jitterBufferTimer = null;\n\n // Wire TTS audio events\n this._unsubTTSAudio?.();\n const ttsStartTime = Date.now();\n\n await new Promise<void>((resolve) => {\n let resolved = false;\n const done = () => {\n if (resolved) return;\n resolved = true;\n this._unsubTTSAudio?.();\n this._unsubTTSAudio = null;\n\n const durationMs = Date.now() - ttsStartTime;\n this._bus.emit('voice:tts-end', { utterance: text, durationMs });\n\n // Only transition to idle if still in speaking state\n // (barge-in may have already changed state)\n if (this._state === 'speaking') {\n this._setState('idle');\n }\n resolve();\n };\n\n if (isWebSpeechTTS) {\n // Web Speech TTS: browser handles audio playback internally.\n // We only listen for start/end events to manage pipeline state.\n this._unsubTTSAudio = (this._tts as WebSpeechTTS).onAudio(\n (event: WebSpeechTTSAudioEvent) => {\n if (event.isFinal) {\n done();\n }\n },\n );\n (this._tts as WebSpeechTTS).speak(text);\n } else {\n // ElevenLabs TTS: audio arrives as chunks over WebSocket\n this._unsubTTSAudio = (this._tts as ElevenLabsTTS).onAudio(\n (event: TTSAudioEvent) => {\n this._handleTTSAudio(event, done);\n },\n );\n (this._tts as ElevenLabsTTS).speak(text);\n (this._tts as ElevenLabsTTS).flush();\n }\n });\n }\n\n // ────────────────────────────────────────────────────────────────────\n // stopSpeaking() — barge-in\n // ────────────────────────────────────────────────────────────────────\n\n /** Stop current TTS playback immediately (barge-in). */\n stopSpeaking(): void {\n if (this._destroyed) return;\n\n this._log('stopSpeaking() — barge-in');\n\n // Stop all active AudioBufferSourceNodes\n for (const node of this._activeSourceNodes) {\n try {\n node.stop();\n node.disconnect();\n } catch {\n // Node may already be stopped\n }\n }\n this._activeSourceNodes.clear();\n this._lastScheduledSource = null;\n\n // Clear jitter buffer\n if (this._jitterBufferTimer !== null) {\n clearTimeout(this._jitterBufferTimer);\n this._jitterBufferTimer = null;\n }\n this._playbackQueue = [];\n this._isPlaybackStarted = false;\n\n // Abort pending LLM request\n if (this._pendingLLMAbort) {\n this._pendingLLMAbort.abort();\n this._pendingLLMAbort = null;\n }\n\n // Stop Web Speech TTS playback or close ElevenLabs TTS connection\n if (this._tts instanceof WebSpeechTTS) {\n this._tts.stop();\n } else if (this._tts?.isConnected) {\n this._tts.close();\n }\n }\n\n // ────────────────────────────────────────────────────────────────────\n // onStateChange()\n // ────────────────────────────────────────────────────────────────────\n\n /** Subscribe to state changes. Returns an unsubscribe function. */\n onStateChange(callback: (state: VoiceState, previous: VoiceState) => void): () => void {\n this._stateChangeCallbacks.add(callback);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this._stateChangeCallbacks.delete(callback);\n };\n }\n\n // ────────────────────────────────────────────────────────────────────\n // onTranscript()\n // ────────────────────────────────────────────────────────────────────\n\n /** Subscribe to transcript events. Returns an unsubscribe function. */\n onTranscript(callback: (text: string, isFinal: boolean) => void): () => void {\n this._transcriptCallbacks.add(callback);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n this._transcriptCallbacks.delete(callback);\n };\n }\n\n // ────────────────────────────────────────────────────────────────────\n // destroy()\n // ────────────────────────────────────────────────────────────────────\n\n /** Destroy all resources held by the pipeline. */\n async destroy(): Promise<void> {\n if (this._destroyed) return;\n this._destroyed = true;\n this._log('Destroying...');\n\n // Stop everything\n this.stopSpeaking();\n this.stopListening();\n\n // Tear down subscriptions\n this._unsubVADSpeechStart?.();\n this._unsubVADSpeechEnd?.();\n this._unsubSTTTranscript?.();\n this._unsubTTSAudio?.();\n this._unsubVADSpeechStart = null;\n this._unsubVADSpeechEnd = null;\n this._unsubSTTTranscript = null;\n this._unsubTTSAudio = null;\n\n // Destroy subsystems\n if (this._vad) {\n try {\n await this._vad.destroy();\n } catch {\n // Ignore VAD destroy errors\n }\n this._vad = null;\n }\n\n if (this._stt) {\n this._stt.destroy();\n this._stt = null;\n }\n\n if (this._tts) {\n this._tts.destroy();\n this._tts = null;\n }\n\n // Close AudioContext\n if (this._audioContext) {\n try {\n await this._audioContext.close();\n } catch {\n // Ignore close errors\n }\n this._audioContext = null;\n }\n\n // Clean up mic tracks\n this._stopMicTracks();\n\n // Clear callbacks\n this._stateChangeCallbacks.clear();\n this._transcriptCallbacks.clear();\n this._bus.removeAll();\n\n this._log('Destroyed');\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: State machine\n // ════════════════════════════════════════════════════════════════════\n\n private _setState(next: VoiceState): void {\n const prev = this._state;\n if (prev === next) return;\n\n this._state = next;\n this._log(`State: ${prev} -> ${next}`);\n\n // Emit on internal bus\n this._bus.emit('voice:state-change', { from: prev, to: next });\n\n // Notify external subscribers\n for (const cb of this._stateChangeCallbacks) {\n try {\n cb(next, prev);\n } catch (err) {\n console.error(LOG_PREFIX, 'State change callback threw:', err);\n }\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: AudioContext helpers\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Resolve the AudioContext constructor, with Safari webkitAudioContext\n * fallback. Returns null if Web Audio is not available.\n */\n private _resolveAudioContext(): typeof AudioContext | null {\n if (typeof AudioContext !== 'undefined') {\n return AudioContext;\n }\n if (typeof globalThis.webkitAudioContext !== 'undefined') {\n return globalThis.webkitAudioContext;\n }\n return null;\n }\n\n /**\n * Pre-warm the AudioContext by playing a silent buffer.\n * This forces the context into the \"running\" state and avoids a\n * noticeable delay on the first real playback.\n */\n private _prewarmAudioContext(ctx: AudioContext): void {\n try {\n const buffer = ctx.createBuffer(1, 1, ctx.sampleRate);\n const source = ctx.createBufferSource();\n source.buffer = buffer;\n source.connect(ctx.destination);\n source.start(0);\n this._log('AudioContext pre-warmed');\n } catch {\n // Non-critical — ignore\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: Mic capture → STT forwarding\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Set up a ScriptProcessorNode to capture mic audio and forward it\n * to the STT adapter when `_isForwardingToSTT` is true.\n */\n private _setupMicCapture(): void {\n if (!this._audioContext || !this._mediaStream || !this._stt) return;\n\n this._micSourceNode = this._audioContext.createMediaStreamSource(this._mediaStream);\n\n // Buffer size of 4096 at 48 kHz ≈ 85 ms of audio per callback\n const bufferSize = 4096;\n this._captureProcessor = this._audioContext.createScriptProcessor(bufferSize, 1, 1);\n\n this._captureProcessor.onaudioprocess = (event: AudioProcessingEvent) => {\n if (!this._isForwardingToSTT || !this._stt) return;\n\n const inputData = event.inputBuffer.getChannelData(0);\n // DeepgramSTT.sendAudio accepts Float32Array and converts to Int16 internally\n this._stt.sendAudio(new Float32Array(inputData));\n };\n\n this._micSourceNode.connect(this._captureProcessor);\n // ScriptProcessorNode requires connection to destination to fire events\n this._captureProcessor.connect(this._audioContext.destination);\n this._log('Mic capture pipeline set up');\n }\n\n /** Tear down the mic capture ScriptProcessorNode. */\n private _teardownMicCapture(): void {\n if (this._captureProcessor) {\n try {\n this._captureProcessor.disconnect();\n } catch {\n // Ignore\n }\n this._captureProcessor.onaudioprocess = null;\n this._captureProcessor = null;\n }\n\n if (this._micSourceNode) {\n try {\n this._micSourceNode.disconnect();\n } catch {\n // Ignore\n }\n this._micSourceNode = null;\n }\n }\n\n /** Stop all tracks on the current MediaStream. */\n private _stopMicTracks(): void {\n if (this._mediaStream) {\n for (const track of this._mediaStream.getTracks()) {\n track.stop();\n }\n this._mediaStream = null;\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: VAD event handlers\n // ════════════════════════════════════════════════════════════════════\n\n private _handleVADSpeechStart(): void {\n this._log('VAD: speech-start, current state:', this._state);\n\n if (this._state === 'speaking') {\n // Barge-in: user is speaking while TTS is playing\n if (this._isEchoDetected()) {\n this._log('Echo detected — ignoring barge-in');\n return;\n }\n\n this._log('Barge-in detected');\n this.stopSpeaking();\n // Restart listening (we keep the mic stream alive)\n this._isForwardingToSTT = true;\n this._setState('listening');\n return;\n }\n\n if (this._state === 'listening') {\n // Start forwarding audio to STT\n this._isForwardingToSTT = true;\n this._log('Started forwarding audio to STT');\n }\n }\n\n private _handleVADSpeechEnd(): void {\n this._log('VAD: speech-end, current state:', this._state);\n\n if (this._state === 'listening') {\n // Stop forwarding to STT; we wait for a final transcript\n this._isForwardingToSTT = false;\n this._log('Stopped forwarding audio to STT');\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: STT transcript handler\n // ════════════════════════════════════════════════════════════════════\n\n private _handleTranscript(event: STTTranscriptEvent): void {\n const { text, isFinal } = event;\n\n if (!text || !text.trim()) return;\n\n // Echo detection: discard transcripts that match recent TTS output\n if (isFinal && this._isTranscriptEcho(text)) {\n this._log('Echo detected — discarding transcript:', text);\n return;\n }\n\n // Notify external transcript subscribers\n this._bus.emit('voice:transcript', {\n text,\n isFinal,\n confidence: event.confidence,\n });\n\n for (const cb of this._transcriptCallbacks) {\n try {\n cb(text, isFinal);\n } catch (err) {\n console.error(LOG_PREFIX, 'Transcript callback threw:', err);\n }\n }\n\n // On final transcript while listening → transition to PROCESSING\n // (The actual LLM call is driven by the consumer calling processTranscript)\n if (isFinal && this._state === 'listening') {\n this._log('Final transcript received:', text);\n this._isForwardingToSTT = false;\n // Note: we do NOT transition to PROCESSING here. The consumer is\n // responsible for calling processTranscript() which sets the state.\n // This keeps the pipeline composable — consumers can decide to\n // ignore transcripts, batch them, etc.\n }\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: TTS audio playback\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Handle an audio chunk from ElevenLabs TTS.\n *\n * Implements a jitter buffer: we accumulate audio for JITTER_BUFFER_MS\n * before starting playback to smooth out network jitter.\n */\n private _handleTTSAudio(event: TTSAudioEvent, onDone: () => void): void {\n if (this._state !== 'speaking') {\n // State changed (e.g. barge-in) — discard audio\n return;\n }\n\n if (event.isFinal && event.audio.byteLength === 0) {\n // Final marker with no audio — flush whatever we have and finish\n this._flushJitterBuffer(onDone);\n return;\n }\n\n if (event.audio.byteLength === 0) return;\n\n // Add to jitter buffer queue\n this._playbackQueue.push(event.audio);\n\n if (!this._isPlaybackStarted) {\n // Start the jitter buffer timer on the first chunk\n if (this._jitterBufferTimer === null) {\n this._jitterBufferTimer = setTimeout(() => {\n this._jitterBufferTimer = null;\n this._startPlayback(event.isFinal ? onDone : undefined);\n }, JITTER_BUFFER_MS);\n }\n } else {\n // Playback already started — decode and schedule immediately\n this._decodeAndSchedule(event.audio, event.isFinal ? onDone : undefined);\n }\n\n if (event.isFinal) {\n // Clear the jitter buffer timer since we got the final chunk\n if (this._jitterBufferTimer !== null) {\n clearTimeout(this._jitterBufferTimer);\n this._jitterBufferTimer = null;\n this._startPlayback(onDone);\n }\n }\n }\n\n /** Flush the jitter buffer and start playback. */\n private _flushJitterBuffer(onDone: () => void): void {\n if (this._jitterBufferTimer !== null) {\n clearTimeout(this._jitterBufferTimer);\n this._jitterBufferTimer = null;\n }\n\n if (this._playbackQueue.length > 0) {\n this._startPlayback(onDone);\n } else {\n // No audio to play — done immediately\n onDone();\n }\n }\n\n /**\n * Begin playback: decode all queued chunks and schedule them.\n * If `onDone` is provided, it is called when the last chunk finishes playing.\n */\n private _startPlayback(onDone?: () => void): void {\n if (this._isPlaybackStarted) {\n // Already started — just flush the remaining queue\n if (this._playbackQueue.length > 0) {\n const remaining = this._playbackQueue.splice(0);\n const lastIdx = remaining.length - 1;\n for (let i = 0; i < remaining.length; i++) {\n this._decodeAndSchedule(\n remaining[i]!,\n i === lastIdx ? onDone : undefined,\n );\n }\n } else if (onDone) {\n // If there are active sources wait for the last one, otherwise call done now\n if (this._lastScheduledSource) {\n const prevOnEnded = this._lastScheduledSource.onended;\n this._lastScheduledSource.onended = () => {\n if (typeof prevOnEnded === 'function') {\n prevOnEnded.call(this._lastScheduledSource!, new Event('ended'));\n }\n onDone();\n };\n } else {\n onDone();\n }\n }\n return;\n }\n\n this._isPlaybackStarted = true;\n this._nextPlaybackTime = 0;\n\n const queued = this._playbackQueue.splice(0);\n const lastIdx = queued.length - 1;\n\n for (let i = 0; i < queued.length; i++) {\n this._decodeAndSchedule(\n queued[i]!,\n i === lastIdx ? onDone : undefined,\n );\n }\n }\n\n /**\n * Decode an audio chunk (mp3 from ElevenLabs) and schedule it for\n * sequential playback via AudioBufferSourceNode.\n */\n private _decodeAndSchedule(audioData: ArrayBuffer, onDone?: () => void): void {\n // Guard against multiple invocations of onDone. This can happen when\n // multiple pending decode operations reference the same callback, or\n // when both the success and error paths fire (e.g. state change\n // during decode).\n let onDoneCalled = false;\n const safeOnDone = onDone\n ? () => {\n if (onDoneCalled) return;\n onDoneCalled = true;\n onDone();\n }\n : undefined;\n\n if (!this._audioContext || this._state !== 'speaking') {\n safeOnDone?.();\n return;\n }\n\n const ctx = this._audioContext;\n\n // decodeAudioData needs a copy because it detaches the ArrayBuffer\n const copy = audioData.slice(0);\n\n ctx.decodeAudioData(\n copy,\n (decodedBuffer) => {\n if (this._state !== 'speaking' || !this._audioContext) {\n safeOnDone?.();\n return;\n }\n\n const source = ctx.createBufferSource();\n source.buffer = decodedBuffer;\n source.connect(ctx.destination);\n\n // Track active sources for barge-in cleanup\n this._activeSourceNodes.add(source);\n this._lastScheduledSource = source;\n\n source.onended = () => {\n this._activeSourceNodes.delete(source);\n if (this._lastScheduledSource === source) {\n this._lastScheduledSource = null;\n }\n\n // If this was the last source and we have onDone, call it\n if (safeOnDone) {\n safeOnDone();\n }\n };\n\n // Schedule playback sequentially\n const now = ctx.currentTime;\n const startTime = Math.max(now, this._nextPlaybackTime);\n source.start(startTime);\n this._nextPlaybackTime = startTime + decodedBuffer.duration;\n\n this._log(\n 'Scheduled audio chunk:',\n decodedBuffer.duration.toFixed(3) + 's',\n 'at',\n startTime.toFixed(3),\n );\n },\n (err) => {\n this._log('Failed to decode audio chunk:', err);\n safeOnDone?.();\n },\n );\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: Echo detection\n // ════════════════════════════════════════════════════════════════════\n\n /**\n * Check if VAD speech-start during SPEAKING state is likely echo from\n * the speaker playing TTS audio rather than genuine user speech.\n *\n * Simple heuristic: if we are still within the echo window of a recent\n * TTS utterance, treat it as potential echo.\n */\n private _isEchoDetected(): boolean {\n if (!this._lastTTSEcho) return false;\n const elapsed = Date.now() - this._lastTTSEcho.timestamp;\n // During active TTS playback, suppress barge-in only if within window\n // and the speaker is still audibly outputting. We use the echo window\n // as a conservative guard.\n return elapsed < ECHO_WINDOW_MS;\n }\n\n /**\n * Check if a transcript is an echo of recent TTS output.\n *\n * Uses word overlap: if intersection of words > 60% of max set size\n * and the transcript arrived within the echo window, discard it.\n */\n private _isTranscriptEcho(transcript: string): boolean {\n if (!this._lastTTSEcho) return false;\n\n const elapsed = Date.now() - this._lastTTSEcho.timestamp;\n if (elapsed > ECHO_WINDOW_MS) return false;\n\n const transcriptWords = new Set(this._normalizeWords(transcript));\n const ttsWords = this._lastTTSEcho.words;\n\n if (transcriptWords.size === 0 || ttsWords.size === 0) return false;\n\n // Compute intersection\n let intersectionCount = 0;\n for (const word of transcriptWords) {\n if (ttsWords.has(word)) {\n intersectionCount++;\n }\n }\n\n const maxSize = Math.max(transcriptWords.size, ttsWords.size);\n const overlap = intersectionCount / maxSize;\n\n this._log(\n 'Echo check: overlap =',\n (overlap * 100).toFixed(1) + '%,',\n 'threshold =',\n (ECHO_OVERLAP_THRESHOLD * 100).toFixed(1) + '%',\n );\n\n return overlap >= ECHO_OVERLAP_THRESHOLD;\n }\n\n /**\n * Normalize text into a set of lowercase words, stripping punctuation.\n */\n private _normalizeWords(text: string): string[] {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 0);\n }\n\n // ════════════════════════════════════════════════════════════════════\n // PRIVATE: Logging\n // ════════════════════════════════════════════════════════════════════\n\n private _log(...args: unknown[]): void {\n if (this._debug) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport { WebSocketManager } from './websocket-manager.js';\nexport type { WSState, WebSocketManagerOptions } from './websocket-manager.js';\nexport { DeepgramSTT } from './deepgram-stt.js';\nexport type { DeepgramSTTOptions, STTTranscriptEvent } from './deepgram-stt.js';\nexport { ElevenLabsSTT } from './elevenlabs-stt.js';\nexport type { ElevenLabsSTTOptions } from './elevenlabs-stt.js';\nexport { ElevenLabsTTS } from './elevenlabs-tts.js';\nexport type { ElevenLabsTTSOptions, TTSAudioEvent } from './elevenlabs-tts.js';\nexport { WebSpeechSTT } from './web-speech-stt.js';\nexport type { WebSpeechSTTOptions } from './web-speech-stt.js';\nexport { WebSpeechTTS } from './web-speech-tts.js';\nexport type { WebSpeechTTSOptions, WebSpeechTTSAudioEvent } from './web-speech-tts.js';\n","/**\n * @module @guidekit/core/visual\n *\n * Visual Guidance System for the GuideKit SDK.\n * Provides spotlight overlays, tooltips, smooth scrolling, and guided tours\n * to visually direct users to page elements identified by the LLM.\n *\n * Key design decisions:\n * - Overlay lives on document.body (NOT Shadow DOM) so it can cover the entire page.\n * - Uses box-shadow cutout technique for the spotlight effect.\n * - Tracks element position via ResizeObserver + scroll listeners (NOT rAF polling).\n * - All text is set via textContent (never innerHTML) to prevent XSS.\n * - SSR-safe: every browser API is guarded behind typeof checks.\n * - Compositor-only animations (transform, opacity) for smooth 60fps.\n * - Respects prefers-reduced-motion.\n */\n\nimport { DOMScanner } from '../dom/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Visual]';\nconst DEFAULT_OVERLAY_COLOR = 'rgba(0, 0, 0, 0.5)';\nconst DEFAULT_SPOTLIGHT_COLOR = '#4a9eed';\nconst DEFAULT_ANIMATION_DURATION = 300;\nconst DEFAULT_SPOTLIGHT_PADDING = 8;\nconst AUTO_TOUR_INTERVAL_MS = 5000;\nconst TOOLTIP_ARROW_SIZE = 8;\nconst TOOLTIP_MARGIN = 12;\nconst OVERLAY_Z_INDEX = 999998;\nconst TOOLTIP_Z_INDEX = 999999;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface VisualGuidanceOptions {\n /** Color of the spotlight overlay. Default: 'rgba(0, 0, 0, 0.5)' */\n overlayColor?: string;\n /** Color of the spotlight cutout border. Default: '#4a9eed' */\n spotlightColor?: string;\n /** Animation duration in ms. Default: 300 */\n animationDuration?: number;\n /** Padding around the highlighted element in px. Default: 8 */\n spotlightPadding?: number;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n}\n\nexport interface TooltipOptions {\n text: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n}\n\nexport interface SpotlightState {\n isActive: boolean;\n selector: string | null;\n sectionId: string | null;\n tooltip: string | null;\n}\n\ntype TooltipPosition = 'top' | 'bottom' | 'left' | 'right';\n\n// ---------------------------------------------------------------------------\n// Utility: Scrollable ancestor detection\n// ---------------------------------------------------------------------------\n\n/**\n * Walk up the DOM tree and collect every ancestor that has an overflow\n * style allowing scroll (auto or scroll).\n */\nfunction getScrollableAncestors(element: Element): Element[] {\n if (typeof getComputedStyle === 'undefined') return [];\n\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n while (parent) {\n const style = getComputedStyle(parent);\n const overflow = style.overflow + style.overflowX + style.overflowY;\n if (/(auto|scroll)/.test(overflow)) {\n ancestors.push(parent);\n }\n parent = parent.parentElement;\n }\n return ancestors;\n}\n\n/**\n * Detect whether the user prefers reduced motion.\n */\nfunction prefersReducedMotion(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n// ---------------------------------------------------------------------------\n// VisualGuidance\n// ---------------------------------------------------------------------------\n\nexport class VisualGuidance {\n // Configuration\n private readonly overlayColor: string;\n private readonly spotlightColor: string;\n private readonly animationDuration: number;\n private readonly spotlightPadding: number;\n private readonly debug: boolean;\n\n // DOM elements (created lazily)\n private overlayEl: HTMLDivElement | null = null;\n private spotlightEl: HTMLDivElement | null = null;\n private tooltipEl: HTMLDivElement | null = null;\n private liveRegionEl: HTMLDivElement | null = null;\n\n // State\n private _state: SpotlightState = {\n isActive: false,\n selector: null,\n sectionId: null,\n tooltip: null,\n };\n\n // Tracking infrastructure\n private resizeObserver: ResizeObserver | null = null;\n private scrollListenerCleanups: Array<() => void> = [];\n private currentTargetElement: Element | null = null;\n\n // Tour state\n private tourSectionIds: string[] = [];\n private tourCurrentStep = -1;\n private tourMode: 'auto' | 'manual' = 'manual';\n private tourAutoTimer: ReturnType<typeof setTimeout> | null = null;\n private tourPausedByInteraction = false;\n\n // Subscribers\n private spotlightChangeCallbacks: Array<(state: SpotlightState) => void> = [];\n private tourStepCallbacks: Array<(step: number, total: number, sectionId: string) => void> = [];\n\n // DOMScanner for resolving sectionIds\n private domScanner: DOMScanner | null = null;\n\n // Track whether destroy() has been called\n private destroyed = false;\n\n constructor(options?: VisualGuidanceOptions) {\n this.overlayColor = options?.overlayColor ?? DEFAULT_OVERLAY_COLOR;\n this.spotlightColor = options?.spotlightColor ?? DEFAULT_SPOTLIGHT_COLOR;\n this.animationDuration = options?.animationDuration ?? DEFAULT_ANIMATION_DURATION;\n this.spotlightPadding = options?.spotlightPadding ?? DEFAULT_SPOTLIGHT_PADDING;\n this.debug = options?.debug ?? false;\n\n this.log('Initialised', {\n overlayColor: this.overlayColor,\n spotlightColor: this.spotlightColor,\n animationDuration: this.animationDuration,\n spotlightPadding: this.spotlightPadding,\n });\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /**\n * Highlight an element by selector or sectionId.\n * Returns true if the element was found and highlighted, false otherwise.\n */\n highlight(params: {\n sectionId?: string;\n selector?: string;\n tooltip?: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n }): boolean {\n if (typeof document === 'undefined') return false;\n if (this.destroyed) return false;\n\n const { sectionId, selector, tooltip, position } = params;\n\n // Resolve the target element\n const target = this.resolveTarget(sectionId, selector);\n if (!target) {\n this.log('Target element not found', { sectionId, selector });\n return false;\n }\n\n const resolvedSelector = selector ?? this.buildSelectorForElement(target);\n\n // Dismiss any existing highlight first (without notifying to avoid flicker)\n this.cleanupTrackingInfrastructure();\n\n // Update state\n this._state = {\n isActive: true,\n selector: resolvedSelector,\n sectionId: sectionId ?? null,\n tooltip: tooltip ?? null,\n };\n\n this.currentTargetElement = target;\n\n // Check if the element has zero size (e.g., display: none)\n const rect = target.getBoundingClientRect();\n const hasSize = rect.width > 0 && rect.height > 0;\n\n if (hasSize) {\n // Create/update overlay and spotlight\n this.ensureOverlay();\n this.ensureSpotlight();\n this.positionSpotlight(rect);\n this.showOverlay();\n } else {\n this.log('Element has zero size, showing tooltip only');\n }\n\n // Show tooltip if requested\n if (tooltip) {\n this.showTooltip(target, tooltip, position ?? 'auto');\n } else {\n this.removeTooltip();\n }\n\n // Set up position tracking\n this.setupPositionTracking(target);\n\n // Announce for screen readers\n const label = sectionId ?? resolvedSelector;\n this.announce(`Highlighting ${label}`);\n\n // Notify subscribers\n this.notifySpotlightChange();\n\n this.log('Highlighted element', { sectionId, selector: resolvedSelector, tooltip });\n return true;\n }\n\n /**\n * Remove the spotlight and all associated elements.\n */\n dismissHighlight(): void {\n if (typeof document === 'undefined') return;\n\n this.cleanupTrackingInfrastructure();\n this.hideOverlay();\n this.removeTooltip();\n this.removeAriaDescribedBy();\n\n this.currentTargetElement = null;\n\n this._state = {\n isActive: false,\n selector: null,\n sectionId: null,\n tooltip: null,\n };\n\n this.notifySpotlightChange();\n this.log('Highlight dismissed');\n }\n\n /**\n * Smooth scroll to a section by its sectionId.\n */\n scrollToSection(sectionId: string, offset?: number): void {\n if (typeof document === 'undefined') return;\n\n const target = this.resolveTarget(sectionId, undefined);\n if (!target) {\n this.log('scrollToSection: section not found', { sectionId });\n return;\n }\n\n this.scrollToElement(target, offset);\n this.log('Scrolled to section', { sectionId });\n }\n\n /**\n * Smooth scroll to an element by CSS selector.\n */\n scrollToSelector(selector: string, offset?: number): void {\n if (typeof document === 'undefined') return;\n\n let target: Element | null;\n try {\n target = document.querySelector(selector);\n } catch {\n this.log('scrollToSelector: invalid selector', { selector });\n return;\n }\n\n if (!target) {\n this.log('scrollToSelector: element not found', { selector });\n return;\n }\n\n this.scrollToElement(target, offset);\n this.log('Scrolled to selector', { selector });\n }\n\n /**\n * Start a guided tour through the given section IDs.\n */\n startTour(sectionIds: string[], mode: 'auto' | 'manual' = 'manual'): void {\n if (typeof document === 'undefined') return;\n if (this.destroyed) return;\n if (sectionIds.length === 0) return;\n\n // Stop any existing tour\n this.stopTour();\n\n this.tourSectionIds = [...sectionIds];\n this.tourMode = mode;\n this.tourCurrentStep = -1;\n this.tourPausedByInteraction = false;\n\n this.log('Tour started', { steps: sectionIds.length, mode });\n\n // Advance to the first step\n this.nextTourStep();\n }\n\n /**\n * Move to the next tour step. No-op if no tour is active.\n */\n nextTourStep(): void {\n if (this.tourSectionIds.length === 0) return;\n\n // Clear any existing auto timer\n this.clearAutoTimer();\n\n const nextStep = this.tourCurrentStep + 1;\n if (nextStep >= this.tourSectionIds.length) {\n // Tour complete\n this.stopTour();\n return;\n }\n\n this.tourCurrentStep = nextStep;\n this.tourPausedByInteraction = false;\n\n this.executeTourStep();\n }\n\n /**\n * Move to the previous tour step. No-op if no tour is active or at first step.\n */\n prevTourStep(): void {\n if (this.tourSectionIds.length === 0) return;\n if (this.tourCurrentStep <= 0) return;\n\n // Clear any existing auto timer\n this.clearAutoTimer();\n\n this.tourCurrentStep -= 1;\n this.tourPausedByInteraction = false;\n\n this.executeTourStep();\n }\n\n /**\n * Stop the tour and dismiss all highlights.\n */\n stopTour(): void {\n this.clearAutoTimer();\n\n const wasActive = this.tourSectionIds.length > 0;\n\n this.tourSectionIds = [];\n this.tourCurrentStep = -1;\n this.tourPausedByInteraction = false;\n\n this.dismissHighlight();\n\n if (wasActive) {\n this.log('Tour stopped');\n }\n }\n\n /**\n * Get the current spotlight state.\n */\n get state(): SpotlightState {\n return { ...this._state };\n }\n\n /**\n * Get the current tour state, or null if no tour is active.\n */\n get tourState(): { active: boolean; step: number; total: number } | null {\n if (this.tourSectionIds.length === 0) {\n return null;\n }\n return {\n active: true,\n step: this.tourCurrentStep,\n total: this.tourSectionIds.length,\n };\n }\n\n /**\n * Subscribe to spotlight state changes.\n * Returns an unsubscribe function.\n */\n onSpotlightChange(callback: (state: SpotlightState) => void): () => void {\n this.spotlightChangeCallbacks.push(callback);\n return () => {\n const idx = this.spotlightChangeCallbacks.indexOf(callback);\n if (idx !== -1) {\n this.spotlightChangeCallbacks.splice(idx, 1);\n }\n };\n }\n\n /**\n * Subscribe to tour step events.\n * Returns an unsubscribe function.\n */\n onTourStep(callback: (step: number, total: number, sectionId: string) => void): () => void {\n this.tourStepCallbacks.push(callback);\n return () => {\n const idx = this.tourStepCallbacks.indexOf(callback);\n if (idx !== -1) {\n this.tourStepCallbacks.splice(idx, 1);\n }\n };\n }\n\n /**\n * Clean up all DOM elements, observers, and event listeners.\n * After calling destroy(), the instance is unusable.\n */\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.stopTour();\n this.dismissHighlight();\n this.cleanupTrackingInfrastructure();\n\n // Remove overlay\n if (this.overlayEl?.parentNode) {\n this.overlayEl.parentNode.removeChild(this.overlayEl);\n }\n this.overlayEl = null;\n\n // Remove spotlight\n if (this.spotlightEl?.parentNode) {\n this.spotlightEl.parentNode.removeChild(this.spotlightEl);\n }\n this.spotlightEl = null;\n\n // Remove tooltip\n this.removeTooltip();\n\n // Remove live region\n if (this.liveRegionEl?.parentNode) {\n this.liveRegionEl.parentNode.removeChild(this.liveRegionEl);\n }\n this.liveRegionEl = null;\n\n // Disconnect resize observer\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n // Clear subscriber lists\n this.spotlightChangeCallbacks = [];\n this.tourStepCallbacks = [];\n\n this.domScanner = null;\n\n this.log('Destroyed');\n }\n\n // -------------------------------------------------------------------------\n // Private: Target resolution\n // -------------------------------------------------------------------------\n\n /**\n * Resolve a target element from either a sectionId or a CSS selector.\n * If sectionId is provided, uses DOMScanner to find the section's selector.\n */\n private resolveTarget(sectionId?: string, selector?: string): Element | null {\n if (typeof document === 'undefined') return null;\n\n // Try selector first if provided\n if (selector) {\n try {\n const el = document.querySelector(selector);\n if (el) return el;\n } catch {\n this.log('Invalid selector', { selector });\n }\n }\n\n // Try sectionId via DOMScanner\n if (sectionId) {\n // Try common patterns: data-guidekit-target, id, aria-label\n const strategies = [\n `[data-guidekit-target=\"${sectionId}\"]`,\n `#${CSS.escape(sectionId)}`,\n `[aria-label=\"${sectionId}\"]`,\n ];\n\n for (const strategy of strategies) {\n try {\n const el = document.querySelector(strategy);\n if (el) return el;\n } catch {\n // Invalid selector, try next\n }\n }\n\n // Fall back to DOMScanner for a full scan\n if (!this.domScanner) {\n this.domScanner = new DOMScanner({ debug: this.debug });\n }\n const model = this.domScanner.scan();\n const section = model.sections.find((s) => s.id === sectionId);\n if (section) {\n try {\n const el = document.querySelector(section.selector);\n if (el) return el;\n } catch {\n this.log('DOMScanner selector invalid', { selector: section.selector });\n }\n }\n }\n\n return null;\n }\n\n /**\n * Build a CSS selector for an element, using the same priority hierarchy\n * as the DOMScanner.\n */\n private buildSelectorForElement(el: Element): string {\n const guideKitTarget = el.getAttribute('data-guidekit-target');\n if (guideKitTarget) return `[data-guidekit-target=\"${guideKitTarget}\"]`;\n\n const id = el.id;\n if (id) {\n try {\n const escaped = CSS.escape(id);\n if (document.querySelectorAll(`#${escaped}`).length === 1) {\n return `#${escaped}`;\n }\n } catch {\n // Fall through\n }\n }\n\n const testId = el.getAttribute('data-testid');\n if (testId) return `[data-testid=\"${testId}\"]`;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return `[aria-label=\"${ariaLabel}\"]`;\n\n // Structural path fallback\n return this.buildStructuralPath(el);\n }\n\n private buildStructuralPath(el: Element): string {\n if (typeof document === 'undefined') return '';\n\n const parts: string[] = [];\n let current: Element | null = el;\n\n while (current && current !== document.documentElement) {\n const tag = current.tagName.toLowerCase();\n\n if (tag === 'body' || tag === 'html') {\n parts.unshift(tag);\n current = current.parentElement;\n continue;\n }\n\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c) => c.tagName === current!.tagName,\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n parts.unshift(`${tag}:nth-child(${index})`);\n } else {\n parts.unshift(tag);\n }\n } else {\n parts.unshift(tag);\n }\n\n current = parent;\n }\n\n return parts.join(' > ');\n }\n\n // -------------------------------------------------------------------------\n // Private: Overlay management\n // -------------------------------------------------------------------------\n\n /**\n * Ensure the full-page overlay element exists on document.body.\n */\n private ensureOverlay(): void {\n if (typeof document === 'undefined') return;\n if (this.overlayEl) return;\n\n const overlay = document.createElement('div');\n overlay.setAttribute('aria-hidden', 'true');\n overlay.setAttribute('data-guidekit-overlay', 'true');\n overlay.style.cssText = [\n 'position: fixed',\n 'inset: 0',\n `z-index: ${OVERLAY_Z_INDEX}`,\n 'pointer-events: none',\n 'opacity: 0',\n `transition: opacity ${this.getTransitionDuration()}ms ease-out`,\n ].join('; ');\n\n document.body.appendChild(overlay);\n this.overlayEl = overlay;\n }\n\n /**\n * Ensure the spotlight (cutout) element exists on document.body.\n */\n private ensureSpotlight(): void {\n if (typeof document === 'undefined') return;\n if (this.spotlightEl) return;\n\n const spotlight = document.createElement('div');\n spotlight.setAttribute('aria-hidden', 'true');\n spotlight.setAttribute('data-guidekit-spotlight', 'true');\n\n const transitionDuration = this.getTransitionDuration();\n spotlight.style.cssText = [\n 'position: fixed',\n `z-index: ${OVERLAY_Z_INDEX}`,\n 'pointer-events: none',\n 'border-radius: 4px',\n `border: 2px solid ${this.spotlightColor}`,\n `box-shadow: 0 0 0 9999px ${this.overlayColor}`,\n 'will-change: transform, opacity',\n 'opacity: 0',\n `transition: transform ${transitionDuration}ms ease-out, opacity ${transitionDuration}ms ease-out, width ${transitionDuration}ms ease-out, height ${transitionDuration}ms ease-out`,\n ].join('; ');\n\n document.body.appendChild(spotlight);\n this.spotlightEl = spotlight;\n }\n\n /**\n * Position the spotlight element over the target's bounding rect.\n */\n private positionSpotlight(rect: DOMRect): void {\n if (!this.spotlightEl) return;\n\n const pad = this.spotlightPadding;\n const left = rect.left - pad;\n const top = rect.top - pad;\n const width = rect.width + pad * 2;\n const height = rect.height + pad * 2;\n\n this.spotlightEl.style.left = `${left}px`;\n this.spotlightEl.style.top = `${top}px`;\n this.spotlightEl.style.width = `${width}px`;\n this.spotlightEl.style.height = `${height}px`;\n }\n\n /**\n * Show the overlay and spotlight with entrance animation.\n */\n private showOverlay(): void {\n if (typeof document === 'undefined') return;\n\n // Force a reflow so the transition triggers\n if (this.overlayEl) {\n void this.overlayEl.offsetHeight;\n this.overlayEl.style.opacity = '1';\n }\n if (this.spotlightEl) {\n void this.spotlightEl.offsetHeight;\n this.spotlightEl.style.opacity = '1';\n }\n }\n\n /**\n * Hide the overlay and spotlight.\n */\n private hideOverlay(): void {\n if (this.overlayEl) {\n this.overlayEl.style.opacity = '0';\n }\n if (this.spotlightEl) {\n this.spotlightEl.style.opacity = '0';\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Tooltip management\n // -------------------------------------------------------------------------\n\n /**\n * Show a tooltip near the target element.\n */\n private showTooltip(\n target: Element,\n text: string,\n positionPref: 'top' | 'bottom' | 'left' | 'right' | 'auto',\n ): void {\n if (typeof document === 'undefined') return;\n\n // Create or reuse tooltip element\n if (!this.tooltipEl) {\n const tooltip = document.createElement('div');\n tooltip.setAttribute('role', 'tooltip');\n tooltip.setAttribute('data-guidekit-tooltip', 'true');\n\n const transitionDuration = this.getTransitionDuration();\n tooltip.style.cssText = [\n 'position: fixed',\n `z-index: ${TOOLTIP_Z_INDEX}`,\n 'pointer-events: none',\n 'background: #ffffff',\n 'color: #1a1a2e',\n 'padding: 10px 14px',\n 'border-radius: 8px',\n 'font-size: 14px',\n 'line-height: 1.4',\n 'max-width: 300px',\n 'box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15)',\n 'opacity: 0',\n `transition: opacity ${transitionDuration}ms ease-out`,\n 'font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n ].join('; ');\n\n document.body.appendChild(tooltip);\n this.tooltipEl = tooltip;\n }\n\n // Set text content (NEVER innerHTML to prevent XSS)\n this.tooltipEl.textContent = text;\n\n // Add step indicator if in a tour\n if (this.tourSectionIds.length > 0 && this.tourCurrentStep >= 0) {\n const stepText = `Step ${this.tourCurrentStep + 1} of ${this.tourSectionIds.length}`;\n this.tooltipEl.textContent = `${stepText}: ${text}`;\n }\n\n // Set aria-describedby on the target\n const tooltipId = 'guidekit-tooltip-' + Date.now();\n this.tooltipEl.id = tooltipId;\n if (target instanceof HTMLElement) {\n target.setAttribute('aria-describedby', tooltipId);\n }\n\n // Position the tooltip\n const rect = target.getBoundingClientRect();\n const position = positionPref === 'auto'\n ? this.computeAutoPosition(rect)\n : positionPref;\n\n this.positionTooltip(rect, position);\n\n // Animate in\n void this.tooltipEl.offsetHeight;\n this.tooltipEl.style.opacity = '1';\n }\n\n /**\n * Remove the tooltip element from the DOM.\n */\n private removeTooltip(): void {\n if (this.tooltipEl?.parentNode) {\n this.tooltipEl.parentNode.removeChild(this.tooltipEl);\n }\n this.tooltipEl = null;\n }\n\n /**\n * Remove aria-describedby from the current target element.\n */\n private removeAriaDescribedBy(): void {\n if (this.currentTargetElement instanceof HTMLElement) {\n this.currentTargetElement.removeAttribute('aria-describedby');\n }\n }\n\n /**\n * Compute the best auto-position for the tooltip relative to the target rect.\n * Preference order: bottom, top, right, left.\n */\n private computeAutoPosition(rect: DOMRect): TooltipPosition {\n if (typeof window === 'undefined') return 'bottom';\n\n const viewportHeight = window.innerHeight;\n const viewportWidth = window.innerWidth;\n\n const spaceBelow = viewportHeight - rect.bottom;\n const spaceAbove = rect.top;\n const spaceRight = viewportWidth - rect.right;\n const spaceLeft = rect.left;\n\n const minSpace = 80; // Minimum space needed for tooltip\n\n // Prefer bottom\n if (spaceBelow >= minSpace) return 'bottom';\n // Then top\n if (spaceAbove >= minSpace) return 'top';\n // Then right\n if (spaceRight >= minSpace) return 'right';\n // Then left\n if (spaceLeft >= minSpace) return 'left';\n\n // Default to bottom even if tight\n return 'bottom';\n }\n\n /**\n * Position the tooltip element relative to the target rect.\n */\n private positionTooltip(rect: DOMRect, position: TooltipPosition): void {\n if (!this.tooltipEl || typeof window === 'undefined') return;\n\n const pad = this.spotlightPadding;\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // We need the tooltip's dimensions. Force layout to measure.\n this.tooltipEl.style.left = '0px';\n this.tooltipEl.style.top = '0px';\n const tooltipRect = this.tooltipEl.getBoundingClientRect();\n const tw = tooltipRect.width;\n const th = tooltipRect.height;\n\n let left = 0;\n let top = 0;\n\n switch (position) {\n case 'bottom':\n left = rect.left + rect.width / 2 - tw / 2;\n top = rect.bottom + pad + TOOLTIP_ARROW_SIZE + TOOLTIP_MARGIN;\n break;\n case 'top':\n left = rect.left + rect.width / 2 - tw / 2;\n top = rect.top - pad - th - TOOLTIP_ARROW_SIZE - TOOLTIP_MARGIN;\n break;\n case 'right':\n left = rect.right + pad + TOOLTIP_ARROW_SIZE + TOOLTIP_MARGIN;\n top = rect.top + rect.height / 2 - th / 2;\n break;\n case 'left':\n left = rect.left - pad - tw - TOOLTIP_ARROW_SIZE - TOOLTIP_MARGIN;\n top = rect.top + rect.height / 2 - th / 2;\n break;\n }\n\n // Clamp within viewport\n left = Math.max(8, Math.min(left, viewportWidth - tw - 8));\n top = Math.max(8, Math.min(top, viewportHeight - th - 8));\n\n this.tooltipEl.style.left = `${left}px`;\n this.tooltipEl.style.top = `${top}px`;\n\n // Remove any existing arrow pseudo-element styling (via data attribute)\n this.tooltipEl.setAttribute('data-guidekit-position', position);\n\n // Apply arrow using a CSS trick with box-shadow on a pseudo :before\n // Since we can't use CSS stylesheets easily, we inline arrow via border trick\n this.applyTooltipArrow(position, rect);\n }\n\n /**\n * Apply an arrow on the tooltip pointing toward the target element.\n * Uses a child div with CSS border triangle technique.\n */\n private applyTooltipArrow(position: TooltipPosition, targetRect: DOMRect): void {\n if (!this.tooltipEl) return;\n\n // Remove any existing arrow\n const existingArrow = this.tooltipEl.querySelector('[data-guidekit-arrow]');\n if (existingArrow) {\n existingArrow.remove();\n }\n\n const arrow = document.createElement('div');\n arrow.setAttribute('data-guidekit-arrow', 'true');\n arrow.setAttribute('aria-hidden', 'true');\n\n const size = TOOLTIP_ARROW_SIZE;\n const baseStyle = [\n 'position: absolute',\n 'width: 0',\n 'height: 0',\n 'border-style: solid',\n ];\n\n switch (position) {\n case 'bottom':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: 0 ${size}px ${size}px ${size}px`,\n `border-color: transparent transparent #ffffff transparent`,\n `top: -${size}px`,\n `left: 50%`,\n `margin-left: -${size}px`,\n ].join('; ');\n // Adjust arrow horizontal position to point at target center\n this.adjustArrowHorizontal(arrow, targetRect, size);\n break;\n case 'top':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: ${size}px ${size}px 0 ${size}px`,\n `border-color: #ffffff transparent transparent transparent`,\n `bottom: -${size}px`,\n `left: 50%`,\n `margin-left: -${size}px`,\n ].join('; ');\n this.adjustArrowHorizontal(arrow, targetRect, size);\n break;\n case 'right':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: ${size}px ${size}px ${size}px 0`,\n `border-color: transparent #ffffff transparent transparent`,\n `left: -${size}px`,\n `top: 50%`,\n `margin-top: -${size}px`,\n ].join('; ');\n break;\n case 'left':\n arrow.style.cssText = [\n ...baseStyle,\n `border-width: ${size}px 0 ${size}px ${size}px`,\n `border-color: transparent transparent transparent #ffffff`,\n `right: -${size}px`,\n `top: 50%`,\n `margin-top: -${size}px`,\n ].join('; ');\n break;\n }\n\n this.tooltipEl.appendChild(arrow);\n }\n\n /**\n * Adjust arrow horizontal position so it points toward the target center\n * even when the tooltip is clamped to viewport edges.\n */\n private adjustArrowHorizontal(arrow: HTMLDivElement, targetRect: DOMRect, size: number): void {\n if (!this.tooltipEl) return;\n\n const tooltipRect = this.tooltipEl.getBoundingClientRect();\n const targetCenter = targetRect.left + targetRect.width / 2;\n const arrowLeft = targetCenter - tooltipRect.left;\n\n // Clamp arrow within tooltip bounds\n const minLeft = size + 4;\n const maxLeft = tooltipRect.width - size - 4;\n const clampedLeft = Math.max(minLeft, Math.min(arrowLeft, maxLeft));\n\n arrow.style.left = `${clampedLeft}px`;\n arrow.style.marginLeft = `0`;\n }\n\n // -------------------------------------------------------------------------\n // Private: Position tracking\n // -------------------------------------------------------------------------\n\n /**\n * Set up ResizeObserver and scroll listeners to track the target element\n * and update spotlight/tooltip positions.\n */\n private setupPositionTracking(target: Element): void {\n this.cleanupTrackingInfrastructure();\n\n // ResizeObserver\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => {\n this.updatePositions();\n });\n this.resizeObserver.observe(target);\n // Also observe body for layout changes\n if (typeof document !== 'undefined') {\n this.resizeObserver.observe(document.body);\n }\n }\n\n // Scroll listeners on all scrollable ancestors + window\n const scrollableAncestors = getScrollableAncestors(target);\n\n const handleScroll = (): void => {\n this.updatePositions();\n\n // In auto-tour mode, pause on user interaction\n if (this.tourMode === 'auto' && !this.tourPausedByInteraction) {\n this.tourPausedByInteraction = true;\n this.clearAutoTimer();\n // Resume after a delay\n this.tourAutoTimer = setTimeout(() => {\n this.tourPausedByInteraction = false;\n this.scheduleAutoAdvance();\n }, AUTO_TOUR_INTERVAL_MS);\n }\n };\n\n // Attach to each scrollable ancestor\n for (const ancestor of scrollableAncestors) {\n ancestor.addEventListener('scroll', handleScroll, { passive: true });\n this.scrollListenerCleanups.push(() => {\n ancestor.removeEventListener('scroll', handleScroll);\n });\n }\n\n // Always attach to window for document-level scroll\n if (typeof window !== 'undefined') {\n window.addEventListener('scroll', handleScroll, { passive: true });\n this.scrollListenerCleanups.push(() => {\n window.removeEventListener('scroll', handleScroll);\n });\n\n // Also listen for window resize\n window.addEventListener('resize', handleScroll, { passive: true });\n this.scrollListenerCleanups.push(() => {\n window.removeEventListener('resize', handleScroll);\n });\n }\n }\n\n /**\n * Remove all tracking observers and event listeners.\n */\n private cleanupTrackingInfrastructure(): void {\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n for (const cleanup of this.scrollListenerCleanups) {\n cleanup();\n }\n this.scrollListenerCleanups = [];\n }\n\n /**\n * Update spotlight and tooltip positions based on the current target\n * element's bounding rect.\n */\n private updatePositions(): void {\n if (!this.currentTargetElement) return;\n\n const rect = this.currentTargetElement.getBoundingClientRect();\n const hasSize = rect.width > 0 && rect.height > 0;\n\n if (hasSize && this.spotlightEl) {\n this.positionSpotlight(rect);\n }\n\n if (this.tooltipEl && this._state.tooltip) {\n const position = this.tooltipEl.getAttribute('data-guidekit-position') as TooltipPosition | null;\n this.positionTooltip(rect, position ?? 'bottom');\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Smooth scrolling\n // -------------------------------------------------------------------------\n\n /**\n * Scroll to an element, respecting reduced motion preferences.\n */\n private scrollToElement(target: Element, offset?: number): void {\n if (typeof window === 'undefined') return;\n\n const behavior = prefersReducedMotion() ? 'instant' as ScrollBehavior : 'smooth';\n\n if (offset !== undefined && offset !== 0) {\n // Use window.scrollTo with calculated position for header offset\n const rect = target.getBoundingClientRect();\n const scrollTop = window.pageYOffset ?? document.documentElement.scrollTop;\n const targetTop = rect.top + scrollTop - offset;\n\n window.scrollTo({\n top: targetTop,\n behavior,\n });\n } else {\n target.scrollIntoView({\n behavior,\n block: 'center',\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Tour logic\n // -------------------------------------------------------------------------\n\n /**\n * Execute the current tour step: scroll to and highlight the section.\n */\n private executeTourStep(): void {\n if (this.tourCurrentStep < 0 || this.tourCurrentStep >= this.tourSectionIds.length) {\n return;\n }\n\n const sectionId = this.tourSectionIds[this.tourCurrentStep] as string | undefined;\n if (!sectionId) return;\n\n const total = this.tourSectionIds.length;\n const step = this.tourCurrentStep;\n\n // Scroll to the section first\n this.scrollToSection(sectionId);\n\n // Slight delay to let scroll settle, then highlight\n // Use a timeout so scrollIntoView can initiate\n setTimeout(() => {\n if (this.destroyed) return;\n\n const tooltipText = `Step ${step + 1} of ${total}`;\n\n this.highlight({\n sectionId,\n tooltip: tooltipText,\n position: 'auto',\n });\n\n // Notify tour step subscribers\n for (const cb of this.tourStepCallbacks) {\n try {\n cb(step, total, sectionId);\n } catch (e) {\n this.log('Tour step callback error', { error: String(e) });\n }\n }\n\n // Schedule auto-advance if in auto mode\n if (this.tourMode === 'auto') {\n this.scheduleAutoAdvance();\n }\n }, 100);\n }\n\n /**\n * Schedule auto-advance to the next tour step.\n */\n private scheduleAutoAdvance(): void {\n this.clearAutoTimer();\n\n if (this.tourMode !== 'auto') return;\n if (this.tourPausedByInteraction) return;\n\n this.tourAutoTimer = setTimeout(() => {\n if (!this.destroyed && !this.tourPausedByInteraction) {\n this.nextTourStep();\n }\n }, AUTO_TOUR_INTERVAL_MS);\n }\n\n /**\n * Clear the auto-advance timer.\n */\n private clearAutoTimer(): void {\n if (this.tourAutoTimer !== null) {\n clearTimeout(this.tourAutoTimer);\n this.tourAutoTimer = null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Accessibility — aria-live announcements\n // -------------------------------------------------------------------------\n\n /**\n * Announce a message to screen readers via an aria-live region.\n */\n private announce(message: string): void {\n if (typeof document === 'undefined') return;\n\n if (!this.liveRegionEl) {\n const region = document.createElement('div');\n region.setAttribute('aria-live', 'assertive');\n region.setAttribute('aria-atomic', 'true');\n region.setAttribute('data-guidekit-live', 'true');\n region.style.cssText = [\n 'position: absolute',\n 'width: 1px',\n 'height: 1px',\n 'padding: 0',\n 'margin: -1px',\n 'overflow: hidden',\n 'clip: rect(0, 0, 0, 0)',\n 'white-space: nowrap',\n 'border: 0',\n ].join('; ');\n document.body.appendChild(region);\n this.liveRegionEl = region;\n }\n\n // Clear and re-set to trigger announcement\n this.liveRegionEl.textContent = '';\n // Use a microtask to ensure the DOM update is flushed before re-setting\n requestAnimationFrame(() => {\n if (this.liveRegionEl) {\n this.liveRegionEl.textContent = message;\n }\n });\n }\n\n // -------------------------------------------------------------------------\n // Private: Subscriber notifications\n // -------------------------------------------------------------------------\n\n private notifySpotlightChange(): void {\n const stateCopy = this.state;\n for (const cb of this.spotlightChangeCallbacks) {\n try {\n cb(stateCopy);\n } catch (e) {\n this.log('Spotlight change callback error', { error: String(e) });\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: Utilities\n // -------------------------------------------------------------------------\n\n /**\n * Get the transition duration, respecting prefers-reduced-motion.\n */\n private getTransitionDuration(): number {\n return prefersReducedMotion() ? 0 : this.animationDuration;\n }\n\n /**\n * Debug logger.\n */\n private log(message: string, data?: Record<string, unknown>): void {\n if (!this.debug) return;\n if (typeof console !== 'undefined') {\n if (data) {\n console.log(`${LOG_PREFIX} ${message}`, data);\n } else {\n console.log(`${LOG_PREFIX} ${message}`);\n }\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – User Awareness System\n// ---------------------------------------------------------------------------\n// Monitors user behavior signals (scroll, dwell, idle, rage-click, section\n// visibility) and emits awareness events via the EventBus.\n// ---------------------------------------------------------------------------\n\nimport { EventBus } from '../bus/index.js';\n\nconst LOG_PREFIX = '[GuideKit:Awareness]';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_IDLE_TIMEOUT_MS = 60_000;\nconst DEFAULT_DWELL_TIMEOUT_MS = 8_000;\nconst DEFAULT_RAGE_CLICK_THRESHOLD = 3;\nconst DEFAULT_RAGE_CLICK_WINDOW_MS = 2_000;\nconst RAGE_CLICK_RADIUS_PX = 50;\nconst MOUSE_THROTTLE_MS = 200;\n\n/** Selectors used to discover observable sections. */\nconst SECTION_SELECTOR = [\n '[data-guidekit-target]',\n '[id]',\n 'main',\n 'section',\n 'article',\n 'aside',\n 'nav',\n 'header',\n 'footer',\n].join(', ');\n\n/** IntersectionObserver thresholds for section visibility. */\nconst IO_THRESHOLDS: number[] = [0, 0.25, 0.5, 0.75, 1.0];\n\n// ---------------------------------------------------------------------------\n// Exported types\n// ---------------------------------------------------------------------------\n\nexport interface AwarenessOptions {\n bus: EventBus;\n rootElement?: HTMLElement;\n idleTimeoutMs?: number;\n dwellTimeoutMs?: number;\n rageClickThreshold?: number;\n rageClickWindowMs?: number;\n debug?: boolean;\n}\n\nexport interface AwarenessState {\n scrollPercent: number;\n scrollDirection: 'up' | 'down' | 'none';\n focusedSectionId: string | null;\n focusedSectionDwellMs: number;\n isIdle: boolean;\n lastInteractionAt: number;\n visibleSections: Map<string, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ninterface ClickRecord {\n x: number;\n y: number;\n timestamp: number;\n target: Element;\n}\n\n// ---------------------------------------------------------------------------\n// AwarenessSystem\n// ---------------------------------------------------------------------------\n\n/**\n * Observes user interactions with the page and emits structured awareness\n * events on the shared {@link EventBus}.\n *\n * All browser API usage is gated behind `typeof window !== 'undefined'` so\n * the module can be safely imported in SSR contexts.\n */\nexport class AwarenessSystem {\n // ---- Configuration ------------------------------------------------------\n\n private readonly bus: EventBus;\n private readonly rootElement: HTMLElement | undefined;\n private readonly idleTimeoutMs: number;\n private readonly dwellTimeoutMs: number;\n private readonly rageClickThreshold: number;\n private readonly rageClickWindowMs: number;\n private readonly debugEnabled: boolean;\n\n // ---- Runtime state ------------------------------------------------------\n\n private running = false;\n\n /** AbortController whose signal is passed to every addEventListener call. */\n private abortController: AbortController | null = null;\n\n /** IntersectionObserver for section visibility tracking. */\n private sectionObserver: IntersectionObserver | null = null;\n\n /** Section id -> current visibility ratio. */\n private readonly visibleSections = new Map<string, number>();\n\n // ---- Scroll tracking ----------------------------------------------------\n\n private scrollPercent = 0;\n private scrollDirection: 'up' | 'down' | 'none' = 'none';\n private lastScrollY = 0;\n private scrollRafPending = false;\n\n // ---- Dwell detection ----------------------------------------------------\n\n private focusedSectionId: string | null = null;\n private focusedSectionSince = 0;\n private dwellTimer: ReturnType<typeof setInterval> | null = null;\n private dwellEmitted = false;\n\n // ---- Idle detection -----------------------------------------------------\n\n private lastInteractionAt = 0;\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private isIdle = false;\n\n // ---- Rage click detection -----------------------------------------------\n\n private readonly recentClicks: ClickRecord[] = [];\n\n // ---- Mouse throttle -----------------------------------------------------\n\n private lastMouseMoveAt = 0;\n\n // -----------------------------------------------------------------------\n // Constructor\n // -----------------------------------------------------------------------\n\n constructor(options: AwarenessOptions) {\n this.bus = options.bus;\n this.rootElement = options.rootElement;\n this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.dwellTimeoutMs = options.dwellTimeoutMs ?? DEFAULT_DWELL_TIMEOUT_MS;\n this.rageClickThreshold = options.rageClickThreshold ?? DEFAULT_RAGE_CLICK_THRESHOLD;\n this.rageClickWindowMs = options.rageClickWindowMs ?? DEFAULT_RAGE_CLICK_WINDOW_MS;\n this.debugEnabled = options.debug ?? false;\n\n this.log('AwarenessSystem created');\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Begin observing user behavior. No-op if already running or in SSR. */\n start(): void {\n if (this.running) return;\n if (typeof window === 'undefined') {\n this.log('SSR environment detected — start() is a no-op');\n return;\n }\n\n this.running = true;\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n\n this.lastInteractionAt = Date.now();\n this.lastScrollY = window.scrollY;\n\n // -- Event listeners (all using the shared AbortController signal) -----\n const listenerOpts = { signal, passive: true } as const;\n\n window.addEventListener('scroll', this.handleScroll, listenerOpts);\n window.addEventListener('mousemove', this.handleMouseMove, listenerOpts);\n window.addEventListener('keydown', this.handleInteraction, listenerOpts);\n window.addEventListener('click', this.handleClick, { signal });\n window.addEventListener('touchstart', this.handleInteraction, listenerOpts);\n window.addEventListener('touchend', this.handleInteraction, listenerOpts);\n\n // -- IntersectionObserver for sections ---------------------------------\n this.initSectionObserver();\n\n // -- Idle timer --------------------------------------------------------\n this.scheduleIdleTimer();\n\n // -- Dwell check interval ---------------------------------------------\n this.dwellTimer = setInterval(this.checkDwell, 1_000);\n\n this.log('Monitoring started');\n }\n\n /** Stop all observers and listeners. */\n stop(): void {\n if (!this.running) return;\n\n this.running = false;\n\n // Abort all listeners in one call.\n this.abortController?.abort();\n this.abortController = null;\n\n // Tear down IntersectionObserver.\n if (this.sectionObserver) {\n this.sectionObserver.disconnect();\n this.sectionObserver = null;\n }\n\n // Clear timers.\n this.clearIdleTimer();\n this.clearDwellTimer();\n\n // Reset state.\n this.visibleSections.clear();\n this.recentClicks.length = 0;\n this.focusedSectionId = null;\n this.focusedSectionSince = 0;\n this.dwellEmitted = false;\n this.isIdle = false;\n this.scrollPercent = 0;\n this.scrollDirection = 'none';\n this.scrollRafPending = false;\n\n this.log('Monitoring stopped');\n }\n\n /** Alias for {@link stop}. */\n destroy(): void {\n this.stop();\n }\n\n /** Return a snapshot of the current awareness state. */\n getState(): AwarenessState {\n const now = Date.now();\n const dwellMs =\n this.focusedSectionId !== null\n ? now - this.focusedSectionSince\n : 0;\n\n return {\n scrollPercent: this.scrollPercent,\n scrollDirection: this.scrollDirection,\n focusedSectionId: this.focusedSectionId,\n focusedSectionDwellMs: dwellMs,\n isIdle: this.isIdle,\n lastInteractionAt: this.lastInteractionAt,\n visibleSections: new Map(this.visibleSections),\n };\n }\n\n // -----------------------------------------------------------------------\n // Scroll tracking\n // -----------------------------------------------------------------------\n\n private readonly handleScroll = (): void => {\n this.recordInteraction();\n\n if (this.scrollRafPending) return;\n this.scrollRafPending = true;\n\n requestAnimationFrame(() => {\n this.scrollRafPending = false;\n if (!this.running) return;\n\n const y = window.scrollY;\n const maxScroll = document.documentElement.scrollHeight - window.innerHeight;\n this.scrollPercent = maxScroll > 0 ? Math.min(1, y / maxScroll) : 0;\n\n if (y > this.lastScrollY) {\n this.scrollDirection = 'down';\n } else if (y < this.lastScrollY) {\n this.scrollDirection = 'up';\n }\n // If y === lastScrollY, keep the current direction.\n\n this.lastScrollY = y;\n });\n };\n\n // -----------------------------------------------------------------------\n // Mouse tracking (throttled)\n // -----------------------------------------------------------------------\n\n private readonly handleMouseMove = (): void => {\n const now = Date.now();\n if (now - this.lastMouseMoveAt < MOUSE_THROTTLE_MS) return;\n this.lastMouseMoveAt = now;\n\n this.recordInteraction();\n };\n\n // -----------------------------------------------------------------------\n // Click tracking & rage click detection\n // -----------------------------------------------------------------------\n\n private readonly handleClick = (e: Event): void => {\n this.recordInteraction();\n\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element | null;\n if (!target) return;\n\n const now = Date.now();\n const record: ClickRecord = {\n x: mouseEvent.clientX,\n y: mouseEvent.clientY,\n timestamp: now,\n target,\n };\n\n this.recentClicks.push(record);\n\n // Prune clicks outside the rage-click time window.\n const windowStart = now - this.rageClickWindowMs;\n while (this.recentClicks.length > 0 && this.recentClicks[0]!.timestamp < windowStart) {\n this.recentClicks.shift();\n }\n\n // Check for rage clicks: N+ clicks within the window on the same\n // element or within a small radius.\n const nearby = this.recentClicks.filter((c) => {\n const sameElement = c.target === target;\n const dx = c.x - record.x;\n const dy = c.y - record.y;\n const withinRadius = Math.sqrt(dx * dx + dy * dy) <= RAGE_CLICK_RADIUS_PX;\n return sameElement || withinRadius;\n });\n\n if (nearby.length >= this.rageClickThreshold) {\n const selector = this.buildSelector(target);\n this.bus.emit('awareness:rage-click', {\n selector,\n clicks: nearby.length,\n });\n this.log(`Rage click detected (${nearby.length} clicks) on \"${selector}\"`);\n\n // Clear clicks so we don't keep re-emitting for the same burst.\n this.recentClicks.length = 0;\n }\n };\n\n // -----------------------------------------------------------------------\n // Generic interaction handler (touch, keydown)\n // -----------------------------------------------------------------------\n\n private readonly handleInteraction = (): void => {\n this.recordInteraction();\n };\n\n // -----------------------------------------------------------------------\n // Interaction bookkeeping (shared by all handlers)\n // -----------------------------------------------------------------------\n\n private recordInteraction(): void {\n this.lastInteractionAt = Date.now();\n\n // If user was idle, mark active again and reset idle timer.\n if (this.isIdle) {\n this.isIdle = false;\n this.log('User returned from idle');\n }\n\n this.scheduleIdleTimer();\n }\n\n // -----------------------------------------------------------------------\n // Idle detection\n // -----------------------------------------------------------------------\n\n private scheduleIdleTimer(): void {\n this.clearIdleTimer();\n\n this.idleTimer = setTimeout(() => {\n if (!this.running) return;\n\n this.isIdle = true;\n const durationMs = Date.now() - this.lastInteractionAt;\n\n this.bus.emit('awareness:idle', { durationMs });\n this.log(`User idle for ${durationMs}ms`);\n }, this.idleTimeoutMs);\n }\n\n private clearIdleTimer(): void {\n if (this.idleTimer !== null) {\n clearTimeout(this.idleTimer);\n this.idleTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // Dwell detection\n // -----------------------------------------------------------------------\n\n /**\n * Periodically (every 1s) check whether the user has been focused on the\n * same section long enough to trigger a dwell event.\n */\n private readonly checkDwell = (): void => {\n if (!this.running) return;\n\n // Determine the section with the highest visibility ratio.\n let bestId: string | null = null;\n let bestRatio = 0;\n\n for (const [id, ratio] of this.visibleSections) {\n if (ratio > bestRatio) {\n bestRatio = ratio;\n bestId = id;\n }\n }\n\n // If the focused section changed, reset the dwell tracker.\n if (bestId !== this.focusedSectionId) {\n this.focusedSectionId = bestId;\n this.focusedSectionSince = Date.now();\n this.dwellEmitted = false;\n return;\n }\n\n // If we have a focused section and haven't emitted yet, check duration.\n if (this.focusedSectionId !== null && !this.dwellEmitted) {\n const dwellMs = Date.now() - this.focusedSectionSince;\n if (dwellMs >= this.dwellTimeoutMs) {\n this.dwellEmitted = true;\n this.bus.emit('awareness:dwell', {\n sectionId: this.focusedSectionId,\n durationMs: dwellMs,\n });\n this.log(`Dwell on \"${this.focusedSectionId}\" (${dwellMs}ms)`);\n }\n }\n };\n\n private clearDwellTimer(): void {\n if (this.dwellTimer !== null) {\n clearInterval(this.dwellTimer);\n this.dwellTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // IntersectionObserver — section visibility\n // -----------------------------------------------------------------------\n\n private initSectionObserver(): void {\n if (typeof IntersectionObserver === 'undefined') {\n this.log('IntersectionObserver not available — section tracking disabled');\n return;\n }\n\n this.sectionObserver = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const sectionId = this.getSectionId(entry.target);\n if (!sectionId) continue;\n\n const ratio = Math.round(entry.intersectionRatio * 100) / 100;\n const previous = this.visibleSections.get(sectionId);\n\n if (previous === ratio) continue;\n\n if (ratio === 0) {\n this.visibleSections.delete(sectionId);\n } else {\n this.visibleSections.set(sectionId, ratio);\n }\n\n this.bus.emit('awareness:section-visible', {\n sectionId,\n ratio,\n });\n }\n },\n {\n root: this.rootElement ?? null,\n threshold: IO_THRESHOLDS,\n },\n );\n\n this.observeSections();\n }\n\n /**\n * Query the DOM for observable sections and start observing them.\n */\n private observeSections(): void {\n if (!this.sectionObserver) return;\n\n const root = this.rootElement ?? document;\n const elements = root.querySelectorAll(SECTION_SELECTOR);\n\n if (elements.length === 0) {\n this.log('No observable sections found');\n return;\n }\n\n for (const el of elements) {\n this.sectionObserver.observe(el);\n }\n\n this.log(`Observing ${elements.length} section(s)`);\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n /**\n * Derive a stable string identifier for a DOM element used as a section.\n *\n * Priority: `data-guidekit-target` > `id` > tagName.\n */\n private getSectionId(el: Element): string | null {\n const guidekitTarget = el.getAttribute('data-guidekit-target');\n if (guidekitTarget) return guidekitTarget;\n\n const id = el.getAttribute('id');\n if (id) return `#${id}`;\n\n // For semantic landmarks, use the tag name (lowercase).\n const tag = el.tagName.toLowerCase();\n const landmarks = ['main', 'section', 'article', 'aside', 'nav', 'header', 'footer'];\n if (landmarks.includes(tag)) return tag;\n\n return null;\n }\n\n /**\n * Build a simple CSS selector string for an element, suitable for\n * inclusion in rage-click events.\n */\n private buildSelector(el: Element): string {\n // Prefer id.\n if (el.id) return `#${el.id}`;\n\n // data-guidekit-target\n const target = el.getAttribute('data-guidekit-target');\n if (target) return `[data-guidekit-target=\"${target}\"]`;\n\n // Construct a tag.class selector.\n const tag = el.tagName.toLowerCase();\n const classes = Array.from(el.classList)\n .slice(0, 3) // Limit to avoid absurdly long selectors\n .map((c) => `.${c}`)\n .join('');\n\n return `${tag}${classes}`;\n }\n\n /** Conditional debug logging. */\n private log(...args: unknown[]): void {\n if (this.debugEnabled) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Proactive Trigger Engine\n// ---------------------------------------------------------------------------\n// Listens to awareness events on the EventBus and decides when to\n// proactively engage the user. The engine itself never shows UI or sends\n// LLM messages — it communicates via the `onTrigger` callback so the core\n// orchestrator can decide what action to take.\n// ---------------------------------------------------------------------------\n\nimport { EventBus } from '../bus/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:Proactive]';\nconst STORAGE_KEY = 'guidekit:visited';\nconst SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** Progressive dwell cooldowns in ms: 30s → 60s → 120s → stop. */\nconst DWELL_COOLDOWNS = [30_000, 60_000, 120_000];\nconst DWELL_THRESHOLD_MS = 8_000;\nconst IDLE_THRESHOLD_MS = 60_000;\nconst NAVIGATION_COOLDOWN_MS = 30_000;\nconst FORM_ABANDON_MS = 15_000;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ProactiveOptions {\n bus: EventBus;\n debug?: boolean;\n /** Callback invoked whenever a proactive trigger fires. */\n onTrigger?: (trigger: ProactiveTrigger) => void;\n}\n\nexport type ProactiveTriggerType =\n | 'greeting'\n | 'idle-help'\n | 'dwell-commentary'\n | 'navigation-commentary'\n | 'frustration'\n | 'form-abandonment';\n\nexport interface ProactiveTrigger {\n type: ProactiveTriggerType;\n sectionId?: string;\n selector?: string;\n /** Suggested context message for the LLM. */\n message?: string;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// ProactiveTriggerEngine\n// ---------------------------------------------------------------------------\n\nexport class ProactiveTriggerEngine {\n private readonly bus: EventBus;\n private readonly debug: boolean;\n private readonly onTrigger?: (trigger: ProactiveTrigger) => void;\n\n /** Collected unsubscribe functions from bus.on(). */\n private unsubs: Array<() => void> = [];\n\n /** Cooldown map: trigger key → last-fired timestamp. */\n private cooldowns = new Map<string, number>();\n\n /** Progressive dwell: sectionId → number of times triggered. */\n private dwellCounts = new Map<string, number>();\n\n /** Track forms the user started interacting with. */\n private formTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Track sections where frustration already fired (once per section). */\n private frustrationFired = new Set<string>();\n\n /** Track whether idle-help has fired on this page. */\n private idleFiredThisPage = false;\n\n private _quietMode = false;\n private started = false;\n\n constructor(options: ProactiveOptions) {\n this.bus = options.bus;\n this.debug = options.debug ?? false;\n this.onTrigger = options.onTrigger;\n }\n\n // ---- quietMode accessor -------------------------------------------------\n\n get quietMode(): boolean {\n return this._quietMode;\n }\n\n set quietMode(value: boolean) {\n this._quietMode = value;\n if (this.debug) {\n console.debug(LOG_PREFIX, `Quiet mode ${value ? 'enabled' : 'disabled'}`);\n }\n }\n\n // ---- Lifecycle -----------------------------------------------------------\n\n /** Subscribe to bus events and check for first-visit greeting. */\n start(): void {\n if (this.started) return;\n this.started = true;\n\n this.checkFirstVisitGreeting();\n\n // awareness:idle\n this.unsubs.push(\n this.bus.on('awareness:idle', (data) => {\n this.handleIdle(data.durationMs);\n }),\n );\n\n // awareness:dwell\n this.unsubs.push(\n this.bus.on('awareness:dwell', (data) => {\n this.handleDwell(data.sectionId, data.durationMs);\n }),\n );\n\n // awareness:rage-click\n this.unsubs.push(\n this.bus.on('awareness:rage-click', (data) => {\n this.handleRageClick(data.selector, data.clicks);\n }),\n );\n\n // dom:route-change — used for navigation commentary + page reset\n this.unsubs.push(\n this.bus.on('dom:route-change', (data) => {\n this.handleDomRouteChange(data.from, data.to);\n }),\n );\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Started — subscribed to awareness & dom events');\n }\n }\n\n /** Unsubscribe all bus listeners and clear internal state. */\n stop(): void {\n for (const unsub of this.unsubs) {\n unsub();\n }\n this.unsubs = [];\n\n // Clear any pending form-abandonment timers\n for (const timer of this.formTimers.values()) {\n clearTimeout(timer);\n }\n this.formTimers.clear();\n\n this.started = false;\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Stopped — all listeners removed');\n }\n }\n\n /** Alias for {@link stop}. */\n destroy(): void {\n this.stop();\n }\n\n // ---- External notifications ---------------------------------------------\n\n /**\n * Notify the engine about a route change.\n * Called from the NavigationController or externally.\n */\n onRouteChange(from: string, to: string): void {\n this.handleNavigation(from, to);\n }\n\n /**\n * Notify the engine that the user started interacting with a form.\n * If the user does not continue within {@link FORM_ABANDON_MS}, a\n * `form-abandonment` trigger fires (once per form).\n */\n onFormInteractionStart(formSelector: string): void {\n // If there is already a timer for this form, reset it\n const existing = this.formTimers.get(formSelector);\n if (existing) {\n clearTimeout(existing);\n }\n\n const timer = setTimeout(() => {\n this.formTimers.delete(formSelector);\n this.fireTrigger({\n type: 'form-abandonment',\n selector: formSelector,\n message: `User started a form (${formSelector}) but stopped interacting for ${FORM_ABANDON_MS / 1000}s. They may need help.`,\n }, `form-abandonment:${formSelector}`);\n }, FORM_ABANDON_MS);\n\n this.formTimers.set(formSelector, timer);\n\n if (this.debug) {\n console.debug(LOG_PREFIX, `Form interaction started: ${formSelector}`);\n }\n }\n\n /** Reset all cooldowns and internal tracking state (useful for testing). */\n resetCooldowns(): void {\n this.cooldowns.clear();\n this.dwellCounts.clear();\n this.frustrationFired.clear();\n this.idleFiredThisPage = false;\n\n for (const timer of this.formTimers.values()) {\n clearTimeout(timer);\n }\n this.formTimers.clear();\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'All cooldowns and state reset');\n }\n }\n\n // ---- Internal handlers ---------------------------------------------------\n\n private checkFirstVisitGreeting(): void {\n if (typeof window === 'undefined' || typeof localStorage === 'undefined') {\n return;\n }\n\n try {\n const visited = localStorage.getItem(STORAGE_KEY);\n\n if (visited === null) {\n // First visit ever — fire greeting\n localStorage.setItem(STORAGE_KEY, Date.now().toString());\n\n this.fireTrigger({\n type: 'greeting',\n message: 'First-time visitor detected. Show a visual greeting (no audio).',\n }, 'greeting');\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'First visit — greeting triggered');\n }\n return;\n }\n\n // Return visitor — check if within 7 days\n const visitedAt = parseInt(visited, 10);\n if (Number.isNaN(visitedAt)) {\n // Stored timestamp is corrupt — skip return-visitor logic\n return;\n }\n\n const elapsed = Date.now() - visitedAt;\n if (elapsed <= SEVEN_DAYS_MS && this.debug) {\n console.debug(LOG_PREFIX, 'Return visitor within 7 days — silent');\n } else if (this.debug) {\n console.debug(LOG_PREFIX, 'Return visitor after 7 days');\n }\n } catch {\n // localStorage may be unavailable (e.g. iframe sandbox)\n if (this.debug) {\n console.warn(LOG_PREFIX, 'localStorage unavailable — skipping greeting check');\n }\n }\n }\n\n private handleIdle(durationMs: number): void {\n if (durationMs < IDLE_THRESHOLD_MS) return;\n if (this.idleFiredThisPage) return;\n\n this.idleFiredThisPage = true;\n\n this.fireTrigger({\n type: 'idle-help',\n message: `User has been idle for ${Math.round(durationMs / 1000)}s. They may be stuck or unsure what to do next.`,\n }, 'idle-help');\n }\n\n private handleDwell(sectionId: string, durationMs: number): void {\n if (durationMs < DWELL_THRESHOLD_MS) return;\n\n const count = this.dwellCounts.get(sectionId) ?? 0;\n\n // After 4 dwell triggers for the same section, stop entirely\n if (count >= DWELL_COOLDOWNS.length + 1) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Dwell cap reached for section \"${sectionId}\" — suppressed`);\n }\n return;\n }\n\n // Check progressive cooldown\n if (count > 0) {\n const cooldownMs = DWELL_COOLDOWNS[Math.min(count - 1, DWELL_COOLDOWNS.length - 1)]!;\n const key = `dwell:${sectionId}`;\n const lastFired = this.cooldowns.get(key) ?? 0;\n\n if (Date.now() - lastFired < cooldownMs) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Dwell cooldown active for \"${sectionId}\" — suppressed`);\n }\n return;\n }\n }\n\n this.dwellCounts.set(sectionId, count + 1);\n\n this.fireTrigger({\n type: 'dwell-commentary',\n sectionId,\n message: `User has been dwelling on section \"${sectionId}\" for ${Math.round(durationMs / 1000)}s. They may need more context.`,\n }, `dwell:${sectionId}`);\n }\n\n private handleRageClick(selector: string, clicks: number): void {\n // Derive a \"section\" key from the selector for once-per-section tracking\n const sectionKey = selector;\n\n if (this.frustrationFired.has(sectionKey)) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Frustration already fired for \"${selector}\" — suppressed`);\n }\n return;\n }\n\n this.frustrationFired.add(sectionKey);\n\n this.fireTrigger({\n type: 'frustration',\n selector,\n message: `User rage-clicked (${clicks} clicks) on \"${selector}\". They seem frustrated — offer help.`,\n }, `frustration:${sectionKey}`);\n }\n\n private handleNavigation(from: string, to: string): void {\n // Reset per-page cooldowns on page change\n this.idleFiredThisPage = false;\n\n const key = 'navigation-commentary';\n if (this.isCooldownActive(key, NAVIGATION_COOLDOWN_MS)) {\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Navigation cooldown active — suppressed');\n }\n return;\n }\n\n this.fireTrigger({\n type: 'navigation-commentary',\n message: `User navigated from \"${from}\" to \"${to}\". Offer context about the new page.`,\n }, key);\n }\n\n /**\n * Handler for the bus `dom:route-change` event.\n * Delegates to the shared navigation logic.\n */\n private handleDomRouteChange(from: string, to: string): void {\n this.handleNavigation(from, to);\n }\n\n // ---- Trigger dispatch ----------------------------------------------------\n\n /**\n * Fire a trigger if quiet mode is off, recording the cooldown timestamp.\n */\n private fireTrigger(\n partial: Omit<ProactiveTrigger, 'timestamp'>,\n cooldownKey: string,\n ): void {\n if (this._quietMode) {\n if (this.debug) {\n console.debug(LOG_PREFIX, `Quiet mode — suppressed trigger: ${partial.type}`);\n }\n return;\n }\n\n const trigger: ProactiveTrigger = {\n ...partial,\n timestamp: Date.now(),\n };\n\n this.cooldowns.set(cooldownKey, trigger.timestamp);\n\n if (this.debug) {\n console.debug(LOG_PREFIX, 'Trigger fired:', trigger.type, trigger);\n }\n\n if (this.onTrigger) {\n try {\n this.onTrigger(trigger);\n } catch (err) {\n console.error(LOG_PREFIX, 'onTrigger callback error:', err);\n }\n }\n }\n\n // ---- Cooldown helpers ----------------------------------------------------\n\n private isCooldownActive(key: string, cooldownMs: number): boolean {\n const lastFired = this.cooldowns.get(key);\n if (lastFired === undefined) return false;\n return Date.now() - lastFired < cooldownMs;\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Client-Side Rate Limiter\n// ---------------------------------------------------------------------------\n//\n// Cost-protection guardrails. These limits are trivially bypassable and exist\n// solely to:\n// 1. Protect users from unexpected costs on BYOK keys\n// 2. Prevent runaway SDK loops from burning through API quotas\n//\n// NOT a security measure — documented as \"cost protection, not security\".\n// ---------------------------------------------------------------------------\n\nimport { EventBus } from '../bus/index.js';\nimport {\n ResourceExhaustedError,\n ErrorCodes,\n} from '../errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LOG_PREFIX = '[GuideKit:RateLimiter]';\n\nconst DEFAULT_MAX_LLM_CALLS_PER_MINUTE = 10;\nconst DEFAULT_MAX_STT_MINUTES_PER_SESSION = 60;\nconst DEFAULT_MAX_TTS_CHARS_PER_SESSION = 50_000;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface RateLimits {\n maxLLMCallsPerMinute?: number;\n maxSTTMinutesPerSession?: number;\n maxTTSCharsPerSession?: number;\n}\n\nexport interface RateLimiterOptions {\n bus?: EventBus;\n limits?: RateLimits;\n debug?: boolean;\n}\n\nexport interface RateLimiterState {\n llmCallsInWindow: number;\n sttMinutesUsed: number;\n ttsCharsUsed: number;\n llmWindowStart: number;\n}\n\n// ---------------------------------------------------------------------------\n// RateLimiter\n// ---------------------------------------------------------------------------\n\nexport class RateLimiter {\n private readonly bus: EventBus | null;\n private readonly debug: boolean;\n\n // Configurable limits\n private maxLLMCallsPerMinute: number;\n private maxSTTMinutesPerSession: number;\n private maxTTSCharsPerSession: number;\n\n // LLM: sliding window (timestamps of recent calls)\n private llmCallTimestamps: number[] = [];\n\n // STT: cumulative session total (milliseconds for precision)\n private sttMs = 0;\n private sttStartedAt: number | null = null;\n\n // TTS: cumulative session total (characters)\n private ttsChars = 0;\n\n constructor(options?: RateLimiterOptions) {\n this.bus = options?.bus ?? null;\n this.debug = options?.debug ?? false;\n\n const limits = options?.limits;\n this.maxLLMCallsPerMinute =\n limits?.maxLLMCallsPerMinute ?? DEFAULT_MAX_LLM_CALLS_PER_MINUTE;\n this.maxSTTMinutesPerSession =\n limits?.maxSTTMinutesPerSession ?? DEFAULT_MAX_STT_MINUTES_PER_SESSION;\n this.maxTTSCharsPerSession =\n limits?.maxTTSCharsPerSession ?? DEFAULT_MAX_TTS_CHARS_PER_SESSION;\n }\n\n // -------------------------------------------------------------------------\n // LLM rate limiting\n // -------------------------------------------------------------------------\n\n /**\n * Check whether an LLM call is allowed. If allowed, records the call.\n * Throws `ResourceExhaustedError` if the limit is exceeded.\n */\n checkLLMCall(): void {\n const now = Date.now();\n const windowStart = now - 60_000;\n\n // Prune timestamps outside the 1-minute window\n this.llmCallTimestamps = this.llmCallTimestamps.filter(\n (t) => t > windowStart,\n );\n\n if (this.llmCallTimestamps.length >= this.maxLLMCallsPerMinute) {\n const err = new ResourceExhaustedError({\n code: ErrorCodes.RATE_LIMIT_CLIENT,\n message: `LLM rate limit exceeded: ${this.maxLLMCallsPerMinute} calls per minute.`,\n suggestion: `Wait a moment before sending another message, or increase rateLimits.maxLLMCallsPerMinute.`,\n });\n this.emitError(err);\n throw err;\n }\n\n this.llmCallTimestamps.push(now);\n this.log('LLM call recorded', {\n count: this.llmCallTimestamps.length,\n max: this.maxLLMCallsPerMinute,\n });\n }\n\n // -------------------------------------------------------------------------\n // STT rate limiting\n // -------------------------------------------------------------------------\n\n /** Call when STT streaming starts. */\n sttStart(): void {\n if (this.sttStartedAt !== null) return; // already streaming\n this.sttStartedAt = Date.now();\n this.log('STT streaming started');\n }\n\n /** Call when STT streaming stops. Accumulates duration. */\n sttStop(): void {\n if (this.sttStartedAt === null) return;\n const elapsed = Date.now() - this.sttStartedAt;\n this.sttMs += elapsed;\n this.sttStartedAt = null;\n this.log('STT streaming stopped', {\n elapsedMs: elapsed,\n totalMinutes: this.sttMinutesUsed,\n });\n }\n\n /**\n * Check whether STT streaming is within limits.\n * Throws `ResourceExhaustedError` if exceeded.\n */\n checkSTT(): void {\n const totalMinutes = this.sttMinutesUsed;\n if (totalMinutes >= this.maxSTTMinutesPerSession) {\n this.sttStop(); // stop the clock\n const err = new ResourceExhaustedError({\n code: ErrorCodes.RATE_LIMIT_CLIENT,\n message: `STT session limit exceeded: ${this.maxSTTMinutesPerSession} minutes per session.`,\n suggestion: `Voice input limit reached. Use text input, or increase rateLimits.maxSTTMinutesPerSession.`,\n });\n this.emitError(err);\n throw err;\n }\n }\n\n /** Current STT minutes used (including active stream). */\n private get sttMinutesUsed(): number {\n let totalMs = this.sttMs;\n if (this.sttStartedAt !== null) {\n const activeMs = Date.now() - this.sttStartedAt;\n const maxSessionMs = this.maxSTTMinutesPerSession * 60_000;\n const maxActiveMs = maxSessionMs * 2;\n\n if (activeMs > maxActiveMs) {\n console.warn(\n `${LOG_PREFIX} STT stream running for ${Math.round(activeMs / 60_000)}min without sttStop() — ` +\n `capping at 2x session limit (${this.maxSTTMinutesPerSession * 2}min).`,\n );\n // Auto-cap: freeze the accumulated time and clear the start marker\n this.sttMs += maxActiveMs;\n this.sttStartedAt = null;\n totalMs = this.sttMs;\n } else {\n totalMs += activeMs;\n }\n }\n return totalMs / 60_000;\n }\n\n // -------------------------------------------------------------------------\n // TTS rate limiting\n // -------------------------------------------------------------------------\n\n /**\n * Record TTS character usage. Throws `ResourceExhaustedError` if limit exceeded.\n */\n checkTTS(charCount: number): void {\n if (this.ttsChars + charCount > this.maxTTSCharsPerSession) {\n const err = new ResourceExhaustedError({\n code: ErrorCodes.RATE_LIMIT_CLIENT,\n message: `TTS character limit exceeded: ${this.maxTTSCharsPerSession} characters per session.`,\n suggestion: `Voice output limit reached. Responses will be text-only, or increase rateLimits.maxTTSCharsPerSession.`,\n });\n this.emitError(err);\n throw err;\n }\n\n this.ttsChars += charCount;\n this.log('TTS chars recorded', {\n added: charCount,\n total: this.ttsChars,\n max: this.maxTTSCharsPerSession,\n });\n }\n\n // -------------------------------------------------------------------------\n // State & config\n // -------------------------------------------------------------------------\n\n /** Get the current rate limiter state for monitoring. */\n getState(): RateLimiterState {\n const now = Date.now();\n const windowStart = now - 60_000;\n return {\n llmCallsInWindow: this.llmCallTimestamps.filter((t) => t > windowStart)\n .length,\n sttMinutesUsed: Math.round(this.sttMinutesUsed * 100) / 100,\n ttsCharsUsed: this.ttsChars,\n llmWindowStart: windowStart,\n };\n }\n\n /** Update limits at runtime. */\n setLimits(limits: RateLimits): void {\n if (limits.maxLLMCallsPerMinute !== undefined) {\n this.maxLLMCallsPerMinute = limits.maxLLMCallsPerMinute;\n }\n if (limits.maxSTTMinutesPerSession !== undefined) {\n this.maxSTTMinutesPerSession = limits.maxSTTMinutesPerSession;\n }\n if (limits.maxTTSCharsPerSession !== undefined) {\n this.maxTTSCharsPerSession = limits.maxTTSCharsPerSession;\n }\n this.log('Limits updated', limits);\n }\n\n /** Reset all counters (e.g., for testing or new session). */\n reset(): void {\n this.llmCallTimestamps = [];\n this.sttMs = 0;\n this.sttStartedAt = null;\n this.ttsChars = 0;\n this.log('Counters reset');\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private emitError(err: ResourceExhaustedError): void {\n if (this.bus) {\n this.bus.emit('error', err);\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.debug(LOG_PREFIX, ...args);\n }\n }\n}\n","// -----------------------------------------------------------------------\n// GuideKit SDK - Internationalization (i18n) Module\n// Provides localized strings for all SDK UI elements.\n// -----------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All translatable string keys used by the SDK UI. */\nexport interface I18nStrings {\n // Widget\n widgetTitle: string;\n openAssistant: string;\n closeAssistant: string;\n closePanel: string;\n sendMessage: string;\n inputPlaceholder: string;\n listeningPlaceholder: string;\n startVoice: string;\n stopVoice: string;\n\n // Status\n statusOnline: string;\n statusConnecting: string;\n statusOffline: string;\n statusListening: string;\n statusSpeaking: string;\n statusProcessing: string;\n\n // Empty state\n emptyStateMessage: string;\n\n // Errors\n errorGeneric: string;\n errorNetwork: string;\n errorMicDenied: string;\n errorRateLimit: string;\n\n // Proactive\n greetingMessage: string;\n idleHelpMessage: string;\n\n // Voice\n voiceDegradedNotice: string;\n\n // Quiet mode\n quietModeOn: string;\n quietModeOff: string;\n}\n\nexport type SupportedLocale = 'en' | 'es' | 'fr' | 'de' | 'ja' | 'zh' | 'ar' | 'pt';\n\nexport type LocaleInput = SupportedLocale | 'auto' | I18nStrings;\n\nexport interface I18nOptions {\n locale?: LocaleInput;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in locale data\n// ---------------------------------------------------------------------------\n\nconst en: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Open assistant',\n closeAssistant: 'Close assistant',\n closePanel: 'Close assistant panel',\n sendMessage: 'Send message',\n inputPlaceholder: 'Ask a question...',\n listeningPlaceholder: 'Listening...',\n startVoice: 'Start voice input',\n stopVoice: 'Stop voice input',\n\n statusOnline: 'Online',\n statusConnecting: 'Connecting...',\n statusOffline: 'Offline',\n statusListening: 'Listening...',\n statusSpeaking: 'Speaking...',\n statusProcessing: 'Processing...',\n\n emptyStateMessage:\n 'Ask me anything about this page. I can help you navigate, understand content, and more.',\n\n errorGeneric: 'Something went wrong. Please try again.',\n errorNetwork: 'Connection lost. Reconnecting...',\n errorMicDenied:\n 'Microphone access was denied. Please enable it in your browser settings.',\n errorRateLimit: 'Too many requests. Please wait a moment.',\n\n greetingMessage: 'Hi! Need help navigating this page?',\n idleHelpMessage: 'Still here if you need help!',\n\n voiceDegradedNotice: 'Voice unavailable. Switched to text mode.',\n\n quietModeOn: 'Notifications paused',\n quietModeOff: 'Notifications resumed',\n};\n\nconst es: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Abrir asistente',\n closeAssistant: 'Cerrar asistente',\n closePanel: 'Cerrar panel del asistente',\n sendMessage: 'Enviar mensaje',\n inputPlaceholder: 'Haz una pregunta...',\n listeningPlaceholder: 'Escuchando...',\n startVoice: 'Iniciar entrada de voz',\n stopVoice: 'Detener entrada de voz',\n\n statusOnline: 'En linea',\n statusConnecting: 'Conectando...',\n statusOffline: 'Sin conexion',\n statusListening: 'Escuchando...',\n statusSpeaking: 'Hablando...',\n statusProcessing: 'Procesando...',\n\n emptyStateMessage:\n 'Preguntame lo que quieras sobre esta pagina. Puedo ayudarte a navegar, entender el contenido y mucho mas.',\n\n errorGeneric: 'Algo salio mal. Por favor, intentalo de nuevo.',\n errorNetwork: 'Se perdio la conexion. Reconectando...',\n errorMicDenied:\n 'Se denego el acceso al microfono. Activalo en la configuracion de tu navegador.',\n errorRateLimit: 'Demasiadas solicitudes. Espera un momento, por favor.',\n\n greetingMessage: 'Hola! Necesitas ayuda para navegar esta pagina?',\n idleHelpMessage: 'Sigo aqui por si necesitas ayuda.',\n\n voiceDegradedNotice: 'Voz no disponible. Se cambio al modo de texto.',\n\n quietModeOn: 'Notificaciones en pausa',\n quietModeOff: 'Notificaciones reanudadas',\n};\n\nconst fr: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: \"Ouvrir l'assistant\",\n closeAssistant: \"Fermer l'assistant\",\n closePanel: \"Fermer le panneau de l'assistant\",\n sendMessage: 'Envoyer le message',\n inputPlaceholder: 'Posez une question...',\n listeningPlaceholder: \"A l'ecoute...\",\n startVoice: 'Activer la saisie vocale',\n stopVoice: 'Arreter la saisie vocale',\n\n statusOnline: 'En ligne',\n statusConnecting: 'Connexion en cours...',\n statusOffline: 'Hors ligne',\n statusListening: \"A l'ecoute...\",\n statusSpeaking: 'En train de parler...',\n statusProcessing: 'Traitement en cours...',\n\n emptyStateMessage:\n 'Posez-moi vos questions sur cette page. Je peux vous aider a naviguer, comprendre le contenu et bien plus.',\n\n errorGeneric: \"Une erreur s'est produite. Veuillez reessayer.\",\n errorNetwork: 'Connexion perdue. Reconnexion en cours...',\n errorMicDenied:\n \"L'acces au microphone a ete refuse. Veuillez l'activer dans les parametres de votre navigateur.\",\n errorRateLimit: 'Trop de requetes. Veuillez patienter un instant.',\n\n greetingMessage: 'Bonjour ! Besoin d\\'aide pour naviguer sur cette page ?',\n idleHelpMessage: 'Je suis toujours la si vous avez besoin d\\'aide !',\n\n voiceDegradedNotice: 'Voix indisponible. Passage en mode texte.',\n\n quietModeOn: 'Notifications en pause',\n quietModeOff: 'Notifications reprises',\n};\n\nconst de: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Assistent oeffnen',\n closeAssistant: 'Assistent schliessen',\n closePanel: 'Assistenten-Panel schliessen',\n sendMessage: 'Nachricht senden',\n inputPlaceholder: 'Stelle eine Frage...',\n listeningPlaceholder: 'Hoert zu...',\n startVoice: 'Spracheingabe starten',\n stopVoice: 'Spracheingabe stoppen',\n\n statusOnline: 'Online',\n statusConnecting: 'Verbindung wird hergestellt...',\n statusOffline: 'Offline',\n statusListening: 'Hoert zu...',\n statusSpeaking: 'Spricht...',\n statusProcessing: 'Verarbeitung...',\n\n emptyStateMessage:\n 'Frag mich alles zu dieser Seite. Ich kann dir bei der Navigation helfen, Inhalte erklaeren und vieles mehr.',\n\n errorGeneric: 'Etwas ist schiefgelaufen. Bitte versuche es erneut.',\n errorNetwork: 'Verbindung verloren. Verbindung wird wiederhergestellt...',\n errorMicDenied:\n 'Mikrofonzugriff wurde verweigert. Bitte aktiviere ihn in deinen Browsereinstellungen.',\n errorRateLimit: 'Zu viele Anfragen. Bitte warte einen Moment.',\n\n greetingMessage: 'Hallo! Brauchst du Hilfe beim Navigieren auf dieser Seite?',\n idleHelpMessage: 'Ich bin noch da, falls du Hilfe brauchst!',\n\n voiceDegradedNotice: 'Sprache nicht verfuegbar. Wechsel zum Textmodus.',\n\n quietModeOn: 'Benachrichtigungen pausiert',\n quietModeOff: 'Benachrichtigungen fortgesetzt',\n};\n\nconst ja: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'アシスタントを開く',\n closeAssistant: 'アシスタントを閉じる',\n closePanel: 'アシスタントパネルを閉じる',\n sendMessage: 'メッセージを送信',\n inputPlaceholder: '質問してください...',\n listeningPlaceholder: '聞いています...',\n startVoice: '音声入力を開始',\n stopVoice: '音声入力を停止',\n\n statusOnline: 'オンライン',\n statusConnecting: '接続中...',\n statusOffline: 'オフライン',\n statusListening: '聞いています...',\n statusSpeaking: '話しています...',\n statusProcessing: '処理中...',\n\n emptyStateMessage:\n 'このページについて何でも聞いてください。ナビゲーション、コンテンツの理解など、お手伝いします。',\n\n errorGeneric: '問題が発生しました。もう一度お試しください。',\n errorNetwork: '接続が切断されました。再接続しています...',\n errorMicDenied:\n 'マイクへのアクセスが拒否されました。ブラウザの設定で有効にしてください。',\n errorRateLimit: 'リクエストが多すぎます。少々お待ちください。',\n\n greetingMessage: 'こんにちは!このページのナビゲーションでお手伝いしましょうか?',\n idleHelpMessage: 'お手伝いが必要でしたら、いつでもどうぞ!',\n\n voiceDegradedNotice: '音声が利用できません。テキストモードに切り替えました。',\n\n quietModeOn: '通知を一時停止中',\n quietModeOff: '通知を再開しました',\n};\n\nconst zh: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: '打开助手',\n closeAssistant: '关闭助手',\n closePanel: '关闭助手面板',\n sendMessage: '发送消息',\n inputPlaceholder: '请提问...',\n listeningPlaceholder: '正在聆听...',\n startVoice: '开始语音输入',\n stopVoice: '停止语音输入',\n\n statusOnline: '在线',\n statusConnecting: '连接中...',\n statusOffline: '离线',\n statusListening: '正在聆听...',\n statusSpeaking: '正在播报...',\n statusProcessing: '处理中...',\n\n emptyStateMessage:\n '关于这个页面,你可以问我任何问题。我可以帮你浏览页面、理解内容等等。',\n\n errorGeneric: '出了点问题,请重试。',\n errorNetwork: '连接已断开,正在重新连接...',\n errorMicDenied: '麦克风权限被拒绝,请在浏览器设置中开启。',\n errorRateLimit: '请求过于频繁,请稍候再试。',\n\n greetingMessage: '你好!需要帮你浏览这个页面吗?',\n idleHelpMessage: '我还在这里,随时可以帮忙!',\n\n voiceDegradedNotice: '语音不可用,已切换为文字模式。',\n\n quietModeOn: '通知已暂停',\n quietModeOff: '通知已恢复',\n};\n\nconst ar: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'فتح المساعد',\n closeAssistant: 'إغلاق المساعد',\n closePanel: 'إغلاق لوحة المساعد',\n sendMessage: 'إرسال الرسالة',\n inputPlaceholder: 'اطرح سؤالاً...',\n listeningPlaceholder: 'جارٍ الاستماع...',\n startVoice: 'بدء الإدخال الصوتي',\n stopVoice: 'إيقاف الإدخال الصوتي',\n\n statusOnline: 'متصل',\n statusConnecting: 'جارٍ الاتصال...',\n statusOffline: 'غير متصل',\n statusListening: 'جارٍ الاستماع...',\n statusSpeaking: 'جارٍ التحدث...',\n statusProcessing: 'جارٍ المعالجة...',\n\n emptyStateMessage:\n 'اسألني أي شيء عن هذه الصفحة. يمكنني مساعدتك في التنقل وفهم المحتوى والمزيد.',\n\n errorGeneric: 'حدث خطأ ما. يرجى المحاولة مرة أخرى.',\n errorNetwork: 'انقطع الاتصال. جارٍ إعادة الاتصال...',\n errorMicDenied:\n 'تم رفض الوصول إلى الميكروفون. يرجى تفعيله من إعدادات المتصفح.',\n errorRateLimit: 'طلبات كثيرة جداً. يرجى الانتظار لحظة.',\n\n greetingMessage: 'مرحباً! هل تحتاج مساعدة في تصفح هذه الصفحة؟',\n idleHelpMessage: 'ما زلت هنا إذا احتجت مساعدة!',\n\n voiceDegradedNotice: 'الصوت غير متاح. تم التبديل إلى الوضع النصي.',\n\n quietModeOn: 'الإشعارات متوقفة مؤقتاً',\n quietModeOff: 'تم استئناف الإشعارات',\n};\n\nconst pt: I18nStrings = {\n widgetTitle: 'GuideKit',\n openAssistant: 'Abrir assistente',\n closeAssistant: 'Fechar assistente',\n closePanel: 'Fechar painel do assistente',\n sendMessage: 'Enviar mensagem',\n inputPlaceholder: 'Faca uma pergunta...',\n listeningPlaceholder: 'Ouvindo...',\n startVoice: 'Iniciar entrada de voz',\n stopVoice: 'Parar entrada de voz',\n\n statusOnline: 'Online',\n statusConnecting: 'Conectando...',\n statusOffline: 'Offline',\n statusListening: 'Ouvindo...',\n statusSpeaking: 'Falando...',\n statusProcessing: 'Processando...',\n\n emptyStateMessage:\n 'Pergunte-me o que quiser sobre esta pagina. Posso ajudar a navegar, entender o conteudo e muito mais.',\n\n errorGeneric: 'Algo deu errado. Por favor, tente novamente.',\n errorNetwork: 'Conexao perdida. Reconectando...',\n errorMicDenied:\n 'O acesso ao microfone foi negado. Ative-o nas configuracoes do seu navegador.',\n errorRateLimit: 'Muitas solicitacoes. Aguarde um momento, por favor.',\n\n greetingMessage: 'Ola! Precisa de ajuda para navegar nesta pagina?',\n idleHelpMessage: 'Ainda estou aqui se precisar de ajuda!',\n\n voiceDegradedNotice: 'Voz indisponivel. Alternado para o modo texto.',\n\n quietModeOn: 'Notificacoes pausadas',\n quietModeOff: 'Notificacoes retomadas',\n};\n\n// ---------------------------------------------------------------------------\n// Locale registry\n// ---------------------------------------------------------------------------\n\nconst BUILTIN_LOCALES: Record<SupportedLocale, I18nStrings> = {\n en,\n es,\n fr,\n de,\n ja,\n zh,\n ar,\n pt,\n};\n\nconst SUPPORTED_LOCALE_CODES = new Set<string>(Object.keys(BUILTIN_LOCALES));\n\nconst LOG_PREFIX = '[GuideKit:I18n]';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isSupportedLocale(code: string): code is SupportedLocale {\n return SUPPORTED_LOCALE_CODES.has(code);\n}\n\nfunction isI18nStrings(input: unknown): input is I18nStrings {\n if (typeof input !== 'object' || input === null) return false;\n // Check for a handful of required keys to distinguish from other objects\n const obj = input as Record<string, unknown>;\n return (\n typeof obj.widgetTitle === 'string' &&\n typeof obj.sendMessage === 'string' &&\n typeof obj.errorGeneric === 'string'\n );\n}\n\n/**\n * Detect the user's locale from the `<html lang>` attribute.\n * SSR-safe: returns 'en' when `document` is not available.\n */\nfunction detectLocaleFromDocument(): SupportedLocale {\n if (typeof document === 'undefined') {\n return 'en';\n }\n\n const htmlLang = document.documentElement?.lang;\n if (!htmlLang) {\n return 'en';\n }\n\n const normalized = htmlLang.trim().toLowerCase();\n\n // Exact match (e.g. 'en', 'pt')\n if (isSupportedLocale(normalized)) {\n return normalized;\n }\n\n // Language prefix match (e.g. 'en-US' -> 'en', 'pt-BR' -> 'pt')\n const prefix = normalized.split('-')[0] ?? '';\n if (isSupportedLocale(prefix)) {\n return prefix;\n }\n\n return 'en';\n}\n\n// ---------------------------------------------------------------------------\n// I18n class\n// ---------------------------------------------------------------------------\n\nexport class I18n {\n private strings: I18nStrings;\n private resolvedLocale: string;\n private debug: boolean;\n\n constructor(options?: I18nOptions) {\n this.debug = options?.debug ?? false;\n const locale = options?.locale ?? 'auto';\n const { strings, resolvedLocale } = this.resolve(locale);\n this.strings = strings;\n this.resolvedLocale = resolvedLocale;\n\n if (this.debug) {\n console.debug(`${LOG_PREFIX} Initialized with locale \"${this.resolvedLocale}\"`);\n }\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Get a translated string by key. */\n t(key: keyof I18nStrings): string {\n const value = this.strings[key];\n if (value === undefined) {\n if (this.debug) {\n console.warn(`${LOG_PREFIX} Missing translation key \"${key}\"`);\n }\n // Fallback to English; in non-production show a debug marker\n return en[key] ?? (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production' ? key : `[MISSING: ${key}]`);\n }\n return value;\n }\n\n /** Get all strings for the current locale. */\n getStrings(): I18nStrings {\n return { ...this.strings };\n }\n\n /** Change the current locale at runtime. */\n setLocale(locale: LocaleInput): void {\n const { strings, resolvedLocale } = this.resolve(locale);\n this.strings = strings;\n this.resolvedLocale = resolvedLocale;\n\n if (this.debug) {\n console.debug(`${LOG_PREFIX} Locale changed to \"${this.resolvedLocale}\"`);\n }\n }\n\n /** The current resolved locale code (e.g. 'en', 'fr', or 'custom'). */\n get currentLocale(): string {\n return this.resolvedLocale;\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private resolve(locale: LocaleInput): {\n strings: I18nStrings;\n resolvedLocale: string;\n } {\n // Custom string map provided directly\n if (isI18nStrings(locale)) {\n // Merge with English defaults so partial overrides still work\n return {\n strings: { ...en, ...locale },\n resolvedLocale: 'custom',\n };\n }\n\n // Auto-detect from the document\n if (locale === 'auto') {\n const detected = detectLocaleFromDocument();\n if (this.debug) {\n console.debug(`${LOG_PREFIX} Auto-detected locale \"${detected}\"`);\n }\n return {\n strings: BUILTIN_LOCALES[detected],\n resolvedLocale: detected,\n };\n }\n\n // Explicit supported locale code\n if (isSupportedLocale(locale)) {\n return {\n strings: BUILTIN_LOCALES[locale],\n resolvedLocale: locale,\n };\n }\n\n // Unknown locale code -- fall back to English\n if (this.debug) {\n console.warn(\n `${LOG_PREFIX} Unknown locale \"${String(locale)}\", falling back to \"en\"`,\n );\n }\n return {\n strings: en,\n resolvedLocale: 'en',\n };\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Client-side Token Manager\n// ---------------------------------------------------------------------------\n//\n// Handles the full token lifecycle:\n// - Fetch token from the developer's token endpoint on init\n// - Auto-refresh at 80% of TTL\n// - BroadcastChannel multi-tab coordination with leader election\n// - localStorage fallback for browsers without BroadcastChannel\n// - Emits auth events (token-refreshed, token-refresh-failed, token-expired)\n// ---------------------------------------------------------------------------\n\nimport type { EventBus } from '../bus/index.js';\nimport { AuthenticationError, ErrorCodes } from '../errors/index.js';\n\nconst LOG_PREFIX = '[GuideKit:Auth]';\nconst REFRESH_THRESHOLD = 0.8; // Refresh at 80% of TTL\nconst MAX_RETRY_ATTEMPTS = 3;\nconst RETRY_BASE_MS = 1_000;\nconst BC_CHANNEL_NAME = 'guidekit-token';\nconst LS_KEY_PREFIX = 'guidekit-token:';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TokenData {\n token: string;\n expiresAt: number; // Unix seconds\n expiresIn: number; // Seconds from issuance\n fetchedAt: number; // Date.now() when fetched\n}\n\nexport interface TokenManagerOptions {\n tokenEndpoint: string;\n instanceId: string;\n bus: EventBus;\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TokenManager\n// ---------------------------------------------------------------------------\n\nexport class TokenManager {\n private readonly endpoint: string;\n private readonly instanceId: string;\n private readonly bus: EventBus;\n private readonly debug: boolean;\n\n private _token: TokenData | null = null;\n private _refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _isLeader = false;\n private _bc: BroadcastChannel | null = null;\n private _destroyed = false;\n\n constructor(options: TokenManagerOptions) {\n this.endpoint = options.tokenEndpoint;\n this.instanceId = options.instanceId;\n this.bus = options.bus;\n this.debug = options.debug ?? false;\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Current token string, or null if not yet fetched. */\n get token(): string | null {\n return this._token?.token ?? null;\n }\n\n /** Current token data, or null if not yet fetched. */\n get tokenData(): TokenData | null {\n return this._token;\n }\n\n /** Whether this tab is the leader for token refresh. */\n get isLeader(): boolean {\n return this._isLeader;\n }\n\n /**\n * Initialize the token manager: elect leader, fetch initial token,\n * schedule auto-refresh.\n */\n async start(): Promise<void> {\n if (this._destroyed) return;\n\n this.setupBroadcastChannel();\n this.electLeader();\n\n // Try to load a cached token from localStorage first\n const cached = this.loadFromStorage();\n if (cached && !this.isExpired(cached)) {\n this._token = cached;\n this.log('Loaded cached token from localStorage');\n this.scheduleRefresh();\n return;\n }\n\n // Fetch a fresh token\n await this.fetchToken();\n }\n\n /**\n * Force a token refresh, regardless of TTL.\n */\n async refresh(): Promise<void> {\n await this.fetchToken();\n }\n\n /**\n * Clean up timers, BroadcastChannel, and release leader.\n */\n destroy(): void {\n this._destroyed = true;\n\n if (this._refreshTimer !== null) {\n clearTimeout(this._refreshTimer);\n this._refreshTimer = null;\n }\n\n if (this._bc) {\n this._bc.close();\n this._bc = null;\n }\n\n this._token = null;\n this._isLeader = false;\n }\n\n // -------------------------------------------------------------------------\n // Token fetching\n // -------------------------------------------------------------------------\n\n private async fetchToken(attempt = 1): Promise<void> {\n if (this._destroyed) return;\n\n this.log(`Fetching token (attempt ${attempt}/${MAX_RETRY_ATTEMPTS})`);\n\n try {\n const response = await fetch(this.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ instanceId: this.instanceId }),\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_INVALID_KEY,\n message: `Token endpoint returned ${response.status}: ${body}`,\n suggestion: 'Check your tokenEndpoint URL and server authentication.',\n });\n }\n // Retryable server error\n throw new Error(`Token endpoint returned ${response.status}: ${body}`);\n }\n\n const data = await response.json() as {\n token?: string;\n expiresIn?: number;\n expiresAt?: number;\n };\n\n if (!data.token || typeof data.token !== 'string') {\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_ENDPOINT_FAILED,\n message: 'Token endpoint response missing \"token\" field.',\n suggestion: 'Ensure your token endpoint returns { token, expiresIn, expiresAt }.',\n });\n }\n\n const tokenData: TokenData = {\n token: data.token,\n expiresAt: data.expiresAt ?? Math.floor(Date.now() / 1000) + (data.expiresIn ?? 900),\n expiresIn: data.expiresIn ?? 900,\n fetchedAt: Date.now(),\n };\n\n this._token = tokenData;\n this.saveToStorage(tokenData);\n this.broadcastToken(tokenData);\n this.scheduleRefresh();\n\n this.bus.emit('auth:token-refreshed', { expiresAt: tokenData.expiresAt });\n this.log(`Token fetched, expires at ${new Date(tokenData.expiresAt * 1000).toISOString()}`);\n } catch (error) {\n const remaining = MAX_RETRY_ATTEMPTS - attempt;\n\n if (remaining > 0 && !(error instanceof AuthenticationError)) {\n this.log(`Token fetch failed, retrying in ${RETRY_BASE_MS * attempt}ms`);\n this.bus.emit('auth:token-refresh-failed', {\n error: error instanceof Error ? error : new Error(String(error)),\n attemptsRemaining: remaining,\n });\n\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_BASE_MS * attempt),\n );\n return this.fetchToken(attempt + 1);\n }\n\n // All retries exhausted\n this.bus.emit('auth:token-refresh-failed', {\n error: error instanceof Error ? error : new Error(String(error)),\n attemptsRemaining: 0,\n });\n\n if (error instanceof AuthenticationError) throw error;\n\n throw new AuthenticationError({\n code: ErrorCodes.AUTH_ENDPOINT_FAILED,\n message: `Failed to fetch token after ${MAX_RETRY_ATTEMPTS} attempts: ${error instanceof Error ? error.message : String(error)}`,\n suggestion: 'Check your tokenEndpoint URL and network connection.',\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Auto-refresh scheduling\n // -------------------------------------------------------------------------\n\n private scheduleRefresh(): void {\n if (this._destroyed || !this._token) return;\n\n // Clear existing timer\n if (this._refreshTimer !== null) {\n clearTimeout(this._refreshTimer);\n }\n\n const now = Date.now();\n const tokenAgeMs = now - this._token.fetchedAt;\n const ttlMs = this._token.expiresIn * 1000;\n const refreshAtMs = ttlMs * REFRESH_THRESHOLD;\n const delayMs = Math.max(0, refreshAtMs - tokenAgeMs);\n\n this.log(`Scheduling refresh in ${Math.round(delayMs / 1000)}s (80% of ${this._token.expiresIn}s TTL)`);\n\n this._refreshTimer = setTimeout(() => {\n if (this._destroyed) return;\n\n // Only the leader refreshes\n if (this._isLeader) {\n this.log('Leader performing scheduled refresh');\n this.fetchToken().catch((err) => {\n this.log(`Scheduled refresh failed: ${err}`);\n });\n } else {\n this.log('Not leader, skipping refresh (will receive via BroadcastChannel)');\n // Schedule another check in case we become leader\n this.scheduleExpiredCheck();\n }\n }, delayMs);\n }\n\n private scheduleExpiredCheck(): void {\n if (this._destroyed || !this._token) return;\n\n const now = Date.now();\n const expiresAtMs = this._token.expiresAt * 1000;\n const delayMs = Math.max(0, expiresAtMs - now);\n\n this._refreshTimer = setTimeout(() => {\n if (this._destroyed) return;\n if (this._token && this.isExpired(this._token)) {\n this.bus.emit('auth:token-expired', {} as Record<string, never>);\n // Try to refresh as last resort\n this.electLeader();\n if (this._isLeader) {\n this.fetchToken().catch(() => {});\n }\n }\n }, delayMs);\n }\n\n // -------------------------------------------------------------------------\n // BroadcastChannel (multi-tab coordination)\n // -------------------------------------------------------------------------\n\n private setupBroadcastChannel(): void {\n if (typeof BroadcastChannel === 'undefined') {\n // Fallback: always be leader if no BroadcastChannel\n this._isLeader = true;\n this.log('BroadcastChannel unavailable, acting as leader');\n return;\n }\n\n try {\n this._bc = new BroadcastChannel(`${BC_CHANNEL_NAME}:${this.instanceId}`);\n this._bc.onmessage = (event) => {\n const msg = event.data as { type: string; token?: TokenData; tabId?: string };\n\n if (msg.type === 'token-updated' && msg.token) {\n this.log('Received token from leader via BroadcastChannel');\n this._token = msg.token;\n this.saveToStorage(msg.token);\n this.scheduleRefresh();\n this.bus.emit('auth:token-refreshed', { expiresAt: msg.token.expiresAt });\n }\n\n if (msg.type === 'leader-election') {\n // Another tab is claiming leadership — yield if we're not already leader\n // or if their tabId is lexicographically lower (deterministic)\n if (this._isLeader && msg.tabId && msg.tabId < this._tabId) {\n this._isLeader = false;\n this.log('Yielded leadership to another tab');\n }\n }\n };\n } catch {\n this._isLeader = true;\n this.log('BroadcastChannel setup failed, acting as leader');\n }\n }\n\n private readonly _tabId = typeof crypto !== 'undefined' && crypto.randomUUID\n ? crypto.randomUUID()\n : Math.random().toString(36).slice(2);\n\n private electLeader(): void {\n // Simple leader election: broadcast our intent, wait for contestation\n // If no BroadcastChannel, we're always leader\n if (!this._bc) {\n this._isLeader = true;\n return;\n }\n\n this._isLeader = true;\n try {\n this._bc.postMessage({\n type: 'leader-election',\n tabId: this._tabId,\n });\n } catch {\n // Channel may be closed\n }\n\n this.log(`Elected as leader (tabId: ${this._tabId.slice(0, 8)}...)`);\n }\n\n private broadcastToken(tokenData: TokenData): void {\n if (!this._bc) return;\n try {\n this._bc.postMessage({\n type: 'token-updated',\n token: tokenData,\n });\n } catch {\n // Channel may be closed\n }\n }\n\n // -------------------------------------------------------------------------\n // localStorage fallback\n // -------------------------------------------------------------------------\n\n private get storageKey(): string {\n return `${LS_KEY_PREFIX}${this.instanceId}`;\n }\n\n private saveToStorage(data: TokenData): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(this.storageKey, JSON.stringify(data));\n }\n } catch {\n // localStorage may be full or unavailable (incognito, SSR)\n }\n }\n\n private loadFromStorage(): TokenData | null {\n try {\n if (typeof localStorage === 'undefined') return null;\n const raw = localStorage.getItem(this.storageKey);\n if (!raw) return null;\n return JSON.parse(raw) as TokenData;\n } catch {\n return null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private isExpired(data: TokenData): boolean {\n const nowSec = Math.floor(Date.now() / 1000);\n return nowSec >= data.expiresAt;\n }\n\n private log(message: string): void {\n if (this.debug) {\n console.debug(`${LOG_PREFIX} ${message}`);\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// GuideKit SDK – Core Orchestrator\n// ---------------------------------------------------------------------------\n//\n// The main class that wires all subsystems together. The constructor does NOT\n// call any browser APIs — everything is lazily initialized in `init()` so the\n// module is safe to import in SSR / Node environments.\n// ---------------------------------------------------------------------------\n\nimport { EventBus, createEventBus } from './bus/index.js';\nimport { ResourceManager, SingletonGuard } from './resources/index.js';\nimport { DOMScanner } from './dom/index.js';\nimport { ContextManager } from './context/index.js';\nimport { LLMOrchestrator } from './llm/index.js';\nimport { ToolExecutor } from './llm/tool-executor.js';\nimport { ConnectionManager } from './connectivity/index.js';\nimport { NavigationController } from './navigation/index.js';\nimport { VoicePipeline, type VoicePipelineOptions } from './voice/index.js';\nimport { VisualGuidance } from './visual/index.js';\nimport { AwarenessSystem } from './awareness/index.js';\nimport { ProactiveTriggerEngine } from './awareness/proactive.js';\nimport { RateLimiter } from './llm/rate-limiter.js';\nimport { I18n, type LocaleInput } from './i18n/index.js';\nimport { TokenManager } from './auth/token-manager.js';\nimport type {\n PageModel,\n AgentConfig,\n ContentMapInput,\n LLMConfig,\n STTConfig,\n TTSConfig,\n GuideKitOptions,\n ToolDefinition,\n ToolParameterSchema,\n GuideKitEvent,\n AgentState,\n GuideKitStore,\n} from './types/index.js';\nimport { GuideKitError, ConfigurationError, ErrorCodes } from './errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Default deny-list for clickElement tool\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_CLICK_DENY = [\n '[type=\"submit\"]',\n '[type=\"reset\"]',\n 'button[formaction]',\n '[data-guidekit-no-click]',\n 'form',\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a UUID, guarded for non-browser environments where\n * `crypto.randomUUID()` may not be available.\n */\nfunction generateUUID(): string {\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.randomUUID === 'function'\n ) {\n return crypto.randomUUID();\n }\n\n // Fallback: manual v4 UUID generation (RFC 4122 compliant)\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Options interface\n// ---------------------------------------------------------------------------\n\n/** Result of a health check on a single service. */\nexport interface HealthCheckStatus {\n status: 'ok' | 'degraded' | 'unavailable' | 'not-configured';\n latencyMs?: number;\n error?: string;\n}\n\n/** Full health check result. */\nexport interface HealthCheckResult {\n llm: HealthCheckStatus;\n stt: HealthCheckStatus;\n tts: HealthCheckStatus;\n mic: HealthCheckStatus;\n overall: 'ok' | 'degraded' | 'unavailable';\n}\n\n/** Context passed to onBeforeLLMCall for privacy filtering. */\nexport interface BeforeLLMCallContext {\n systemPrompt: string;\n userMessage: string;\n conversationHistory: Array<{ role: string; content: string }>;\n}\n\nexport interface GuideKitCoreOptions {\n tokenEndpoint?: string;\n stt?: STTConfig;\n tts?: TTSConfig;\n llm?: LLMConfig;\n agent?: AgentConfig;\n contentMap?: ContentMapInput;\n options?: GuideKitOptions;\n instanceId?: string;\n rootElement?: HTMLElement;\n onError?: (error: GuideKitError) => void;\n onEvent?: (event: GuideKitEvent) => void;\n onReady?: () => void;\n /**\n * Privacy hook: called before every LLM request. Return modified context\n * or throw to cancel the request. Use for custom PII scrubbing.\n */\n onBeforeLLMCall?: (context: BeforeLLMCallContext) => BeforeLLMCallContext | Promise<BeforeLLMCallContext>;\n}\n\n// ---------------------------------------------------------------------------\n// GuideKitCore\n// ---------------------------------------------------------------------------\n\nexport class GuideKitCore {\n // ---- Public readonly accessors ------------------------------------------\n\n readonly instanceId: string;\n readonly bus: EventBus;\n\n // ---- Subsystems (created lazily or on init) -----------------------------\n\n private resourceManager: ResourceManager;\n private domScanner: DOMScanner | null = null;\n private contextManager: ContextManager;\n private llmOrchestrator: LLMOrchestrator | null = null;\n private connectionManager: ConnectionManager | null = null;\n private navigationController: NavigationController | null = null;\n private voicePipeline: VoicePipeline | null = null;\n private visualGuidance: VisualGuidance | null = null;\n private toolExecutor: ToolExecutor | null = null;\n private awarenessSystem: AwarenessSystem | null = null;\n private proactiveEngine: ProactiveTriggerEngine | null = null;\n private rateLimiter: RateLimiter;\n private _i18n: I18n;\n private tokenManager: TokenManager | null = null;\n\n // ---- State --------------------------------------------------------------\n\n private _isReady = false;\n private _agentState: AgentState = { status: 'idle' };\n private _currentPageModel: PageModel | null = null;\n private readonly _options: GuideKitCoreOptions;\n private _debug: boolean;\n private _sendInFlight = false;\n private _instanceAbortController = new AbortController();\n private _initPromise: Promise<void> | null = null;\n\n // ---- Store for useSyncExternalStore -------------------------------------\n\n private storeListeners: Set<() => void> = new Set();\n private _storeSnapshot: GuideKitStore;\n\n // ---- Custom actions -----------------------------------------------------\n\n private customActions = new Map<\n string,\n {\n description: string;\n parameters: Record<string, unknown>;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n }\n >();\n\n // -------------------------------------------------------------------------\n // Constructor — NO browser APIs (SSR safe)\n // -------------------------------------------------------------------------\n\n constructor(options: GuideKitCoreOptions) {\n this._options = options;\n this.instanceId = options.instanceId ?? 'default';\n this._debug = options.options?.debug ?? false;\n\n // Create EventBus (no browser APIs)\n this.bus = createEventBus({ debug: this._debug });\n\n // Get or create ResourceManager via SingletonGuard\n this.resourceManager = SingletonGuard.acquire(\n this.instanceId,\n () => new ResourceManager(this.instanceId),\n );\n\n // Create ContextManager (no browser APIs in constructor)\n this.contextManager = new ContextManager({\n agent: options.agent,\n contentMap: options.contentMap,\n debug: this._debug,\n });\n\n // Create RateLimiter (no browser APIs)\n this.rateLimiter = new RateLimiter({\n bus: this.bus,\n limits: options.options?.rateLimits,\n debug: this._debug,\n });\n\n // Create I18n (auto-detect is SSR-safe)\n this._i18n = new I18n({\n locale: (options.options?.locale as LocaleInput) ?? 'auto',\n debug: this._debug,\n });\n\n // Initialize store snapshot\n this._storeSnapshot = this.buildSnapshot();\n\n // Wire up error handler\n if (options.onError) {\n this.bus.on('error', (err) => {\n if (err instanceof GuideKitError) {\n options.onError!(err);\n }\n });\n }\n\n // Wire up event forwarding\n if (options.onEvent) {\n this.bus.onAny((data, eventName) => {\n options.onEvent!({\n type: eventName,\n data:\n typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)\n : {},\n timestamp: Date.now(),\n });\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // init() — starts all browser-dependent subsystems\n // -------------------------------------------------------------------------\n\n async init(): Promise<void> {\n if (typeof window === 'undefined') return;\n if (this._isReady) return;\n if (this._initPromise) return this._initPromise;\n\n this._initPromise = this._doInit();\n try {\n await this._initPromise;\n } catch (err) {\n this._initPromise = null;\n throw err;\n }\n }\n\n private async _doInit(): Promise<void> {\n // Validate LLM config\n const llmConfig = this._options.llm;\n if (!llmConfig && !this._options.tokenEndpoint) {\n throw new ConfigurationError({\n code: ErrorCodes.CONFIG_MISSING_REQUIRED,\n message: 'Either tokenEndpoint or llm config must be provided.',\n suggestion:\n 'Add tokenEndpoint=\"/api/guidekit/token\" or llm={{ provider: \"gemini\", apiKey: \"...\" }} to GuideKitProvider.',\n });\n }\n\n // -- Token Manager (if tokenEndpoint is provided) -----------------------\n\n if (this._options.tokenEndpoint) {\n this.tokenManager = new TokenManager({\n tokenEndpoint: this._options.tokenEndpoint,\n instanceId: this.instanceId,\n bus: this.bus,\n debug: this._debug,\n });\n await this.tokenManager.start();\n if (!this._options.llm) {\n console.warn(\n '[GuideKit] tokenEndpoint provided without llm config. ' +\n 'The session token handles auth only — llm: { provider, apiKey } is still required ' +\n 'for LLM calls. See: https://guidekit.dev/docs/provider#token-endpoint',\n );\n }\n this.resourceManager.register({\n name: 'token-manager',\n cleanup: () => this.tokenManager?.destroy(),\n });\n }\n\n // -- DOM Scanner --------------------------------------------------------\n\n this.domScanner = new DOMScanner({\n rootElement: this._options.rootElement,\n debug: this._debug,\n });\n\n // Initial scan\n this._currentPageModel = this.domScanner.scan();\n this.bus.emit('dom:scan-complete', {\n pageModel: this._currentPageModel,\n durationMs: 0,\n });\n\n // Set up MutationObserver for auto-rescan\n const unobserve = this.domScanner.observe((model) => {\n this._currentPageModel = model;\n this.bus.emit('dom:scan-complete', {\n pageModel: model,\n durationMs: 0,\n });\n this.notifyStoreListeners();\n });\n this.resourceManager.register({\n name: 'dom-observer',\n cleanup: unobserve,\n });\n\n // -- LLM Orchestrator ---------------------------------------------------\n\n if (llmConfig) {\n this.llmOrchestrator = new LLMOrchestrator({\n config: llmConfig,\n debug: this._debug,\n onChunk: (chunk) => {\n this.bus.emit('llm:response-chunk', chunk);\n },\n onToolCall: (toolCall) => {\n this.bus.emit('llm:tool-call', toolCall);\n },\n onTokenUsage: (usage) => {\n this.bus.emit('llm:token-usage', usage);\n },\n onError: (error) => {\n this.bus.emit('error', error);\n },\n });\n }\n\n // -- ConnectionManager --------------------------------------------------\n\n this.connectionManager = new ConnectionManager({\n healthEndpoint: this._options.tokenEndpoint\n ? this._options.tokenEndpoint.replace(/\\/token$/, '/health')\n : undefined,\n debug: this._debug,\n });\n this.connectionManager.onStateChange((state, previous) => {\n this.bus.emit('connectivity:state-change', { state, previous });\n });\n this.connectionManager.start();\n this.resourceManager.register({\n name: 'connection-manager',\n cleanup: () => this.connectionManager?.stop(),\n });\n\n // -- NavigationController -----------------------------------------------\n\n this.navigationController = new NavigationController({\n debug: this._debug,\n });\n this.navigationController.onRouteChange((from, to) => {\n this.bus.emit('dom:route-change', { from, to });\n\n // Re-scan DOM on route change (allow a brief settling period)\n if (this.domScanner) {\n setTimeout(() => {\n this._currentPageModel = this.domScanner!.scan();\n this.bus.emit('dom:scan-complete', {\n pageModel: this._currentPageModel,\n durationMs: 0,\n });\n this.notifyStoreListeners();\n }, 100);\n }\n });\n this.navigationController.start();\n this.resourceManager.register({\n name: 'navigation-controller',\n cleanup: () => this.navigationController?.stop(),\n });\n\n // -- Visual Guidance System -----------------------------------------------\n\n this.visualGuidance = new VisualGuidance({\n spotlightColor: this._options.options?.spotlightColor,\n debug: this._debug,\n });\n this.resourceManager.register({\n name: 'visual-guidance',\n cleanup: () => this.visualGuidance?.destroy(),\n });\n\n // -- Awareness System ---------------------------------------------------\n\n this.awarenessSystem = new AwarenessSystem({\n bus: this.bus,\n rootElement: this._options.rootElement,\n debug: this._debug,\n });\n this.awarenessSystem.start();\n this.resourceManager.register({\n name: 'awareness-system',\n cleanup: () => this.awarenessSystem?.destroy(),\n });\n\n // -- Proactive Trigger Engine ------------------------------------------\n\n this.proactiveEngine = new ProactiveTriggerEngine({\n bus: this.bus,\n debug: this._debug,\n onTrigger: (trigger) => {\n if (this._debug) {\n console.debug('[GuideKit:Core] Proactive trigger:', trigger.type, trigger);\n }\n // Forward as a generic event for developer hooks\n this._options.onEvent?.({\n type: `proactive:${trigger.type}`,\n data: trigger as unknown as Record<string, unknown>,\n timestamp: trigger.timestamp,\n });\n },\n });\n this.proactiveEngine.start();\n this.resourceManager.register({\n name: 'proactive-engine',\n cleanup: () => this.proactiveEngine?.destroy(),\n });\n\n // -- Tool Executor (multi-turn tool calling) ----------------------------\n\n this.toolExecutor = new ToolExecutor({\n maxRounds: 5,\n debug: this._debug,\n onToolCall: (name, args) => {\n this.bus.emit('llm:tool-call', { name, arguments: args });\n },\n });\n\n this.registerBuiltinTools();\n\n // -- Voice Pipeline (lazy — only init on first startListening) ----------\n // Default to web-speech (browser-native, zero-config) when no STT/TTS\n // config is provided. Falls back gracefully in non-browser environments.\n\n {\n const sttConfig: STTConfig = this._options.stt ?? { provider: 'web-speech' };\n const ttsConfig: TTSConfig = this._options.tts ?? { provider: 'web-speech' };\n\n // Build the VoicePipeline options based on provider type\n let voiceSttConfig: VoicePipelineOptions['sttConfig'];\n let voiceTtsConfig: VoicePipelineOptions['ttsConfig'];\n\n if (sttConfig.provider === 'deepgram') {\n voiceSttConfig = {\n provider: 'deepgram',\n apiKey: sttConfig.apiKey,\n model: sttConfig.model,\n };\n } else if (sttConfig.provider === 'elevenlabs') {\n voiceSttConfig = {\n provider: 'elevenlabs',\n apiKey: sttConfig.apiKey,\n language: sttConfig.language,\n };\n } else {\n voiceSttConfig = {\n provider: 'web-speech',\n language: sttConfig.language,\n continuous: sttConfig.continuous,\n interimResults: sttConfig.interimResults,\n };\n }\n\n if (ttsConfig.provider === 'elevenlabs') {\n voiceTtsConfig = {\n provider: 'elevenlabs',\n apiKey: ttsConfig.apiKey,\n voiceId: 'voiceId' in ttsConfig ? ttsConfig.voiceId : undefined,\n };\n } else {\n voiceTtsConfig = {\n provider: 'web-speech',\n voice: ttsConfig.voice,\n rate: ttsConfig.rate,\n pitch: ttsConfig.pitch,\n language: ttsConfig.language,\n };\n }\n\n try {\n this.voicePipeline = new VoicePipeline({\n sttConfig: voiceSttConfig,\n ttsConfig: voiceTtsConfig,\n debug: this._debug,\n });\n\n // Forward voice events to the EventBus\n this.voicePipeline.onStateChange((state, previous) => {\n this.bus.emit('voice:state-change', { from: previous, to: state });\n // Map voice state to agent state\n switch (state) {\n case 'listening':\n this.setAgentState({ status: 'listening', durationMs: 0 });\n break;\n case 'speaking':\n this.setAgentState({ status: 'speaking', utterance: '' });\n break;\n case 'idle':\n if (this._agentState.status !== 'processing') {\n this.setAgentState({ status: 'idle' });\n }\n break;\n }\n });\n\n this.voicePipeline.onTranscript((text, isFinal) => {\n this.bus.emit('voice:transcript', {\n text,\n isFinal,\n confidence: 0.95,\n });\n if (isFinal && text.trim()) {\n this.voicePipeline?.processTranscript(text, (t) => this.sendText(t));\n }\n });\n\n this.resourceManager.register({\n name: 'voice-pipeline',\n cleanup: () => this.voicePipeline?.destroy(),\n });\n } catch (_err) {\n // Voice pipeline may fail in non-browser environments (SSR, jsdom)\n this.voicePipeline = null as unknown as VoicePipeline;\n if (this._debug) {\n console.debug('[GuideKit:Core] Voice pipeline unavailable in this environment');\n }\n }\n }\n\n // -- Restore session ----------------------------------------------------\n\n const session = this.contextManager.restoreSession();\n if (session && this._debug) {\n console.debug(\n '[GuideKit:Core] Restored session with',\n session.conversationHistory.length,\n 'turns',\n );\n }\n\n // -- Mark ready ---------------------------------------------------------\n\n this.resourceManager.markReady();\n this._isReady = true;\n this.notifyStoreListeners();\n this._options.onReady?.();\n\n if (this._debug) {\n console.debug('[GuideKit:Core] Initialized', {\n instanceId: this.instanceId,\n sections: this._currentPageModel?.sections.length,\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // sendText — send a text message to the LLM\n // -------------------------------------------------------------------------\n\n async sendText(message_: string): Promise<string> {\n let message = message_;\n if (!this._isReady || !this.llmOrchestrator) {\n throw new ConfigurationError({\n code: ErrorCodes.CONFIG_MISSING_REQUIRED,\n message: 'SDK not initialized or LLM not configured.',\n suggestion:\n 'Ensure init() has been called and LLM config is provided.',\n });\n }\n\n if (this._sendInFlight) {\n throw new GuideKitError({\n code: 'SEND_IN_FLIGHT',\n message: 'A message is already being processed. Wait for it to complete.',\n recoverable: true,\n suggestion: 'Await the previous sendText() call before sending another message.',\n });\n }\n this._sendInFlight = true;\n\n const maxLen = this._options.options?.maxMessageLength ?? 10_000;\n if (message_.length > maxLen) {\n throw new GuideKitError({\n code: 'INPUT_TOO_LONG',\n message: `Message exceeds maximum length of ${maxLen} characters.`,\n recoverable: true,\n suggestion: `Shorten your message to ${maxLen} characters or fewer, or increase maxMessageLength in options.`,\n });\n }\n\n // Check rate limits before proceeding\n this.rateLimiter.checkLLMCall();\n\n // Update agent state\n this.setAgentState({ status: 'processing', transcript: message });\n\n // Add user turn\n this.contextManager.addTurn({\n role: 'user',\n content: message,\n timestamp: Date.now(),\n });\n\n // Build system prompt\n let systemPrompt = this.contextManager.buildSystemPrompt(\n this._currentPageModel!,\n this.getToolDefinitions(),\n );\n\n // Privacy hook — allow developer to scrub PII before LLM call\n if (this._options.onBeforeLLMCall) {\n try {\n const ctx = await this._options.onBeforeLLMCall({\n systemPrompt,\n userMessage: message,\n conversationHistory: this.contextManager\n .getHistory()\n .map((t) => ({ role: t.role, content: t.content })),\n });\n systemPrompt = ctx.systemPrompt;\n message = ctx.userMessage;\n } catch (hookErr) {\n // Hook threw — cancel the LLM call\n this.setAgentState({ status: 'idle' });\n const err =\n hookErr instanceof GuideKitError\n ? hookErr\n : new GuideKitError({\n code: ErrorCodes.PRIVACY_HOOK_CANCELLED,\n message:\n hookErr instanceof Error\n ? hookErr.message\n : 'onBeforeLLMCall hook cancelled the request.',\n recoverable: true,\n suggestion: 'Check your onBeforeLLMCall implementation.',\n });\n this.bus.emit('error', err);\n throw err;\n }\n }\n\n const conversationId = generateUUID();\n this.bus.emit('llm:response-start', { conversationId });\n\n try {\n let responseText: string;\n let totalTokens: number;\n\n // Use multi-turn ToolExecutor if available, else single-turn\n if (this.toolExecutor) {\n const result = await this.toolExecutor.executeWithTools({\n llm: this.llmOrchestrator,\n systemPrompt,\n history: this.contextManager.getHistory().slice(0, -1),\n userMessage: message,\n tools: this.getToolDefinitions(),\n signal: this._instanceAbortController.signal,\n });\n responseText = result.text;\n totalTokens = result.totalUsage.total;\n } else {\n const result = await this.llmOrchestrator.sendMessage({\n systemPrompt,\n history: this.contextManager.getHistory().slice(0, -1),\n userMessage: message,\n tools: this.getToolDefinitions(),\n signal: this._instanceAbortController.signal,\n });\n responseText = result.text;\n totalTokens = result.usage.total;\n }\n\n // Add assistant turn\n this.contextManager.addTurn({\n role: 'assistant',\n content: responseText,\n timestamp: Date.now(),\n });\n\n // Save session\n this.contextManager.saveSession();\n\n this.bus.emit('llm:response-end', {\n conversationId,\n totalTokens,\n });\n\n this.setAgentState({ status: 'idle' });\n\n return responseText;\n } catch (error) {\n const err =\n error instanceof GuideKitError\n ? error\n : new GuideKitError({\n code: ErrorCodes.UNKNOWN,\n message:\n error instanceof Error ? error.message : 'Unknown error',\n recoverable: false,\n suggestion: 'Check the console for details.',\n });\n\n this.setAgentState({ status: 'error', error: err });\n this.bus.emit('error', err);\n throw err;\n } finally {\n this._sendInFlight = false;\n }\n }\n\n // -------------------------------------------------------------------------\n // Accessors\n // -------------------------------------------------------------------------\n\n /** Get the current page model. */\n get pageModel(): PageModel | null {\n return this._currentPageModel;\n }\n\n /** Whether the SDK has been fully initialized. */\n get isReady(): boolean {\n return this._isReady;\n }\n\n /** Current agent state. */\n get agentState(): AgentState {\n return this._agentState;\n }\n\n /** Current auth token string, or null if not using token-based auth. */\n get currentToken(): string | null {\n return this.tokenManager?.token ?? null;\n }\n\n // -------------------------------------------------------------------------\n // Store subscription (for useSyncExternalStore)\n // -------------------------------------------------------------------------\n\n subscribe(listener: () => void): () => void {\n this.storeListeners.add(listener);\n return () => {\n this.storeListeners.delete(listener);\n };\n }\n\n getSnapshot(): GuideKitStore {\n return this._storeSnapshot;\n }\n\n // -------------------------------------------------------------------------\n // Custom actions\n // -------------------------------------------------------------------------\n\n registerAction(\n actionId: string,\n action: {\n description: string;\n parameters: Record<string, unknown>;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n },\n ): void {\n this.customActions.set(actionId, action);\n }\n\n // -------------------------------------------------------------------------\n // Voice control\n // -------------------------------------------------------------------------\n\n /** Start listening for voice input. Initializes voice pipeline on first call. */\n async startListening(): Promise<void> {\n if (!this.voicePipeline) {\n if (this._debug) {\n console.debug('[GuideKit:Core] No voice pipeline configured — cannot start listening');\n }\n return;\n }\n await this.voicePipeline.init();\n await this.voicePipeline.startListening();\n }\n\n /** Stop listening for voice input. */\n stopListening(): void {\n this.voicePipeline?.stopListening();\n }\n\n /** Stop current TTS playback (barge-in). */\n stopSpeaking(): void {\n this.voicePipeline?.stopSpeaking();\n }\n\n /** Whether voice pipeline is available. */\n get hasVoice(): boolean {\n return this.voicePipeline !== null;\n }\n\n // -------------------------------------------------------------------------\n // Visual guidance (public API)\n // -------------------------------------------------------------------------\n\n /** Highlight an element by sectionId or CSS selector. */\n highlight(params: {\n sectionId?: string;\n selector?: string;\n tooltip?: string;\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';\n }): boolean {\n if (!this.visualGuidance) return false;\n const result = this.visualGuidance.highlight(params);\n if (result) {\n this.bus.emit('visual:spotlight-shown', {\n selector: params.selector ?? params.sectionId ?? '',\n sectionId: params.sectionId,\n });\n }\n return result;\n }\n\n /** Dismiss the current spotlight highlight. */\n dismissHighlight(): void {\n this.visualGuidance?.dismissHighlight();\n this.bus.emit('visual:spotlight-dismissed', {});\n }\n\n /** Smooth scroll to a section. */\n scrollToSection(sectionId: string, offset?: number): void {\n this.visualGuidance?.scrollToSection(sectionId, offset);\n }\n\n /** Smooth scroll to a CSS selector. */\n scrollToSelector(selector: string, offset?: number): void {\n this.visualGuidance?.scrollToSelector(selector, offset);\n }\n\n /** Start a guided tour. */\n startTour(sectionIds: string[], mode?: 'auto' | 'manual'): void {\n this.visualGuidance?.startTour(sectionIds, mode);\n }\n\n /** Advance to next tour step. */\n nextTourStep(): void {\n this.visualGuidance?.nextTourStep();\n }\n\n /** Go back to previous tour step. */\n prevTourStep(): void {\n this.visualGuidance?.prevTourStep();\n }\n\n /** Stop the guided tour. */\n stopTour(): void {\n this.visualGuidance?.stopTour();\n }\n\n /** Navigate to a same-origin URL. */\n async navigate(href: string): Promise<boolean> {\n if (!this.navigationController) return false;\n return this.navigationController.navigate(href);\n }\n\n // -------------------------------------------------------------------------\n // Context management\n // -------------------------------------------------------------------------\n\n setPageContext(context: Record<string, unknown>): void {\n this.contextManager.setPageContext(context);\n if (this._debug) {\n console.debug('[GuideKit:Core] setPageContext', context);\n }\n }\n\n /** Get the i18n instance for localized strings. */\n get i18n(): I18n {\n return this._i18n;\n }\n\n /** Get/set quiet mode on proactive triggers. */\n get quietMode(): boolean {\n return this.proactiveEngine?.quietMode ?? false;\n }\n\n set quietMode(value: boolean) {\n if (this.proactiveEngine) {\n this.proactiveEngine.quietMode = value;\n }\n this.contextManager.quietMode = value;\n }\n\n /** Get/set user preference (voice/text). */\n get userPreference(): 'voice' | 'text' {\n return this.contextManager.userPreference;\n }\n\n set userPreference(value: 'voice' | 'text') {\n this.contextManager.userPreference = value;\n }\n\n /** Get the rate limiter for monitoring usage. */\n get rateLimiterState() {\n return this.rateLimiter.getState();\n }\n\n // -------------------------------------------------------------------------\n // Health check\n // -------------------------------------------------------------------------\n\n /**\n * Check health of all connected services.\n * Returns per-service status and an overall assessment.\n */\n async checkHealth(): Promise<HealthCheckResult> {\n const results: HealthCheckResult = {\n llm: { status: 'not-configured' },\n stt: { status: 'not-configured' },\n tts: { status: 'not-configured' },\n mic: { status: 'not-configured' },\n overall: 'ok',\n };\n\n // LLM check\n if (this.llmOrchestrator) {\n try {\n const start = Date.now();\n // Lightweight check — just verify the orchestrator is alive\n results.llm = {\n status: 'ok',\n latencyMs: Date.now() - start,\n };\n } catch (err) {\n results.llm = {\n status: 'unavailable',\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n }\n\n // STT check — report as configured only if user explicitly provided STT config\n // or if voice pipeline is active (web-speech auto-default still works on demand)\n if (this._options.stt) {\n results.stt = { status: this.voicePipeline ? 'ok' : 'degraded' };\n }\n\n // TTS check — same logic as STT\n if (this._options.tts) {\n results.tts = { status: this.voicePipeline ? 'ok' : 'degraded' };\n }\n\n // Mic check\n if (typeof navigator !== 'undefined' && navigator.mediaDevices) {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const hasMic = devices.some((d) => d.kind === 'audioinput');\n results.mic = { status: hasMic ? 'ok' : 'unavailable' };\n } catch (err) {\n results.mic = {\n status: 'unavailable',\n error: err instanceof Error ? err.message : 'Permission denied',\n };\n }\n }\n\n // Compute overall\n const statuses = [results.llm, results.stt, results.tts, results.mic];\n const configured = statuses.filter((s) => s.status !== 'not-configured');\n if (configured.some((s) => s.status === 'unavailable')) {\n results.overall = 'unavailable';\n } else if (configured.some((s) => s.status === 'degraded')) {\n results.overall = 'degraded';\n } else {\n results.overall = 'ok';\n }\n\n return results;\n }\n\n // -------------------------------------------------------------------------\n // Cleanup\n // -------------------------------------------------------------------------\n\n async destroy(): Promise<void> {\n this._instanceAbortController.abort();\n this.contextManager.saveSession();\n SingletonGuard.release(this.instanceId);\n this._isReady = false;\n this.notifyStoreListeners();\n\n if (this._debug) {\n console.debug('[GuideKit:Core] Destroyed instance', this.instanceId);\n }\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private setAgentState(state: AgentState): void {\n this._agentState = state;\n this.notifyStoreListeners();\n }\n\n private notifyStoreListeners(): void {\n this._storeSnapshot = this.buildSnapshot();\n for (const listener of this.storeListeners) {\n listener();\n }\n }\n\n private buildSnapshot(): GuideKitStore {\n return {\n status: {\n isReady: this._isReady,\n agentState: this._agentState,\n error:\n this._agentState.status === 'error'\n ? this._agentState.error\n : null,\n },\n voice: {\n isListening: this._agentState.status === 'listening',\n isSpeaking: this._agentState.status === 'speaking',\n },\n };\n }\n\n /**\n * Unified built-in tool specifications — single source of truth for both\n * tool definitions (sent to LLM) and handler registration.\n */\n private getBuiltinToolSpecs(): Array<ToolDefinition & { execute: (args: Record<string, unknown>) => Promise<unknown> }> {\n return [\n {\n name: 'highlight',\n description:\n 'Spotlight an element on the page to draw the user\\'s attention. Use sectionId to highlight a page section, or selector for a specific CSS selector. Optionally add a tooltip with explanation text.',\n parameters: {\n sectionId: { type: 'string', description: 'ID of the section to highlight' },\n selector: { type: 'string', description: 'CSS selector (overrides sectionId)' },\n tooltip: { type: 'string', description: 'Text to show in tooltip' },\n position: { type: 'string', enum: ['top', 'bottom', 'left', 'right', 'auto'], description: 'Tooltip position' },\n },\n required: [],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionId = args.sectionId as string | undefined;\n const selector = args.selector as string | undefined;\n const tooltip = args.tooltip as string | undefined;\n const position = args.position as 'top' | 'bottom' | 'left' | 'right' | 'auto' | undefined;\n const result = this.highlight({ sectionId, selector, tooltip, position });\n return { success: result };\n },\n },\n {\n name: 'dismissHighlight',\n description: 'Remove the current spotlight overlay.',\n parameters: {},\n required: [],\n schemaVersion: 1,\n execute: async () => {\n this.dismissHighlight();\n return { success: true };\n },\n },\n {\n name: 'scrollToSection',\n description:\n 'Smooth scroll to a section by its ID. Use offset to account for sticky headers.',\n parameters: {\n sectionId: { type: 'string', description: 'ID of the section to scroll to' },\n offset: { type: 'number', description: 'Pixel offset for sticky headers' },\n },\n required: ['sectionId'],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionId = args.sectionId as string;\n const offset = args.offset as number | undefined;\n this.scrollToSection(sectionId, offset);\n return { success: true };\n },\n },\n {\n name: 'navigate',\n description:\n 'Navigate to a different page within the same site. Only same-origin URLs are allowed.',\n parameters: {\n href: { type: 'string', description: 'URL or path to navigate to (same-origin only)' },\n },\n required: ['href'],\n schemaVersion: 1,\n execute: async (args) => {\n const href = args.href as string;\n const result = await this.navigate(href);\n return { success: result, navigatedTo: result ? href : null };\n },\n },\n {\n name: 'startTour',\n description:\n 'Start a guided tour through multiple sections in sequence.',\n parameters: {\n sectionIds: { type: 'array', items: { type: 'string' }, description: 'Section IDs in tour order' },\n mode: { type: 'string', enum: ['auto', 'manual'], description: 'auto advances automatically; manual waits for user' },\n },\n required: ['sectionIds'],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionIds = args.sectionIds as string[];\n const mode = (args.mode as 'auto' | 'manual') ?? 'manual';\n this.startTour(sectionIds, mode);\n return { success: true, steps: sectionIds.length };\n },\n },\n {\n name: 'readPageContent',\n description:\n 'Read visible text content of a section by ID, or search across all sections by keyword.',\n parameters: {\n sectionId: { type: 'string', description: 'Section ID to read' },\n query: { type: 'string', description: 'Keyword to search for across sections' },\n },\n required: [],\n schemaVersion: 1,\n execute: async (args) => {\n const sectionId = args.sectionId as string | undefined;\n const query = args.query as string | undefined;\n const model = this._currentPageModel;\n if (!model) return { error: 'No page model available' };\n\n if (sectionId) {\n const section = model.sections.find((s) => s.id === sectionId);\n if (section) {\n const contentMapResult = await this.contextManager.getContent(sectionId);\n return {\n sectionId: section.id,\n label: section.label,\n summary: section.summary,\n contentMap: contentMapResult,\n };\n }\n return { error: `Section \"${sectionId}\" not found` };\n }\n\n if (query) {\n const queryLower = query.toLowerCase();\n const matches = model.sections.filter(\n (s) =>\n s.label?.toLowerCase().includes(queryLower) ||\n s.summary?.toLowerCase().includes(queryLower),\n );\n return {\n query,\n results: matches.slice(0, 5).map((s) => ({\n sectionId: s.id,\n label: s.label,\n snippet: s.summary?.slice(0, 200),\n })),\n };\n }\n\n return { error: 'Provide either sectionId or query' };\n },\n },\n {\n name: 'getVisibleSections',\n description:\n 'Get the list of sections currently visible in the user viewport.',\n parameters: {},\n required: [],\n schemaVersion: 1,\n execute: async () => {\n const model = this._currentPageModel;\n if (!model) return { sections: [] };\n return {\n sections: model.sections.slice(0, 10).map((s) => ({\n id: s.id,\n label: s.label,\n selector: s.selector,\n score: s.score,\n })),\n };\n },\n },\n {\n name: 'clickElement',\n description:\n 'Programmatically click an interactive element on the page.',\n parameters: {\n selector: { type: 'string', description: 'CSS selector of the element to click' },\n },\n required: ['selector'],\n schemaVersion: 1,\n execute: async (args) => {\n if (typeof document === 'undefined') return { success: false, error: 'Not in browser' };\n const selector = args.selector as string;\n\n const el = document.querySelector(selector);\n if (!el) return { success: false, error: `Element not found: ${selector}` };\n if (!(el instanceof HTMLElement)) return { success: false, error: 'Element is not clickable' };\n\n const clickableRules = this._options.options?.clickableSelectors;\n const isInDevAllowList = clickableRules?.allow?.some((pattern) => {\n try { return el.matches(pattern); } catch { return selector === pattern; }\n }) ?? false;\n\n if (!isInDevAllowList) {\n const defaultDenied = DEFAULT_CLICK_DENY.some((pattern) => {\n try { return el.matches(pattern); } catch { return false; }\n });\n if (defaultDenied) {\n return { success: false, error: `Selector \"${selector}\" matches the default deny list. Add it to clickableSelectors.allow to override.` };\n }\n }\n\n if (clickableRules?.deny?.length) {\n const denied = clickableRules.deny.some((pattern) => {\n try { return el.matches(pattern); } catch { return selector === pattern; }\n });\n if (denied) {\n return { success: false, error: `Selector \"${selector}\" is blocked by the deny list.` };\n }\n }\n\n if (clickableRules?.allow?.length && !isInDevAllowList) {\n return { success: false, error: `Selector \"${selector}\" is not in the allowed clickable selectors list.` };\n }\n\n el.click();\n return { success: true };\n },\n },\n {\n name: 'executeCustomAction',\n description:\n 'Execute a developer-registered custom action (e.g., add to cart, submit form).',\n parameters: {\n actionId: { type: 'string', description: 'ID of the custom action' },\n params: { type: 'object', description: 'Parameters for the action' },\n },\n required: ['actionId'],\n schemaVersion: 1,\n execute: async (args) => {\n const actionId = args.actionId as string;\n const params = (args.params as Record<string, unknown>) ?? {};\n const action = this.customActions.get(actionId);\n if (!action) return { error: `Unknown action: ${actionId}` };\n try {\n const result = await action.handler(params);\n return { success: true, result };\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) };\n }\n },\n },\n ];\n }\n\n /**\n * Register all built-in tool handlers with the ToolExecutor.\n * Called once during init() after VisualGuidance and all subsystems are ready.\n */\n private registerBuiltinTools(): void {\n if (!this.toolExecutor) return;\n for (const spec of this.getBuiltinToolSpecs()) {\n this.toolExecutor.registerTool({ name: spec.name, execute: spec.execute });\n }\n }\n\n private getToolDefinitions(): ToolDefinition[] {\n const builtinTools: ToolDefinition[] = this.getBuiltinToolSpecs().map(\n ({ execute: _execute, ...def }) => def,\n );\n\n // Add custom actions as individual tool definitions for better LLM discoverability\n for (const [actionId, action] of this.customActions) {\n builtinTools.push({\n name: `action_${actionId}`,\n description: action.description,\n parameters: action.parameters as Record<string, ToolParameterSchema>,\n schemaVersion: 1,\n });\n }\n\n return builtinTools;\n }\n}\n"],"mappings":"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","names":["i","env","j","A","Float16Array","Tensor","Tensor","byteLength","InferenceSession","isNode","init_wasm_utils_env","origin","isEsmImportMetaUrlHardcodedAsFileUri","getScriptSrc","scriptSrc","inferWasmPathPrefixFromScriptSrc","isSameOrigin","normalizeUrl","fallbackUrl","preload","dynamicImportDefault","embeddedWasmModule","importWasmModule","init_wasm_utils_import","wasm","initialized","initializing","aborted","isMultiThreadSupported","isSimdSupported","isRelaxedSimdSupported","initializeWebAssembly","getInstance","init_wasm_factory","allocWasmString","iterateExtraOptions","checkLastError","init_wasm_utils","setRunOptions","init_run_options","getGraphOptimzationLevel","getExecutionMode","appendDefaultOptions","appendSessionConfig","setExecutionProviders","setSessionOptions","init_session_options","tensorDataTypeStringToEnum","tensorDataTypeEnumToString","calculateTensorSizeInBytes","tensorTypeToTypedArrayConstructor","logLevelStringToEnum","isGpuBufferSupportedType","isMLTensorSupportedType","dataLocationStringToEnum","init_wasm_common","loadFile","init_wasm_utils_load_file","initOrt","initRuntime","initEp","activeSessions","getSessionInputOutputCount","getSessionInputOutputMetadata","copyFromExternalBuffer","createSession","releaseSession","prepareInputOutputTensor","run","endProfiling","init_wasm_core_impl","initializeWebAssemblyAndOrtRuntime","initializeOrtEp","init_proxy_wrapper","encodeTensorMetadata","decodeTensorMetadata","OnnxruntimeWebAssemblySessionHandler","init_session_handler_inference","backend_wasm_exports","initializeFlags","OnnxruntimeWebAssemblyBackend","wasmBackend","init_backend_wasm","version","__esmMin","URL2","filename","prefixOverride","baseUrl","absoluteUrl","blob","url","urlOverride","isMultiThreaded","isWasmOverridden","useEmbeddedModule","wasmModuleFilename","wasmModuleUrl","needPreload","flags","timeout","numThreads","multiThreadSupported","wasmPaths","wasmPrefixOverride","mjsPathOverrideFlag","mjsPathOverride","wasmPathOverrideFlag","wasmPathOverride","wasmBinaryOverride","objectUrl","ortWasmFactory","isTimeout","tasks","resolve","reject","config","fileName","inferredWasmPathPrefix","module","what","data","allocs","dataLength","dataOffset","options","prefix","seen","handler","key","value","name","message","stack","ptrSize","paramsOffset","errorCode","errorMessagePointer","errorMessage","runOptionsHandle","runOptions","tagDataOffset","keyDataOffset","valueDataOffset","e","alloc","graphOptimizationLevel","executionMode","session","ep","sessionOptionsHandle","sessionOptions","executionProviders","epName","epOptions","deviceType","webgpuOptions","epNameDataOffset","epOptionsCount","keysOffset","valuesOffset","i","logIdDataOffset","logSeverityLevel","logVerbosityLevel","optimizedModelFilePathOffset","nameOffset","type","typeProto","dateType","dimsOrSize","elementSize","size","a","b","logLevel","location","file","readFile","createReadStream","stream","chunks","chunk","response","contentLengthHeader","fileSize","reader","buffer","pages","offset","done","chunkSize","loggingLevel","env","webgpuAdapter","powerPreference","forceFallbackAdapter","sessionHandle","index","metadataOffset","elementType","dimsCount","dims","symbolicDimNameOffset","model","modelDataOffset","modelData","modelDataLength","ioBindingHandle","inputNamesUTF8Encoded","outputNamesUTF8Encoded","loadingPromises","path","provider","webnnOptions","context","gpuDevice","inputCount","outputCount","enableGraphCapture","inputNames","outputNames","inputMetadata","outputMetadata","outputPreferredLocations","shape","nameString","buf","sessionId","ioBindingState","tensor","tensorHandles","tensorNameUTF8Encoded","dataType","actualLocation","rawData","dataByteLength","gpuBuffer","registerBuffer","mlTensor","registerMLTensor","isGraphInput","isGraphOutput","tensorName","dataTypeEnum","createTemporaryTensor","uploadTensor","tensorId","dimsOffset","d","inputIndices","inputTensors","outputIndices","outputTensors","inputOutputBound","runOptionsAllocs","inputTensorHandles","outputTensorHandles","inputOutputAllocs","preAllocatedOutputs","beforeRunStack","inputValuesOffset","inputNamesOffset","outputValuesOffset","outputNamesOffset","TRACE_EVENT_BEGIN","TRACE_EVENT_END","output","outputPromises","beforeGetTensorDataStack","tensorDataOffset","keepOutputTensor","valueType","dimsLength","preferredLocation","stringData","nextOffset","maxBytesToRead","getBuffer","bufferSize","ensureTensor","isGraphInputOutputTypeSupported","result","typedArrayConstructor","v","p","profileFileName","inputs","outputs","getName","Tensor","download","dispose","pathOrBuffer","TRACE_FUNC_BEGIN","TRACE_FUNC_END","feeds","fetches","inputArray","kvp","outputArray","t","results","resultMap","__export","simd","numCpuLogicalCores","backendName","registerBackend","InferenceSession","Tensor","LOG_PREFIX","manager","withTimeout","truncate","errorMsg","LOG_PREFIX","MAX_QUEUE_SIZE","DEFAULT_LANGUAGE","float32ToInt16","SileroVAD","lastIdx","de","pt"]}
|