{"version":3,"sources":["src/sdk/Recognizer.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,eAAe,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAIH,eAAe,EACf,kBAAkB,EAElB,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,4EAA4E,CAAC;AAQ7G,OAAO,EACH,WAAW,EACX,kBAAkB,EAElB,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EAC1B,MAAM,cAAc,CAAC;AAEtB;;;GAGG;AACH,8BAAsB,UAAU;IAC5B,OAAO,CAAC,YAAY,CAAU;IAC9B,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IACnC,SAAS,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IAC1C,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC7C,SAAS,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC5C,OAAO,CAAC,qBAAqB,CAAqB;IAElD;;;;;;OAMG;IACH,SAAS,aAAa,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,CAAC,EAAE,eAAe;IASxJ;;;;;OAKG;IACI,cAAc,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAE7E;;;;;OAKG;IACI,cAAc,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAE7E;;;;;OAKG;IACI,mBAAmB,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAEtF;;;;;OAKG;IACI,iBAAiB,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAEpF;;;;;OAKG;IACI,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAKtE;;;;OAIG;IACH,IAAW,YAAY,IAAI,MAAM,CAEhC;IAED;;;;;;;;;OASG;cACa,OAAO,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAe1D;;;;;;OAMG;IACH,WAAkB,gBAAgB,IAAI,OAAO,CAE5C;IAED;;;;;;;;;OASG;WACW,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAUrD,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CAAC,YAAY,EAAE,mBAAmB,GAAG,gBAAgB;IAG9F,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CACtC,cAAc,EAAE,eAAe,EAC/B,iBAAiB,EAAE,kBAAkB,EACrC,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,GAAG,qBAAqB;IAG9D,SAAS,CAAC,yBAAyB,IAAI,IAAI;cAuB3B,sBAAsB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,uBAAuB,CAAC;cAa1F,mCAAmC,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;cAOpF,kCAAkC,IAAI,OAAO,CAAC,IAAI,CAAC;cAKnD,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmCnD,OAAO,CAAC,WAAW;IAWnB,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,kBAAkB,EAAE,eAAe,CAAC,EAAE,eAAe,GAAG,eAAe;CAsC/G","file":"Recognizer.d.ts","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license.\r\nimport {\r\n    TokenCredential\r\n} from \"@azure/core-auth\";\r\nimport {\r\n    CognitiveSubscriptionKeyAuthentication,\r\n    CognitiveTokenAuthentication,\r\n    Context,\r\n    IAuthentication,\r\n    IConnectionFactory,\r\n    OS,\r\n    RecognizerConfig,\r\n    ServiceRecognizerBase,\r\n    SpeechServiceConfig,\r\n} from \"../common.speech/Exports.js\";\r\nimport { RecognitionMode } from \"../common.speech/ServiceMessages/PhraseDetection/PhraseDetectionContext.js\";\r\nimport {\r\n    Deferred,\r\n    marshalPromiseToCallbacks\r\n} from \"../common/Exports.js\";\r\nimport {\r\n    Contracts\r\n} from \"./Contracts.js\";\r\nimport {\r\n    AudioConfig,\r\n    PropertyCollection,\r\n    PropertyId,\r\n    RecognitionEventArgs,\r\n    SessionEventArgs,\r\n    SpeechRecognitionResult,\r\n} from \"./Exports.js\";\r\n\r\n/**\r\n * Defines the base class Recognizer which mainly contains common event handlers.\r\n * @class Recognizer\r\n */\r\nexport abstract class Recognizer {\r\n    private privDisposed: boolean;\r\n    protected audioConfig: AudioConfig;\r\n    protected privReco: ServiceRecognizerBase;\r\n    protected privProperties: PropertyCollection;\r\n    protected tokenCredential?: TokenCredential;\r\n    private privConnectionFactory: IConnectionFactory;\r\n\r\n    /**\r\n     * Creates and initializes an instance of a Recognizer\r\n     * @constructor\r\n     * @param {AudioConfig} audioInput - An optional audio input stream associated with the recognizer\r\n     * @param {PropertyCollection} properties - A set of properties to set on the recognizer\r\n     * @param {IConnectionFactory} connectionFactory - The factory class used to create a custom IConnection for the recognizer\r\n     */\r\n    protected constructor(audioConfig: AudioConfig, properties: PropertyCollection, connectionFactory: IConnectionFactory, tokenCredential?: TokenCredential) {\r\n        this.audioConfig = (audioConfig !== undefined) ? audioConfig : AudioConfig.fromDefaultMicrophoneInput();\r\n        this.privDisposed = false;\r\n        this.privProperties = properties.clone();\r\n        this.privConnectionFactory = connectionFactory;\r\n        this.tokenCredential = tokenCredential;\r\n        this.implCommonRecognizerSetup();\r\n    }\r\n\r\n    /**\r\n     * Defines event handler for session started events.\r\n     * @member Recognizer.prototype.sessionStarted\r\n     * @function\r\n     * @public\r\n     */\r\n    public sessionStarted: (sender: Recognizer, event: SessionEventArgs) => void;\r\n\r\n    /**\r\n     * Defines event handler for session stopped events.\r\n     * @member Recognizer.prototype.sessionStopped\r\n     * @function\r\n     * @public\r\n     */\r\n    public sessionStopped: (sender: Recognizer, event: SessionEventArgs) => void;\r\n\r\n    /**\r\n     * Defines event handler for speech started events.\r\n     * @member Recognizer.prototype.speechStartDetected\r\n     * @function\r\n     * @public\r\n     */\r\n    public speechStartDetected: (sender: Recognizer, event: RecognitionEventArgs) => void;\r\n\r\n    /**\r\n     * Defines event handler for speech stopped events.\r\n     * @member Recognizer.prototype.speechEndDetected\r\n     * @function\r\n     * @public\r\n     */\r\n    public speechEndDetected: (sender: Recognizer, event: RecognitionEventArgs) => void;\r\n\r\n    /**\r\n     * Dispose of associated resources.\r\n     * @member Recognizer.prototype.close\r\n     * @function\r\n     * @public\r\n     */\r\n    public close(cb?: () => void, errorCb?: (error: string) => void): void {\r\n        Contracts.throwIfDisposed(this.privDisposed);\r\n        marshalPromiseToCallbacks(this.dispose(true), cb, errorCb);\r\n    }\r\n\r\n    /**\r\n     * @Internal\r\n     * Internal data member to support fromRecognizer* pattern methods on other classes.\r\n     * Do not use externally, object returned will change without warning or notice.\r\n     */\r\n    public get internalData(): object {\r\n        return this.privReco;\r\n    }\r\n\r\n    /**\r\n     * This method performs cleanup of resources.\r\n     * The Boolean parameter disposing indicates whether the method is called\r\n     * from Dispose (if disposing is true) or from the finalizer (if disposing is false).\r\n     * Derived classes should override this method to dispose resource if needed.\r\n     * @member Recognizer.prototype.dispose\r\n     * @function\r\n     * @public\r\n     * @param {boolean} disposing - Flag to request disposal.\r\n     */\r\n    protected async dispose(disposing: boolean): Promise<void> {\r\n        if (this.privDisposed) {\r\n            return;\r\n        }\r\n\r\n        this.privDisposed = true;\r\n\r\n        if (disposing) {\r\n            if (this.privReco) {\r\n                await this.privReco.audioSource.turnOff();\r\n                await this.privReco.dispose();\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * This method returns the current state of the telemetry setting.\r\n     * @member Recognizer.prototype.telemetryEnabled\r\n     * @function\r\n     * @public\r\n     * @returns true if the telemetry is enabled, false otherwise.\r\n     */\r\n    public static get telemetryEnabled(): boolean {\r\n        return ServiceRecognizerBase.telemetryDataEnabled;\r\n    }\r\n\r\n    /**\r\n     * This method globally enables or disables telemetry.\r\n     * @member Recognizer.prototype.enableTelemetry\r\n     * @function\r\n     * @public\r\n     * @param enabled - Global setting for telemetry collection.\r\n     * If set to true, telemetry information like microphone errors,\r\n     * recognition errors are collected and sent to Microsoft.\r\n     * If set to false, no telemetry is sent to Microsoft.\r\n     */\r\n    public static enableTelemetry(enabled: boolean): void {\r\n        ServiceRecognizerBase.telemetryDataEnabled = enabled;\r\n    }\r\n\r\n    //\r\n    // ################################################################################################################\r\n    // IMPLEMENTATION.\r\n    // Move to independent class\r\n    // ################################################################################################################\r\n    //\r\n    protected abstract createRecognizerConfig(speechConfig: SpeechServiceConfig): RecognizerConfig;\r\n\r\n    // Creates the correct service recognizer for the type\r\n    protected abstract createServiceRecognizer(\r\n        authentication: IAuthentication,\r\n        connectionFactory: IConnectionFactory,\r\n        audioConfig: AudioConfig,\r\n        recognizerConfig: RecognizerConfig): ServiceRecognizerBase;\r\n\r\n    // Does the generic recognizer setup that is common across all recognizer types.\r\n    protected implCommonRecognizerSetup(): void {\r\n\r\n        let osPlatform = (typeof window !== \"undefined\") ? \"Browser\" : \"Node\";\r\n        let osName = \"unknown\";\r\n        let osVersion = \"unknown\";\r\n\r\n        if (typeof navigator !== \"undefined\") {\r\n            osPlatform = osPlatform + \"/\" + navigator.platform;\r\n            osName = navigator.userAgent;\r\n            osVersion = navigator.appVersion;\r\n        }\r\n\r\n        const recognizerConfig = this.createRecognizerConfig(\r\n            new SpeechServiceConfig(\r\n                new Context(new OS(osPlatform, osName, osVersion))));\r\n\r\n        this.privReco = this.createServiceRecognizer(\r\n            Recognizer.getAuth(this.privProperties, this.tokenCredential),\r\n            this.privConnectionFactory,\r\n            this.audioConfig,\r\n            recognizerConfig);\r\n    }\r\n\r\n    protected async recognizeOnceAsyncImpl(recognitionMode: RecognitionMode): Promise<SpeechRecognitionResult> {\r\n        Contracts.throwIfDisposed(this.privDisposed);\r\n        const ret: Deferred<SpeechRecognitionResult> = new Deferred<SpeechRecognitionResult>();\r\n\r\n        await this.implRecognizerStop();\r\n        await this.privReco.recognize(recognitionMode, ret.resolve, ret.reject);\r\n        const result: SpeechRecognitionResult = await ret.promise;\r\n        await this.implRecognizerStop();\r\n\r\n        return result;\r\n\r\n    }\r\n\r\n    protected async startContinuousRecognitionAsyncImpl(recognitionMode: RecognitionMode): Promise<void> {\r\n        Contracts.throwIfDisposed(this.privDisposed);\r\n\r\n        await this.implRecognizerStop();\r\n        await this.privReco.recognize(recognitionMode, undefined, undefined);\r\n    }\r\n\r\n    protected async stopContinuousRecognitionAsyncImpl(): Promise<void> {\r\n        Contracts.throwIfDisposed(this.privDisposed);\r\n        await this.implRecognizerStop();\r\n    }\r\n\r\n    protected async implRecognizerStop(): Promise<void> {\r\n        if (this.privReco) {\r\n            // Get timeout property - undefined/empty means no timeout (existing behavior)\r\n            const timeoutProperty = this.privProperties.getProperty(\r\n                PropertyId.Recognizer_StopTimeoutMs,\r\n                undefined\r\n            );\r\n\r\n            // Only apply timeout if explicitly set to a positive value\r\n            if (timeoutProperty !== undefined && timeoutProperty !== \"\") {\r\n                const timeoutMs = parseInt(timeoutProperty, 10);\r\n\r\n                if (timeoutMs > 0) {\r\n                    // User wants timeout protection\r\n                    try {\r\n                        await this.withTimeout(\r\n                            this.privReco.stopRecognizing(),\r\n                            timeoutMs,\r\n                            `Stop operation timed out after ${timeoutMs}ms waiting for service to complete turn`\r\n                        );\r\n                    } catch (error) {\r\n                        // On timeout, use existing disconnect() which cancels immediately\r\n                        await this.privReco.disconnect();\r\n                        throw error;\r\n                    }\r\n                    return;\r\n                }\r\n            }\r\n\r\n            // No timeout configured - use existing behavior (wait indefinitely)\r\n            await this.privReco.stopRecognizing();\r\n        }\r\n        return;\r\n    }\r\n\r\n    private withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string): Promise<T> {\r\n        return Promise.race([\r\n            promise,\r\n            new Promise<T>((_: (value: T) => void, reject: (reason: Error) => void): void => {\r\n                setTimeout((): void => {\r\n                    reject(new Error(errorMessage));\r\n                }, timeoutMs);\r\n            })\r\n        ]);\r\n    }\r\n\r\n    protected static getAuth(properties: PropertyCollection, tokenCredential?: TokenCredential): IAuthentication {\r\n        const subscriptionKey = properties.getProperty(PropertyId.SpeechServiceConnection_Key, undefined);\r\n        if (subscriptionKey && subscriptionKey !== \"\") {\r\n            return new CognitiveSubscriptionKeyAuthentication(subscriptionKey);\r\n        }\r\n\r\n        if (tokenCredential) {\r\n            return new CognitiveTokenAuthentication(\r\n                async (): Promise<string> => {\r\n                    try {\r\n                        const tokenResponse = await tokenCredential.getToken(\"https://cognitiveservices.azure.com/.default\");\r\n                        return tokenResponse?.token ?? \"\";\r\n                    } catch (err) {\r\n                        throw err;\r\n                    }\r\n                },\r\n                async (): Promise<string> => {\r\n                    try {\r\n                        const tokenResponse = await tokenCredential.getToken(\"https://cognitiveservices.azure.com/.default\");\r\n                        return tokenResponse?.token ?? \"\";\r\n                    } catch (err) {\r\n                        throw err;\r\n                    }\r\n                }\r\n            );\r\n        }\r\n\r\n        return new CognitiveTokenAuthentication(\r\n            (): Promise<string> => {\r\n                const authorizationToken = properties.getProperty(PropertyId.SpeechServiceAuthorization_Token, undefined);\r\n                return Promise.resolve(authorizationToken);\r\n            },\r\n            (): Promise<string> => {\r\n                const authorizationToken = properties.getProperty(PropertyId.SpeechServiceAuthorization_Token, undefined);\r\n                return Promise.resolve(authorizationToken);\r\n            }\r\n        );\r\n    }\r\n}\r\n"]}