@voiceinput/core 0.1.0-beta.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["#frameSamples","#ratio","#input","#filter","#filterHistory","#createLowPassFilter","#frame","#flush","#filterSample","#drain","#filterIndex","#position","#frameOffset","#emitFrame","VoiceInputError","safely","#closed","#samples","VoiceInputError","#chunks","#wake","#listeners","#textEngine","#nextOptions","#provider","#audioSource","#configuration","#snapshot","#setPreflightError","#normalizeValidationError","#setSnapshot","#activeRun","#isActive","#emit","#transition","#scheduleConnectionDeadline","#failRun","#normalizeError","#captureAudio","#scheduleDurationLimit","#consumeProviderStream","#pumpAudio","#clearConnectionTimer","#performStop","#abortRun","#clearRunTimers","#completeTextEngine","#handleProviderPart","VoiceInputError","reportUnhandledError","#past","#future","#group","#retainedBytes","#controlled","#callbacks","#target","#withGuard","#handleBeforeInput","#handleKeyDown","#handleCompositionStart","#handleCompositionEnd","#form","#handleReset","#observer","#handleInput","#handleSelectionChange","#composing","#writeDepth","VoiceInputError","#interimBehavior","#maxLength","#source","#limit","#value","#selection","#runActive","#spans","#interimTranscript","#provisional","#currentFinalSpan","#freezeProvisional","#runId","#replaceOwnedSpan","#abandonProvisional","#insertAtAnchor","#mergeFinalizedSpan","#removeOwnedSpan","#nextGeneration","sameSelection","#adjustSpansForEdit","#limitReplacement","#replaceText","#createMutation","#nextSpanId","#controlled","#model","#target","invalidConfiguration","#nextOptions","#history","#listeners","#suppressed","#closedSegments","#restoreHistory","#composing","#takeOwnership","#invalidateCompletion","#currentSegment","#emit","#beforeInput","#transformTranscript","#transformTimeoutMs","#state","#inputType","#handleInput","#reset","#availabilityChanged","#handleSelectionChange","#reconcileUncontrolledDomValue","#implicitSegment","#limitedSegment","#applyTranscript","#applyMutation","#completionGeneration","#transformSpan","VoiceInputError","VoiceInputError"],"sources":["../src/audio-worklet-source.ts","../src/browser-audio.ts","../src/audio-queue.ts","../src/transcript-boundary.ts","../src/session.ts","../src/text-engine/history.ts","../src/text-engine/dom-target.ts","../src/text-engine/ownership-model.ts","../src/text-engine/transform.ts","../src/text-engine/controller.ts","../src/text-engine.ts"],"sourcesContent":["export const VOICE_INPUT_PROCESSOR_NAME = \"voiceinput-pcm16\";\n\ninterface ProcessorOptions {\n readonly processorOptions?: {\n readonly frameSamples?: number;\n readonly targetSampleRate?: number;\n };\n}\n\ninterface WorkletMessageEvent {\n readonly data: unknown;\n}\n\ninterface WorkletPort {\n onmessage: ((event: WorkletMessageEvent) => void) | null;\n postMessage(message: unknown, transfer?: readonly ArrayBuffer[]): void;\n}\n\ninterface WorkletProcessorInstance {\n readonly port: WorkletPort;\n}\n\nexport type VoiceInputWorkletProcessor = WorkletProcessorInstance & {\n process(inputs: readonly (readonly Float32Array[])[]): boolean;\n};\n\ntype WorkletProcessorBase = new () => WorkletProcessorInstance;\ntype WorkletProcessorConstructor = new (\n options: ProcessorOptions,\n) => VoiceInputWorkletProcessor;\n\n/** Self-contained so the emitted function can also be loaded as a worklet. */\nexport function registerVoiceInputPcm16Processor(\n ProcessorBase: WorkletProcessorBase,\n sourceSampleRate: number,\n register: (name: string, processor: WorkletProcessorConstructor) => void,\n processorName: string,\n): void {\n class VoiceInputPcm16Processor\n extends ProcessorBase\n implements VoiceInputWorkletProcessor\n {\n readonly #frameSamples: number;\n readonly #ratio: number;\n readonly #input: number[] = [];\n readonly #filter: readonly number[];\n readonly #filterHistory: Float32Array;\n\n #position = 0;\n #frame: Int16Array;\n #frameOffset = 0;\n #filterIndex = 0;\n\n constructor(options: ProcessorOptions) {\n super();\n const processorOptions = options.processorOptions ?? {};\n const targetSampleRate = processorOptions.targetSampleRate ?? 16_000;\n this.#frameSamples = processorOptions.frameSamples ?? 320;\n this.#ratio = sourceSampleRate / targetSampleRate;\n this.#filter = this.#createLowPassFilter();\n this.#filterHistory = new Float32Array(this.#filter.length);\n this.#frame = new Int16Array(this.#frameSamples);\n this.port.onmessage = (event) => {\n if (\n typeof event.data === \"object\" &&\n event.data !== null &&\n \"type\" in event.data &&\n event.data.type === \"flush\"\n ) {\n this.#flush();\n this.port.postMessage({ type: \"flushed\" });\n }\n };\n }\n\n process(inputs: readonly (readonly Float32Array[])[]): boolean {\n const channels = inputs[0];\n const sampleCount = channels?.[0]?.length ?? 0;\n if (\n channels === undefined ||\n channels.length === 0 ||\n sampleCount === 0\n ) {\n return true;\n }\n for (let index = 0; index < sampleCount; index += 1) {\n let monoSample = 0;\n for (const channel of channels) {\n monoSample += channel[index] ?? 0;\n }\n this.#input.push(this.#filterSample(monoSample / channels.length));\n }\n this.#drain();\n return true;\n }\n\n #createLowPassFilter(): readonly number[] {\n if (this.#ratio <= 1) {\n return [1];\n }\n const tapCount = 31;\n const center = (tapCount - 1) / 2;\n const cutoff = 0.45 / this.#ratio;\n const coefficients: number[] = [];\n let sum = 0;\n\n for (let index = 0; index < tapCount; index += 1) {\n const offset = index - center;\n const sinc =\n offset === 0\n ? 2 * cutoff\n : Math.sin(2 * Math.PI * cutoff * offset) / (Math.PI * offset);\n const window =\n 0.42 -\n 0.5 * Math.cos((2 * Math.PI * index) / (tapCount - 1)) +\n 0.08 * Math.cos((4 * Math.PI * index) / (tapCount - 1));\n const coefficient = sinc * window;\n coefficients.push(coefficient);\n sum += coefficient;\n }\n return coefficients.map((coefficient) => coefficient / sum);\n }\n\n #filterSample(sample: number): number {\n this.#filterHistory[this.#filterIndex] = sample;\n let filtered = 0;\n for (let tap = 0; tap < this.#filter.length; tap += 1) {\n const historyIndex =\n (this.#filterIndex - tap + this.#filter.length) % this.#filter.length;\n filtered +=\n (this.#filter[tap] ?? 0) * (this.#filterHistory[historyIndex] ?? 0);\n }\n this.#filterIndex = (this.#filterIndex + 1) % this.#filter.length;\n return filtered;\n }\n\n #drain(): void {\n while (this.#position + 1 < this.#input.length) {\n const lower = Math.floor(this.#position);\n const fraction = this.#position - lower;\n const first = this.#input[lower] ?? 0;\n const second = this.#input[lower + 1] ?? first;\n const sample = first + (second - first) * fraction;\n const clamped = Math.max(-1, Math.min(1, sample));\n this.#frame[this.#frameOffset] =\n clamped < 0 ? clamped * 0x8000 : clamped * 0x7fff;\n this.#frameOffset += 1;\n\n if (this.#frameOffset === this.#frame.length) {\n this.#emitFrame(this.#frame);\n this.#frame = new Int16Array(this.#frameSamples);\n this.#frameOffset = 0;\n }\n this.#position += this.#ratio;\n }\n\n // Retain the last source sample so interpolation and phase continue\n // correctly across AudioWorklet render quanta.\n const consumed = Math.min(\n Math.floor(this.#position),\n Math.max(0, this.#input.length - 1),\n );\n if (consumed > 0) {\n this.#input.splice(0, consumed);\n this.#position -= consumed;\n }\n }\n\n #flush(): void {\n const lastSample = this.#input.at(-1);\n if (lastSample !== undefined) {\n this.#input.push(lastSample);\n this.#drain();\n }\n if (this.#frameOffset > 0) {\n this.#emitFrame(this.#frame.slice(0, this.#frameOffset));\n }\n this.#input.length = 0;\n this.#position = 0;\n this.#frame = new Int16Array(this.#frameSamples);\n this.#frameOffset = 0;\n }\n\n #emitFrame(frame: Int16Array): void {\n const buffer = frame.buffer as ArrayBuffer;\n this.port.postMessage(buffer, [buffer]);\n }\n }\n\n register(processorName, VoiceInputPcm16Processor);\n}\n\nexport const AUDIO_WORKLET_SOURCE = `(${registerVoiceInputPcm16Processor.toString()})(AudioWorkletProcessor, sampleRate, registerProcessor, ${JSON.stringify(\n VOICE_INPUT_PROCESSOR_NAME,\n)});`;\n","import { VoiceInputError } from \"@voiceinput/provider\";\n\nimport {\n AUDIO_WORKLET_SOURCE,\n VOICE_INPUT_PROCESSOR_NAME,\n} from \"./audio-worklet-source.js\";\nimport type {\n PreparedVoiceAudioSource,\n VoiceAudioSource,\n VoiceAudioSourcePrepareOptions,\n} from \"./session.js\";\n\nconst DEFAULT_FRAME_DURATION_MS = 20;\nconst FLUSH_TIMEOUT_MS = 500;\n\nexport type BrowserVoiceInputCapability =\n | \"secure-context\"\n | \"media-devices\"\n | \"get-user-media\"\n | \"audio-context\"\n | \"audio-worklet\";\n\nexport interface BrowserVoiceInputSupport {\n readonly isSupported: boolean;\n readonly missingCapabilities: readonly BrowserVoiceInputCapability[];\n}\n\nexport interface CreateBrowserAudioSourceOptions {\n /** Additional microphone constraints. VoiceInput always requests mono audio. */\n constraints?: MediaTrackConstraints;\n /** Duration of each emitted PCM16 frame. Defaults to 20 milliseconds. */\n frameDurationMs?: number;\n /** Self-hosted AudioWorklet module URL. The Blob-backed module is used by default. */\n workletModuleUrl?: string | URL;\n}\n\nexport function getBrowserVoiceInputSupport(): BrowserVoiceInputSupport {\n const missingCapabilities: BrowserVoiceInputCapability[] = [];\n const browser = globalThis as typeof globalThis & {\n AudioContext?: typeof AudioContext;\n webkitAudioContext?: typeof AudioContext;\n };\n\n if (globalThis.isSecureContext !== true) {\n missingCapabilities.push(\"secure-context\");\n }\n if (\n typeof navigator === \"undefined\" ||\n navigator.mediaDevices === undefined\n ) {\n missingCapabilities.push(\"media-devices\");\n } else if (typeof navigator.mediaDevices.getUserMedia !== \"function\") {\n missingCapabilities.push(\"get-user-media\");\n }\n if (\n browser.AudioContext === undefined &&\n browser.webkitAudioContext === undefined\n ) {\n missingCapabilities.push(\"audio-context\");\n } else {\n const AudioContextConstructor =\n browser.AudioContext ?? browser.webkitAudioContext;\n if (\n AudioContextConstructor === undefined ||\n !(\"audioWorklet\" in AudioContextConstructor.prototype) ||\n typeof globalThis.AudioWorkletNode !== \"function\"\n ) {\n missingCapabilities.push(\"audio-worklet\");\n }\n }\n\n return Object.freeze({\n isSupported: missingCapabilities.length === 0,\n missingCapabilities: Object.freeze(missingCapabilities),\n });\n}\n\nexport function createBrowserAudioSource(\n options: CreateBrowserAudioSourceOptions = {},\n): VoiceAudioSource {\n const frameDurationMs = options.frameDurationMs ?? DEFAULT_FRAME_DURATION_MS;\n if (!Number.isFinite(frameDurationMs) || frameDurationMs <= 0) {\n throw new VoiceInputError({\n code: \"invalid-configuration\",\n message: \"frameDurationMs must be a positive finite number.\",\n });\n }\n const workletModuleUrl =\n options.workletModuleUrl === undefined\n ? undefined\n : String(options.workletModuleUrl);\n if (workletModuleUrl !== undefined && workletModuleUrl.trim().length === 0) {\n throw new VoiceInputError({\n code: \"invalid-configuration\",\n message: \"workletModuleUrl must be a non-empty URL.\",\n });\n }\n\n return {\n async prepare(prepareOptions) {\n assertBrowserSupport();\n assertUserActivation();\n return prepareBrowserAudio(prepareOptions, {\n constraints: options.constraints,\n frameDurationMs,\n workletModuleUrl,\n });\n },\n };\n}\n\nasync function prepareBrowserAudio(\n prepareOptions: VoiceAudioSourcePrepareOptions,\n options: {\n constraints: MediaTrackConstraints | undefined;\n frameDurationMs: number;\n workletModuleUrl: string | undefined;\n },\n): Promise<PreparedVoiceAudioSource> {\n const { abortSignal, sampleRate } = prepareOptions;\n throwIfAborted(abortSignal);\n\n let mediaStream: MediaStream | undefined;\n let audioContext: AudioContext | undefined;\n let sourceNode: MediaStreamAudioSourceNode | undefined;\n let workletNode: AudioWorkletNode | undefined;\n let silentOutput: GainNode | undefined;\n let streamController: ReadableStreamDefaultController<Int16Array> | undefined;\n let closeContextPromise: Promise<void> | undefined;\n let flushTimer: ReturnType<typeof setTimeout> | undefined;\n let resolveFlush: (() => void) | undefined;\n let started = false;\n let closed = false;\n let tracksStopped = false;\n\n const stream = new ReadableStream<Int16Array>(\n {\n start(controller) {\n streamController = controller;\n },\n },\n { highWaterMark: sampleRate * 15, size: (chunk) => chunk.length },\n );\n\n const cleanup = (error?: unknown): void => {\n if (closed) {\n return;\n }\n closed = true;\n abortSignal.removeEventListener(\"abort\", handleAbort);\n safely(() => sourceNode?.disconnect());\n safely(() => workletNode?.disconnect());\n safely(() => silentOutput?.disconnect());\n safely(() => workletNode?.port.close());\n stopTracks();\n if (audioContext !== undefined && audioContext.state !== \"closed\") {\n closeContextPromise ??= audioContext.close().catch(() => {});\n }\n if (streamController !== undefined) {\n if (error === undefined) {\n safely(() => streamController?.close());\n } else {\n safely(() => streamController?.error(error));\n }\n }\n if (flushTimer !== undefined) {\n clearTimeout(flushTimer);\n flushTimer = undefined;\n }\n resolveFlush?.();\n resolveFlush = undefined;\n };\n\n function stopTracks(): void {\n if (tracksStopped || mediaStream === undefined) {\n return;\n }\n tracksStopped = true;\n for (const track of mediaStream.getTracks()) {\n safely(() => track.stop());\n }\n }\n\n const handleAbort = (): void => cleanup();\n abortSignal.addEventListener(\"abort\", handleAbort, { once: true });\n\n try {\n mediaStream = await navigator.mediaDevices.getUserMedia({\n audio: {\n ...options.constraints,\n channelCount: 1,\n },\n video: false,\n });\n if (closed || abortSignal.aborted) {\n stopTracks();\n }\n throwIfAborted(abortSignal);\n prepareOptions.onAcquired?.();\n throwIfAborted(abortSignal);\n\n const AudioContextConstructor = getAudioContextConstructor();\n audioContext = createAudioContext(AudioContextConstructor, sampleRate);\n if (audioContext.audioWorklet === undefined) {\n throw unsupportedBrowser([\"audio-worklet\"]);\n }\n\n try {\n await loadWorklet(audioContext, options.workletModuleUrl);\n } catch (cause) {\n throwIfAborted(abortSignal);\n throw new VoiceInputError({\n code: \"audio-error\",\n message:\n \"The microphone AudioWorklet could not be loaded. Check workletModuleUrl and the page's Content Security Policy.\",\n retryable: true,\n cause,\n });\n }\n throwIfAborted(abortSignal);\n\n sourceNode = audioContext.createMediaStreamSource(mediaStream);\n workletNode = new AudioWorkletNode(\n audioContext,\n VOICE_INPUT_PROCESSOR_NAME,\n {\n numberOfInputs: 1,\n numberOfOutputs: 1,\n outputChannelCount: [1],\n channelCount: 1,\n channelCountMode: \"explicit\",\n channelInterpretation: \"speakers\",\n processorOptions: {\n frameSamples: Math.max(\n 1,\n Math.round((sampleRate * options.frameDurationMs) / 1_000),\n ),\n targetSampleRate: sampleRate,\n },\n },\n );\n silentOutput = audioContext.createGain();\n silentOutput.gain.value = 0;\n workletNode.connect(silentOutput);\n silentOutput.connect(audioContext.destination);\n\n workletNode.port.onmessage = (event: MessageEvent<unknown>) => {\n if (closed || streamController === undefined) {\n return;\n }\n const data = event.data;\n if (data instanceof ArrayBuffer || data instanceof Int16Array) {\n const chunk = data instanceof ArrayBuffer ? new Int16Array(data) : data;\n if ((streamController.desiredSize ?? 0) < chunk.length) {\n cleanup(\n new VoiceInputError({\n code: \"audio-error\",\n retryable: true,\n message: \"The application stopped consuming microphone audio.\",\n }),\n );\n return;\n }\n streamController.enqueue(chunk);\n } else if (\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n data.type === \"flushed\"\n ) {\n resolveFlush?.();\n resolveFlush = undefined;\n }\n };\n workletNode.port.onmessageerror = (event) => {\n cleanup(\n new VoiceInputError({\n code: \"audio-error\",\n message: \"The browser could not read microphone audio frames.\",\n retryable: true,\n cause: event,\n }),\n );\n };\n workletNode.addEventListener(\n \"processorerror\",\n (event) => {\n cleanup(\n new VoiceInputError({\n code: \"audio-error\",\n message: \"The microphone audio processor stopped unexpectedly.\",\n retryable: true,\n cause: event,\n }),\n );\n },\n { once: true },\n );\n\n for (const track of mediaStream.getAudioTracks()) {\n track.addEventListener(\n \"ended\",\n () => {\n if (!closed) {\n cleanup(\n new VoiceInputError({\n code: \"audio-error\",\n message: \"The microphone stopped unexpectedly.\",\n retryable: true,\n }),\n );\n }\n },\n { once: true },\n );\n }\n\n // Safari commonly creates a suspended context. Resume it while the original\n // activation is still available; audio frames do not flow until start().\n if (audioContext.state !== \"running\") {\n await audioContext.resume();\n }\n throwIfAborted(abortSignal);\n audioContext.addEventListener(\"statechange\", () => {\n if (started && !closed && audioContext?.state !== \"running\") {\n cleanup(\n new VoiceInputError({\n code: \"audio-error\",\n retryable: true,\n message:\n \"Microphone capture was interrupted. Start a new recording to continue.\",\n }),\n );\n }\n });\n\n return {\n stream,\n start() {\n if (closed || started) {\n return;\n }\n started = true;\n sourceNode?.connect(workletNode as AudioWorkletNode);\n },\n async stop() {\n stopTracks();\n if (!closed && started && workletNode !== undefined) {\n safely(() => sourceNode?.disconnect());\n started = false;\n await new Promise<void>((resolve) => {\n resolveFlush = resolve;\n flushTimer = setTimeout(resolve, FLUSH_TIMEOUT_MS);\n workletNode?.port.postMessage({ type: \"flush\" });\n });\n }\n cleanup();\n await closeContextPromise;\n },\n abort() {\n cleanup();\n },\n };\n } catch (error) {\n cleanup();\n if (VoiceInputError.isInstance(error)) {\n throw error;\n }\n throw normalizeBrowserAudioError(error);\n }\n}\n\nexport function normalizeBrowserAudioError(error: unknown): VoiceInputError {\n const name = getErrorName(error);\n\n if (name === \"NotAllowedError\" || name === \"SecurityError\") {\n return new VoiceInputError({\n code: \"permission-denied\",\n message: \"Microphone permission was denied.\",\n cause: error,\n });\n }\n if (name === \"NotFoundError\" || name === \"DevicesNotFoundError\") {\n return new VoiceInputError({\n code: \"device-not-found\",\n message: \"No microphone is available.\",\n cause: error,\n });\n }\n if (\n name === \"NotReadableError\" ||\n name === \"TrackStartError\" ||\n name === \"AbortError\"\n ) {\n return new VoiceInputError({\n code: \"device-busy\",\n message:\n \"The microphone is unavailable or in use by another application.\",\n retryable: true,\n cause: error,\n });\n }\n\n return new VoiceInputError({\n code: \"audio-error\",\n message: \"The browser audio pipeline failed.\",\n retryable: true,\n cause: error,\n });\n}\n\nfunction assertBrowserSupport(): void {\n const support = getBrowserVoiceInputSupport();\n if (!support.isSupported) {\n throw unsupportedBrowser(support.missingCapabilities);\n }\n}\n\nfunction assertUserActivation(): void {\n if (\n navigator.userActivation !== undefined &&\n navigator.userActivation.isActive === false\n ) {\n throw new VoiceInputError({\n code: \"permission-denied\",\n message:\n \"Microphone access must be started directly from a user interaction.\",\n });\n }\n}\n\nfunction unsupportedBrowser(\n missingCapabilities: readonly BrowserVoiceInputCapability[],\n): VoiceInputError {\n return new VoiceInputError({\n code: \"unsupported-browser\",\n message: `Voice input is unavailable because the browser is missing: ${missingCapabilities.join(\n \", \",\n )}.`,\n });\n}\n\nfunction getAudioContextConstructor(): typeof AudioContext {\n const browser = globalThis as typeof globalThis & {\n AudioContext?: typeof AudioContext;\n webkitAudioContext?: typeof AudioContext;\n };\n const AudioContextConstructor =\n browser.AudioContext ?? browser.webkitAudioContext;\n if (AudioContextConstructor === undefined) {\n throw unsupportedBrowser([\"audio-context\"]);\n }\n return AudioContextConstructor;\n}\n\nfunction createAudioContext(\n AudioContextConstructor: typeof AudioContext,\n sampleRate: number,\n): AudioContext {\n try {\n return new AudioContextConstructor({\n latencyHint: \"interactive\",\n sampleRate,\n });\n } catch (error) {\n const name = getErrorName(error);\n if (name !== \"NotSupportedError\" && name !== \"TypeError\") {\n throw error;\n }\n return new AudioContextConstructor({ latencyHint: \"interactive\" });\n }\n}\n\nasync function loadWorklet(\n context: AudioContext,\n moduleUrl: string | undefined,\n): Promise<void> {\n if (moduleUrl !== undefined) {\n await context.audioWorklet.addModule(moduleUrl);\n return;\n }\n const url = URL.createObjectURL(\n new Blob([AUDIO_WORKLET_SOURCE], { type: \"text/javascript\" }),\n );\n try {\n await context.audioWorklet.addModule(url);\n } finally {\n URL.revokeObjectURL(url);\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n throw (\n signal.reason ??\n new DOMException(\"The operation was aborted.\", \"AbortError\")\n );\n }\n}\n\nfunction getErrorName(error: unknown): string | undefined {\n return typeof error === \"object\" && error !== null && \"name\" in error\n ? String((error as { name?: unknown }).name)\n : undefined;\n}\n\nfunction safely(operation: () => void): void {\n try {\n operation();\n } catch {\n // Cleanup is best effort and remains idempotent.\n }\n}\n","import { VoiceInputError } from \"@voiceinput/provider\";\n\n/** A bounded FIFO shared by startup buffering and a slow provider transport. */\nexport class AudioQueue {\n #chunks: Int16Array[] = [];\n #samples = 0;\n #closed = false;\n #wake: (() => void) | undefined;\n constructor(readonly maximumSamples: number) {}\n\n push(chunk: Int16Array): void {\n if (this.#closed) return;\n if (this.#samples + chunk.length > this.maximumSamples) {\n throw new VoiceInputError({\n code: \"network-error\",\n retryable: true,\n message:\n \"Audio could not be sent fast enough. Recording stopped before the audio buffer overflowed.\",\n });\n }\n this.#chunks.push(chunk.slice());\n this.#samples += chunk.length;\n this.#wake?.();\n this.#wake = undefined;\n }\n\n async read(): Promise<Int16Array | undefined> {\n while (!this.#closed && this.#chunks.length === 0) {\n await new Promise<void>((resolve) => {\n this.#wake = resolve;\n });\n }\n const chunk = this.#chunks.shift();\n if (chunk) this.#samples -= chunk.length;\n return chunk;\n }\n\n close(discard = false): void {\n this.#closed = true;\n if (discard) {\n this.#chunks = [];\n this.#samples = 0;\n }\n this.#wake?.();\n this.#wake = undefined;\n }\n}\n","const WORD_CHARACTER = /[\\p{L}\\p{N}]/u;\nconst NO_SPACE_CHARACTER =\n /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}]/u;\nconst WHITESPACE_CHARACTER = /\\s/u;\nconst OPENING_PUNCTUATION = /[(\\u005b{<\\u2018\\u201c([{〈《「『【〔]/u;\nconst CLOSING_PUNCTUATION =\n /[.,!?;:%)\\]}\\u003e\\u2019\\u201d\\u2026。、,.!?:;)]}〉》」』】〕]/u;\n\nexport function appendTranscriptPart(current: string, part: string): string {\n return `${current}${normalizeTranscriptInsertion(current, \"\", part)}`;\n}\n\nexport function normalizeTranscriptInsertion(\n left: string,\n right: string,\n text: string,\n): string {\n const core = text.replace(/^\\s+/u, \"\").replace(/\\s+$/u, \"\");\n if (core.length === 0) {\n return \"\";\n }\n\n const prefix = needsBoundarySpace(left.at(-1), core.at(0), \"left\") ? \" \" : \"\";\n const suffix = needsBoundarySpace(core.at(-1), right.at(0), \"right\")\n ? \" \"\n : \"\";\n return `${prefix}${core}${suffix}`;\n}\n\nfunction needsBoundarySpace(\n left: string | undefined,\n right: string | undefined,\n side: \"left\" | \"right\",\n): boolean {\n if (\n left === undefined ||\n right === undefined ||\n WHITESPACE_CHARACTER.test(left) ||\n WHITESPACE_CHARACTER.test(right) ||\n OPENING_PUNCTUATION.test(left) ||\n CLOSING_PUNCTUATION.test(right) ||\n (NO_SPACE_CHARACTER.test(left) && NO_SPACE_CHARACTER.test(right))\n ) {\n return false;\n }\n\n return (\n WORD_CHARACTER.test(left) ||\n WORD_CHARACTER.test(right) ||\n (side === \"right\" && CLOSING_PUNCTUATION.test(left))\n );\n}\n","import {\n VoiceInputError,\n type VoiceInputErrorCode,\n type VoiceInputProviderV1,\n type VoiceInputProviderV1Session,\n type VoiceInputProviderV1StreamPart,\n type VoiceTranscriptionOptions,\n} from \"@voiceinput/provider\";\n\nimport { AudioQueue } from \"./audio-queue.js\";\nimport type {\n VoiceInputTextLimit,\n VoiceInputTextEngine,\n} from \"./text-engine.js\";\nimport { appendTranscriptPart } from \"./transcript-boundary.js\";\n\nexport { VoiceInputError };\nexport type {\n VoiceInputErrorCode,\n VoiceInputErrorOptions,\n} from \"@voiceinput/provider\";\n\nconst DEFAULT_MAX_DURATION_MS = 300_000;\nconst DEFAULT_CONNECTION_TIMEOUT_MS = 15_000;\nconst DURATION_WARNING_MS = 30_000;\nconst FINALIZATION_TIMEOUT_MS = 5_000;\n\nexport type VoiceInputStatus =\n | \"idle\"\n | \"requesting-permission\"\n | \"connecting\"\n | \"listening\"\n | \"stopping\"\n | \"processing\"\n | \"error\";\n\nexport type VoiceInputStopReason =\n | \"user\"\n | \"max-duration\"\n | \"replaced\"\n | \"max-length\"\n | \"target-unavailable\"\n | \"backgrounded\";\n\nexport interface VoiceInputSnapshot {\n readonly status: VoiceInputStatus;\n readonly transcript: string;\n readonly interimTranscript: string;\n readonly finalTranscript: string;\n readonly error: VoiceInputError | null;\n}\n\nexport type VoiceInputSessionEvent =\n | VoiceInputTextLimit\n | {\n type: \"status-change\";\n previousStatus: VoiceInputStatus;\n status: VoiceInputStatus;\n }\n | {\n type: \"interim\";\n text: string;\n segmentId: string;\n transcript: string;\n transcriptChanged: boolean;\n }\n | {\n type: \"final\";\n text: string;\n segmentId: string;\n transcript: string;\n transcriptChanged: boolean;\n finalTranscriptChanged: boolean;\n }\n | {\n type: \"duration-warning\";\n remainingMs: number;\n maxDurationMs: number;\n }\n | { type: \"stop\"; reason: VoiceInputStopReason }\n | { type: \"cancel\" }\n | { type: \"speech-start\" }\n | { type: \"speech-end\" }\n | { type: \"error\"; error: VoiceInputError };\n\nexport interface VoiceAudioSourcePrepareOptions {\n sampleRate: number;\n abortSignal: AbortSignal;\n onAcquired?(): void;\n}\n\nexport interface PreparedVoiceAudioSource {\n readonly stream: ReadableStream<Int16Array>;\n start(): PromiseLike<void> | void;\n stop(): PromiseLike<void> | void;\n abort(reason?: unknown): void;\n}\n\nexport interface VoiceAudioSource {\n prepare(\n options: VoiceAudioSourcePrepareOptions,\n ): PromiseLike<PreparedVoiceAudioSource>;\n}\n\nexport interface CreateVoiceInputSessionOptions extends VoiceTranscriptionOptions {\n provider: VoiceInputProviderV1;\n audioSource: VoiceAudioSource;\n textEngine?: VoiceInputTextEngine;\n maxDurationMs?: number;\n connectionTimeoutMs?: number;\n}\n\nexport interface VoiceInputSession {\n getSnapshot(): VoiceInputSnapshot;\n subscribe(listener: (event: VoiceInputSessionEvent) => void): () => void;\n /** Applies to the next recording; a running session keeps its configuration. */\n updateOptions(\n options: Omit<CreateVoiceInputSessionOptions, \"textEngine\">,\n ): void;\n start(): Promise<void>;\n stop(reason?: VoiceInputStopReason): Promise<void>;\n cancel(): Promise<void>;\n toggle(): Promise<void>;\n}\n\ninterface SessionConfiguration extends VoiceTranscriptionOptions {\n maxDurationMs: number;\n connectionTimeoutMs: number;\n}\n\ninterface ActiveRun {\n abortController: AbortController;\n audio?: PreparedVoiceAudioSource;\n providerSession?: VoiceInputProviderV1Session;\n audioTask?: Promise<void>;\n captureTask?: Promise<void>;\n queue: AudioQueue;\n closedSegments: Set<string>;\n implicitSegment: number;\n cleanup: Array<() => void>;\n providerTask?: Promise<void>;\n stopPromise?: Promise<void>;\n warningTimer?: ReturnType<typeof setTimeout>;\n durationTimer?: ReturnType<typeof setTimeout>;\n connectionTimer?: ReturnType<typeof setTimeout>;\n connectionDeadlineStarted?: boolean;\n}\n\nexport function createVoiceInputSession(\n options: CreateVoiceInputSessionOptions,\n): VoiceInputSession {\n assertProvider(options.provider);\n assertAudioSource(options.audioSource);\n if (options.textEngine !== undefined) {\n assertTextEngine(options.textEngine);\n }\n\n const configuration = validateSessionConfiguration(options);\n\n return new VoiceInputSessionController(\n options.provider,\n options.audioSource,\n options.textEngine,\n configuration,\n );\n}\n\nclass VoiceInputSessionController implements VoiceInputSession {\n readonly #listeners = new Set<(event: VoiceInputSessionEvent) => void>();\n #provider: VoiceInputProviderV1;\n #audioSource: VoiceAudioSource;\n readonly #textEngine: VoiceInputTextEngine | undefined;\n #configuration: SessionConfiguration;\n\n #snapshot: VoiceInputSnapshot = Object.freeze({\n status: \"idle\",\n transcript: \"\",\n interimTranscript: \"\",\n finalTranscript: \"\",\n error: null,\n });\n #activeRun: ActiveRun | undefined;\n #nextOptions: Omit<CreateVoiceInputSessionOptions, \"textEngine\"> | undefined;\n\n updateOptions(\n options: Omit<CreateVoiceInputSessionOptions, \"textEngine\">,\n ): void {\n this.#nextOptions = options;\n }\n\n constructor(\n provider: VoiceInputProviderV1,\n audioSource: VoiceAudioSource,\n textEngine: VoiceInputTextEngine | undefined,\n configuration: SessionConfiguration,\n ) {\n this.#provider = provider;\n this.#audioSource = audioSource;\n this.#textEngine = textEngine;\n this.#configuration = configuration;\n }\n\n getSnapshot(): VoiceInputSnapshot {\n return this.#snapshot;\n }\n\n subscribe(listener: (event: VoiceInputSessionEvent) => void): () => void {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n }\n\n async start(): Promise<void> {\n if (this.#snapshot.status !== \"idle\" && this.#snapshot.status !== \"error\") {\n return;\n }\n\n try {\n if (this.#nextOptions) {\n const options = this.#nextOptions;\n assertProvider(options.provider);\n assertAudioSource(options.audioSource);\n this.#provider = options.provider;\n this.#audioSource = options.audioSource;\n this.#configuration = validateSessionConfiguration(options);\n }\n } catch (error) {\n this.#setPreflightError(this.#normalizeValidationError(error));\n return;\n }\n this.#setSnapshot({\n transcript: \"\",\n interimTranscript: \"\",\n finalTranscript: \"\",\n error: null,\n });\n\n const transcriptionOptions = getTranscriptionOptions(this.#configuration);\n\n try {\n this.#provider.validateOptions(transcriptionOptions);\n } catch (error) {\n this.#setPreflightError(this.#normalizeValidationError(error));\n return;\n }\n\n const run: ActiveRun = {\n abortController: new AbortController(),\n queue: new AudioQueue(this.#provider.sampleRate * 15),\n closedSegments: new Set(),\n implicitSegment: 0,\n cleanup: [],\n };\n this.#textEngine?.begin();\n this.#activeRun = run;\n if (this.#textEngine) {\n run.cleanup.push(\n this.#textEngine.subscribe((event) => {\n if (!this.#isActive(run)) return;\n if (event.type === \"text-limit\") this.#emit(event);\n const reason =\n event.type === \"text-limit\"\n ? \"max-length\"\n : event.type === \"reset\"\n ? \"replaced\"\n : \"target-unavailable\";\n queueMicrotask(() => {\n if (this.#isActive(run)) void this.stop(reason);\n });\n }),\n );\n }\n if (typeof document !== \"undefined\") {\n const onVisibility = (): void => {\n if (document.hidden && this.#isActive(run))\n void this.stop(\"backgrounded\");\n };\n document.addEventListener(\"visibilitychange\", onVisibility);\n run.cleanup.push(() =>\n document.removeEventListener(\"visibilitychange\", onVisibility),\n );\n }\n this.#transition(\"requesting-permission\");\n\n if (!this.#isActive(run)) {\n return;\n }\n\n const startConnectionDeadline = (): void => {\n if (this.#isActive(run)) {\n this.#scheduleConnectionDeadline(run);\n }\n };\n let audio: PreparedVoiceAudioSource;\n try {\n const preparation = Promise.resolve(\n this.#audioSource.prepare({\n sampleRate: this.#provider.sampleRate,\n abortSignal: run.abortController.signal,\n onAcquired: startConnectionDeadline,\n }),\n );\n void preparation.then(\n (lateAudio) => {\n if (!this.#isActive(run)) {\n safely(() =>\n lateAudio.abort(\n run.abortController.signal.reason ?? \"stale-session\",\n ),\n );\n }\n },\n () => {},\n );\n audio = await untilAborted(preparation, run.abortController.signal);\n } catch (error) {\n if (this.#isActive(run)) {\n this.#failRun(run, this.#normalizeError(error, \"audio-error\"));\n }\n return;\n }\n\n if (!this.#isActive(run)) {\n safely(() => audio.abort(\"stale-session\"));\n return;\n }\n\n run.audio = audio;\n startConnectionDeadline();\n run.captureTask = this.#captureAudio(run, audio.stream);\n this.#scheduleDurationLimit(run);\n try {\n await untilAborted(\n Promise.resolve(audio.start()),\n run.abortController.signal,\n );\n } catch (error) {\n if (this.#isActive(run))\n this.#failRun(run, this.#normalizeError(error, \"audio-error\"));\n return;\n }\n if (!this.#isActive(run)) return;\n this.#transition(\"connecting\");\n\n if (!this.#isActive(run)) {\n return;\n }\n\n let providerSession: VoiceInputProviderV1Session;\n try {\n const opening = Promise.resolve(\n this.#provider.doOpen({\n ...transcriptionOptions,\n abortSignal: run.abortController.signal,\n }),\n );\n void opening.then(\n (lateSession) => {\n if (!this.#isActive(run)) {\n safely(() =>\n lateSession.abort(\n run.abortController.signal.reason ?? \"stale-session\",\n ),\n );\n }\n },\n () => {},\n );\n providerSession = await untilAborted(opening, run.abortController.signal);\n } catch (error) {\n if (this.#isActive(run)) {\n this.#failRun(run, this.#normalizeError(error, \"provider-error\"));\n }\n return;\n }\n\n if (!this.#isActive(run)) {\n safely(() => providerSession.abort(\"stale-session\"));\n safely(() => audio.abort(\"stale-session\"));\n return;\n }\n\n run.providerSession = providerSession;\n run.providerTask = this.#consumeProviderStream(run, providerSession);\n run.audioTask = this.#pumpAudio(run, providerSession);\n\n this.#clearConnectionTimer(run);\n this.#transition(\"listening\");\n }\n\n async stop(reason: VoiceInputStopReason = \"user\"): Promise<void> {\n const run = this.#activeRun;\n\n if (run === undefined) {\n return;\n }\n\n if (run.stopPromise === undefined) {\n run.stopPromise = this.#performStop(run, reason);\n }\n\n await run.stopPromise;\n }\n\n async cancel(): Promise<void> {\n const run = this.#activeRun;\n\n if (run === undefined) {\n return;\n }\n\n this.#activeRun = undefined;\n this.#abortRun(run, \"cancelled\");\n this.#textEngine?.cancel();\n this.#setSnapshot({\n transcript: this.#snapshot.finalTranscript,\n interimTranscript: \"\",\n error: null,\n });\n this.#transition(\"idle\");\n this.#emit({ type: \"cancel\" });\n }\n\n async toggle(): Promise<void> {\n if (this.#activeRun === undefined) {\n await this.start();\n } else {\n await this.stop();\n }\n }\n\n async #performStop(\n run: ActiveRun,\n reason: VoiceInputStopReason,\n ): Promise<void> {\n this.#clearRunTimers(run);\n this.#transition(\"stopping\");\n\n if (!this.#isActive(run)) {\n return;\n }\n\n const audio = run.audio;\n const providerSession = run.providerSession;\n const audioTask = run.audioTask;\n const providerTask = run.providerTask;\n\n if (providerSession === undefined) {\n const completed = await this.#completeTextEngine(run);\n if (!completed) {\n return;\n }\n this.#activeRun = undefined;\n this.#abortRun(run, reason);\n this.#transition(\"idle\");\n this.#emit({ type: \"stop\", reason });\n return;\n }\n\n try {\n await withTimeout(\n (async () => {\n await audio?.stop();\n await run.captureTask;\n await audioTask;\n\n if (!this.#isActive(run)) {\n return;\n }\n\n await providerSession.finish();\n await providerTask;\n })(),\n FINALIZATION_TIMEOUT_MS,\n this.#provider.provider,\n );\n\n if (!this.#isActive(run)) {\n return;\n }\n\n const completed = await this.#completeTextEngine(run);\n if (!completed) {\n return;\n }\n\n this.#activeRun = undefined;\n this.#clearRunTimers(run);\n for (const cleanup of run.cleanup.splice(0)) cleanup();\n run.queue.close(true);\n this.#transition(\"idle\");\n this.#emit({ type: \"stop\", reason });\n } catch (error) {\n if (this.#isActive(run)) {\n this.#failRun(run, this.#normalizeError(error, \"provider-error\"));\n }\n }\n }\n\n async #consumeProviderStream(\n run: ActiveRun,\n session: VoiceInputProviderV1Session,\n ): Promise<void> {\n const reader = session.stream.getReader();\n\n try {\n while (this.#isActive(run)) {\n const result = await reader.read();\n\n if (result.done || !this.#isActive(run)) {\n break;\n }\n\n if (this.#handleProviderPart(run, result.value)) {\n return;\n }\n }\n\n if (\n this.#isActive(run) &&\n this.#snapshot.status !== \"stopping\" &&\n this.#snapshot.status !== \"error\"\n ) {\n this.#failRun(\n run,\n new VoiceInputError({\n code: \"provider-error\",\n message: `${this.#provider.provider} ended the transcription stream unexpectedly.`,\n provider: this.#provider.provider,\n retryable: true,\n }),\n );\n }\n } catch (error) {\n if (this.#isActive(run)) {\n this.#failRun(run, this.#normalizeError(error, \"provider-error\"));\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n #handleProviderPart(\n run: ActiveRun,\n part: VoiceInputProviderV1StreamPart,\n ): boolean {\n if (!this.#isActive(run)) {\n return true;\n }\n\n const segmentId =\n part.type === \"interim\" || part.type === \"final\"\n ? (part.segmentId ?? `legacy:${run.implicitSegment}`)\n : \"\";\n if (part.type === \"interim\" || part.type === \"final\") {\n if (typeof segmentId !== \"string\" || segmentId.length === 0)\n throw new TypeError(\n \"Transcription segmentId must be a nonempty string.\",\n );\n if (run.closedSegments.has(segmentId)) return false;\n if (part.type === \"final\") {\n run.closedSegments.add(segmentId);\n run.implicitSegment++;\n }\n }\n switch (part.type) {\n case \"interim\": {\n this.#textEngine?.applyInterim(part.text, segmentId);\n const previousTranscript = this.#snapshot.transcript;\n const transcript = appendTranscriptPart(\n this.#snapshot.finalTranscript,\n part.text,\n );\n this.#setSnapshot({\n interimTranscript: part.text,\n transcript,\n });\n this.#emit({\n type: \"interim\",\n text: part.text,\n segmentId,\n transcript,\n transcriptChanged: transcript !== previousTranscript,\n });\n return false;\n }\n case \"final\": {\n this.#textEngine?.applyFinal(part.text, segmentId);\n const previousTranscript = this.#snapshot.transcript;\n const previousFinalTranscript = this.#snapshot.finalTranscript;\n const finalTranscript = appendTranscriptPart(\n previousFinalTranscript,\n part.text,\n );\n this.#setSnapshot({\n finalTranscript,\n interimTranscript: \"\",\n transcript: finalTranscript,\n });\n this.#emit({\n type: \"final\",\n text: part.text,\n segmentId,\n transcript: finalTranscript,\n transcriptChanged: finalTranscript !== previousTranscript,\n finalTranscriptChanged: finalTranscript !== previousFinalTranscript,\n });\n return false;\n }\n case \"error\": {\n this.#failRun(\n run,\n VoiceInputError.isInstance(part.error)\n ? part.error\n : this.#normalizeError(part.error, \"provider-error\"),\n );\n return true;\n }\n case \"speech-start\": {\n this.#emit({ type: \"speech-start\" });\n return false;\n }\n case \"speech-end\": {\n this.#emit({ type: \"speech-end\" });\n return false;\n }\n }\n }\n\n async #captureAudio(\n run: ActiveRun,\n stream: ReadableStream<Int16Array>,\n ): Promise<void> {\n const reader = stream.getReader();\n const cancelReader = (): void => {\n void reader.cancel().catch(() => {});\n };\n run.abortController.signal.addEventListener(\"abort\", cancelReader, {\n once: true,\n });\n\n try {\n while (this.#isActive(run)) {\n const result = await reader.read();\n\n if (result.done || !this.#isActive(run)) {\n break;\n }\n\n if (!(result.value instanceof Int16Array)) {\n throw new VoiceInputError({\n code: \"audio-error\",\n message: \"The audio source emitted a non-PCM16 audio chunk.\",\n });\n }\n\n run.queue.push(result.value);\n }\n } catch (error) {\n if (this.#isActive(run)) {\n this.#failRun(run, this.#normalizeError(error, \"audio-error\"));\n }\n } finally {\n run.abortController.signal.removeEventListener(\"abort\", cancelReader);\n reader.releaseLock();\n run.queue.close();\n }\n }\n\n async #pumpAudio(\n run: ActiveRun,\n session: VoiceInputProviderV1Session,\n ): Promise<void> {\n try {\n while (this.#isActive(run)) {\n const chunk = await run.queue.read();\n if (!chunk || !this.#isActive(run)) return;\n await untilAborted(\n Promise.resolve(session.sendAudio(chunk)),\n run.abortController.signal,\n );\n }\n } catch (error) {\n if (this.#isActive(run))\n this.#failRun(run, this.#normalizeError(error, \"audio-error\"));\n }\n }\n\n #scheduleDurationLimit(run: ActiveRun): void {\n const { maxDurationMs } = this.#configuration;\n const warningDelayMs = maxDurationMs - DURATION_WARNING_MS;\n const warn = (): void => {\n if (this.#isActive(run) && this.#snapshot.status !== \"stopping\") {\n this.#emit({\n type: \"duration-warning\",\n remainingMs: Math.min(DURATION_WARNING_MS, maxDurationMs),\n maxDurationMs,\n });\n }\n };\n\n if (warningDelayMs <= 0) {\n warn();\n } else {\n run.warningTimer = setTimeout(warn, warningDelayMs);\n }\n\n run.durationTimer = setTimeout(() => {\n if (this.#isActive(run) && this.#snapshot.status !== \"stopping\") {\n void this.stop(\"max-duration\");\n }\n }, maxDurationMs);\n }\n\n #scheduleConnectionDeadline(run: ActiveRun): void {\n if (run.connectionDeadlineStarted === true) {\n return;\n }\n run.connectionDeadlineStarted = true;\n const { connectionTimeoutMs } = this.#configuration;\n run.connectionTimer = setTimeout(() => {\n if (!this.#isActive(run)) {\n return;\n }\n this.#failRun(\n run,\n new VoiceInputError({\n code: \"network-error\",\n message: `${this.#provider.provider} did not connect within ${connectionTimeoutMs} ms. Check the network and try again.`,\n provider: this.#provider.provider,\n retryable: true,\n }),\n );\n }, connectionTimeoutMs);\n }\n\n #setPreflightError(error: VoiceInputError): void {\n this.#setSnapshot({\n transcript: \"\",\n interimTranscript: \"\",\n finalTranscript: \"\",\n error,\n });\n this.#transition(\"error\");\n this.#emit({ type: \"error\", error });\n }\n\n #failRun(run: ActiveRun, error: VoiceInputError): void {\n if (!this.#isActive(run)) {\n return;\n }\n\n this.#activeRun = undefined;\n this.#abortRun(run, error);\n this.#textEngine?.cancel();\n this.#setSnapshot({\n transcript: this.#snapshot.finalTranscript,\n interimTranscript: \"\",\n error,\n });\n this.#transition(\"error\");\n this.#emit({ type: \"error\", error });\n }\n\n #abortRun(run: ActiveRun, reason: unknown): void {\n this.#clearRunTimers(run);\n for (const cleanup of run.cleanup.splice(0)) cleanup();\n run.queue.close(true);\n safely(() => run.audio?.abort(reason));\n safely(() => run.abortController.abort(reason));\n safely(() => run.providerSession?.abort(reason));\n }\n\n #normalizeValidationError(error: unknown): VoiceInputError {\n if (VoiceInputError.isInstance(error)) {\n return error;\n }\n\n return new VoiceInputError({\n code: \"invalid-configuration\",\n message: `The ${this.#provider.provider} provider could not validate the session options.`,\n provider: this.#provider.provider,\n cause: error,\n });\n }\n\n #normalizeError(\n error: unknown,\n code: Extract<VoiceInputErrorCode, \"audio-error\" | \"provider-error\">,\n ): VoiceInputError {\n if (VoiceInputError.isInstance(error)) {\n return error;\n }\n\n return new VoiceInputError({\n code,\n message:\n code === \"audio-error\"\n ? \"The audio source failed.\"\n : `${this.#provider.provider} failed during the transcription session.`,\n ...(code === \"provider-error\"\n ? { provider: this.#provider.provider }\n : {}),\n retryable: true,\n cause: error,\n });\n }\n\n #isActive(run: ActiveRun): boolean {\n return this.#activeRun === run;\n }\n\n #transition(status: VoiceInputStatus): void {\n const previousStatus = this.#snapshot.status;\n\n if (previousStatus === status) {\n return;\n }\n\n this.#setSnapshot({ status });\n this.#emit({ type: \"status-change\", previousStatus, status });\n }\n\n #setSnapshot(patch: Partial<VoiceInputSnapshot>): void {\n this.#snapshot = Object.freeze({ ...this.#snapshot, ...patch });\n }\n\n #emit(event: VoiceInputSessionEvent): void {\n for (const listener of this.#listeners) {\n try {\n listener(event);\n } catch (error) {\n reportUnhandledError(error);\n }\n }\n }\n\n #clearRunTimers(run: ActiveRun): void {\n this.#clearConnectionTimer(run);\n if (run.warningTimer !== undefined) {\n clearTimeout(run.warningTimer);\n delete run.warningTimer;\n }\n if (run.durationTimer !== undefined) {\n clearTimeout(run.durationTimer);\n delete run.durationTimer;\n }\n }\n\n #clearConnectionTimer(run: ActiveRun): void {\n if (run.connectionTimer !== undefined) {\n clearTimeout(run.connectionTimer);\n delete run.connectionTimer;\n }\n }\n\n async #completeTextEngine(run: ActiveRun): Promise<boolean> {\n const completion = this.#textEngine?.complete();\n if (completion === undefined) {\n return this.#isActive(run);\n }\n\n if (completion.processing) {\n this.#transition(\"processing\");\n }\n\n const errors = await completion.result;\n if (!this.#isActive(run)) {\n return false;\n }\n\n for (const error of errors) {\n this.#setSnapshot({ error });\n this.#emit({ type: \"error\", error });\n }\n return true;\n }\n}\n\nfunction getTranscriptionOptions(options: {\n language?: string | undefined;\n vocabulary?: readonly string[] | undefined;\n endpointing?: VoiceTranscriptionOptions[\"endpointing\"] | undefined;\n}): VoiceTranscriptionOptions {\n return {\n ...(options.language === undefined ? {} : { language: options.language }),\n ...(options.vocabulary === undefined\n ? {}\n : { vocabulary: options.vocabulary }),\n ...(options.endpointing === undefined\n ? {}\n : { endpointing: options.endpointing }),\n };\n}\n\nfunction isValidLanguage(language: string): boolean {\n if (language.length === 0 || language !== language.trim()) {\n return false;\n }\n\n try {\n return Intl.getCanonicalLocales(language).length === 1;\n } catch {\n return false;\n }\n}\n\nfunction validateSessionConfiguration(\n options: CreateVoiceInputSessionOptions,\n): SessionConfiguration {\n const issues: string[] = [];\n const language: unknown = options.language;\n const vocabulary: unknown = options.vocabulary;\n const endpointing: unknown = options.endpointing;\n const maxDurationMs: unknown = options.maxDurationMs;\n const connectionTimeoutMs: unknown = options.connectionTimeoutMs;\n let validatedLanguage: string | undefined;\n let validatedVocabulary: readonly string[] | undefined;\n let validatedEndpointing: VoiceTranscriptionOptions[\"endpointing\"];\n\n if (language !== undefined) {\n if (typeof language !== \"string\" || !isValidLanguage(language)) {\n issues.push(\n \"language: must be a valid BCP 47 language tag without whitespace.\",\n );\n } else {\n validatedLanguage = language;\n }\n }\n\n if (vocabulary !== undefined) {\n if (!Array.isArray(vocabulary)) {\n issues.push(\"vocabulary: must be an array of strings.\");\n } else {\n const copy: unknown[] = [...vocabulary];\n for (const [index, term] of copy.entries()) {\n if (\n typeof term !== \"string\" ||\n term.length === 0 ||\n term !== term.trim()\n ) {\n issues.push(\n `vocabulary.${index}: must be a non-empty string with no outer whitespace.`,\n );\n }\n }\n validatedVocabulary = Object.freeze(copy as string[]);\n }\n }\n\n if (endpointing === false) {\n validatedEndpointing = false;\n } else if (endpointing !== undefined) {\n if (!isObject(endpointing) || !hasOnlySilenceMs(endpointing)) {\n issues.push(\n \"endpointing: must be false or an object containing only silenceMs.\",\n );\n } else {\n const silenceMs = endpointing[\"silenceMs\"];\n if (!isPositiveInteger(silenceMs)) {\n issues.push(\"endpointing.silenceMs: must be a positive safe integer.\");\n } else {\n validatedEndpointing = { silenceMs };\n }\n }\n }\n\n if (maxDurationMs !== undefined && !isPositiveInteger(maxDurationMs)) {\n issues.push(\"maxDurationMs: must be a positive safe integer.\");\n }\n if (\n connectionTimeoutMs !== undefined &&\n !isPositiveInteger(connectionTimeoutMs)\n ) {\n issues.push(\"connectionTimeoutMs: must be a positive safe integer.\");\n }\n\n if (issues.length > 0) {\n const cause = new TypeError(issues.join(\"; \"));\n throw new VoiceInputError({\n code: \"invalid-configuration\",\n message: cause.message,\n cause,\n });\n }\n\n return {\n ...getTranscriptionOptions({\n language: validatedLanguage,\n vocabulary: validatedVocabulary,\n endpointing: validatedEndpointing,\n }),\n maxDurationMs:\n (maxDurationMs as number | undefined) ?? DEFAULT_MAX_DURATION_MS,\n connectionTimeoutMs:\n (connectionTimeoutMs as number | undefined) ??\n DEFAULT_CONNECTION_TIMEOUT_MS,\n };\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction hasOnlySilenceMs(value: Record<string, unknown>): boolean {\n let count = 0;\n for (const key in value) {\n if (key !== \"silenceMs\" || ++count > 1) {\n return false;\n }\n }\n return count === 1 && Object.hasOwn(value, \"silenceMs\");\n}\n\nfunction isPositiveInteger(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n}\n\nfunction assertProvider(provider: VoiceInputProviderV1): void {\n if (\n typeof provider !== \"object\" ||\n provider === null ||\n provider.specificationVersion !== \"v1\" ||\n typeof provider.provider !== \"string\" ||\n provider.provider.length === 0 ||\n typeof provider.modelId !== \"string\" ||\n provider.modelId.length === 0 ||\n !Number.isInteger(provider.sampleRate) ||\n provider.sampleRate <= 0 ||\n typeof provider.validateOptions !== \"function\" ||\n typeof provider.doOpen !== \"function\"\n ) {\n throw new VoiceInputError({\n code: \"invalid-configuration\",\n message:\n \"provider must implement the VoiceInputProviderV1 specification.\",\n });\n }\n}\n\nfunction assertAudioSource(audioSource: VoiceAudioSource): void {\n if (\n typeof audioSource !== \"object\" ||\n audioSource === null ||\n typeof audioSource.prepare !== \"function\"\n ) {\n throw new VoiceInputError({\n code: \"invalid-configuration\",\n message: \"audioSource must implement the VoiceAudioSource interface.\",\n });\n }\n}\n\nfunction assertTextEngine(textEngine: VoiceInputTextEngine): void {\n if (\n typeof textEngine !== \"object\" ||\n textEngine === null ||\n typeof textEngine.begin !== \"function\" ||\n typeof textEngine.applyInterim !== \"function\" ||\n typeof textEngine.applyFinal !== \"function\" ||\n typeof textEngine.complete !== \"function\" ||\n typeof textEngine.cancel !== \"function\"\n ) {\n throw new VoiceInputError({\n code: \"invalid-configuration\",\n message: \"textEngine must implement the VoiceInputTextEngine interface.\",\n });\n }\n}\n\nfunction safely(operation: () => void): void {\n try {\n operation();\n } catch (error) {\n reportUnhandledError(error);\n }\n}\n\nfunction reportUnhandledError(error: unknown): void {\n const reportError = (\n globalThis as typeof globalThis & {\n reportError?: (error: unknown) => void;\n }\n ).reportError;\n\n if (typeof reportError === \"function\") {\n reportError(error);\n } else {\n queueMicrotask(() => {\n throw error;\n });\n }\n}\n\nasync function untilAborted<T>(\n promise: PromiseLike<T>,\n signal: AbortSignal,\n): Promise<T> {\n if (signal.aborted) {\n throw signal.reason;\n }\n\n let onAbort: (() => void) | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_resolve, reject) => {\n onAbort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }),\n ]);\n } finally {\n if (onAbort !== undefined) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n}\n\nasync function withTimeout(\n promise: Promise<void>,\n timeoutMs: number,\n provider: string,\n): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n try {\n await Promise.race([\n promise,\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n reject(\n new VoiceInputError({\n code: \"provider-error\",\n message: `${provider} did not finish the transcription session in time.`,\n provider,\n retryable: true,\n }),\n );\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n }\n}\n","import type { VoiceInputTextSelection } from \"./types.js\";\n\nexport interface HistoryValue {\n readonly value: string;\n readonly selection: VoiceInputTextSelection | null;\n}\n\ninterface Transaction {\n before: HistoryValue;\n after: HistoryValue;\n key: string;\n at: number;\n}\n\n/** History belongs to one attachment, never to a provider or recording. */\nexport class TextHistory {\n #past: Transaction[] = [];\n #future: Transaction[] = [];\n #group = 0;\n\n clear(): void {\n this.#past = [];\n this.#future = [];\n this.breakGroup();\n }\n\n breakGroup(): void {\n this.#group += 1;\n }\n\n record(before: HistoryValue, after: HistoryValue, key: string): void {\n if (before.value === after.value) return;\n const now = Date.now();\n const groupedKey = `${this.#group}:${key}`;\n const last = this.#past.at(-1);\n const coalesce =\n last?.key === groupedKey &&\n last.after.value === before.value &&\n (key.startsWith(\"voice:\") ||\n key === \"composition\" ||\n now - last.at < 1_000);\n if (coalesce && last) {\n last.after = after;\n last.at = now;\n if (last.before.value === last.after.value) this.#past.pop();\n } else {\n this.#past.push({ before, after, key: groupedKey, at: now });\n }\n this.#future = [];\n while (this.#past.length > 100 || this.#retainedBytes() > 2 * 1024 * 1024) {\n this.#past.shift();\n }\n }\n\n undo(): HistoryValue | undefined {\n this.breakGroup();\n const entry = this.#past.pop();\n if (!entry) return undefined;\n this.#future.push(entry);\n return entry.before;\n }\n\n redo(): HistoryValue | undefined {\n this.breakGroup();\n const entry = this.#future.pop();\n if (!entry) return undefined;\n this.#past.push(entry);\n return entry.after;\n }\n\n #retainedBytes(): number {\n return this.#past.reduce(\n (bytes, item) =>\n bytes + 2 * (item.before.value.length + item.after.value.length),\n 0,\n );\n }\n}\n","import { VoiceInputError } from \"@voiceinput/provider\";\n\nimport type {\n VoiceInputControlledTextBinding,\n VoiceInputTextSelection,\n VoiceInputTextTarget,\n} from \"./types.js\";\nimport type { TextMutation } from \"./ownership-model.js\";\n\nconst SUPPORTED_INPUT_TYPES = new Set([\"text\", \"search\", \"url\", \"tel\"]);\n\nexport interface TextTargetCallbacks {\n readonly onBeforeInput: (inputType: string) => void;\n readonly onHistory: (redo: boolean) => void;\n readonly onComposition: (active: boolean) => void;\n readonly onReset: () => void;\n readonly onAvailability: () => void;\n readonly onInput: () => void;\n readonly onSelectionChange: () => void;\n readonly onUnhandledError: (error: unknown) => void;\n}\n\nexport class TextTargetAdapter {\n readonly #controlled: VoiceInputControlledTextBinding | undefined;\n readonly #callbacks: TextTargetCallbacks;\n\n #target: VoiceInputTextTarget | null = null;\n #writeDepth = 0;\n #observer: MutationObserver | undefined;\n #form: HTMLFormElement | null = null;\n #composing = false;\n\n constructor(\n controlled: VoiceInputControlledTextBinding | undefined,\n callbacks: TextTargetCallbacks,\n ) {\n this.#controlled = controlled;\n this.#callbacks = callbacks;\n }\n\n get target(): VoiceInputTextTarget | null {\n return this.#target;\n }\n\n get isControlled(): boolean {\n return this.#controlled !== undefined;\n }\n\n attach(target: VoiceInputTextTarget): string {\n assertSupportedTarget(target);\n this.detach();\n this.#target = target;\n const value = this.#controlled?.getValue() ?? target.value;\n this.#withGuard(() => {\n if (target.value !== value) target.value = value;\n });\n target.addEventListener(\"beforeinput\", this.#handleBeforeInput);\n target.addEventListener(\"keydown\", this.#handleKeyDown);\n target.addEventListener(\"compositionstart\", this.#handleCompositionStart);\n target.addEventListener(\"compositionend\", this.#handleCompositionEnd);\n this.#form = target.form;\n this.#form?.addEventListener(\"reset\", this.#handleReset);\n this.#observer = new MutationObserver(() =>\n this.#callbacks.onAvailability(),\n );\n this.#observer.observe(target, {\n attributes: true,\n attributeFilter: [\"disabled\", \"readonly\", \"type\", \"maxlength\"],\n });\n for (\n let ancestor = target.parentElement;\n ancestor;\n ancestor = ancestor.parentElement\n ) {\n this.#observer.observe(ancestor, {\n attributes: true,\n attributeFilter: [\"disabled\"],\n });\n }\n target.addEventListener(\"input\", this.#handleInput);\n target.addEventListener(\"select\", this.#handleSelectionChange);\n target.ownerDocument.addEventListener(\n \"selectionchange\",\n this.#handleSelectionChange,\n );\n return value;\n }\n\n detach(): void {\n const target = this.#target;\n if (target === null) {\n return;\n }\n target.removeEventListener(\"beforeinput\", this.#handleBeforeInput);\n target.removeEventListener(\"keydown\", this.#handleKeyDown);\n target.removeEventListener(\n \"compositionstart\",\n this.#handleCompositionStart,\n );\n target.removeEventListener(\"compositionend\", this.#handleCompositionEnd);\n this.#form?.removeEventListener(\"reset\", this.#handleReset);\n this.#form = null;\n this.#observer?.disconnect();\n this.#observer = undefined;\n this.#composing = false;\n target.removeEventListener(\"input\", this.#handleInput);\n target.removeEventListener(\"select\", this.#handleSelectionChange);\n target.ownerDocument.removeEventListener(\n \"selectionchange\",\n this.#handleSelectionChange,\n );\n this.#target = null;\n }\n\n isWritable(): boolean {\n return (\n this.#target !== null &&\n isSupportedTarget(this.#target) &&\n !this.#target.matches(\":disabled\") &&\n !this.#target.readOnly\n );\n }\n\n readValue(): string {\n return this.#target?.value ?? \"\";\n }\n\n readSelection(): VoiceInputTextSelection | null {\n return this.#target === null || !isSupportedTarget(this.#target)\n ? null\n : readSelection(this.#target);\n }\n\n readSelectionWhenValueIs(value: string): VoiceInputTextSelection | null {\n return this.#target !== null &&\n isSupportedTarget(this.#target) &&\n this.#target.value === value\n ? readSelection(this.#target)\n : null;\n }\n\n applyMutation(mutation: TextMutation): void {\n const target = this.#target;\n if (target === null || !this.isWritable() || this.#composing) {\n return;\n }\n this.#withGuard(() => {\n setNativeValue(target, mutation.value);\n restoreSelection(target, mutation.selection);\n if (!mutation.changed) {\n return;\n }\n try {\n if (!this.#controlled?.dispatchInput)\n this.#controlled?.onValueChange(mutation.value);\n } catch (error) {\n this.#callbacks.onUnhandledError(error);\n }\n if (this.#controlled === undefined || this.#controlled.dispatchInput) {\n const InputEventConstructor =\n target.ownerDocument.defaultView?.InputEvent ?? InputEvent;\n target.dispatchEvent(\n new InputEventConstructor(\"input\", {\n bubbles: true,\n inputType: \"insertText\",\n }),\n );\n }\n });\n }\n\n synchronize(value: string, selection: VoiceInputTextSelection | null): void {\n const target = this.#target;\n if (target === null || !isSupportedTarget(target) || this.#composing) {\n return;\n }\n this.#withGuard(() => {\n if (target.value !== value) target.value = value;\n restoreSelection(target, selection);\n });\n }\n\n #handleBeforeInput = (event: Event): void => {\n if (this.#writeDepth !== 0) return;\n const inputType = (event as InputEvent).inputType ?? \"insertText\";\n if (inputType === \"historyUndo\" || inputType === \"historyRedo\") {\n if (event.cancelable && !this.#composing) {\n event.preventDefault();\n this.#callbacks.onHistory(inputType === \"historyRedo\");\n }\n return;\n }\n this.#callbacks.onBeforeInput(inputType);\n };\n\n #handleKeyDown = (rawEvent: Event): void => {\n const event = rawEvent as KeyboardEvent;\n if (\n event.defaultPrevented ||\n event.isComposing ||\n this.#composing ||\n !this.isWritable()\n )\n return;\n const modifier = event.ctrlKey || event.metaKey;\n const key = event.key.toLowerCase();\n if (\n modifier &&\n !event.altKey &&\n (key === \"z\" || (event.ctrlKey && key === \"y\"))\n ) {\n event.preventDefault();\n this.#callbacks.onHistory(key === \"y\" || event.shiftKey);\n }\n };\n\n #handleCompositionStart = (): void => {\n this.#composing = true;\n this.#callbacks.onComposition(true);\n };\n\n #handleCompositionEnd = (): void => {\n this.#composing = false;\n // The browser commits the last composition input before the microtask.\n const target = this.#target;\n queueMicrotask(() => {\n if (target === this.#target) this.#callbacks.onComposition(false);\n });\n };\n\n #handleReset = (event: Event): void => {\n const target = this.#target;\n queueMicrotask(() => {\n if (!event.defaultPrevented && target === this.#target)\n this.#callbacks.onReset();\n });\n };\n\n #handleInput = (): void => {\n if (this.#writeDepth === 0) {\n this.#callbacks.onInput();\n }\n };\n\n #handleSelectionChange = (): void => {\n if (this.#writeDepth === 0) {\n this.#callbacks.onSelectionChange();\n }\n };\n\n #withGuard(operation: () => void): void {\n this.#writeDepth += 1;\n try {\n operation();\n } finally {\n this.#writeDepth -= 1;\n }\n }\n}\n\nfunction assertSupportedTarget(target: VoiceInputTextTarget): void {\n if (!isSupportedTarget(target)) {\n throw invalidTarget();\n }\n}\n\nfunction isSupportedTarget(\n target: VoiceInputTextTarget,\n): target is VoiceInputTextTarget {\n if (typeof target !== \"object\" || target === null) {\n return false;\n }\n if (target.tagName === \"TEXTAREA\") {\n return true;\n }\n return target.tagName === \"INPUT\" && SUPPORTED_INPUT_TYPES.has(target.type);\n}\n\nfunction readSelection(target: VoiceInputTextTarget): VoiceInputTextSelection {\n const start = target.selectionStart;\n const end = target.selectionEnd;\n if (start === null || end === null) {\n throw invalidTarget(\"The text target does not expose a selection.\");\n }\n const direction = target.selectionDirection;\n return {\n start,\n end,\n direction:\n direction === \"forward\" || direction === \"backward\" ? direction : \"none\",\n };\n}\n\nfunction restoreSelection(\n target: VoiceInputTextTarget,\n selection: VoiceInputTextSelection | null,\n): void {\n if (selection === null) {\n return;\n }\n const start = Math.min(selection.start, target.value.length);\n const end = Math.min(selection.end, target.value.length);\n target.setSelectionRange(start, end, selection.direction);\n}\n\nfunction invalidTarget(\n message = \"Text targets must be <textarea> elements or <input> elements of type text, search, url, or tel.\",\n): VoiceInputError {\n return new VoiceInputError({ code: \"invalid-configuration\", message });\n}\n\nfunction setNativeValue(target: VoiceInputTextTarget, value: string): void {\n const view = target.ownerDocument.defaultView;\n const prototype =\n target.tagName === \"TEXTAREA\"\n ? view?.HTMLTextAreaElement.prototype\n : view?.HTMLInputElement.prototype;\n const descriptor =\n prototype && Object.getOwnPropertyDescriptor(prototype, \"value\");\n if (descriptor?.set) descriptor.set.call(target, value);\n else target.value = value;\n}\n","import type {\n VoiceInputInterimBehavior,\n VoiceInputTextLimit,\n VoiceInputTextEngineSnapshot,\n VoiceInputTextSelection,\n VoiceInputTextSpanState,\n} from \"./types.js\";\nimport { normalizeTranscriptInsertion } from \"../transcript-boundary.js\";\n\nexport interface MutableTextSpan {\n id: number;\n start: number;\n end: number;\n state: VoiceInputTextSpanState;\n runId: number;\n generation: number;\n expectedText: string;\n replacedText?: string;\n}\n\ninterface MutableTextSelection {\n start: number;\n end: number;\n direction: \"forward\" | \"backward\" | \"none\";\n replacePending: boolean;\n}\n\nexport interface TextEdit {\n oldStart: number;\n oldEnd: number;\n newEnd: number;\n}\n\nexport interface TextMutation {\n readonly changed: boolean;\n readonly selection: VoiceInputTextSelection | null;\n readonly value: string;\n}\n\nexport interface TextCompletionState {\n readonly mutation: TextMutation | null;\n readonly runId: number;\n readonly spans: readonly MutableTextSpan[];\n}\n\nexport class TextOwnershipModel {\n #interimBehavior: VoiceInputInterimBehavior;\n\n #maxLength = -1;\n #source: VoiceInputTextLimit[\"source\"] = \"final\";\n #limit: VoiceInputTextLimit | undefined;\n #value = \"\";\n #selection: MutableTextSelection | null = null;\n #spans: MutableTextSpan[] = [];\n #provisional: MutableTextSpan | undefined;\n #currentFinalSpan: MutableTextSpan | undefined;\n #interimTranscript = \"\";\n #runId = 0;\n #runActive = false;\n #nextSpanId = 1;\n #nextGeneration = 1;\n\n constructor(interimBehavior: VoiceInputInterimBehavior) {\n this.#interimBehavior = interimBehavior;\n }\n\n configureMutation(\n maxLength: number,\n source: VoiceInputTextLimit[\"source\"],\n ): void {\n this.#maxLength = maxLength;\n this.#source = source;\n this.#limit = undefined;\n }\n\n takeLimit(): VoiceInputTextLimit | undefined {\n const limit = this.#limit;\n this.#limit = undefined;\n return limit;\n }\n\n #limitReplacement(start: number, end: number, text: string): string {\n if (this.#maxLength < 0) return text;\n const available = Math.max(\n 0,\n this.#maxLength - (this.#value.length - (end - start)),\n );\n if (text.length < available || text.length === 0) return text;\n let insertedText = \"\";\n for (const { segment } of new Intl.Segmenter(undefined, {\n granularity: \"grapheme\",\n }).segment(text)) {\n if (insertedText.length + segment.length > available) break;\n insertedText += segment;\n }\n this.#limit = {\n type: \"text-limit\",\n maxLength: this.#maxLength,\n text,\n insertedText,\n source: this.#source,\n };\n return insertedText;\n }\n\n setInterimBehavior(behavior: VoiceInputInterimBehavior): void {\n this.#interimBehavior = behavior;\n }\n\n get value(): string {\n return this.#value;\n }\n\n get selection(): VoiceInputTextSelection | null {\n return this.#selection === null\n ? null\n : {\n start: this.#selection.start,\n end: this.#selection.end,\n direction: this.#selection.direction,\n };\n }\n\n get hasSelection(): boolean {\n return this.#selection !== null;\n }\n\n get isRunActive(): boolean {\n return this.#runActive;\n }\n\n getSnapshot(): VoiceInputTextEngineSnapshot {\n const selection =\n this.#selection === null\n ? null\n : Object.freeze({\n start: this.#selection.start,\n end: this.#selection.end,\n direction: this.#selection.direction,\n });\n const spans = this.#spans.map((span) =>\n Object.freeze({\n id: span.id,\n start: span.start,\n end: span.end,\n text: this.#value.slice(span.start, span.end),\n state: span.state,\n }),\n );\n\n return Object.freeze({\n value: this.#value,\n selection,\n interimTranscript: this.#interimTranscript,\n spans: Object.freeze(spans),\n });\n }\n\n replaceTarget(value: string): void {\n this.freezeForTargetReplacement();\n this.#value = value;\n this.#selection = null;\n this.#spans = [];\n this.#provisional = undefined;\n this.#currentFinalSpan = undefined;\n }\n\n captureSelection(selection: VoiceInputTextSelection): void {\n this.#freezeProvisional();\n this.#currentFinalSpan = undefined;\n this.#selection = toMutableSelection(selection);\n }\n\n begin(): void {\n this.#runId += 1;\n this.#runActive = true;\n this.#interimTranscript = \"\";\n this.#provisional = undefined;\n this.#currentFinalSpan = undefined;\n }\n\n applyInterim(text: string, canInsert: boolean): TextMutation | null {\n if (!this.#runActive || !canInsert) {\n return null;\n }\n\n this.#interimTranscript = text;\n if (this.#interimBehavior === \"expose\") {\n return null;\n }\n\n if (this.#provisional !== undefined) {\n if (this.proveSpan(this.#provisional)) {\n return this.#replaceOwnedSpan(this.#provisional, text, \"provisional\")\n .mutation;\n }\n this.#abandonProvisional();\n }\n\n if (text.length === 0 || !canInsert) {\n return null;\n }\n\n const inserted = this.#insertAtAnchor(text, \"provisional\");\n this.#provisional = inserted?.span;\n return inserted?.mutation ?? null;\n }\n\n applyFinal(text: string, canInsert: boolean): TextMutation | null {\n if (!this.#runActive || !canInsert) {\n return null;\n }\n\n this.#interimTranscript = \"\";\n let finalized: MutableTextSpan | undefined;\n let mutation: TextMutation | null = null;\n\n if (this.#provisional !== undefined) {\n if (this.proveSpan(this.#provisional)) {\n const replaced = this.#replaceOwnedSpan(\n this.#provisional,\n text,\n \"finalized\",\n );\n finalized = replaced?.span;\n mutation = replaced?.mutation ?? null;\n } else {\n this.#abandonProvisional();\n }\n this.#provisional = undefined;\n }\n\n if (finalized === undefined && text.length > 0 && canInsert) {\n const inserted = this.#insertAtAnchor(text, \"finalized\");\n finalized = inserted?.span;\n mutation = inserted?.mutation ?? mutation;\n }\n\n if (finalized !== undefined) {\n this.#mergeFinalizedSpan(finalized);\n }\n return mutation;\n }\n\n complete(canInsert: boolean): TextCompletionState {\n let mutation: TextMutation | null = null;\n\n if (this.#runActive && this.#provisional !== undefined) {\n if (this.proveSpan(this.#provisional)) {\n this.#provisional.state = \"finalized\";\n delete this.#provisional.replacedText;\n this.#mergeFinalizedSpan(this.#provisional);\n } else {\n this.#abandonProvisional();\n }\n this.#provisional = undefined;\n } else if (\n this.#runActive &&\n this.#interimBehavior === \"expose\" &&\n this.#interimTranscript.length > 0 &&\n canInsert\n ) {\n const inserted = this.#insertAtAnchor(\n this.#interimTranscript,\n \"finalized\",\n );\n if (inserted !== undefined) {\n this.#mergeFinalizedSpan(inserted.span);\n mutation = inserted.mutation;\n }\n }\n\n this.#interimTranscript = \"\";\n const runId = this.#runId;\n const spans = this.#spans.filter(\n (span) => span.runId === runId && span.state === \"finalized\",\n );\n this.#runActive = false;\n this.#currentFinalSpan = undefined;\n return { mutation, runId, spans };\n }\n\n cancel(): TextMutation | null {\n let mutation: TextMutation | null = null;\n if (this.#provisional !== undefined) {\n if (this.proveSpan(this.#provisional)) {\n mutation = this.#removeOwnedSpan(this.#provisional);\n } else {\n this.#abandonProvisional();\n }\n }\n this.#provisional = undefined;\n this.#interimTranscript = \"\";\n this.#currentFinalSpan = undefined;\n this.#runActive = false;\n return mutation;\n }\n\n freezeForTargetReplacement(): void {\n this.#freezeProvisional();\n for (const span of this.#spans) {\n if (span.state === \"finalized\") {\n span.state = \"frozen\";\n span.generation = this.#nextGeneration++;\n }\n }\n this.#currentFinalSpan = undefined;\n }\n\n destroy(): void {\n this.freezeForTargetReplacement();\n this.#selection = null;\n this.#interimTranscript = \"\";\n this.#runActive = false;\n }\n\n beforeInput(): void {\n this.#freezeProvisional();\n this.#currentFinalSpan = undefined;\n }\n\n reconcileExternalValue(\n value: string,\n committedSelection: VoiceInputTextSelection | null,\n ): void {\n if (value === this.#value) {\n if (\n committedSelection !== null &&\n !sameSelection(this.#selection, committedSelection)\n ) {\n this.#freezeProvisional();\n this.#currentFinalSpan = undefined;\n this.#selection = toMutableSelection(committedSelection);\n }\n return;\n }\n\n const edit = findSingleEdit(this.#value, value);\n const delta = edit.newEnd - edit.oldEnd;\n const adjustedSelection = adjustSelectionForEdit(\n this.#selection,\n edit,\n delta,\n );\n const provisional = this.#provisional;\n const provisionalOverlaps =\n provisional !== undefined && spanOverlapsEdit(provisional, edit);\n\n this.#adjustSpansForEdit(edit.oldStart, edit.oldEnd, delta);\n this.#value = value;\n this.#selection = adjustedSelection;\n this.#currentFinalSpan = undefined;\n\n if (provisionalOverlaps) {\n this.#interimTranscript = \"\";\n this.#provisional = undefined;\n } else if (\n this.#provisional !== undefined &&\n !this.proveSpan(this.#provisional)\n ) {\n this.#abandonProvisional();\n }\n\n if (\n committedSelection !== null &&\n !sameSelection(this.#selection, committedSelection)\n ) {\n this.#freezeProvisional();\n this.#selection = toMutableSelection(committedSelection);\n }\n }\n\n selectionChanged(selection: VoiceInputTextSelection): void {\n if (sameSelection(this.#selection, selection)) {\n return;\n }\n this.#freezeProvisional();\n this.#currentFinalSpan = undefined;\n this.#selection = toMutableSelection(selection);\n }\n\n proveSpan(span: MutableTextSpan): boolean {\n return (\n this.#spans.includes(span) &&\n span.start >= 0 &&\n span.end >= span.start &&\n span.end <= this.#value.length &&\n this.#value.slice(span.start, span.end) === span.expectedText\n );\n }\n\n getSpanText(span: MutableTextSpan): string {\n return this.#value.slice(span.start, span.end);\n }\n\n canApplyTransform(\n span: MutableTextSpan,\n generation: number,\n originalText: string,\n ): boolean {\n return (\n span.generation === generation &&\n span.state === \"finalized\" &&\n this.proveSpan(span) &&\n this.#value.slice(span.start, span.end) === originalText\n );\n }\n\n applyTransform(span: MutableTextSpan, text: string): TextMutation {\n const replacement = this.#limitReplacement(\n span.start,\n span.end,\n normalizeInsertion(\n this.#value.slice(0, span.start),\n this.#value.slice(span.end),\n text,\n ),\n );\n const changed = this.#replaceText(\n span.start,\n span.end,\n replacement,\n span.id,\n );\n if (replacement.length === 0) {\n this.#spans = this.#spans.filter((candidate) => candidate !== span);\n this.#selection = {\n start: span.start,\n end: span.start,\n direction: \"none\",\n replacePending: false,\n };\n } else {\n span.end = span.start + replacement.length;\n span.state = \"transformed\";\n span.generation = this.#nextGeneration++;\n span.expectedText = replacement;\n this.#selection = {\n start: span.end,\n end: span.end,\n direction: \"none\",\n replacePending: false,\n };\n }\n return this.#createMutation(changed);\n }\n\n freezeFailedTransform(span: MutableTextSpan): void {\n if (span.state === \"finalized\" && this.proveSpan(span)) {\n span.state = \"frozen\";\n span.generation = this.#nextGeneration++;\n }\n }\n\n #insertAtAnchor(\n text: string,\n state: Extract<VoiceInputTextSpanState, \"provisional\" | \"finalized\">,\n ): { mutation: TextMutation; span: MutableTextSpan } | undefined {\n const selection = this.#selection;\n if (selection === null) {\n return undefined;\n }\n\n const start = selection.start;\n const end = selection.replacePending ? selection.end : selection.start;\n const replacement = this.#limitReplacement(\n start,\n end,\n normalizeInsertion(\n this.#value.slice(0, start),\n this.#value.slice(end),\n text,\n ),\n );\n if (replacement.length === 0) {\n return undefined;\n }\n\n selection.replacePending = false;\n const replacedText = this.#value.slice(start, end);\n const changed = this.#replaceText(start, end, replacement);\n const span: MutableTextSpan = {\n id: this.#nextSpanId++,\n start,\n end: start + replacement.length,\n state,\n runId: this.#runId,\n generation: this.#nextGeneration++,\n expectedText: replacement,\n ...(end > start ? { replacedText } : {}),\n };\n this.#spans.push(span);\n this.#selection = {\n start: span.end,\n end: span.end,\n direction: \"none\",\n replacePending: false,\n };\n return { mutation: this.#createMutation(changed), span };\n }\n\n #replaceOwnedSpan(\n span: MutableTextSpan,\n text: string,\n state: Extract<VoiceInputTextSpanState, \"provisional\" | \"finalized\">,\n ): { mutation: TextMutation; span?: MutableTextSpan } {\n const replacement = this.#limitReplacement(\n span.start,\n span.end,\n normalizeInsertion(\n this.#value.slice(0, span.start),\n this.#value.slice(span.end),\n text,\n ),\n );\n if (replacement.length === 0) {\n return { mutation: this.#removeOwnedSpan(span) };\n }\n\n const changed = this.#replaceText(\n span.start,\n span.end,\n replacement,\n span.id,\n );\n span.end = span.start + replacement.length;\n span.state = state;\n span.generation = this.#nextGeneration++;\n span.expectedText = replacement;\n if (state === \"finalized\") {\n delete span.replacedText;\n }\n this.#selection = {\n start: span.end,\n end: span.end,\n direction: \"none\",\n replacePending: false,\n };\n return { mutation: this.#createMutation(changed), span };\n }\n\n #removeOwnedSpan(span: MutableTextSpan): TextMutation {\n const start = span.start;\n const replacement = span.replacedText ?? \"\";\n const changed = this.#replaceText(start, span.end, replacement, span.id);\n this.#spans = this.#spans.filter((candidate) => candidate !== span);\n this.#selection = {\n start,\n end: start + replacement.length,\n direction: \"none\",\n replacePending: replacement.length > 0,\n };\n return this.#createMutation(changed);\n }\n\n #replaceText(\n start: number,\n end: number,\n replacement: string,\n excludedSpanId?: number,\n ): boolean {\n const previousValue = this.#value;\n const nextValue = `${previousValue.slice(0, start)}${replacement}${previousValue.slice(end)}`;\n if (nextValue === previousValue) {\n return false;\n }\n const delta = replacement.length - (end - start);\n this.#adjustSpansForEdit(start, end, delta, excludedSpanId);\n this.#value = nextValue;\n return true;\n }\n\n #mergeFinalizedSpan(span: MutableTextSpan): void {\n const previous = this.#currentFinalSpan;\n if (\n previous !== undefined &&\n previous !== span &&\n previous.state === \"finalized\" &&\n previous.runId === span.runId &&\n previous.end === span.start &&\n this.proveSpan(previous) &&\n this.proveSpan(span)\n ) {\n previous.end = span.end;\n previous.generation = this.#nextGeneration++;\n previous.expectedText = this.#value.slice(previous.start, previous.end);\n this.#spans = this.#spans.filter((candidate) => candidate !== span);\n this.#currentFinalSpan = previous;\n return;\n }\n this.#currentFinalSpan = span;\n }\n\n #freezeProvisional(): void {\n if (this.#provisional !== undefined) {\n this.#provisional.state = \"frozen\";\n this.#provisional.generation = this.#nextGeneration++;\n this.#provisional = undefined;\n }\n this.#interimTranscript = \"\";\n this.#currentFinalSpan = undefined;\n }\n\n #abandonProvisional(): void {\n const provisional = this.#provisional;\n if (provisional !== undefined) {\n this.#spans = this.#spans.filter((span) => span !== provisional);\n this.#provisional = undefined;\n }\n this.#interimTranscript = \"\";\n this.#currentFinalSpan = undefined;\n }\n\n #adjustSpansForEdit(\n start: number,\n end: number,\n delta: number,\n excludedSpanId?: number,\n ): void {\n const retained: MutableTextSpan[] = [];\n for (const span of this.#spans) {\n if (span.id === excludedSpanId) {\n retained.push(span);\n } else if (span.end <= start) {\n retained.push(span);\n } else if (span.start >= end) {\n span.start += delta;\n span.end += delta;\n retained.push(span);\n } else {\n if (span === this.#provisional) {\n this.#provisional = undefined;\n }\n if (span === this.#currentFinalSpan) {\n this.#currentFinalSpan = undefined;\n }\n }\n }\n this.#spans = retained;\n }\n\n #createMutation(changed: boolean): TextMutation {\n return {\n changed,\n selection: this.selection,\n value: this.#value,\n };\n }\n}\n\nexport function normalizeInsertion(\n left: string,\n right: string,\n text: string,\n): string {\n return normalizeTranscriptInsertion(left, right, text);\n}\n\nexport function findSingleEdit(previous: string, next: string): TextEdit {\n let prefix = 0;\n const maximumPrefix = Math.min(previous.length, next.length);\n while (prefix < maximumPrefix && previous[prefix] === next[prefix]) {\n prefix += 1;\n }\n\n let suffix = 0;\n const maximumSuffix = Math.min(\n previous.length - prefix,\n next.length - prefix,\n );\n while (\n suffix < maximumSuffix &&\n previous[previous.length - suffix - 1] === next[next.length - suffix - 1]\n ) {\n suffix += 1;\n }\n\n return {\n oldStart: prefix,\n oldEnd: previous.length - suffix,\n newEnd: next.length - suffix,\n };\n}\n\nexport function adjustSelectionForEdit(\n selection: MutableTextSelection | null,\n edit: TextEdit,\n delta: number,\n): MutableTextSelection | null {\n if (selection === null) {\n return null;\n }\n if (selection.end <= edit.oldStart) {\n return selection;\n }\n if (selection.start >= edit.oldEnd) {\n return {\n ...selection,\n start: selection.start + delta,\n end: selection.end + delta,\n };\n }\n return {\n start: edit.newEnd,\n end: edit.newEnd,\n direction: \"none\",\n replacePending: false,\n };\n}\n\nfunction spanOverlapsEdit(span: MutableTextSpan, edit: TextEdit): boolean {\n return !(span.end <= edit.oldStart || span.start >= edit.oldEnd);\n}\n\nfunction toMutableSelection(\n selection: VoiceInputTextSelection,\n): MutableTextSelection {\n return {\n ...selection,\n replacePending: selection.start !== selection.end,\n };\n}\n\nfunction sameSelection(\n current: MutableTextSelection | null,\n next: VoiceInputTextSelection,\n): boolean {\n return (\n current !== null &&\n current.start === next.start &&\n current.end === next.end &&\n (current.start === current.end || current.direction === next.direction)\n );\n}\n","export class TransformTimeoutError extends Error {\n constructor() {\n super(\"Transcript transform timed out.\");\n this.name = \"TransformTimeoutError\";\n }\n}\n\nexport async function runTransformWithTimeout(\n transform: () => unknown,\n timeoutMs: number,\n): Promise<unknown> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n const result = transform();\n return await Promise.race([\n Promise.resolve(result),\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(\n () => reject(new TransformTimeoutError()),\n timeoutMs,\n );\n }),\n ]);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n }\n}\n","import { VoiceInputError } from \"@voiceinput/provider\";\n\nimport { TextHistory, type HistoryValue } from \"./history.js\";\nimport { TextTargetAdapter } from \"./dom-target.js\";\nimport {\n TextOwnershipModel,\n type MutableTextSpan,\n type TextMutation,\n} from \"./ownership-model.js\";\nimport { TransformTimeoutError, runTransformWithTimeout } from \"./transform.js\";\nimport type {\n VoiceInputControlledTextBinding,\n CreateVoiceInputTextEngineOptions,\n VoiceInputTextEngineEvent,\n VoiceInputInterimBehavior,\n VoiceInputTextCompletion,\n VoiceInputTextEngine,\n VoiceInputTextEngineSnapshot,\n VoiceInputTextSelection,\n VoiceInputTextTarget,\n VoiceInputTransformTranscript,\n} from \"./types.js\";\n\nexport class VoiceInputTextEngineController implements VoiceInputTextEngine {\n readonly #controlled: VoiceInputControlledTextBinding | undefined;\n #transformTranscript: VoiceInputTransformTranscript | undefined;\n #transformTimeoutMs: number;\n readonly #model: TextOwnershipModel;\n readonly #target: TextTargetAdapter;\n\n #nextOptions:\n Omit<CreateVoiceInputTextEngineOptions, \"controlled\"> | undefined;\n updateOptions(\n options: Omit<CreateVoiceInputTextEngineOptions, \"controlled\">,\n ): void {\n if (\n options.interimBehavior !== undefined &&\n options.interimBehavior !== \"inline\" &&\n options.interimBehavior !== \"expose\"\n ) {\n throw invalidConfiguration(\"interimBehavior must be inline or expose.\");\n }\n if (\n options.transformTimeoutMs !== undefined &&\n (!Number.isInteger(options.transformTimeoutMs) ||\n options.transformTimeoutMs <= 0)\n ) {\n throw invalidConfiguration(\n \"transformTimeoutMs must be a positive finite integer.\",\n );\n }\n if (\n options.transformTranscript !== undefined &&\n typeof options.transformTranscript !== \"function\"\n ) {\n throw invalidConfiguration(\"transformTranscript must be a function.\");\n }\n this.#nextOptions = options;\n }\n #completionGeneration = 0;\n readonly #history = new TextHistory();\n readonly #listeners = new Set<(event: VoiceInputTextEngineEvent) => void>();\n readonly #suppressed = new Set<string>();\n readonly #closedSegments = new Set<string>();\n #implicitSegment = 0;\n #currentSegment: string | undefined;\n #limitedSegment: string | undefined;\n #composing = false;\n #beforeInput: HistoryValue | undefined;\n #inputType = \"insertText\";\n\n subscribe(listener: (event: VoiceInputTextEngineEvent) => void): () => void {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n }\n\n isWritable(): boolean {\n return this.#target.isWritable();\n }\n\n undo(): void {\n this.#restoreHistory(false);\n }\n redo(): void {\n this.#restoreHistory(true);\n }\n\n #restoreHistory(redo: boolean): void {\n if (!this.isWritable() || this.#composing) return;\n const state = redo ? this.#history.redo() : this.#history.undo();\n if (!state) return;\n this.#takeOwnership();\n this.#invalidateCompletion();\n this.#model.replaceTarget(state.value);\n if (state.selection) this.#model.captureSelection(state.selection);\n this.#target.applyMutation({ ...state, changed: true });\n }\n\n #takeOwnership(): void {\n if (this.#currentSegment !== undefined)\n this.#suppressed.add(this.#currentSegment);\n this.#model.beforeInput();\n this.#history.breakGroup();\n }\n\n #emit(event: VoiceInputTextEngineEvent): void {\n for (const listener of this.#listeners) {\n try {\n listener(event);\n } catch (error) {\n reportUnhandledError(error);\n }\n }\n }\n\n #state(): HistoryValue {\n return {\n value: this.#model.value,\n selection: this.#target.readSelection() ?? this.#model.selection,\n };\n }\n\n #availabilityChanged(): void {\n if (!this.isWritable()) {\n this.#takeOwnership();\n this.#invalidateCompletion();\n this.#emit({ type: \"target-unavailable\" });\n }\n }\n\n #reset(): void {\n this.#beforeInput = undefined;\n this.#takeOwnership();\n this.#invalidateCompletion();\n this.#model.replaceTarget(this.#target.readValue());\n this.#model.cancel();\n this.#history.clear();\n this.#emit({ type: \"reset\" });\n }\n\n constructor(options: {\n interimBehavior: VoiceInputInterimBehavior;\n controlled: VoiceInputControlledTextBinding | undefined;\n transformTranscript: VoiceInputTransformTranscript | undefined;\n transformTimeoutMs: number;\n }) {\n this.#controlled = options.controlled;\n this.#transformTranscript = options.transformTranscript;\n this.#transformTimeoutMs = options.transformTimeoutMs;\n this.#model = new TextOwnershipModel(options.interimBehavior);\n this.#target = new TextTargetAdapter(options.controlled, {\n onBeforeInput: (inputType) => {\n this.#beforeInput = this.#state();\n this.#inputType = inputType;\n if (!this.#composing) {\n if (this.#currentSegment !== undefined)\n this.#suppressed.add(this.#currentSegment);\n this.#model.beforeInput();\n }\n },\n onHistory: (redo) => this.#restoreHistory(redo),\n onComposition: (active) => {\n if (active) this.#takeOwnership();\n this.#composing = active;\n if (!active) {\n this.#handleInput();\n this.#history.breakGroup();\n }\n },\n onReset: () => this.#reset(),\n onAvailability: () => this.#availabilityChanged(),\n onInput: () => this.#handleInput(),\n onSelectionChange: () => this.#handleSelectionChange(),\n onUnhandledError: reportUnhandledError,\n });\n }\n\n getSnapshot(): VoiceInputTextEngineSnapshot {\n return this.#model.getSnapshot();\n }\n\n setTarget(target: VoiceInputTextTarget | null): void {\n if (target === this.#target.target) {\n return;\n }\n\n const wasAttached = this.#target.target !== null;\n this.#takeOwnership();\n this.#history.clear();\n this.#beforeInput = undefined;\n this.#composing = false;\n this.#invalidateCompletion();\n this.#model.cancel();\n if (wasAttached) this.#emit({ type: \"reset\" });\n if (target === null) {\n this.#target.detach();\n this.#model.replaceTarget(\"\");\n return;\n }\n\n const value = this.#target.attach(target);\n this.#model.replaceTarget(value);\n this.#target.synchronize(this.#model.value, this.#model.selection);\n }\n\n captureSelection(): VoiceInputTextSelection | null {\n if (!this.#target.isWritable()) {\n return null;\n }\n\n this.#reconcileUncontrolledDomValue();\n const selection = this.#target.readSelection();\n if (selection === null) {\n return null;\n }\n if (!sameSelection(this.#model.selection, selection)) this.#takeOwnership();\n this.#model.captureSelection(selection);\n return Object.freeze({ ...selection });\n }\n\n reconcileControlledValue(value: string): void {\n if (this.#controlled === undefined) {\n throw invalidConfiguration(\n \"reconcileControlledValue is only available for controlled text engines.\",\n );\n }\n if (typeof value !== \"string\") {\n throw invalidConfiguration(\"A controlled value must be a string.\");\n }\n\n if (this.#composing) return;\n if (value !== this.#model.value) this.#history.clear();\n const committedSelection = this.#target.readSelectionWhenValueIs(value);\n this.#model.reconcileExternalValue(value, committedSelection);\n if (\n this.#currentSegment !== undefined &&\n !this.#model\n .getSnapshot()\n .spans.some((span) => span.state === \"provisional\")\n )\n this.#suppressed.add(this.#currentSegment);\n this.#target.synchronize(this.#model.value, this.#model.selection);\n }\n\n begin(): void {\n if (this.#nextOptions) {\n this.#model.setInterimBehavior(\n this.#nextOptions.interimBehavior ?? \"inline\",\n );\n this.#transformTranscript = this.#nextOptions.transformTranscript;\n this.#transformTimeoutMs = this.#nextOptions.transformTimeoutMs ?? 10_000;\n }\n this.#invalidateCompletion();\n this.#model.begin();\n this.#suppressed.clear();\n this.#closedSegments.clear();\n this.#implicitSegment = 0;\n this.#currentSegment = undefined;\n this.#limitedSegment = undefined;\n this.#history.breakGroup();\n if (!this.#model.hasSelection) {\n this.captureSelection();\n }\n }\n\n applyInterim(text: string, segmentId?: string): void {\n this.#applyTranscript(text, segmentId, false);\n }\n\n applyFinal(text: string, segmentId?: string): void {\n this.#applyTranscript(text, segmentId, true);\n }\n\n #applyTranscript(\n text: string,\n segmentId: string | undefined,\n final: boolean,\n ): void {\n if (typeof text !== \"string\" || !this.#model.isRunActive) return;\n const id = segmentId ?? `implicit:${this.#implicitSegment}`;\n if (this.#closedSegments.has(id)) return;\n this.#reconcileUncontrolledDomValue();\n if (this.#currentSegment !== undefined && this.#currentSegment !== id) {\n this.#takeOwnership();\n }\n if (this.#currentSegment !== id) this.#history.breakGroup();\n this.#currentSegment = id;\n if (\n this.#composing ||\n !this.isWritable() ||\n (this.#limitedSegment !== undefined && this.#limitedSegment !== id)\n ) {\n this.#suppressed.add(id);\n this.#model.beforeInput();\n }\n if (!this.#suppressed.has(id)) {\n const before = this.#state();\n this.#model.configureMutation(\n this.#target.target?.maxLength ?? -1,\n final ? \"final\" : \"interim\",\n );\n const mutation = final\n ? this.#model.applyFinal(text, true)\n : this.#model.applyInterim(text, true);\n this.#applyMutation(mutation, before, `voice:${id}`);\n const limit = this.#model.takeLimit();\n if (limit) {\n const firstLimit = this.#limitedSegment === undefined;\n this.#limitedSegment = id;\n if (firstLimit) this.#emit(limit);\n }\n }\n if (final) {\n this.#closedSegments.add(id);\n this.#currentSegment = undefined;\n this.#implicitSegment += 1;\n this.#history.breakGroup();\n }\n }\n\n complete(): VoiceInputTextCompletion {\n if (!this.#model.isRunActive) {\n return { processing: false, result: Promise.resolve([]) };\n }\n\n const before = this.#state();\n this.#model.configureMutation(\n this.#target.target?.maxLength ?? -1,\n \"final\",\n );\n const completion = this.#model.complete(\n this.#target.isWritable() && !this.#composing,\n );\n this.#applyMutation(\n completion.mutation,\n before,\n `voice:${this.#currentSegment}`,\n );\n const limit = this.#model.takeLimit();\n if (limit) this.#emit(limit);\n this.#history.breakGroup();\n const processing =\n this.#transformTranscript !== undefined && completion.spans.length > 0;\n const completionGeneration = ++this.#completionGeneration;\n\n if (!processing || this.#transformTranscript === undefined) {\n return { processing: false, result: Promise.resolve([]) };\n }\n\n return {\n processing: true,\n result: Promise.all(\n completion.spans.map((span) =>\n this.#transformSpan(span, completionGeneration),\n ),\n ).then((errors) => errors.filter(isVoiceInputError)),\n };\n }\n\n cancel(): void {\n this.#invalidateCompletion();\n const before = this.#state();\n if (!this.isWritable() || this.#composing) this.#takeOwnership();\n this.#applyMutation(\n this.#model.cancel(),\n before,\n `voice:${this.#currentSegment}`,\n );\n this.#currentSegment = undefined;\n this.#history.breakGroup();\n }\n\n destroy(): void {\n this.#invalidateCompletion();\n this.#model.destroy();\n this.#target.detach();\n this.#history.clear();\n this.#listeners.clear();\n }\n\n async #transformSpan(\n span: MutableTextSpan,\n completionGeneration: number,\n ): Promise<VoiceInputError | null> {\n const transform = this.#transformTranscript;\n if (transform === undefined || !this.#model.proveSpan(span)) {\n return null;\n }\n\n const generation = span.generation;\n const originalText = this.#model.getSpanText(span);\n const transcript = originalText.trim();\n\n try {\n const transformed = await runTransformWithTimeout(\n () => transform(transcript),\n this.#transformTimeoutMs,\n );\n if (typeof transformed !== \"string\") {\n throw new TypeError(\"transformTranscript must resolve to a string.\");\n }\n if (\n !this.isWritable() ||\n this.#composing ||\n completionGeneration !== this.#completionGeneration ||\n !this.#model.canApplyTransform(span, generation, originalText)\n ) {\n return null;\n }\n\n const before = this.#state();\n this.#model.configureMutation(\n this.#target.target?.maxLength ?? -1,\n \"transform\",\n );\n this.#history.breakGroup();\n this.#applyMutation(\n this.#model.applyTransform(span, transformed),\n before,\n `transform:${span.id}`,\n );\n const limit = this.#model.takeLimit();\n if (limit) this.#emit(limit);\n return null;\n } catch (cause) {\n if (completionGeneration !== this.#completionGeneration) {\n return null;\n }\n this.#model.freezeFailedTransform(span);\n return new VoiceInputError({\n code: \"transform-error\",\n message:\n cause instanceof TransformTimeoutError\n ? `Transcript transform timed out after ${this.#transformTimeoutMs}ms.`\n : \"Transcript transform failed.\",\n cause,\n });\n }\n }\n\n #handleInput(): void {\n const selection = this.#target.readSelection();\n const before = this.#beforeInput ?? {\n value: this.#model.value,\n selection: this.#model.selection,\n };\n this.#beforeInput = undefined;\n this.#model.reconcileExternalValue(this.#target.readValue(), selection);\n const key = this.#composing ? \"composition\" : this.#inputType;\n if (\n ![\n \"insertText\",\n \"deleteContentBackward\",\n \"deleteContentForward\",\n \"composition\",\n ].includes(key)\n )\n this.#history.breakGroup();\n this.#history.record(before, this.#state(), key);\n }\n\n #handleSelectionChange(): void {\n const selection = this.#target.readSelection();\n if (selection !== null && !this.#composing) {\n if (!sameSelection(selection, this.#model.selection))\n this.#takeOwnership();\n this.#model.selectionChanged(selection);\n }\n }\n\n #reconcileUncontrolledDomValue(): void {\n if (this.#target.isControlled || this.#target.target === null) {\n return;\n }\n const value = this.#target.readValue();\n if (value !== this.#model.value) {\n this.#takeOwnership();\n this.#history.clear();\n this.#model.reconcileExternalValue(value, this.#target.readSelection());\n }\n }\n\n #applyMutation(\n mutation: TextMutation | null,\n before?: HistoryValue,\n key = \"voice\",\n ): void {\n if (mutation !== null) {\n if (before && mutation.changed)\n this.#history.record(before, mutation, key);\n this.#target.applyMutation(mutation);\n }\n }\n\n #invalidateCompletion(): void {\n this.#completionGeneration += 1;\n }\n}\n\nfunction invalidConfiguration(message: string): VoiceInputError {\n return new VoiceInputError({ code: \"invalid-configuration\", message });\n}\n\nfunction isVoiceInputError(\n error: VoiceInputError | null,\n): error is VoiceInputError {\n return error !== null;\n}\n\nfunction reportUnhandledError(error: unknown): void {\n const reportError = (\n globalThis as typeof globalThis & {\n reportError?: (error: unknown) => void;\n }\n ).reportError;\n if (typeof reportError === \"function\") {\n reportError(error);\n } else {\n queueMicrotask(() => {\n throw error;\n });\n }\n}\n\nfunction sameSelection(\n left: VoiceInputTextSelection | null,\n right: VoiceInputTextSelection | null,\n): boolean {\n return (\n left?.start === right?.start &&\n left?.end === right?.end &&\n (left?.start === left?.end || left?.direction === right?.direction)\n );\n}\n","import { VoiceInputError } from \"@voiceinput/provider\";\n\nimport { VoiceInputTextEngineController } from \"./text-engine/controller.js\";\nimport type {\n CreateVoiceInputTextEngineOptions,\n VoiceInputTextEngine,\n} from \"./text-engine/types.js\";\n\nconst DEFAULT_TRANSFORM_TIMEOUT_MS = 10_000;\n\nexport type {\n CreateVoiceInputTextEngineOptions,\n VoiceInputControlledTextBinding,\n VoiceInputInterimBehavior,\n VoiceInputTextCompletion,\n VoiceInputTextLimit,\n VoiceInputTextEngineEvent,\n VoiceInputTextEngine,\n VoiceInputTextEngineSnapshot,\n VoiceInputTextSelection,\n VoiceInputTextSpan,\n VoiceInputTextSpanState,\n VoiceInputTextTarget,\n VoiceInputTransformTranscript,\n} from \"./text-engine/types.js\";\n\nexport function createVoiceInputTextEngine(\n options: CreateVoiceInputTextEngineOptions = {},\n): VoiceInputTextEngine {\n const interimBehavior = options.interimBehavior ?? \"inline\";\n if (interimBehavior !== \"inline\" && interimBehavior !== \"expose\") {\n throw invalidConfiguration(\n 'interimBehavior must be either \"inline\" or \"expose\".',\n );\n }\n if (\n options.transformTimeoutMs !== undefined &&\n (!Number.isFinite(options.transformTimeoutMs) ||\n !Number.isInteger(options.transformTimeoutMs) ||\n options.transformTimeoutMs <= 0)\n ) {\n throw invalidConfiguration(\n \"transformTimeoutMs must be a positive finite integer.\",\n );\n }\n if (\n options.controlled !== undefined &&\n (typeof options.controlled.getValue !== \"function\" ||\n typeof options.controlled.onValueChange !== \"function\")\n ) {\n throw invalidConfiguration(\n \"controlled must provide getValue and onValueChange functions.\",\n );\n }\n if (\n options.transformTranscript !== undefined &&\n typeof options.transformTranscript !== \"function\"\n ) {\n throw invalidConfiguration(\"transformTranscript must be a function.\");\n }\n\n return new VoiceInputTextEngineController({\n interimBehavior,\n controlled: options.controlled,\n transformTranscript: options.transformTranscript,\n transformTimeoutMs:\n options.transformTimeoutMs ?? DEFAULT_TRANSFORM_TIMEOUT_MS,\n });\n}\n\nfunction invalidConfiguration(message: string): VoiceInputError {\n return new VoiceInputError({ code: \"invalid-configuration\", message });\n}\n"],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ import { VoiceInputError, VoiceInputError as VoiceInputError$1, VoiceInputErrorCode, VoiceInputErrorOptions, VoiceInputProviderV1, VoiceTranscriptionOptions } from "@voiceinput/provider";
2
+ //#region src/text-engine/types.d.ts
3
+ type VoiceInputTextTarget = HTMLInputElement | HTMLTextAreaElement;
4
+ type VoiceInputInterimBehavior = "inline" | "expose";
5
+ type VoiceInputTextSpanState = "provisional" | "finalized" | "frozen" | "transformed";
6
+ interface VoiceInputTextSelection {
7
+ readonly start: number;
8
+ readonly end: number;
9
+ readonly direction: "forward" | "backward" | "none";
10
+ }
11
+ interface VoiceInputTextSpan {
12
+ readonly id: number;
13
+ readonly start: number;
14
+ readonly end: number;
15
+ readonly text: string;
16
+ readonly state: VoiceInputTextSpanState;
17
+ }
18
+ interface VoiceInputTextEngineSnapshot {
19
+ readonly value: string;
20
+ readonly selection: VoiceInputTextSelection | null;
21
+ readonly interimTranscript: string;
22
+ readonly spans: readonly VoiceInputTextSpan[];
23
+ }
24
+ /**
25
+ * Connects the engine's immediate shadow value to controlled application state.
26
+ *
27
+ * `getValue` supplies the value when a target is attached. `onValueChange`
28
+ * requests an application update but is not expected to commit synchronously.
29
+ * Pass each value committed by the application to
30
+ * `reconcileControlledValue` on the text engine.
31
+ */
32
+ interface VoiceInputControlledTextBinding {
33
+ getValue(): string;
34
+ onValueChange(value: string): void;
35
+ /** Notify through a native input event instead of the binding callback. */
36
+ dispatchInput?: boolean;
37
+ }
38
+ type VoiceInputTransformTranscript = (text: string) => PromiseLike<string> | string;
39
+ interface VoiceInputTextLimit {
40
+ readonly type: "text-limit";
41
+ readonly maxLength: number;
42
+ readonly text: string;
43
+ readonly insertedText: string;
44
+ readonly source: "interim" | "final" | "transform";
45
+ }
46
+ type VoiceInputTextEngineEvent = VoiceInputTextLimit | {
47
+ type: "target-unavailable" | "reset";
48
+ };
49
+ interface CreateVoiceInputTextEngineOptions {
50
+ interimBehavior?: VoiceInputInterimBehavior;
51
+ controlled?: VoiceInputControlledTextBinding;
52
+ transformTranscript?: VoiceInputTransformTranscript;
53
+ transformTimeoutMs?: number;
54
+ }
55
+ interface VoiceInputTextCompletion {
56
+ readonly processing: boolean;
57
+ readonly result: Promise<readonly VoiceInputError$1[]>;
58
+ }
59
+ interface VoiceInputTextEngine {
60
+ getSnapshot(): VoiceInputTextEngineSnapshot;
61
+ setTarget(target: VoiceInputTextTarget | null): void;
62
+ captureSelection(): VoiceInputTextSelection | null;
63
+ reconcileControlledValue(value: string): void;
64
+ updateOptions(options: Omit<CreateVoiceInputTextEngineOptions, "controlled">): void;
65
+ begin(): void;
66
+ applyInterim(text: string, segmentId?: string): void;
67
+ applyFinal(text: string, segmentId?: string): void;
68
+ complete(): VoiceInputTextCompletion;
69
+ cancel(): void;
70
+ undo(): void;
71
+ redo(): void;
72
+ isWritable(): boolean;
73
+ subscribe(listener: (event: VoiceInputTextEngineEvent) => void): () => void;
74
+ destroy(): void;
75
+ }
76
+ //#endregion
77
+ //#region src/text-engine.d.ts
78
+ declare function createVoiceInputTextEngine(options?: CreateVoiceInputTextEngineOptions): VoiceInputTextEngine;
79
+ //#endregion
80
+ //#region src/session.d.ts
81
+ type VoiceInputStatus = "idle" | "requesting-permission" | "connecting" | "listening" | "stopping" | "processing" | "error";
82
+ type VoiceInputStopReason = "user" | "max-duration" | "replaced" | "max-length" | "target-unavailable" | "backgrounded";
83
+ interface VoiceInputSnapshot {
84
+ readonly status: VoiceInputStatus;
85
+ readonly transcript: string;
86
+ readonly interimTranscript: string;
87
+ readonly finalTranscript: string;
88
+ readonly error: VoiceInputError | null;
89
+ }
90
+ type VoiceInputSessionEvent = VoiceInputTextLimit | {
91
+ type: "status-change";
92
+ previousStatus: VoiceInputStatus;
93
+ status: VoiceInputStatus;
94
+ } | {
95
+ type: "interim";
96
+ text: string;
97
+ segmentId: string;
98
+ transcript: string;
99
+ transcriptChanged: boolean;
100
+ } | {
101
+ type: "final";
102
+ text: string;
103
+ segmentId: string;
104
+ transcript: string;
105
+ transcriptChanged: boolean;
106
+ finalTranscriptChanged: boolean;
107
+ } | {
108
+ type: "duration-warning";
109
+ remainingMs: number;
110
+ maxDurationMs: number;
111
+ } | {
112
+ type: "stop";
113
+ reason: VoiceInputStopReason;
114
+ } | {
115
+ type: "cancel";
116
+ } | {
117
+ type: "speech-start";
118
+ } | {
119
+ type: "speech-end";
120
+ } | {
121
+ type: "error";
122
+ error: VoiceInputError;
123
+ };
124
+ interface VoiceAudioSourcePrepareOptions {
125
+ sampleRate: number;
126
+ abortSignal: AbortSignal;
127
+ onAcquired?(): void;
128
+ }
129
+ interface PreparedVoiceAudioSource {
130
+ readonly stream: ReadableStream<Int16Array>;
131
+ start(): PromiseLike<void> | void;
132
+ stop(): PromiseLike<void> | void;
133
+ abort(reason?: unknown): void;
134
+ }
135
+ interface VoiceAudioSource {
136
+ prepare(options: VoiceAudioSourcePrepareOptions): PromiseLike<PreparedVoiceAudioSource>;
137
+ }
138
+ interface CreateVoiceInputSessionOptions extends VoiceTranscriptionOptions {
139
+ provider: VoiceInputProviderV1;
140
+ audioSource: VoiceAudioSource;
141
+ textEngine?: VoiceInputTextEngine;
142
+ maxDurationMs?: number;
143
+ connectionTimeoutMs?: number;
144
+ }
145
+ interface VoiceInputSession {
146
+ getSnapshot(): VoiceInputSnapshot;
147
+ subscribe(listener: (event: VoiceInputSessionEvent) => void): () => void;
148
+ /** Applies to the next recording; a running session keeps its configuration. */
149
+ updateOptions(options: Omit<CreateVoiceInputSessionOptions, "textEngine">): void;
150
+ start(): Promise<void>;
151
+ stop(reason?: VoiceInputStopReason): Promise<void>;
152
+ cancel(): Promise<void>;
153
+ toggle(): Promise<void>;
154
+ }
155
+ declare function createVoiceInputSession(options: CreateVoiceInputSessionOptions): VoiceInputSession;
156
+ //#endregion
157
+ //#region src/browser-audio.d.ts
158
+ type BrowserVoiceInputCapability = "secure-context" | "media-devices" | "get-user-media" | "audio-context" | "audio-worklet";
159
+ interface BrowserVoiceInputSupport {
160
+ readonly isSupported: boolean;
161
+ readonly missingCapabilities: readonly BrowserVoiceInputCapability[];
162
+ }
163
+ interface CreateBrowserAudioSourceOptions {
164
+ /** Additional microphone constraints. VoiceInput always requests mono audio. */
165
+ constraints?: MediaTrackConstraints;
166
+ /** Duration of each emitted PCM16 frame. Defaults to 20 milliseconds. */
167
+ frameDurationMs?: number;
168
+ /** Self-hosted AudioWorklet module URL. The Blob-backed module is used by default. */
169
+ workletModuleUrl?: string | URL;
170
+ }
171
+ declare function getBrowserVoiceInputSupport(): BrowserVoiceInputSupport;
172
+ declare function createBrowserAudioSource(options?: CreateBrowserAudioSourceOptions): VoiceAudioSource;
173
+ declare function normalizeBrowserAudioError(error: unknown): VoiceInputError$1;
174
+ //#endregion
175
+ //#region src/audio-worklet-source.d.ts
176
+ declare const AUDIO_WORKLET_SOURCE: string;
177
+ //#endregion
178
+ export { type BrowserVoiceInputCapability, type BrowserVoiceInputSupport, type CreateBrowserAudioSourceOptions, type CreateVoiceInputSessionOptions, type CreateVoiceInputTextEngineOptions, type PreparedVoiceAudioSource, AUDIO_WORKLET_SOURCE as VOICE_INPUT_AUDIO_WORKLET_SOURCE, type VoiceAudioSource, type VoiceAudioSourcePrepareOptions, type VoiceInputControlledTextBinding, VoiceInputError, type VoiceInputErrorCode, type VoiceInputErrorOptions, type VoiceInputInterimBehavior, type VoiceInputSession, type VoiceInputSessionEvent, type VoiceInputSnapshot, type VoiceInputStatus, type VoiceInputStopReason, type VoiceInputTextCompletion, type VoiceInputTextEngine, type VoiceInputTextEngineEvent, type VoiceInputTextEngineSnapshot, type VoiceInputTextLimit, type VoiceInputTextSelection, type VoiceInputTextSpan, type VoiceInputTextSpanState, type VoiceInputTextTarget, type VoiceInputTransformTranscript, createBrowserAudioSource, createVoiceInputSession, createVoiceInputTextEngine, getBrowserVoiceInputSupport, normalizeBrowserAudioError };
179
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/text-engine/types.ts","../src/text-engine.ts","../src/session.ts","../src/browser-audio.ts","../src/audio-worklet-source.ts"],"mappings":";;KAEY,uBAAuB,mBAAmB;KAC1C;KACA;UAGK;WACN;WACA;WACA;;UAGM;WACN;WACA;WACA;WACA;WACA,OAAO;;UAGD;WACN;WACA,WAAW;WACX;WACA,gBAAgB;;;;;;;;;;UAWV;EACf;EACA,cAAc;;EAEd;;KAGU,iCACV,iBACG;UAEY;WACN;WACA;WACA;WACA;WACA;;KAGC,4BACV;EAAwB;;UAET;EACf,kBAAkB;EAClB,aAAa;EACb,sBAAsB;EACtB;;UAGe;WACN;WACA,QAAQ,iBAAiB;;UAGnB;EACf,eAAe;EACf,UAAU,QAAQ;EAClB,oBAAoB;EACpB,yBAAyB;EACzB,cACE,SAAS,KAAK;EAEhB;EACA,aAAa,cAAc;EAC3B,WAAW,cAAc;EACzB,YAAY;EACZ;EACA;EACA;EACA;EACA,UAAU,WAAW,OAAO;EAC5B;;;;iBC7Dc,2BACd,UAAS,oCACR;;;KCDS;KASA;UAQK;WACN,QAAQ;WACR;WACA;WACA;WACA,OAAO;;KAGN,yBACR;EAEE;EACA,gBAAgB;EAChB,QAAQ;;EAGR;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;;EAEA;EAAc,QAAQ;;EACtB;;EACA;;EACA;;EACA;EAAe,OAAO;;UAEX;EACf;EACA,aAAa;EACb;;UAGe;WACN,QAAQ,eAAe;EAChC,SAAS;EACT,QAAQ;EACR,MAAM;;UAGS;EACf,QACE,SAAS,iCACR,YAAY;;UAGA,uCAAuC;EACtD,UAAU;EACV,aAAa;EACb,aAAa;EACb;EACA;;UAGe;EACf,eAAe;EACf,UAAU,WAAW,OAAO;;EAE5B,cACE,SAAS,KAAK;EAEhB,SAAS;EACT,KAAK,SAAS,uBAAuB;EACrC,UAAU;EACV,UAAU;;iBA0BI,wBACd,SAAS,iCACR;;;KCvIS;UAOK;WACN;WACA,8BAA8B;;UAGxB;;EAEf,cAAc;;EAEd;;EAEA,4BAA4B;;iBAGd,+BAA+B;iBAyC/B,yBACd,UAAS,kCACR;iBAqSa,2BAA2B,iBAAiB;;;cCpL/C"}