From d132592ddb57a1f7c3d9ee35b94bf88679408048 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Fri, 12 Dec 2025 13:26:30 +0000 Subject: [PATCH 01/32] initial no-op s2s core implementation --- packages/api/src/hooks/useSpeechToSpeech.ts | 3 + packages/api/src/hooks/useVoiceActivities.ts | 11 + .../SpeechToSpeech/SpeechToSpeechComposer.tsx | 134 +++++++++ .../SpeechToSpeech/private/Context.ts | 14 + .../private/useAudioPlayer.spec.tsx | 279 ++++++++++++++++++ .../SpeechToSpeech/private/useAudioPlayer.ts | 69 +++++ .../SpeechToSpeech/private/useContext.ts | 15 + .../private/useRecorder.spec.tsx | 160 ++++++++++ .../SpeechToSpeech/private/useRecorder.ts | 128 ++++++++ .../SpeechToSpeech/types/SpeechState.ts | 1 + .../SpeechToSpeech/useSpeechToSpeech.ts | 6 + packages/core/src/index.ts | 2 + .../voiceActivity/isVoiceActivity.spec.ts | 88 ++++++ .../utils/voiceActivity/isVoiceActivity.ts | 14 + 14 files changed, 924 insertions(+) create mode 100644 packages/api/src/hooks/useSpeechToSpeech.ts create mode 100644 packages/api/src/hooks/useVoiceActivities.ts create mode 100644 packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx create mode 100644 packages/api/src/providers/SpeechToSpeech/private/Context.ts create mode 100644 packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx create mode 100644 packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts create mode 100644 packages/api/src/providers/SpeechToSpeech/private/useContext.ts create mode 100644 packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx create mode 100644 packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts create mode 100644 packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts create mode 100644 packages/api/src/providers/SpeechToSpeech/useSpeechToSpeech.ts create mode 100644 packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts create mode 100644 packages/core/src/utils/voiceActivity/isVoiceActivity.ts diff --git a/packages/api/src/hooks/useSpeechToSpeech.ts b/packages/api/src/hooks/useSpeechToSpeech.ts new file mode 100644 index 0000000000..4f529a2c08 --- /dev/null +++ b/packages/api/src/hooks/useSpeechToSpeech.ts @@ -0,0 +1,3 @@ +import useSpeechToSpeech from '../providers/SpeechToSpeech/useSpeechToSpeech'; + +export default useSpeechToSpeech; diff --git a/packages/api/src/hooks/useVoiceActivities.ts b/packages/api/src/hooks/useVoiceActivities.ts new file mode 100644 index 0000000000..d65e142b17 --- /dev/null +++ b/packages/api/src/hooks/useVoiceActivities.ts @@ -0,0 +1,11 @@ +import { isVoiceActivity, type WebChatActivity } from 'botframework-webchat-core'; +import { useSelector } from './internal/WebChatReduxContext'; + +const activitiesSelector = (state: { activities: WebChatActivity[] }) => state.activities; + +const of = (predicate: (activity: WebChatActivity) => boolean) => (state: { activities: WebChatActivity[] }) => + activitiesSelector(state).filter(predicate); + +export default function useVoiceActivities(): [WebChatActivity[]] { + return [useSelector(of(activity => isVoiceActivity(activity)))]; +} diff --git a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx new file mode 100644 index 0000000000..0ccf1a6f32 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx @@ -0,0 +1,134 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'; +import { isVoiceActivity, WebChatActivity } from 'botframework-webchat-core'; +import { useAudioPlayer } from './private/useAudioPlayer'; +import { useRecorder } from './private/useRecorder'; +import { useDebouncedNotifications, usePostActivity, useVoiceActivities } from '../../hooks'; +import SpeechToSpeechContext from './private/Context'; +import { SpeechState } from './types/SpeechState'; + +export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> = ({ children }) => { + const [voiceActivities] = useVoiceActivities(); + const postActivity = usePostActivity(); + const [{ connectivitystatus }] = useDebouncedNotifications(); + const { playAudio, stopAudio, isPlaying } = useAudioPlayer(); + + const lastProcessedIndexRef = useRef(0); + + // Remove when we have activity protocol changes, we would get this as part of signal activity. + const [speechState, setSpeechState] = useState('idle'); + + const isConnected = useMemo(() => connectivitystatus?.message === 'connected', [connectivitystatus]); + + const sendAudioChunk = useCallback( + (base64: string) => { + postActivity({ + type: 'event', + name: 'stream.chunk', + value: { voiceLiveEvent: { type: 'input_audio_buffer.append', audio: base64 } } + } as any); + }, + [postActivity] + ); + + const { recording, setRecording: baseSetRecording } = useRecorder(sendAudioChunk); + + const cancelActiveResponse = useCallback(() => { + if (isPlaying) { + postActivity({ + type: 'event', + value: { voiceLiveEvent: { type: 'response.cancel' } } + } as any); + } + }, [isPlaying, postActivity]); + + const handleVoiceActivity = useCallback( + (activity: WebChatActivity) => { + if (!isVoiceActivity(activity)) { + return; + } + + const { voiceLiveEvent } = activity.value; + + switch (voiceLiveEvent.type) { + case 'input_audio_buffer.speech_started': + stopAudio(); + setSpeechState('listening'); + break; + case 'input_audio_buffer.speech_stopped': + setSpeechState('processing'); + break; + case 'response.audio.delta': + if (voiceLiveEvent.delta && recording) { + playAudio(voiceLiveEvent.delta); + } + break; + case 'response.done': + if (!isPlaying) { + setSpeechState('listening'); + } + break; + default: + break; + } + }, + [isPlaying, playAudio, recording, stopAudio] + ); + + useEffect(() => { + const startIndex = lastProcessedIndexRef.current; + + if (!voiceActivities.length || startIndex >= voiceActivities.length) { + return; + } + + // If not recording, skip processing voice activities but update ref + // so next time we start recording, we only process new activities. + if (!recording) { + lastProcessedIndexRef.current = voiceActivities.length; + return; + } + + for (let i = startIndex; i < voiceActivities.length; i++) { + // eslint-disable-next-line security/detect-object-injection + handleVoiceActivity(voiceActivities[i]); + } + + if (isPlaying && speechState !== 'bot_speaking') { + setSpeechState('bot_speaking'); + } else if (!isPlaying && speechState === 'bot_speaking') { + setSpeechState('listening'); + } + + lastProcessedIndexRef.current = voiceActivities.length; + }, [voiceActivities, recording, postActivity, isPlaying, playAudio, speechState, stopAudio, handleVoiceActivity]); + + const setRecording = useCallback( + (shouldRecord: boolean) => { + if (!isConnected) { + return; + } + + if (!recording) { + setSpeechState('listening'); + } else { + stopAudio(); + cancelActiveResponse(); + setSpeechState('idle'); + } + + baseSetRecording(shouldRecord); + }, + [isConnected, recording, baseSetRecording, stopAudio, cancelActiveResponse] + ); + + const contextValue = useMemo( + () => ({ + recording, + setRecording, + speechState + }), + [recording, setRecording, speechState] + ); + + return {children}; +}; diff --git a/packages/api/src/providers/SpeechToSpeech/private/Context.ts b/packages/api/src/providers/SpeechToSpeech/private/Context.ts new file mode 100644 index 0000000000..ce85310246 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/private/Context.ts @@ -0,0 +1,14 @@ +import { createContext } from 'react'; +import { SpeechState } from '../types/SpeechState'; + +type SpeechToSpeechContextType = { + recording: boolean; + setRecording: (recording: boolean) => void; + speechState: SpeechState; +}; + +const SpeechToSpeechContext = createContext(undefined!); + +export default SpeechToSpeechContext; + +export type { SpeechToSpeechContextType }; diff --git a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx new file mode 100644 index 0000000000..8c1d42cb08 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx @@ -0,0 +1,279 @@ +/** @jest-environment @happy-dom/jest-environment */ +/// +/// + +import { render, type RenderResult } from '@testing-library/react'; +import React, { type ComponentType } from 'react'; +import { useAudioPlayer } from './useAudioPlayer'; + +// Mock AudioContext and related APIs +const mockAudioContext = { + sampleRate: 24000, + currentTime: 0, + destination: {}, + state: 'running', + resume: jest.fn().mockResolvedValue(undefined), + close: jest.fn().mockResolvedValue(undefined), + createBuffer: jest.fn(), + createBufferSource: jest.fn() +}; + +const mockAudioBuffer = { + duration: 0.1, // 100m + getChannelData: jest.fn().mockReturnValue(new Float32Array(2400)) +}; + +const mockBufferSource = { + buffer: null, + connect: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + disconnect: jest.fn(), + onended: null +}; + +// Mock global AudioContext +global.AudioContext = jest.fn(() => mockAudioContext) as any; +global.atob = jest.fn(str => str); // Simple mock for base64 decode + +type UseAudioPlayerReturn = ReturnType; + +describe('setup', () => { + let HookApp: ComponentType; + let hookData: UseAudioPlayerReturn | undefined; + let renderResult: RenderResult; + const originalAudioContext = global.AudioContext; + + beforeEach(() => { + jest.clearAllMocks(); + mockAudioContext.currentTime = 0; + mockAudioContext.createBuffer.mockReturnValue(mockAudioBuffer); + mockAudioContext.createBufferSource.mockReturnValue(mockBufferSource); + mockBufferSource.buffer = null; + mockBufferSource.onended = null; + + HookApp = () => { + hookData = useAudioPlayer(); + return null; + }; + }); + + afterEach(() => { + global.AudioContext = originalAudioContext; + }); + + describe('Initialization', () => { + test('should initialize with correct default values', () => { + render(); + + expect(hookData?.isPlaying).toBe(false); + expect(typeof hookData?.playAudio).toBe('function'); + expect(typeof hookData?.stopAudio).toBe('function'); + }); + + test('should create AudioContext on first playAudio call', () => { + render(); + + hookData?.playAudio('dGVzdA=='); // base64 for 'test' + + expect(AudioContext).toHaveBeenCalledWith({ sampleRate: 24000 }); + }); + + test('should reuse existing AudioContext on subsequent calls', () => { + render(); + + hookData?.playAudio('dGVzdA=='); + hookData?.playAudio('dGVzdDI='); + + expect(AudioContext).toHaveBeenCalledTimes(1); + }); + }); + + describe('Audio playback', () => { + beforeEach(() => { + renderResult = render(); + }); + + test('should process base64 audio data correctly', () => { + hookData?.playAudio('dGVzdA=='); + + expect(global.atob).toHaveBeenCalledWith('dGVzdA=='); + expect(mockAudioContext.createBuffer).toHaveBeenCalledWith(1, expect.any(Number), 24000); + expect(mockAudioContext.createBufferSource).toHaveBeenCalled(); + }); + + test('should set up audio buffer source correctly', () => { + hookData?.playAudio('dGVzdA=='); + + expect(mockBufferSource.connect).toHaveBeenCalledWith(mockAudioContext.destination); + expect(mockBufferSource.start).toHaveBeenCalled(); + expect(mockBufferSource.buffer).toBe(mockAudioBuffer); + }); + + test('should resume AudioContext if needed', () => { + hookData?.playAudio('dGVzdA=='); + + expect(mockAudioContext.resume).toHaveBeenCalled(); + }); + + test('should queue multiple audio chunks correctly', () => { + mockAudioBuffer.duration = 0.1; // 100ms + + hookData?.playAudio('dGVzdA=='); + hookData?.playAudio('dGVzdDI='); + + expect(mockBufferSource.start).toHaveBeenCalledTimes(2); + // First chunk starts at currentTime (0), second at 0.1 + expect(mockBufferSource.start).toHaveBeenNthCalledWith(1, 0); + expect(mockBufferSource.start).toHaveBeenNthCalledWith(2, 0.1); + }); + }); + + describe('isPlaying state', () => { + beforeEach(() => { + renderResult = render(); + }); + + test('should return true when audio is queued for playback', () => { + mockAudioContext.currentTime = 0; + mockAudioBuffer.duration = 0.1; + + hookData?.playAudio('dGVzdA=='); + renderResult.rerender(); + + expect(hookData?.isPlaying).toBe(true); + }); + + test('should return false when no audio is queued', () => { + expect(hookData?.isPlaying).toBe(false); + }); + + test('should handle multiple chunks and playing state', () => { + mockAudioContext.currentTime = 0.05; // In the middle of first chunk + mockAudioBuffer.duration = 0.1; + + hookData?.playAudio('dGVzdA=='); // 0 - 0.1 + hookData?.playAudio('dGVzdDI='); // 0.1 - 0.2 + renderResult.rerender(); + + expect(hookData?.isPlaying).toBe(true); + }); + }); + + describe('Audio cleanup', () => { + beforeEach(() => { + renderResult = render(); + }); + + test('should clean up buffer source on ended', () => { + hookData?.playAudio('dGVzdA=='); + + // Simulate audio ended + if (mockBufferSource.onended) { + mockBufferSource.onended(); + } + + expect(mockBufferSource.disconnect).toHaveBeenCalled(); + expect(mockBufferSource.buffer).toBeNull(); + }); + + test('should stop all audio and close context', () => { + hookData?.playAudio('dGVzdA=='); + + hookData?.stopAudio(); + renderResult.rerender(); + + expect(mockAudioContext.close).toHaveBeenCalled(); + expect(hookData?.isPlaying).toBe(false); + }); + }); + + describe('Error handling', () => { + beforeEach(() => { + renderResult = render(); + }); + + test('should handle invalid base64 data gracefully', () => { + expect(() => { + hookData?.playAudio('invalid-base64!@#'); + }).not.toThrow(); + }); + + test('should handle AudioContext creation failure', () => { + global.AudioContext = jest.fn(() => { + throw new Error('AudioContext not supported'); + }) as any; + + expect(() => { + hookData?.playAudio('dGVzdA=='); + }).toThrow('AudioContext not supported'); + }); + + test('should handle missing audio context in isPlaying', () => { + // Before any audio is played, audioCtxRef should be null + expect(hookData?.isPlaying).toBe(false); + }); + }); + + describe('Real-world scenarios', () => { + beforeEach(() => { + renderResult = render(); + }); + + test('should handle streaming audio chunks', () => { + mockAudioBuffer.duration = 0.05; // 50ms chunks + + // Simulate streaming 5 chunks + for (let i = 0; i < 5; i++) { + hookData?.playAudio(`chunk${i}`); + } + + expect(mockBufferSource.start).toHaveBeenCalledTimes(5); + renderResult.rerender(); + expect(hookData?.isPlaying).toBe(true); + }); + + test('should handle playback interruption', () => { + hookData?.playAudio('dGVzdA=='); + renderResult.rerender(); + expect(hookData?.isPlaying).toBe(true); + + hookData?.stopAudio(); + renderResult.rerender(); + expect(hookData?.isPlaying).toBe(false); + expect(mockAudioContext.close).toHaveBeenCalled(); + }); + + test('should handle resume after stop', () => { + // Play, stop, then play again + hookData?.playAudio('dGVzdA=='); + hookData?.stopAudio(); + hookData?.playAudio('dGVzdDI='); + + expect(AudioContext).toHaveBeenCalledTimes(2); // New context after stop + }); + }); + + describe('Performance considerations', () => { + beforeEach(() => { + renderResult = render(); + }); + + test('should handle large audio data', () => { + const largeBase64 = 'A'.repeat(10000); + + expect(() => { + hookData?.playAudio(largeBase64); + }).not.toThrow(); + }); + + test('should handle rapid successive calls', () => { + for (let i = 0; i < 100; i++) { + // Ensure the mock "base64" data has an even length as Int16Array (which represents 16-bit audio samples) requires the underlying data to be in multiples of 2 bytes + hookData?.playAudio(`chunk${i}`.padEnd(8, ' ')); + } + + expect(mockBufferSource.start).toHaveBeenCalledTimes(100); + }); + }); +}); diff --git a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts new file mode 100644 index 0000000000..6216932a8c --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts @@ -0,0 +1,69 @@ +import { useRef, useCallback } from 'react'; + +const SAMPLE_RATE = 24000; +const INT16_SCALE = 32768; + +export function useAudioPlayer() { + const audioCtxRef = useRef(null); + const nextPlayTimeRef = useRef(0); + + const initAudio = useCallback(() => { + if (!audioCtxRef.current) { + audioCtxRef.current = new AudioContext({ sampleRate: SAMPLE_RATE }); + } + return audioCtxRef.current; + }, []); + + const playAudio = useCallback( + (base64: string) => { + const audioCtx = initAudio(); + audioCtx.resume?.(); + + try { + const bytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0)); + const int16 = new Int16Array(bytes.buffer); + const float32 = new Float32Array(int16.length); + + for (let i = 0; i < int16.length; i++) { + // eslint-disable-next-line security/detect-object-injection + float32[i] = int16[i] / INT16_SCALE; + } + + const buffer = audioCtx.createBuffer(1, float32.length, SAMPLE_RATE); + buffer.getChannelData(0).set(float32); + + const src = audioCtx.createBufferSource(); + src.buffer = buffer; + src.connect(audioCtx.destination); + + // Clear buffer when finished + src.onended = () => { + src.disconnect(); + src.buffer = null; + }; + + nextPlayTimeRef.current = Math.max(nextPlayTimeRef.current, audioCtx.currentTime); + src.start(nextPlayTimeRef.current); + nextPlayTimeRef.current += buffer.duration; + } catch (error) { + console.warn('botframework-webchat: Error during audio playback in useAudioPlayer:', error); + } + }, + [initAudio] + ); + + const stopAudio = useCallback(() => { + nextPlayTimeRef.current = 0; + + if (audioCtxRef.current) { + audioCtxRef.current.close(); + audioCtxRef.current = null; + } + }, []); + + return { + playAudio, + stopAudio, + isPlaying: audioCtxRef.current ? audioCtxRef.current.currentTime < nextPlayTimeRef.current : false + }; +} diff --git a/packages/api/src/providers/SpeechToSpeech/private/useContext.ts b/packages/api/src/providers/SpeechToSpeech/private/useContext.ts new file mode 100644 index 0000000000..50926b0a12 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/private/useContext.ts @@ -0,0 +1,15 @@ +import { useContext } from 'react'; + +import SpeechToSpeechContext from './Context'; + +import type { SpeechToSpeechContextType } from './Context'; + +export default function useSpeechToSpeechContext(thrownOnUndefined = true): SpeechToSpeechContextType { + const contextValue = useContext(SpeechToSpeechContext); + + if (thrownOnUndefined && !contextValue) { + throw new Error('botframework-webchat internal: This hook can only be used under .'); + } + + return contextValue; +} diff --git a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx new file mode 100644 index 0000000000..01368ceda2 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx @@ -0,0 +1,160 @@ +/** @jest-environment @happy-dom/jest-environment */ +/// + +import { act, render, waitFor, type RenderResult } from '@testing-library/react'; +import React, { type ComponentType } from 'react'; +import { useRecorder } from './useRecorder'; + +// --- Mocks --- + +const mockTrack = { + stop: jest.fn() +}; + +const mockMediaStream = { + getTracks: jest.fn(() => [mockTrack]) +}; + +const mockMediaDevices = { + getUserMedia: jest.fn().mockResolvedValue(mockMediaStream) +}; + +const mockWorkletPort = { + postMessage: jest.fn(), + onmessage: null as ((event: { data: any }) => void) | null +}; + +const mockWorkletNode = { + connect: jest.fn(), + disconnect: jest.fn(), + port: mockWorkletPort +}; + +const mockAudioContext = { + state: 'running', + resume: jest.fn().mockResolvedValue(undefined), + createMediaStreamSource: jest.fn(() => ({ + connect: jest.fn() + })), + destination: {}, + audioWorklet: { + addModule: jest.fn().mockResolvedValue(undefined) + } +}; + +// --- Global Mocks Setup --- + +Object.defineProperty(global.navigator, 'mediaDevices', { + value: mockMediaDevices, + writable: true +}); + +global.AudioContext = jest.fn(() => mockAudioContext as any); +global.AudioWorkletNode = jest.fn(() => mockWorkletNode as any); +global.Blob = jest.fn(parts => ({ parts, type: parts[1]?.type })) as any; +global.URL.createObjectURL = jest.fn(() => 'blob:http://localhost/mock-url'); +global.URL.revokeObjectURL = jest.fn(); +global.btoa = jest.fn(str => `btoa(${str})`); + +// --- Tests --- + +describe('useRecorder', () => { + let onAudioChunk: jest.Mock; + let HookApp: ComponentType<{ onAudioChunk: (base64: string) => void }>; + let hookData: ReturnType | undefined; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let renderResult: RenderResult; + + beforeEach(() => { + // Clear all mocks before each test + jest.clearAllMocks(); + onAudioChunk = jest.fn(); + hookData = undefined; + mockWorkletPort.onmessage = null; + (mockAudioContext.state as any) = 'running'; + + HookApp = ({ onAudioChunk }) => { + hookData = useRecorder(onAudioChunk); + return null; + }; + }); + + test('should be initially not recording', () => { + render(); + expect(hookData?.recording).toBe(false); + }); + + test('should start recording when setRecording(true) is called', async () => { + renderResult = render(); + + act(() => { + hookData?.setRecording(true); + }); + + await waitFor(() => expect(hookData?.recording).toBe(true)); + + expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledTimes(1); + expect(global.AudioContext).toHaveBeenCalledTimes(1); + expect(mockAudioContext.audioWorklet.addModule).toHaveBeenCalledTimes(1); + expect(global.AudioWorkletNode).toHaveBeenCalledWith(expect.anything(), 'audio-recorder'); + expect(mockWorkletNode.connect).toHaveBeenCalledTimes(1); + expect(mockWorkletPort.postMessage).toHaveBeenCalledWith({ command: 'START' }); + }); + + test('should stop recording when setRecording(false) is called', async () => { + renderResult = render(); + + // Start recording + act(() => { + hookData?.setRecording(true); + }); + + await waitFor(() => expect(hookData?.recording).toBe(true)); + + // Stop recording + act(() => { + hookData?.setRecording(false); + }); + + await waitFor(() => expect(hookData?.recording).toBe(false)); + + expect(mockWorkletPort.postMessage).toHaveBeenCalledWith({ command: 'STOP' }); + expect(mockWorkletNode.disconnect).toHaveBeenCalledTimes(1); + expect(mockTrack.stop).toHaveBeenCalledTimes(1); + }); + + test('should process audio chunks sent from the worklet', async () => { + render(); + + act(() => { + hookData?.setRecording(true); + }); + + await waitFor(() => expect(mockWorkletPort.onmessage).not.toBeNull()); + + // Simulate a message from the audio worklet + const mockAudioData = new Float32Array([0.1, 0.2, -0.1]); + act(() => { + mockWorkletPort.onmessage!({ + data: { + eventType: 'audio', + audioData: mockAudioData + } + }); + }); + + await waitFor(() => expect(onAudioChunk).toHaveBeenCalledTimes(1)); + expect(global.btoa).toHaveBeenCalled(); + }); + + test('should handle suspended audio context by resuming it', async () => { + (mockAudioContext.state as any) = 'suspended'; + render(); + + act(() => { + hookData?.setRecording(true); + }); + + await waitFor(() => expect(mockAudioContext.resume).toHaveBeenCalledTimes(1)); + }); +}); diff --git a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts new file mode 100644 index 0000000000..b9930cada1 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts @@ -0,0 +1,128 @@ +import { useRef, useState, useCallback } from 'react'; + +const audioProcessorCode = ` +class AudioRecorderProcessor extends AudioWorkletProcessor { + constructor() { + super() + this.recording = false + this.buffer = [] + this.port.onmessage = e => { + if (e.data.command === 'START') this.recording = true + else if (e.data.command === 'STOP') { + this.recording = false + if (this.buffer.length) this.sendBuffer() + } + } + } + sendBuffer() { + if (this.buffer.length) { + this.port.postMessage({ + eventType: 'audio', + audioData: new Float32Array(this.buffer) + }) + this.buffer = [] + } + } + process(inputs) { + if (inputs[0]?.length && this.recording) { + this.buffer.push(...inputs[0][0]) + if (this.buffer.length >= 2400) this.sendBuffer() + } + return true + } +} +registerProcessor('audio-recorder', AudioRecorderProcessor) +`; + +const INT16_MIN = -32768; +const INT16_MAX = 32767; +const INT16_SCALE = 32767; + +export function useRecorder(onAudioChunk: (base64: string) => void) { + const [recording, setRecordingInternal] = useState(false); + const audioCtxRef = useRef(null); + const workletRef = useRef(null); + const streamRef = useRef(null); + + const initAudio = useCallback(async () => { + if (audioCtxRef.current) { + return; + } + const audioCtx = new AudioContext({ sampleRate: 24000 }); + const blob = new Blob([audioProcessorCode], { + type: 'application/javascript' + }); + // eslint-disable-next-line no-restricted-properties + const url = URL.createObjectURL(blob); + await audioCtx.audioWorklet.addModule(url); + URL.revokeObjectURL(url); + // eslint-disable-next-line require-atomic-updates + audioCtxRef.current = audioCtx; + }, []); + + const startRecording = useCallback(async () => { + await initAudio(); + const audioCtx = audioCtxRef.current!; + if (audioCtx.state === 'suspended') { + await audioCtx.resume(); + } + const stream = await navigator.mediaDevices.getUserMedia({ + audio: { + channelCount: 1, + sampleRate: 24000, + echoCancellation: true + } + }); + streamRef.current = stream; + const source = audioCtx.createMediaStreamSource(stream); + const worklet = new AudioWorkletNode(audioCtx, 'audio-recorder'); + + worklet.port.onmessage = e => { + if (e.data.eventType === 'audio') { + const float32 = e.data.audioData; + const int16 = new Int16Array(float32.length); + for (let i = 0; i < float32.length; i++) { + // eslint-disable-next-line security/detect-object-injection + int16[i] = Math.max(INT16_MIN, Math.min(INT16_MAX, float32[i] * INT16_SCALE)); + } + const base64 = btoa(String.fromCharCode(...new Uint8Array(int16.buffer))); + onAudioChunk(base64); + } + }; + + source.connect(worklet); + worklet.connect(audioCtx.destination); + worklet.port.postMessage({ command: 'START' }); + workletRef.current = worklet; + setRecordingInternal(true); + }, [initAudio, onAudioChunk]); + + const stopRecording = useCallback(() => { + if (workletRef.current) { + workletRef.current.port.postMessage({ command: 'STOP' }); + workletRef.current.disconnect(); + workletRef.current = null; + } + if (streamRef.current) { + streamRef.current.getTracks().forEach(track => track.stop()); + streamRef.current = null; + } + setRecordingInternal(false); + }, []); + + const setRecording = useCallback( + async (shouldRecord: boolean) => { + if (!shouldRecord && recording) { + stopRecording(); + } else if (shouldRecord && !recording) { + await startRecording(); + } + }, + [recording, startRecording, stopRecording] + ); + + return { + recording, + setRecording + }; +} diff --git a/packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts b/packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts new file mode 100644 index 0000000000..62d5cc8c13 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts @@ -0,0 +1 @@ +export type SpeechState = 'idle' | 'listening' | 'processing' | 'bot_speaking'; diff --git a/packages/api/src/providers/SpeechToSpeech/useSpeechToSpeech.ts b/packages/api/src/providers/SpeechToSpeech/useSpeechToSpeech.ts new file mode 100644 index 0000000000..d7ac3fac44 --- /dev/null +++ b/packages/api/src/providers/SpeechToSpeech/useSpeechToSpeech.ts @@ -0,0 +1,6 @@ +import { SpeechToSpeechContextType } from './private/Context'; +import useSpeechToSpeechContext from './private/useContext'; + +export default function useSpeechToSpeech(): readonly [SpeechToSpeechContextType] { + return [useSpeechToSpeechContext()]; +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index e635e6a060..c0580223d8 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -81,6 +81,7 @@ import type { DefinedTerm as OrgSchemaDefinedTerm } from './types/external/OrgSc import type { Project as OrgSchemaProject } from './types/external/OrgSchema/Project'; import type { Thing as OrgSchemaThing } from './types/external/OrgSchema/Thing'; import type { UserReview as OrgSchemaUserReview } from './types/external/OrgSchema/UserReview'; +import isVoiceActivity from './utils/voiceActivity/isVoiceActivity'; const Constants = { ActivityClientState, DictateState }; @@ -96,6 +97,7 @@ export { getActivityLivestreamingMetadata, getOrgSchemaMessage, isForbiddenPropertyName, + isVoiceActivity, markActivity, onErrorResumeNext, parseAction, diff --git a/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts b/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts new file mode 100644 index 0000000000..c8d744595e --- /dev/null +++ b/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts @@ -0,0 +1,88 @@ +import isVoiceActivity from './isVoiceActivity'; +import { WebChatActivity } from '../../types/WebChatActivity'; + +// Mock activity factory for testing +const createMockActivity = (type: string = 'event', value?: any): WebChatActivity => ({ + type: type as any, + id: 'test-activity-id', + from: { id: 'test-user' }, + channelData: { + 'webchat:sequence-id': 1 + }, + ...(value && { value }) +}); + +const createMockVoiceActivity = (voiceEventType: string, additionalProps?: any): WebChatActivity => + createMockActivity('event', { + voiceLiveEvent: { + type: voiceEventType, + ...additionalProps + } + }); + +describe('isVoiceActivity', () => { + describe('Valid voice activities', () => { + test('should return true for event activity with voiceLiveEvent', () => { + const activity = createMockVoiceActivity('response.audio.delta', { delta: 'audiodata' }); + + const result = isVoiceActivity(activity); + + expect(result).toBe(true); + }); + + test('should return true for voice activity with minimal voiceLiveEvent', () => { + const activity = createMockActivity('event', { voiceLiveEvent: {} }); + + const result = isVoiceActivity(activity); + + expect(result).toBe(true); + }); + }); + + describe('Invalid activities', () => { + const testCases = [ + // Invalid by activity type + { + name: 'message activity with voiceLiveEvent', + activity: () => createMockActivity('message', { voiceLiveEvent: { type: 'response.audio.delta' } }) + }, + { + name: 'typing activity', + activity: () => createMockActivity('typing') + }, + { + name: 'event activity with value', + activity: () => ({ ...createMockActivity('event'), value: 'not an object' }) + } + ]; + + test.each(testCases)('should return false for $name', ({ activity }) => { + const result = isVoiceActivity(activity()); + + expect(result).toBe(false); + }); + }); + + describe('Real-world voice event types', () => { + const voiceEventTypes = [ + 'input_audio_buffer.append', + 'input_audio_buffer.speech_started', + 'input_audio_buffer.speech_stopped', + 'conversation.item.input_audio_transcription.completed', + 'response.audio.delta', + 'response.audio_transcript.delta', + 'response.audio_transcript.done', + 'response.done', + 'session.update', + 'response.cancel' + ]; + + test.each(voiceEventTypes)('should return true for voice event type: %s', eventType => { + const activity = createMockVoiceActivity(eventType); + + const result = isVoiceActivity(activity); + + expect(result).toBe(true); + }); + }); +}); diff --git a/packages/core/src/utils/voiceActivity/isVoiceActivity.ts b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts new file mode 100644 index 0000000000..e16154e590 --- /dev/null +++ b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts @@ -0,0 +1,14 @@ +import { WebChatActivity } from '../../types/WebChatActivity'; + +// This is interim type guard until activity protocol is ratified. +const isVoiceActivity = ( + activity: WebChatActivity +): activity is WebChatActivity & { + value: { voiceLiveEvent: any }; +} => + activity.type === 'event' && + activity.value && + typeof activity.value === 'object' && + 'voiceLiveEvent' in activity.value; + +export default isVoiceActivity; From a98245729479f03422a3a2c04ff33222d3368b56 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Fri, 12 Dec 2025 13:41:48 +0000 Subject: [PATCH 02/32] minor --- packages/core/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index c0580223d8..a81d494a07 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -42,6 +42,7 @@ import getOrgSchemaMessage from './utils/getOrgSchemaMessage'; import isForbiddenPropertyName from './utils/isForbiddenPropertyName'; import onErrorResumeNext from './utils/onErrorResumeNext'; import singleToArray from './utils/singleToArray'; +import isVoiceActivity from './utils/voiceActivity/isVoiceActivity'; export { CLEAR_SUGGESTED_ACTIONS, @@ -81,7 +82,6 @@ import type { DefinedTerm as OrgSchemaDefinedTerm } from './types/external/OrgSc import type { Project as OrgSchemaProject } from './types/external/OrgSchema/Project'; import type { Thing as OrgSchemaThing } from './types/external/OrgSchema/Thing'; import type { UserReview as OrgSchemaUserReview } from './types/external/OrgSchema/UserReview'; -import isVoiceActivity from './utils/voiceActivity/isVoiceActivity'; const Constants = { ActivityClientState, DictateState }; From 9ddc63c8878a8d8eefda425688ec69d5fae74492 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Wed, 7 Jan 2026 17:10:14 +0000 Subject: [PATCH 03/32] refactor to align close to activity structure --- packages/api/src/hooks/index.ts | 4 +- packages/api/src/hooks/useVoiceActivities.ts | 9 +- .../SpeechToSpeech/SpeechToSpeechComposer.tsx | 100 +++++------ .../SpeechToSpeech/private/useAudioPlayer.ts | 12 +- .../private/useRecorder.spec.tsx | 6 +- .../SpeechToSpeech/private/useRecorder.ts | 83 +++++---- .../activities/combineActivitiesReducer.ts | 15 +- .../createGroupedActivitiesReducer.ts | 24 ++- .../src/reducers/activities/sort/types.ts | 1 + .../src/reducers/activities/sort/upsert.ts | 16 +- .../voiceActivity/isVoiceActivity.spec.ts | 84 +++++---- .../utils/voiceActivity/isVoiceActivity.ts | 11 +- .../isVoiceTranscriptActivity.spec.ts | 164 ++++++++++++++++++ .../isVoiceTranscriptActivity.ts | 18 ++ 14 files changed, 404 insertions(+), 143 deletions(-) create mode 100644 packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.spec.ts create mode 100644 packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts diff --git a/packages/api/src/hooks/index.ts b/packages/api/src/hooks/index.ts index f5a1a959d7..b1d027ee3a 100644 --- a/packages/api/src/hooks/index.ts +++ b/packages/api/src/hooks/index.ts @@ -71,6 +71,7 @@ import useUIState from './useUIState'; import useUserID from './useUserID'; import useUsername from './useUsername'; import useVoiceSelector from './useVoiceSelector'; +import useVoiceActivities from './useVoiceActivities'; export { useBuildRenderActivityCallback } from '@msinternal/botframework-webchat-api-middleware'; export { useSuggestedActionsHooks } from '@msinternal/botframework-webchat-redux-store'; @@ -148,5 +149,6 @@ export { useUIState, useUserID, useUsername, - useVoiceSelector + useVoiceSelector, + useVoiceActivities }; diff --git a/packages/api/src/hooks/useVoiceActivities.ts b/packages/api/src/hooks/useVoiceActivities.ts index d65e142b17..0abff2229f 100644 --- a/packages/api/src/hooks/useVoiceActivities.ts +++ b/packages/api/src/hooks/useVoiceActivities.ts @@ -1,11 +1,6 @@ -import { isVoiceActivity, type WebChatActivity } from 'botframework-webchat-core'; +import { type WebChatActivity } from 'botframework-webchat-core'; import { useSelector } from './internal/WebChatReduxContext'; -const activitiesSelector = (state: { activities: WebChatActivity[] }) => state.activities; - -const of = (predicate: (activity: WebChatActivity) => boolean) => (state: { activities: WebChatActivity[] }) => - activitiesSelector(state).filter(predicate); - export default function useVoiceActivities(): [WebChatActivity[]] { - return [useSelector(of(activity => isVoiceActivity(activity)))]; + return [useSelector(({ voiceActivities }) => voiceActivities)]; } diff --git a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx index 0ccf1a6f32..b1f978e42c 100644 --- a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx +++ b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx @@ -10,36 +10,28 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> const [voiceActivities] = useVoiceActivities(); const postActivity = usePostActivity(); const [{ connectivitystatus }] = useDebouncedNotifications(); - const { playAudio, stopAudio, isPlaying } = useAudioPlayer(); - const lastProcessedIndexRef = useRef(0); - - // Remove when we have activity protocol changes, we would get this as part of signal activity. const [speechState, setSpeechState] = useState('idle'); + // config received from server on session start, for now ccv2 and mmrt runs on different sample rate and chunk interval. + // we will read those config, free form object as unsure of what all session config would be needed in future. + const [serverConfig, setServerConfig] = useState | null>(null); + const { playAudio, stopAudio, isPlaying } = useAudioPlayer(serverConfig); + const isConnected = useMemo(() => connectivitystatus?.message === 'connected', [connectivitystatus]); const sendAudioChunk = useCallback( - (base64: string) => { + (base64: string, timestamp: string) => { postActivity({ type: 'event', name: 'stream.chunk', - value: { voiceLiveEvent: { type: 'input_audio_buffer.append', audio: base64 } } + value: { voice: { contentUrl: base64, timestamp } } } as any); }, [postActivity] ); - const { recording, setRecording: baseSetRecording } = useRecorder(sendAudioChunk); - - const cancelActiveResponse = useCallback(() => { - if (isPlaying) { - postActivity({ - type: 'event', - value: { voiceLiveEvent: { type: 'response.cancel' } } - } as any); - } - }, [isPlaying, postActivity]); + const { recording, setRecording: baseSetRecording } = useRecorder(sendAudioChunk, serverConfig); const handleVoiceActivity = useCallback( (activity: WebChatActivity) => { @@ -47,50 +39,51 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> return; } - const { voiceLiveEvent } = activity.value; - - switch (voiceLiveEvent.type) { - case 'input_audio_buffer.speech_started': - stopAudio(); - setSpeechState('listening'); - break; - case 'input_audio_buffer.speech_stopped': - setSpeechState('processing'); - break; - case 'response.audio.delta': - if (voiceLiveEvent.delta && recording) { - playAudio(voiceLiveEvent.delta); - } - break; - case 'response.done': - if (!isPlaying) { + const { name, value } = activity; + const { voice } = value; + + // TODO - this will be commandResult activity and not event, need to think on handling of command and commandResult activities. + if (name === 'session.init' && value.session?.config) { + setServerConfig(value.session.config as Record); + } else if (name === 'session.update') { + switch (voice.bot_state) { + case 'voice.request.detected': + stopAudio(); setSpeechState('listening'); - } - break; - default: - break; + break; + case 'voice.request.processing': + setSpeechState('processing'); + break; + default: + break; + } + } else if (name === 'stream.chunk' && voice.contentUrl) { + playAudio(voice.contentUrl); } }, - [isPlaying, playAudio, recording, stopAudio] + [playAudio, stopAudio] ); - useEffect(() => { const startIndex = lastProcessedIndexRef.current; - if (!voiceActivities.length || startIndex >= voiceActivities.length) { return; } - // If not recording, skip processing voice activities but update ref - // so next time we start recording, we only process new activities. - if (!recording) { - lastProcessedIndexRef.current = voiceActivities.length; - return; - } - for (let i = startIndex; i < voiceActivities.length; i++) { // eslint-disable-next-line security/detect-object-injection - handleVoiceActivity(voiceActivities[i]); + const activity = voiceActivities[i]; + + // Skip processing the activity if it's from the user as we want to process only incoming voice activities. + // we may receive (optional) config from server as soon as socket is established + // at that time recording would be off but we still want to process to read config and act on it. + if ( + activity.from?.role === 'user' || + (!recording && isVoiceActivity(activity) && activity.name !== 'session.init') + ) { + continue; + } + + handleVoiceActivity(activity); } if (isPlaying && speechState !== 'bot_speaking') { @@ -100,25 +93,24 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> } lastProcessedIndexRef.current = voiceActivities.length; - }, [voiceActivities, recording, postActivity, isPlaying, playAudio, speechState, stopAudio, handleVoiceActivity]); + }, [voiceActivities, recording, isPlaying, speechState, handleVoiceActivity]); const setRecording = useCallback( - (shouldRecord: boolean) => { + async (shouldRecord: boolean) => { if (!isConnected) { return; } - if (!recording) { + if (shouldRecord) { setSpeechState('listening'); } else { stopAudio(); - cancelActiveResponse(); setSpeechState('idle'); } - baseSetRecording(shouldRecord); + await baseSetRecording(shouldRecord); }, - [isConnected, recording, baseSetRecording, stopAudio, cancelActiveResponse] + [isConnected, baseSetRecording, stopAudio] ); const contextValue = useMemo( diff --git a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts index 6216932a8c..f9b8405387 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts +++ b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts @@ -1,18 +1,20 @@ import { useRef, useCallback } from 'react'; -const SAMPLE_RATE = 24000; +const DEFAULT_SAMPLE_RATE = 24000; const INT16_SCALE = 32768; -export function useAudioPlayer() { +export function useAudioPlayer(config?: Record | null) { const audioCtxRef = useRef(null); const nextPlayTimeRef = useRef(0); + const { sampleRate = DEFAULT_SAMPLE_RATE } = config || {}; + const initAudio = useCallback(() => { if (!audioCtxRef.current) { - audioCtxRef.current = new AudioContext({ sampleRate: SAMPLE_RATE }); + audioCtxRef.current = new AudioContext({ sampleRate: sampleRate as number }); } return audioCtxRef.current; - }, []); + }, [sampleRate]); const playAudio = useCallback( (base64: string) => { @@ -29,7 +31,7 @@ export function useAudioPlayer() { float32[i] = int16[i] / INT16_SCALE; } - const buffer = audioCtx.createBuffer(1, float32.length, SAMPLE_RATE); + const buffer = audioCtx.createBuffer(1, float32.length, audioCtx.sampleRate); buffer.getChannelData(0).set(float32); const src = audioCtx.createBufferSource(); diff --git a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx index 01368ceda2..f2b01ca6b5 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx +++ b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx @@ -7,6 +7,8 @@ import { useRecorder } from './useRecorder'; // --- Mocks --- +jest.mock('../../Ponyfill/usePonyfill', () => ({ __esModule: true, default: jest.fn(() => [{ Date: global.Date }]) })); + const mockTrack = { stop: jest.fn() }; @@ -96,7 +98,9 @@ describe('useRecorder', () => { expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledTimes(1); expect(global.AudioContext).toHaveBeenCalledTimes(1); expect(mockAudioContext.audioWorklet.addModule).toHaveBeenCalledTimes(1); - expect(global.AudioWorkletNode).toHaveBeenCalledWith(expect.anything(), 'audio-recorder'); + expect(global.AudioWorkletNode).toHaveBeenCalledWith(expect.anything(), 'audio-recorder', { + processorOptions: { bufferSize: 2400 } + }); expect(mockWorkletNode.connect).toHaveBeenCalledTimes(1); expect(mockWorkletPort.postMessage).toHaveBeenCalledWith({ command: 'START' }); }); diff --git a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts index b9930cada1..7ba19ba244 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts +++ b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts @@ -1,54 +1,64 @@ import { useRef, useState, useCallback } from 'react'; +import usePonyfill from '../../Ponyfill/usePonyfill'; const audioProcessorCode = ` -class AudioRecorderProcessor extends AudioWorkletProcessor { - constructor() { - super() - this.recording = false - this.buffer = [] - this.port.onmessage = e => { - if (e.data.command === 'START') this.recording = true - else if (e.data.command === 'STOP') { - this.recording = false - if (this.buffer.length) this.sendBuffer() + class AudioRecorderProcessor extends AudioWorkletProcessor { + constructor(options) { + super() + this.recording = false + this.buffer = [] + this.bufferSize = options.processorOptions.bufferSize + this.port.onmessage = e => { + if (e.data.command === 'START') this.recording = true + else if (e.data.command === 'STOP') { + this.recording = false + this.buffer = [] + } } } - } - sendBuffer() { - if (this.buffer.length) { - this.port.postMessage({ - eventType: 'audio', - audioData: new Float32Array(this.buffer) - }) - this.buffer = [] + sendBuffer() { + while (this.buffer.length >= this.bufferSize) { + const chunk = this.buffer.splice(0, this.bufferSize) + this.port.postMessage({ + eventType: 'audio', + audioData: new Float32Array(chunk) + }) + } } - } - process(inputs) { - if (inputs[0]?.length && this.recording) { - this.buffer.push(...inputs[0][0]) - if (this.buffer.length >= 2400) this.sendBuffer() + process(inputs) { + if (inputs[0]?.length && this.recording) { + this.buffer.push(...inputs[0][0]) + if (this.buffer.length >= this.bufferSize) this.sendBuffer() + } + return true } - return true } -} -registerProcessor('audio-recorder', AudioRecorderProcessor) -`; + registerProcessor('audio-recorder', AudioRecorderProcessor)`; const INT16_MIN = -32768; const INT16_MAX = 32767; const INT16_SCALE = 32767; +const DEFAULT_SAMPLE_RATE = 24000; +const DEFAULT_CHUNK_SIZE_IN_MS = 100; +const MS_IN_SECOND = 1000; -export function useRecorder(onAudioChunk: (base64: string) => void) { +export function useRecorder( + onAudioChunk: (base64: string, timestamp: string) => void, + config?: Record | null +) { const [recording, setRecordingInternal] = useState(false); const audioCtxRef = useRef(null); const workletRef = useRef(null); const streamRef = useRef(null); + const [{ Date }] = usePonyfill(); + + const { sampleRate = DEFAULT_SAMPLE_RATE, chunkIntervalMs = DEFAULT_CHUNK_SIZE_IN_MS } = config || {}; const initAudio = useCallback(async () => { if (audioCtxRef.current) { return; } - const audioCtx = new AudioContext({ sampleRate: 24000 }); + const audioCtx = new AudioContext({ sampleRate: sampleRate as number }); const blob = new Blob([audioProcessorCode], { type: 'application/javascript' }); @@ -58,7 +68,7 @@ export function useRecorder(onAudioChunk: (base64: string) => void) { URL.revokeObjectURL(url); // eslint-disable-next-line require-atomic-updates audioCtxRef.current = audioCtx; - }, []); + }, [sampleRate]); const startRecording = useCallback(async () => { await initAudio(); @@ -69,16 +79,21 @@ export function useRecorder(onAudioChunk: (base64: string) => void) { const stream = await navigator.mediaDevices.getUserMedia({ audio: { channelCount: 1, - sampleRate: 24000, + sampleRate, echoCancellation: true } }); streamRef.current = stream; const source = audioCtx.createMediaStreamSource(stream); - const worklet = new AudioWorkletNode(audioCtx, 'audio-recorder'); + const worklet = new AudioWorkletNode(audioCtx, 'audio-recorder', { + processorOptions: { + bufferSize: ((sampleRate as number) * (chunkIntervalMs as number)) / MS_IN_SECOND + } + }); worklet.port.onmessage = e => { if (e.data.eventType === 'audio') { + const timestamp = new Date().toISOString(); const float32 = e.data.audioData; const int16 = new Int16Array(float32.length); for (let i = 0; i < float32.length; i++) { @@ -86,7 +101,7 @@ export function useRecorder(onAudioChunk: (base64: string) => void) { int16[i] = Math.max(INT16_MIN, Math.min(INT16_MAX, float32[i] * INT16_SCALE)); } const base64 = btoa(String.fromCharCode(...new Uint8Array(int16.buffer))); - onAudioChunk(base64); + onAudioChunk(base64, timestamp); } }; @@ -95,7 +110,7 @@ export function useRecorder(onAudioChunk: (base64: string) => void) { worklet.port.postMessage({ command: 'START' }); workletRef.current = worklet; setRecordingInternal(true); - }, [initAudio, onAudioChunk]); + }, [Date, chunkIntervalMs, initAudio, onAudioChunk, sampleRate]); const stopRecording = useCallback(() => { if (workletRef.current) { diff --git a/packages/core/src/reducers/activities/combineActivitiesReducer.ts b/packages/core/src/reducers/activities/combineActivitiesReducer.ts index 488df1be62..49ee3cee3d 100644 --- a/packages/core/src/reducers/activities/combineActivitiesReducer.ts +++ b/packages/core/src/reducers/activities/combineActivitiesReducer.ts @@ -10,6 +10,7 @@ import createGroupedActivitiesReducer, { type ActivitiesState = { activities: readonly WebChatActivity[]; + voiceActivities: readonly WebChatActivity[]; groupedActivities: GroupedActivitiesState; }; @@ -34,7 +35,12 @@ export default function combineActivitiesReducer( state: (ExistingState & ActivitiesState) | undefined, action: ExistingAction & GroupedActivitiesAction ): ExistingState & ActivitiesState { - const { activities: _activities, groupedActivities, ...existingState } = state ?? {}; + const { + activities: _activities, + voiceActivities: _voiceActivities, + groupedActivities, + ...existingState + } = state ?? {}; const nextState = existingSlicedReducer(existingState as ExistingState, action); const nextGroupedActivities = groupedActivitiesReducer(groupedActivities, action); @@ -52,7 +58,12 @@ export default function combineActivitiesReducer( ); return hasChanged - ? { ...nextState, activities: nextGroupedActivities.sortedActivities, groupedActivities: nextGroupedActivities } + ? { + ...nextState, + activities: nextGroupedActivities.sortedActivities, + voiceActivities: nextGroupedActivities.voiceActivities, + groupedActivities: nextGroupedActivities + } : state; }; } diff --git a/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts b/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts index f333c67af1..e7179ac44e 100644 --- a/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts +++ b/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts @@ -32,7 +32,7 @@ import type { WebChatActivity } from '../../types/WebChatActivity'; import patchActivity from './patchActivity'; import deleteActivityByLocalId from './sort/deleteActivityByLocalId'; import { generateLocalIdInActivity, getLocalIdFromActivity, setLocalIdInActivity } from './sort/property/LocalId'; -import { getPositionFromActivity, setPositionInActivity } from './sort/property/Position'; +import { getPositionFromActivity, queryPositionFromActivity, setPositionInActivity } from './sort/property/Position'; import { setReceivedAtInActivity } from './sort/property/ReceivedAt'; import { querySendStatusFromOutgoingActivity, setSendStatusInOutgoingActivity } from './sort/property/SendStatus'; import queryLocalIdAByActivityId from './sort/queryLocalIdByActivityId'; @@ -42,6 +42,8 @@ import updateActivityChannelData, { updateActivityChannelDataInternalSkipNameCheck } from './sort/updateActivityChannelData'; import upsert, { INITIAL_STATE } from './sort/upsert'; +import isVoiceActivity from '../../utils/voiceActivity/isVoiceActivity'; +import isVoiceTranscriptActivity from '../../utils/voiceActivity/isVoiceTranscriptActivity'; type GroupedActivitiesAction = | DeleteActivityAction @@ -100,6 +102,13 @@ function createGroupedActivitiesReducer( payload: { activity } } = action; + // Not transcript voice does not render on UI and mostly fire and forget as we dont't have replay etc. + // hence we don't want to process and simply pass through. + if (isVoiceActivity(activity) && !isVoiceTranscriptActivity(activity)) { + state = upsert(ponyfill, state, activity); + break; + } + // Patch activity so the outgoing blob: URL is not re-downloadable. // Related to /__tests__/html2/accessibility/liveRegion/attachment/file. @@ -151,6 +160,12 @@ function createGroupedActivitiesReducer( } case POST_ACTIVITY_FULFILLED: { + // Not transcript voice does not render on UI and mostly fire and forget as we dont't have replay etc. + // hence we don't want to process and simply pass through. + if (isVoiceActivity(action.payload.activity) && !isVoiceTranscriptActivity(action.payload.activity)) { + state = upsert(ponyfill, state, action.payload.activity); + break; + } const localId = queryLocalIdAByClientActivityId(state, action.meta.clientActivityID); const existingActivity = localId && state.activityMap.get(localId)?.activity; @@ -175,8 +190,11 @@ function createGroupedActivitiesReducer( activity = setSendStatusInOutgoingActivity(activity, SENT); activity = setLocalIdInActivity(activity, localId); - // Keep existing position. - activity = setPositionInActivity(activity, getPositionFromActivity(existingActivity)); + // Keep existing position (if it exists - voice activities don't have positions) + const existingPosition = queryPositionFromActivity(existingActivity); + if (typeof existingPosition !== 'undefined') { + activity = setPositionInActivity(activity, getPositionFromActivity(existingActivity)); + } // Compare the INCOMING_ACTIVITY below: // - POST_ACTIVITY_FULFILLED will mark send status as SENT diff --git a/packages/core/src/reducers/activities/sort/types.ts b/packages/core/src/reducers/activities/sort/types.ts index 286711854f..28be6d1149 100644 --- a/packages/core/src/reducers/activities/sort/types.ts +++ b/packages/core/src/reducers/activities/sort/types.ts @@ -57,6 +57,7 @@ type State = { readonly livestreamSessionMap: LivestreamSessionMap; readonly sortedChatHistoryList: SortedChatHistory; readonly sortedActivities: readonly Activity[]; + readonly voiceActivities: readonly Activity[]; }; export { diff --git a/packages/core/src/reducers/activities/sort/upsert.ts b/packages/core/src/reducers/activities/sort/upsert.ts index c917d77568..9528d1c956 100644 --- a/packages/core/src/reducers/activities/sort/upsert.ts +++ b/packages/core/src/reducers/activities/sort/upsert.ts @@ -18,6 +18,8 @@ import { type SortedChatHistoryEntry, type State } from './types'; +import isVoiceActivity from '../../../utils/voiceActivity/isVoiceActivity'; +import isVoiceTranscriptActivity from '../../../utils/voiceActivity/isVoiceTranscriptActivity'; // Honoring timestamp or not: // @@ -48,7 +50,8 @@ const INITIAL_STATE = Object.freeze({ livestreamSessionMap: Object.freeze(new Map()), howToGroupingMap: Object.freeze(new Map()), sortedActivities: Object.freeze([]), - sortedChatHistoryList: Object.freeze([]) + sortedChatHistoryList: Object.freeze([]), + voiceActivities: Object.freeze([]) } satisfies State); // Question: Why insertion sort works but not quick sort? @@ -58,6 +61,14 @@ const INITIAL_STATE = Object.freeze({ // - Duplicate timestamps: activities without timestamp can't be sort deterministically with quick sort function upsert(ponyfill: Pick, state: State, activity: Activity): State { + // we only want to process transcript voice activities thorugh this as those will be rendered. + // all other voice activities will be stored in separate slice and we don't want to perform any operation on them. + if (isVoiceActivity(activity) && !isVoiceTranscriptActivity(activity)) { + return Object.freeze({ + ...state, + voiceActivities: Object.freeze([...state.voiceActivities, activity]) + } satisfies State); + } const nextActivityIdToLocalIdMap = new Map(state.activityIdToLocalIdMap); const nextActivityMap = new Map(state.activityMap); const nextClientActivityIdToLocalIdMap = new Map(state.clientActivityIdToLocalIdMap); @@ -336,7 +347,8 @@ function upsert(ponyfill: Pick, state: State, activ howToGroupingMap: Object.freeze(nextHowToGroupingMap), livestreamSessionMap: Object.freeze(nextLivestreamSessionMap), sortedActivities: Object.freeze(nextSortedActivities), - sortedChatHistoryList: Object.freeze(nextSortedChatHistoryList) + sortedChatHistoryList: Object.freeze(nextSortedChatHistoryList), + voiceActivities: state.voiceActivities } satisfies State); } diff --git a/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts b/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts index c8d744595e..1b2c3abf77 100644 --- a/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts +++ b/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts @@ -2,36 +2,34 @@ import isVoiceActivity from './isVoiceActivity'; import { WebChatActivity } from '../../types/WebChatActivity'; // Mock activity factory for testing -const createMockActivity = (type: string = 'event', value?: any): WebChatActivity => ({ +const createMockActivity = (type: string = 'event', name?: string, value?: any): WebChatActivity => ({ type: type as any, id: 'test-activity-id', from: { id: 'test-user' }, channelData: { 'webchat:sequence-id': 1 }, + ...(name && { name }), ...(value && { value }) }); -const createMockVoiceActivity = (voiceEventType: string, additionalProps?: any): WebChatActivity => - createMockActivity('event', { - voiceLiveEvent: { - type: voiceEventType, - ...additionalProps - } +const createMockVoiceActivity = (name: string, voiceProps: Record): WebChatActivity => + createMockActivity('event', name, { + voice: voiceProps }); describe('isVoiceActivity', () => { describe('Valid voice activities', () => { - test('should return true for event activity with voiceLiveEvent', () => { - const activity = createMockVoiceActivity('response.audio.delta', { delta: 'audiodata' }); + test('should return true for event activity with voice', () => { + const activity = createMockVoiceActivity('stream.chunk', { contentUrl: 'base64' }); const result = isVoiceActivity(activity); expect(result).toBe(true); }); - test('should return true for voice activity with minimal voiceLiveEvent', () => { - const activity = createMockActivity('event', { voiceLiveEvent: {} }); + test('should return true for voice activity with minimal voice', () => { + const activity = createMockActivity('event', 'stream.chunk', { voice: {} }); const result = isVoiceActivity(activity); @@ -41,18 +39,29 @@ describe('isVoiceActivity', () => { describe('Invalid activities', () => { const testCases = [ - // Invalid by activity type { - name: 'message activity with voiceLiveEvent', - activity: () => createMockActivity('message', { voiceLiveEvent: { type: 'response.audio.delta' } }) + name: 'message activity with voice', + activity: () => createMockActivity('message', 'stream.chunk', { voice: { contentUrl: 'base64' } }) }, { name: 'typing activity', activity: () => createMockActivity('typing') }, { - name: 'event activity with value', - activity: () => ({ ...createMockActivity('event'), value: 'not an object' }) + name: 'event activity with non-object value', + activity: () => ({ ...createMockActivity('event', 'test'), value: 'not an object' }) + }, + { + name: 'event activity without voice property', + activity: () => createMockActivity('event', 'test', { someOtherProp: 'value' }) + }, + { + name: 'event activity with no value', + activity: () => createMockActivity('event', 'test') + }, + { + name: 'event activity with no name', + activity: () => createMockActivity('event', undefined, { voice: {} }) } ]; @@ -63,22 +72,37 @@ describe('isVoiceActivity', () => { }); }); - describe('Real-world voice event types', () => { - const voiceEventTypes = [ - 'input_audio_buffer.append', - 'input_audio_buffer.speech_started', - 'input_audio_buffer.speech_stopped', - 'conversation.item.input_audio_transcription.completed', - 'response.audio.delta', - 'response.audio_transcript.delta', - 'response.audio_transcript.done', - 'response.done', - 'session.update', - 'response.cancel' + describe('Real-world voice activity scenarios', () => { + const voiceScenarios = [ + { + name: 'session.update with speech detected state', + eventName: 'session.update', + voiceProps: { bot_state: 'voice.request.detected', message: 'Your request is identified' } + }, + { + name: 'session.update with processing state', + eventName: 'session.update', + voiceProps: { bot_state: 'voice.request.processing', message: 'Your request is being processed' } + }, + { + name: 'stream.end with user transcription', + eventName: 'stream.end', + voiceProps: { transcription: 'My destination is bangalore', origin: 'user' } + }, + { + name: 'stream.chunk with server audio response', + eventName: 'stream.chunk', + voiceProps: { contentUrl: 'base64chunk' } + }, + { + name: 'stream.end with bot transcription', + eventName: 'stream.end', + voiceProps: { transcription: 'Your destination is at 1000m above sea level', origin: 'bot' } + } ]; - test.each(voiceEventTypes)('should return true for voice event type: %s', eventType => { - const activity = createMockVoiceActivity(eventType); + test.each(voiceScenarios)('should return true for $name', ({ eventName, voiceProps }) => { + const activity = createMockVoiceActivity(eventName, voiceProps); const result = isVoiceActivity(activity); diff --git a/packages/core/src/utils/voiceActivity/isVoiceActivity.ts b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts index e16154e590..a17937d8ba 100644 --- a/packages/core/src/utils/voiceActivity/isVoiceActivity.ts +++ b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts @@ -1,14 +1,17 @@ import { WebChatActivity } from '../../types/WebChatActivity'; -// This is interim type guard until activity protocol is ratified. +// This is interim until activity protocol is ratified. const isVoiceActivity = ( activity: WebChatActivity ): activity is WebChatActivity & { - value: { voiceLiveEvent: any }; + name: string; + type: 'event'; + value: { voice: any }; } => activity.type === 'event' && - activity.value && + !!activity.name && + !!activity.value && typeof activity.value === 'object' && - 'voiceLiveEvent' in activity.value; + 'voice' in activity.value; export default isVoiceActivity; diff --git a/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.spec.ts b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.spec.ts new file mode 100644 index 0000000000..e061e24813 --- /dev/null +++ b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.spec.ts @@ -0,0 +1,164 @@ +import isVoiceTranscriptActivity from './isVoiceTranscriptActivity'; +import { WebChatActivity } from '../../types/WebChatActivity'; + +// Mock activity factory for testing +const createMockActivity = (type: string = 'event', name?: string, value?: any): WebChatActivity => ({ + type: type as any, + id: 'test-activity-id', + from: { id: 'test-user' }, + channelData: { + 'webchat:sequence-id': 1 + }, + ...(name && { name }), + ...(value && { value }) +}); + +const createMockVoiceActivity = (name: string, voiceProps: Record): WebChatActivity => + createMockActivity('event', name, { + voice: voiceProps + }); + +describe('isVoiceTranscriptActivity', () => { + describe('Valid transcript activities', () => { + test('should return true for stream.end with user transcription', () => { + const activity = createMockVoiceActivity('stream.end', { + transcription: 'Hello world', + origin: 'user' + }); + + const result = isVoiceTranscriptActivity(activity); + + expect(result).toBe(true); + }); + + test('should return true for stream.end with bot transcription', () => { + const activity = createMockVoiceActivity('stream.end', { + transcription: 'Hi there!', + origin: 'bot' + }); + + const result = isVoiceTranscriptActivity(activity); + + expect(result).toBe(true); + }); + + test('should return true for stream.end with empty transcription string', () => { + const activity = createMockVoiceActivity('stream.end', { + transcription: '', + origin: 'user' + }); + + const result = isVoiceTranscriptActivity(activity); + + expect(result).toBe(true); + }); + }); + + describe('Invalid activities', () => { + const testCases = [ + { + name: 'stream.chunk voice activity', + activity: () => createMockVoiceActivity('stream.chunk', { contentUrl: 'base64' }) + }, + { + name: 'session.update voice activity', + activity: () => createMockVoiceActivity('session.update', { bot_state: 'voice.request.detected' }) + }, + { + name: 'stream.end without transcription', + activity: () => createMockVoiceActivity('stream.end', { origin: 'user' }) + }, + { + name: 'stream.end with non-string transcription', + activity: () => createMockVoiceActivity('stream.end', { transcription: 123, origin: 'user' }) + }, + { + name: 'stream.end with null transcription', + activity: () => createMockVoiceActivity('stream.end', { transcription: null, origin: 'user' }) + }, + { + name: 'regular message activity', + activity: () => createMockActivity('message', 'test') + }, + { + name: 'typing activity', + activity: () => createMockActivity('typing') + }, + { + name: 'event activity without voice data', + activity: () => createMockActivity('event', 'stream.end', { someData: 'test' }) + }, + { + name: 'event activity with null value', + activity: () => ({ ...createMockActivity('event', 'stream.end'), value: null }) + }, + { + name: 'event activity without value', + activity: () => createMockActivity('event', 'stream.end') + }, + { + name: 'event activity without name', + activity: () => createMockActivity('event', undefined, { voice: { transcription: 'test' } }) + } + ]; + + test.each(testCases)('should return false for $name', ({ activity }) => { + const result = isVoiceTranscriptActivity(activity()); + + expect(result).toBe(false); + }); + }); + + describe('Real-world scenarios', () => { + test('should identify user transcript in conversation flow', () => { + const conversationActivities = [ + createMockVoiceActivity('session.update', { bot_state: 'voice.request.detected' }), + createMockVoiceActivity('session.update', { bot_state: 'voice.request.processing' }), + createMockVoiceActivity('stream.end', { + transcription: 'What is the weather today?', + origin: 'user' + }) + ]; + + const transcriptResults = conversationActivities.map(activity => isVoiceTranscriptActivity(activity)); + + expect(transcriptResults).toEqual([false, false, true]); + }); + + test('should identify bot transcript in response flow', () => { + const responseActivities = [ + createMockVoiceActivity('session.update', { bot_state: 'voice.response.available' }), + createMockVoiceActivity('stream.chunk', { contentUrl: 'chunk1' }), + createMockVoiceActivity('stream.chunk', { contentUrl: 'chunk2' }), + createMockVoiceActivity('stream.end', { + transcription: 'Today will be sunny with a high of 75 degrees.', + origin: 'bot' + }) + ]; + + const transcriptResults = responseActivities.map(activity => isVoiceTranscriptActivity(activity)); + + expect(transcriptResults).toEqual([false, false, false, true]); + }); + + test('should handle complete conversation with mixed activities', () => { + const mixedActivities = [ + createMockActivity('message', 'test'), + createMockVoiceActivity('stream.end', { + transcription: 'Hello', + origin: 'user' + }), + createMockVoiceActivity('stream.chunk', { contentUrl: 'audio' }), + createMockVoiceActivity('stream.end', { + transcription: 'Hi there!', + origin: 'bot' + }), + createMockActivity('typing') + ]; + + const transcriptResults = mixedActivities.map(activity => isVoiceTranscriptActivity(activity)); + + expect(transcriptResults).toEqual([false, true, false, true, false]); + }); + }); +}); diff --git a/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts new file mode 100644 index 0000000000..f6da7a746a --- /dev/null +++ b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts @@ -0,0 +1,18 @@ +import isVoiceActivity from './isVoiceActivity'; +import { WebChatActivity } from '../../types/WebChatActivity'; + +const isVoiceTranscriptActivity = ( + activity: WebChatActivity +): activity is WebChatActivity & { + value: { + voice: { + transcription: string; + origin: 'user' | 'bot'; + }; + }; +} => + isVoiceActivity(activity) && + activity.name === 'stream.end' && + typeof activity.value?.voice?.transcription === 'string'; + +export default isVoiceTranscriptActivity; From 0838e44d585e450425b04990ceea415d754981fe Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Thu, 8 Jan 2026 10:54:44 +0000 Subject: [PATCH 04/32] refactor composer to not use direct state inside effect --- .../api/src/hooks/internal/useStateRef.ts | 31 +++++++++ .../SpeechToSpeech/SpeechToSpeechComposer.tsx | 64 ++++++++++++------- .../isVoiceTranscriptActivity.ts | 2 +- 3 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 packages/api/src/hooks/internal/useStateRef.ts diff --git a/packages/api/src/hooks/internal/useStateRef.ts b/packages/api/src/hooks/internal/useStateRef.ts new file mode 100644 index 0000000000..a6f517fcc3 --- /dev/null +++ b/packages/api/src/hooks/internal/useStateRef.ts @@ -0,0 +1,31 @@ +import { useCallback, useRef, useState } from 'react'; + +import type { Dispatch, MutableRefObject, SetStateAction } from 'react'; + +export default function useStateRef( + initialValue?: T +): readonly [T, Dispatch>, MutableRefObject] { + const [_, forceRender] = useState(); + const valueRef: MutableRefObject = useRef(initialValue); + + const setter: Dispatch> = useCallback( + (value: SetStateAction) => { + const { current } = valueRef; + + value = value instanceof Function ? value(current) : value; + + if (current !== value) { + valueRef.current = value; + + forceRender({}); + } + }, + [forceRender, valueRef] + ); + + return Object.freeze([valueRef.current, setter, valueRef]) as readonly [ + T, + Dispatch>, + MutableRefObject + ]; +} diff --git a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx index b1f978e42c..70d9c3aa4a 100644 --- a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx +++ b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx @@ -1,21 +1,22 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, type ReactNode } from 'react'; import { isVoiceActivity, WebChatActivity } from 'botframework-webchat-core'; import { useAudioPlayer } from './private/useAudioPlayer'; import { useRecorder } from './private/useRecorder'; import { useDebouncedNotifications, usePostActivity, useVoiceActivities } from '../../hooks'; import SpeechToSpeechContext from './private/Context'; import { SpeechState } from './types/SpeechState'; +import useStateRef from '../../hooks/internal/useStateRef'; export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> = ({ children }) => { const [voiceActivities] = useVoiceActivities(); const postActivity = usePostActivity(); const [{ connectivitystatus }] = useDebouncedNotifications(); const lastProcessedIndexRef = useRef(0); - const [speechState, setSpeechState] = useState('idle'); + const [speechState, setSpeechState] = useStateRef('idle'); - // config received from server on session start, for now ccv2 and mmrt runs on different sample rate and chunk interval. + // config received from server on session init (only once), for now ccv2 and mmrt runs on different sample rate and chunk interval. // we will read those config, free form object as unsure of what all session config would be needed in future. - const [serverConfig, setServerConfig] = useState | null>(null); + const [serverConfig, setServerConfig] = useStateRef | null>(null); const { playAudio, stopAudio, isPlaying } = useAudioPlayer(serverConfig); const isConnected = useMemo(() => connectivitystatus?.message === 'connected', [connectivitystatus]); @@ -42,27 +43,44 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> const { name, value } = activity; const { voice } = value; - // TODO - this will be commandResult activity and not event, need to think on handling of command and commandResult activities. - if (name === 'session.init' && value.session?.config) { - setServerConfig(value.session.config as Record); - } else if (name === 'session.update') { - switch (voice.bot_state) { - case 'voice.request.detected': - stopAudio(); - setSpeechState('listening'); - break; - case 'voice.request.processing': - setSpeechState('processing'); - break; - default: - break; + switch (name) { + // TODO - this will be commandResult activity and not event, need to think on handling of command and commandResult activities. + case 'session.init': { + setServerConfig(value.session?.config as Record); + break; } - } else if (name === 'stream.chunk' && voice.contentUrl) { - playAudio(voice.contentUrl); + + case 'session.update': { + switch (voice.bot_state) { + case 'voice.request.detected': + stopAudio(); + setSpeechState('listening'); + break; + + case 'voice.request.processing': + setSpeechState('processing'); + break; + + default: + break; + } + break; + } + + case 'stream.chunk': { + if (voice.contentUrl) { + playAudio(voice.contentUrl); + } + break; + } + + default: + break; } }, - [playAudio, stopAudio] + [playAudio, setServerConfig, setSpeechState, stopAudio] ); + useEffect(() => { const startIndex = lastProcessedIndexRef.current; if (!voiceActivities.length || startIndex >= voiceActivities.length) { @@ -93,7 +111,7 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> } lastProcessedIndexRef.current = voiceActivities.length; - }, [voiceActivities, recording, isPlaying, speechState, handleVoiceActivity]); + }, [handleVoiceActivity, isPlaying, recording, setSpeechState, speechState, voiceActivities]); const setRecording = useCallback( async (shouldRecord: boolean) => { @@ -110,7 +128,7 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> await baseSetRecording(shouldRecord); }, - [isConnected, baseSetRecording, stopAudio] + [isConnected, baseSetRecording, setSpeechState, stopAudio] ); const contextValue = useMemo( diff --git a/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts index f6da7a746a..c6ae5bd742 100644 --- a/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts +++ b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts @@ -7,7 +7,7 @@ const isVoiceTranscriptActivity = ( value: { voice: { transcription: string; - origin: 'user' | 'bot'; + origin: 'user' | 'agent'; }; }; } => From a3b2c8b51cf7caa6fa328ac0d6e3f33a79ec2133 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Wed, 14 Jan 2026 10:53:14 +0000 Subject: [PATCH 05/32] more implementation chunk --- packages/api/src/StyleOptions.ts | 7 + packages/api/src/boot/hook.ts | 2 + packages/api/src/defaultStyleOptions.ts | 5 +- packages/api/src/hooks/Composer.tsx | 5 +- packages/api/src/hooks/index.ts | 6 +- .../bundle/src/boot/actual/hook/minimal.ts | 2 + .../Activity/createCoreMiddleware.tsx | 60 ++++++--- packages/component/src/TextArea/TextArea.tsx | 3 +- packages/component/src/boot/hook.ts | 2 + packages/core/src/index.ts | 6 + .../sort/deleteActivityByLocalId.ts | 4 +- packages/core/src/sagas/postActivitySaga.ts | 9 ++ .../getVoiceActivityRole.spec.ts | 126 ++++++++++++++++++ .../voiceActivity/getVoiceActivityRole.ts | 18 +++ .../getVoiceActivityText.spec.ts | 88 ++++++++++++ .../voiceActivity/getVoiceActivityText.ts | 11 ++ .../voiceActivity/isVoiceActivity.spec.ts | 54 ++++++++ .../utils/voiceActivity/isVoiceActivity.ts | 3 +- .../activity/PartGroupingDecorator.tsx | 7 +- 19 files changed, 387 insertions(+), 31 deletions(-) create mode 100644 packages/core/src/utils/voiceActivity/getVoiceActivityRole.spec.ts create mode 100644 packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts create mode 100644 packages/core/src/utils/voiceActivity/getVoiceActivityText.spec.ts create mode 100644 packages/core/src/utils/voiceActivity/getVoiceActivityText.ts diff --git a/packages/api/src/StyleOptions.ts b/packages/api/src/StyleOptions.ts index 875a02022f..d8e0a30b3b 100644 --- a/packages/api/src/StyleOptions.ts +++ b/packages/api/src/StyleOptions.ts @@ -998,6 +998,13 @@ type StyleOptions = { * New in 4.19.0. */ disableFileUpload?: boolean; + /** + * Indicates if microphone button should be shown in fluent theme sendbox. + * + * @default false + * + */ + showMicrophoneButton?: boolean; }; // StrictStyleOptions is only used internally in Web Chat and for simplifying our code: diff --git a/packages/api/src/boot/hook.ts b/packages/api/src/boot/hook.ts index 8d6df8447f..e171a66fdc 100644 --- a/packages/api/src/boot/hook.ts +++ b/packages/api/src/boot/hook.ts @@ -59,6 +59,7 @@ export { useSendTypingIndicator, useSetNotification, useShouldSpeakIncomingActivity, + useSpeechToSpeech, useStartDictate, useStopDictate, useStyleOptions, @@ -73,5 +74,6 @@ export { useUIState, useUserID, useUsername, + useVoiceActivities, useVoiceSelector } from '../hooks/index'; diff --git a/packages/api/src/defaultStyleOptions.ts b/packages/api/src/defaultStyleOptions.ts index 841a5dd5bd..f64dd4a165 100644 --- a/packages/api/src/defaultStyleOptions.ts +++ b/packages/api/src/defaultStyleOptions.ts @@ -317,7 +317,10 @@ const DEFAULT_OPTIONS: Required = { // Send box attachment bar sendBoxAttachmentBarMaxHeight: 114, - sendBoxAttachmentBarMaxThumbnail: 3 + sendBoxAttachmentBarMaxThumbnail: 3, + + // S2S options + showMicrophoneButton: false }; export default DEFAULT_OPTIONS; diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index abe6b47501..a371c9a657 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -62,6 +62,7 @@ import ActivitySendStatusTelemetryComposer from '../providers/ActivitySendStatus import ActivityTypingComposer from '../providers/ActivityTyping/ActivityTypingComposer'; import GroupActivitiesComposer from '../providers/GroupActivities/GroupActivitiesComposer'; import PonyfillComposer from '../providers/Ponyfill/PonyfillComposer'; +import { SpeechToSpeechComposer } from '../providers/SpeechToSpeech/SpeechToSpeechComposer'; import StyleOptionsComposer from '../providers/StyleOptions/StyleOptionsComposer'; import { type ActivityStatusMiddleware, type RenderActivityStatus } from '../types/ActivityStatusMiddleware'; import AttachmentForScreenReaderMiddleware from '../types/AttachmentForScreenReaderMiddleware'; @@ -599,7 +600,9 @@ const ComposerCore = ({ - {typeof children === 'function' ? children(context) : children} + + {typeof children === 'function' ? children(context) : children} + diff --git a/packages/api/src/hooks/index.ts b/packages/api/src/hooks/index.ts index b1d027ee3a..73a6dc9097 100644 --- a/packages/api/src/hooks/index.ts +++ b/packages/api/src/hooks/index.ts @@ -57,6 +57,7 @@ import useSendTimeoutForActivity from './useSendTimeoutForActivity'; import useSendTypingIndicator from './useSendTypingIndicator'; import useSetNotification from './useSetNotification'; import useShouldSpeakIncomingActivity from './useShouldSpeakIncomingActivity'; +import useSpeechToSpeech from './useSpeechToSpeech'; import useStartDictate from './useStartDictate'; import useStopDictate from './useStopDictate'; import useStyleOptions from './useStyleOptions'; @@ -136,6 +137,7 @@ export { useSendTypingIndicator, useSetNotification, useShouldSpeakIncomingActivity, + useSpeechToSpeech, useStartDictate, useStopDictate, useStyleOptions, @@ -149,6 +151,6 @@ export { useUIState, useUserID, useUsername, - useVoiceSelector, - useVoiceActivities + useVoiceActivities, + useVoiceSelector }; diff --git a/packages/bundle/src/boot/actual/hook/minimal.ts b/packages/bundle/src/boot/actual/hook/minimal.ts index 69eadf421d..1fdf4f65bf 100644 --- a/packages/bundle/src/boot/actual/hook/minimal.ts +++ b/packages/bundle/src/boot/actual/hook/minimal.ts @@ -74,6 +74,7 @@ export { useSetNotification, useShouldReduceMotion, useShouldSpeakIncomingActivity, + useSpeechToSpeech, useStartDictate, useStopDictate, useStyleOptions, @@ -93,6 +94,7 @@ export { useUIState, useUserID, useUsername, + useVoiceActivities, useVoiceSelector, useWebSpeechPonyfill, type SendBoxFocusOptions diff --git a/packages/component/src/Middleware/Activity/createCoreMiddleware.tsx b/packages/component/src/Middleware/Activity/createCoreMiddleware.tsx index a9479b8188..e6b6434cd1 100644 --- a/packages/component/src/Middleware/Activity/createCoreMiddleware.tsx +++ b/packages/component/src/Middleware/Activity/createCoreMiddleware.tsx @@ -1,43 +1,59 @@ /* eslint complexity: ["error", 21] */ import { ActivityMiddleware } from 'botframework-webchat-api'; -import { getActivityLivestreamingMetadata, getOrgSchemaMessage } from 'botframework-webchat-core'; +import { + getActivityLivestreamingMetadata, + getOrgSchemaMessage, + isVoiceTranscriptActivity +} from 'botframework-webchat-core'; import React from 'react'; import CarouselLayout from '../../Activity/CarouselLayout'; import StackedLayout from '../../Activity/StackedLayout'; +// TODO: [P4] Can we simplify these if-statement to something more readable? +function shouldFilterActivity(activity, messageThing) { + const { type } = activity; + if ( + type === 'conversationUpdate' || + (type === 'event' && !isVoiceTranscriptActivity(activity)) || + type === 'invoke' || + // Do not show content for contentless livestream interims, or finalized activity without content. + (type === 'typing' && + (getActivityLivestreamingMetadata(activity)?.type === 'contentless' || + !(activity['text'] || activity.attachments?.length > 0 || messageThing?.abstract))) || + (type === 'message' && + // Do not show postback + (activity.channelData?.postBack || + // Do not show messageBack if displayText is undefined + (activity.channelData?.messageBack && !activity.channelData.messageBack.displayText) || + // Do not show empty bubbles (no text and attachments) + !(activity.text || activity.attachments?.length || messageThing?.abstract))) + ) { + return true; + } + + return false; +} + export default function createCoreMiddleware(): ActivityMiddleware[] { return [ () => next => (...args) => { const [{ activity }] = args; + const isMessageOrTyping = activity.type === 'message' || activity.type === 'typing'; - // TODO: [P4] Can we simplify these if-statement to something more readable? - - const { type } = activity; const messageThing = getOrgSchemaMessage(activity.entities); // Filter out activities that should not visible. - if ( - type === 'conversationUpdate' || - type === 'event' || - type === 'invoke' || - // Do not show content for contentless livestream interims, or finalized activity without content. - (type === 'typing' && - (getActivityLivestreamingMetadata(activity)?.type === 'contentless' || - !(activity['text'] || activity.attachments?.length > 0 || messageThing?.abstract))) || - (type === 'message' && - // Do not show postback - (activity.channelData?.postBack || - // Do not show messageBack if displayText is undefined - (activity.channelData?.messageBack && !activity.channelData.messageBack.displayText) || - // Do not show empty bubbles (no text and attachments) - !(activity.text || activity.attachments?.length || messageThing?.abstract))) - ) { + if (shouldFilterActivity(activity, messageThing)) { return false; - } else if (type === 'message' || type === 'typing') { - if ((activity.attachments?.length || 0) > 1 && activity.attachmentLayout === 'carousel') { + } else if (isMessageOrTyping || isVoiceTranscriptActivity(activity)) { + if ( + isMessageOrTyping && + (activity.attachments?.length || 0) > 1 && + activity.attachmentLayout === 'carousel' + ) { // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. // The function signature need to be compatible with older version of activity middleware, which was: // diff --git a/packages/component/src/TextArea/TextArea.tsx b/packages/component/src/TextArea/TextArea.tsx index fd870ef711..491fcd9198 100644 --- a/packages/component/src/TextArea/TextArea.tsx +++ b/packages/component/src/TextArea/TextArea.tsx @@ -37,13 +37,14 @@ const TextArea = forwardRef< placeholder?: string | undefined; startRows?: number | undefined; value?: string | undefined; + readOnly?: boolean | undefined; }> >((props, ref) => { const [uiState] = useUIState(); const classNames = useStyles(styles); const isInCompositionRef = useRef(false); - const disabled = uiState === 'disabled'; + const disabled = uiState === 'disabled' || props.readOnly; const handleCompositionEnd = useCallback(() => { isInCompositionRef.current = false; diff --git a/packages/component/src/boot/hook.ts b/packages/component/src/boot/hook.ts index 95dd2ec761..bb7c2942c2 100644 --- a/packages/component/src/boot/hook.ts +++ b/packages/component/src/boot/hook.ts @@ -57,6 +57,7 @@ export { useSendTypingIndicator, useSetNotification, useShouldSpeakIncomingActivity, + useSpeechToSpeech, useStartDictate, useStopDictate, useStyleOptions, @@ -71,6 +72,7 @@ export { useUIState, useUserID, useUsername, + useVoiceActivities, useVoiceSelector } from 'botframework-webchat-api/hook'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index fd05b34d75..f9854fdcdf 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -41,6 +41,9 @@ import getOrgSchemaMessage from './utils/getOrgSchemaMessage'; import onErrorResumeNext from './utils/onErrorResumeNext'; import singleToArray from './utils/singleToArray'; import isVoiceActivity from './utils/voiceActivity/isVoiceActivity'; +import isVoiceTranscriptActivity from './utils/voiceActivity/isVoiceTranscriptActivity'; +import getVoiceActivityRole from './utils/voiceActivity/getVoiceActivityRole'; +import getVoiceActivityText from './utils/voiceActivity/getVoiceActivityText'; export { isForbiddenPropertyName, @@ -100,7 +103,10 @@ export { emitTypingIndicator, getActivityLivestreamingMetadata, getOrgSchemaMessage, + getVoiceActivityRole, + getVoiceActivityText, isVoiceActivity, + isVoiceTranscriptActivity, markActivity, onErrorResumeNext, parseAction, diff --git a/packages/core/src/reducers/activities/sort/deleteActivityByLocalId.ts b/packages/core/src/reducers/activities/sort/deleteActivityByLocalId.ts index 87d6e1e02c..16b10476a1 100644 --- a/packages/core/src/reducers/activities/sort/deleteActivityByLocalId.ts +++ b/packages/core/src/reducers/activities/sort/deleteActivityByLocalId.ts @@ -10,6 +10,7 @@ export default function deleteActivityByLocalId(state: State, localId: LocalId): const nextHowToGroupingMap = new Map(state.howToGroupingMap); const nextLivestreamSessionMap = new Map(state.livestreamSessionMap); let nextSortedChatHistoryList = Array.from(state.sortedChatHistoryList); + const nextVoiceActivities = Array.from(state.voiceActivities); if (!nextActivityMap.delete(localId)) { throw new Error(`botframework-webchat: Cannot find activity with local ID "${localId}" to delete`); @@ -172,6 +173,7 @@ export default function deleteActivityByLocalId(state: State, localId: LocalId): howToGroupingMap: Object.freeze(nextHowToGroupingMap), livestreamSessionMap: Object.freeze(nextLivestreamSessionMap), sortedActivities: Object.freeze(nextSortedActivities), - sortedChatHistoryList: Object.freeze(nextSortedChatHistoryList) + sortedChatHistoryList: Object.freeze(nextSortedChatHistoryList), + voiceActivities: Object.freeze(nextVoiceActivities) } satisfies State); } diff --git a/packages/core/src/sagas/postActivitySaga.ts b/packages/core/src/sagas/postActivitySaga.ts index 6b021ceef6..a52fd0f448 100644 --- a/packages/core/src/sagas/postActivitySaga.ts +++ b/packages/core/src/sagas/postActivitySaga.ts @@ -31,6 +31,7 @@ import type { DirectLineJSBotConnection } from '../types/external/DirectLineJSBo import type { GlobalScopePonyfill } from '../types/GlobalScopePonyfill'; import type { WebChatOutgoingActivity } from '../types/internal/WebChatOutgoingActivity'; import type { WebChatActivity } from '../types/WebChatActivity'; +import isVoiceActivity from '../utils/voiceActivity/isVoiceActivity'; // After 5 minutes, the saga will stop from listening for echo backs and consider the outgoing message as permanently undeliverable. // This value must be equals to or larger than the user-defined `styleOptions.sendTimeout`. @@ -126,6 +127,14 @@ function* postActivity( // So, we setup expectation first, then postActivity afterward const echoBackCall = call(function* () { + // Special handling for voice events - they don't echo back normally + // as we send them directly to socket and you dont get them back as incoming activity + // so we immediately return the outgoing activity with echoed true + if (isVoiceActivity(outgoingActivity as WebChatActivity)) { + echoed = true; + return outgoingActivity; + } + for (;;) { const { payload: { activity } diff --git a/packages/core/src/utils/voiceActivity/getVoiceActivityRole.spec.ts b/packages/core/src/utils/voiceActivity/getVoiceActivityRole.spec.ts new file mode 100644 index 0000000000..63a26988d7 --- /dev/null +++ b/packages/core/src/utils/voiceActivity/getVoiceActivityRole.spec.ts @@ -0,0 +1,126 @@ +import getVoiceActivityRole from './getVoiceActivityRole'; +import { WebChatActivity } from '../../types/WebChatActivity'; + +// Mock activity factory for testing +const createMockActivity = (type: string = 'event', name?: string, value?: any): WebChatActivity => ({ + type: type as any, + id: 'test-activity-id', + from: { id: 'test-user' }, + channelData: { + 'webchat:sequence-id': 1 + }, + ...(name && { name }), + ...(value && { value }) +}); + +const createMockVoiceActivity = (name: string, origin?: 'user' | 'agent', transcription?: string): WebChatActivity => + createMockActivity('event', name, { + voice: { + ...(origin && { origin }), + ...(transcription !== undefined && { transcription }) + } + }); + +describe('getVoiceActivityRole', () => { + describe.each([ + ['user', 'user', 'Hello world'], + ['user', 'user', ''] + ] as const)('Voice transcript activities with origin %s', (expectedRole, origin, transcription) => { + test(`should return "${expectedRole}" for stream.end with origin ${origin}${transcription ? '' : ' and empty transcription'}`, () => { + const activity = createMockVoiceActivity('stream.end', origin, transcription); + + const result = getVoiceActivityRole(activity); + + expect(result).toBe(expectedRole); + }); + }); + + describe.each([ + ['bot', 'agent', 'Hello, how can I help you?'], + ['bot', 'agent', ''] + ] as const)('Voice transcript activities with origin %s', (expectedRole, origin, transcription) => { + test(`should return "${expectedRole}" for stream.end with origin ${origin}${transcription ? '' : ' and empty transcription'}`, () => { + const activity = createMockVoiceActivity('stream.end', origin, transcription); + + const result = getVoiceActivityRole(activity); + + expect(result).toBe(expectedRole); + }); + }); + + describe('Non-transcript voice activities', () => { + test.each([ + ['stream.chunk', undefined, undefined], + ['stream.end', undefined, 'Some text'] + ])('should return undefined for %s', (name, origin, transcription) => { + const activity = createMockVoiceActivity(name, origin, transcription); + + const result = getVoiceActivityRole(activity); + + expect(result).toBeUndefined(); + }); + }); + + describe('Non-voice activities', () => { + test.each([ + ['message', 'regular message activity'], + ['typing', 'typing activity'] + ])('should return undefined for %s', type => { + const activity = createMockActivity(type); + + const result = getVoiceActivityRole(activity); + + expect(result).toBeUndefined(); + }); + + test('should return undefined for event activity without voice data', () => { + const activity = createMockActivity('event', undefined, { + someOtherData: 'test' + }); + + const result = getVoiceActivityRole(activity); + + expect(result).toBeUndefined(); + }); + }); + + describe('Real-world scenarios', () => { + test('should correctly identify user transcript in conversation flow', () => { + const userActivities = [ + createMockVoiceActivity('stream.start'), + createMockVoiceActivity('stream.chunk'), + createMockVoiceActivity('stream.end', 'user', 'What is the weather today?') + ]; + + const roles = userActivities.map(activity => getVoiceActivityRole(activity)); + + expect(roles).toEqual([undefined, undefined, 'user']); + }); + + test('should correctly identify bot transcript in conversation flow', () => { + const botActivities = [ + createMockVoiceActivity('stream.chunk'), + createMockVoiceActivity('stream.chunk'), + createMockVoiceActivity('stream.end', 'agent', 'Today will be sunny with a high of 75 degrees.'), + createMockVoiceActivity('session.update') + ]; + + const roles = botActivities.map(activity => getVoiceActivityRole(activity)); + + expect(roles).toEqual([undefined, undefined, 'bot', undefined]); + }); + + test('should handle mixed activity types in conversation', () => { + const mixedActivities = [ + createMockActivity('message'), + createMockVoiceActivity('stream.end', 'user', 'Hello'), + createMockActivity('typing'), + createMockVoiceActivity('stream.end', 'agent', 'Hi there!') + ]; + + const roles = mixedActivities.map(activity => getVoiceActivityRole(activity)); + + expect(roles).toEqual([undefined, 'user', undefined, 'bot']); + }); + }); +}); diff --git a/packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts b/packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts new file mode 100644 index 0000000000..a27fe23619 --- /dev/null +++ b/packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts @@ -0,0 +1,18 @@ +import { WebChatActivity } from '../../types/WebChatActivity'; +import isVoiceTranscriptActivity from './isVoiceTranscriptActivity'; + +const getVoiceActivityRole = (activity: WebChatActivity): 'user' | 'bot' | undefined => { + if (isVoiceTranscriptActivity(activity)) { + if (activity.value.voice.origin === 'agent') { + return 'bot'; + } + + if (activity.value.voice.origin === 'user') { + return 'user'; + } + } + + return undefined; +}; + +export default getVoiceActivityRole; diff --git a/packages/core/src/utils/voiceActivity/getVoiceActivityText.spec.ts b/packages/core/src/utils/voiceActivity/getVoiceActivityText.spec.ts new file mode 100644 index 0000000000..0b8b70bccb --- /dev/null +++ b/packages/core/src/utils/voiceActivity/getVoiceActivityText.spec.ts @@ -0,0 +1,88 @@ +import getVoiceActivityText from './getVoiceActivityText'; +import { WebChatActivity } from '../../types/WebChatActivity'; + +// Mock activity factory for testing +const createMockActivity = (type: string = 'event', name?: string, value?: any): WebChatActivity => ({ + type: type as any, + id: 'test-activity-id', + from: { id: 'test-user' }, + channelData: { + 'webchat:sequence-id': 1 + }, + ...(name && { name }), + ...(value && { value }) +}); + +const createMockVoiceActivity = (name: string, transcription?: string): WebChatActivity => + createMockActivity('event', name, { + voice: { + ...(transcription !== undefined && { transcription }) + } + }); + +describe('getVoiceActivityText', () => { + describe('Voice transcript activities', () => { + test.each([ + ['Hello world', 'Hello world'], + ['How can I help you today?', 'How can I help you today?'], + ['', ''] + ])('should return %p for stream.end with transcription %p', (expected, transcription) => { + const activity = createMockVoiceActivity('stream.end', transcription); + + const result = getVoiceActivityText(activity); + + expect(result).toBe(expected); + }); + + test('should return undefined for stream.end without transcript property', () => { + const activity = createMockVoiceActivity('stream.end'); + + const result = getVoiceActivityText(activity); + + expect(result).toBeUndefined(); + }); + }); + + describe('Non-transcript voice activities', () => { + test.each([['stream.chunk'], ['session.init']])('should return undefined for %s activity', name => { + const activity = createMockVoiceActivity(name); + + const result = getVoiceActivityText(activity); + + expect(result).toBeUndefined(); + }); + }); + + describe('Non-voice activities', () => { + test.each([ + ['message', undefined, undefined], + ['event', undefined, { someData: 'test' }] + ])('should return undefined for %s', (type, name, value) => { + const activity = createMockActivity(type, name, value); + + const result = getVoiceActivityText(activity); + + expect(result).toBeUndefined(); + }); + }); + + describe('Edge cases', () => { + test('should handle transcript with whitespace only', () => { + const activity = createMockVoiceActivity('stream.end', ' '); + + const result = getVoiceActivityText(activity); + + expect(result).toBe(' '); + }); + + test('should handle very long transcript', () => { + const longText = 'A'.repeat(10000); + const activity = createMockVoiceActivity('stream.end', longText); + + const result = getVoiceActivityText(activity); + + expect(result).toBe(longText); + expect(result?.length).toBe(10000); + }); + }); +}); diff --git a/packages/core/src/utils/voiceActivity/getVoiceActivityText.ts b/packages/core/src/utils/voiceActivity/getVoiceActivityText.ts new file mode 100644 index 0000000000..e2d1d2eee1 --- /dev/null +++ b/packages/core/src/utils/voiceActivity/getVoiceActivityText.ts @@ -0,0 +1,11 @@ +import { WebChatActivity } from '../../types/WebChatActivity'; +import isVoiceTranscriptActivity from './isVoiceTranscriptActivity'; + +const getVoiceActivityText = (activity: WebChatActivity): string | undefined => { + if (isVoiceTranscriptActivity(activity)) { + return activity.value.voice?.transcription; + } + return undefined; +}; + +export default getVoiceActivityText; diff --git a/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts b/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts index 1b2c3abf77..0df0199430 100644 --- a/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts +++ b/packages/core/src/utils/voiceActivity/isVoiceActivity.spec.ts @@ -18,6 +18,11 @@ const createMockVoiceActivity = (name: string, voiceProps: Record): voice: voiceProps }); +const createMockDtmfActivity = (name: string, dtmfProps: Record): WebChatActivity => + createMockActivity('event', name, { + dtmf: dtmfProps + }); + describe('isVoiceActivity', () => { describe('Valid voice activities', () => { test('should return true for event activity with voice', () => { @@ -35,6 +40,22 @@ describe('isVoiceActivity', () => { expect(result).toBe(true); }); + + test('should return true for event activity with dtmf', () => { + const activity = createMockDtmfActivity('dtmf.key', { digit: '1' }); + + const result = isVoiceActivity(activity); + + expect(result).toBe(true); + }); + + test('should return true for dtmf activity with minimal dtmf', () => { + const activity = createMockActivity('event', 'dtmf.key', { dtmf: {} }); + + const result = isVoiceActivity(activity); + + expect(result).toBe(true); + }); }); describe('Invalid activities', () => { @@ -109,4 +130,37 @@ describe('isVoiceActivity', () => { expect(result).toBe(true); }); }); + + describe('Real-world DTMF activity scenarios', () => { + const dtmfScenarios = [ + { + name: 'dtmf.key with digit pressed', + eventName: 'dtmf.key', + dtmfProps: { digit: '1' } + }, + { + name: 'dtmf.key with star key', + eventName: 'dtmf.key', + dtmfProps: { digit: '*' } + }, + { + name: 'dtmf.key with hash key', + eventName: 'dtmf.key', + dtmfProps: { digit: '#' } + }, + { + name: 'dtmf.sequence with multiple digits', + eventName: 'dtmf.sequence', + dtmfProps: { sequence: '12345' } + } + ]; + + test.each(dtmfScenarios)('should return true for $name', ({ eventName, dtmfProps }) => { + const activity = createMockDtmfActivity(eventName, dtmfProps); + + const result = isVoiceActivity(activity); + + expect(result).toBe(true); + }); + }); }); diff --git a/packages/core/src/utils/voiceActivity/isVoiceActivity.ts b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts index a17937d8ba..87a12e0a65 100644 --- a/packages/core/src/utils/voiceActivity/isVoiceActivity.ts +++ b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts @@ -1,6 +1,7 @@ import { WebChatActivity } from '../../types/WebChatActivity'; // This is interim until activity protocol is ratified. +// all voice and dtmf activities are considered voice activities. const isVoiceActivity = ( activity: WebChatActivity ): activity is WebChatActivity & { @@ -12,6 +13,6 @@ const isVoiceActivity = ( !!activity.name && !!activity.value && typeof activity.value === 'object' && - 'voice' in activity.value; + ('voice' in activity.value || 'dtmf' in activity.value); export default isVoiceActivity; diff --git a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx index 17b84dbc4a..77ba773625 100644 --- a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx +++ b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx @@ -7,6 +7,7 @@ import { array, custom, object, optional, pipe, readonly, safeParse } from 'vali import { useStyles, useVariantClassName } from '../../styles'; import styles from './PartGroupingDecorator.module.css'; +import { getVoiceActivityRole } from 'botframework-webchat-core'; const partGroupingDecoratorPropsSchema = pipe( object({ @@ -36,8 +37,10 @@ function PartGroupingDecorator(props: PartGroupingDecoratorProps) { [activity, restActivities.length] ); - const isFromUser = activity?.from?.role === 'user'; - const isFromBot = activity?.from?.role === 'bot'; + // S2S-both user and bot transcript comes from server (RT-LLM) hence need to check role explicitly. + const voiceActivityRole = activity && getVoiceActivityRole(activity); + const isFromUser = activity?.from?.role === 'user' || voiceActivityRole === 'user'; + const isFromBot = activity?.from?.role === 'bot' || voiceActivityRole === 'bot'; return (
Date: Thu, 15 Jan 2026 13:24:27 +0000 Subject: [PATCH 06/32] minor refactor --- .../SpeechToSpeech/SpeechToSpeechComposer.tsx | 2 +- .../providers/SpeechToSpeech/private/useRecorder.ts | 10 ++++++++++ .../src/providers/SpeechToSpeech/types/SpeechState.ts | 2 +- .../activities/createGroupedActivitiesReducer.ts | 3 +-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx index 70d9c3aa4a..634545482d 100644 --- a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx +++ b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx @@ -54,7 +54,7 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> switch (voice.bot_state) { case 'voice.request.detected': stopAudio(); - setSpeechState('listening'); + setSpeechState('user_speaking'); break; case 'voice.request.processing': diff --git a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts index 7ba19ba244..2fe36aeafe 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts +++ b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts @@ -1,6 +1,16 @@ import { useRef, useState, useCallback } from 'react'; import usePonyfill from '../../Ponyfill/usePonyfill'; +/** + * AudioWorklet processor code for recording audio. + * This code runs in a separate AudioWorklet context with its own globals + * (AudioWorkletProcessor, registerProcessor, etc.) + * + * IMPORTANT: This must be a plain string template to avoid transpiling issues + * as those don't exist in the AudioWorklet context. + * + * CSP Compliant: check __tests__/html2/speechToSpeech/csp.recording.html for CSP compliance tests. + */ const audioProcessorCode = ` class AudioRecorderProcessor extends AudioWorkletProcessor { constructor(options) { diff --git a/packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts b/packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts index 62d5cc8c13..40e2b87179 100644 --- a/packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts +++ b/packages/api/src/providers/SpeechToSpeech/types/SpeechState.ts @@ -1 +1 @@ -export type SpeechState = 'idle' | 'listening' | 'processing' | 'bot_speaking'; +export type SpeechState = 'idle' | 'listening' | 'user_speaking' | 'processing' | 'bot_speaking'; diff --git a/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts b/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts index e7179ac44e..18ce170790 100644 --- a/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts +++ b/packages/core/src/reducers/activities/createGroupedActivitiesReducer.ts @@ -103,9 +103,8 @@ function createGroupedActivitiesReducer( } = action; // Not transcript voice does not render on UI and mostly fire and forget as we dont't have replay etc. - // hence we don't want to process and simply pass through. + // hence we don't want to process and simply pass through. update state in fulfilled as it will echo back quickly. if (isVoiceActivity(activity) && !isVoiceTranscriptActivity(activity)) { - state = upsert(ponyfill, state, activity); break; } From cf9d2f50f3700f0754a69d41dfbb5de0d78620e3 Mon Sep 17 00:00:00 2001 From: Rushikesh Gavali Date: Thu, 15 Jan 2026 13:40:08 +0000 Subject: [PATCH 07/32] Mic Implementation and animation in fluent theme --- packages/api/src/localization/en-US.json | 8 +++ .../component/src/Activity/StackedLayout.tsx | 15 +++- .../src/components/icon/FluentIcon.module.css | 7 ++ .../sendBox/MicrophoneToolbarButton.tsx | 63 +++++++++++++++++ .../src/components/sendBox/SendBox.module.css | 9 +++ .../src/components/sendBox/SendBox.tsx | 69 ++++++++++++++----- .../src/components/sendBox/Toolbar.module.css | 56 +++++++++++++++ .../sendBox/private/useSpeechStateMessage.ts | 28 ++++++++ packages/fluent-theme/src/testIds.ts | 1 + 9 files changed, 236 insertions(+), 20 deletions(-) create mode 100644 packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx create mode 100644 packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts diff --git a/packages/api/src/localization/en-US.json b/packages/api/src/localization/en-US.json index 74bfece917..5adafb7f9e 100644 --- a/packages/api/src/localization/en-US.json +++ b/packages/api/src/localization/en-US.json @@ -131,6 +131,14 @@ "TEXT_INPUT_ALT": "Message input box", "_TEXT_INPUT_ALT.comment": "This is for screen reader for the label of the message input box.", "TEXT_INPUT_PLACEHOLDER": "Type your message", + "TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER": "Start talking…", + "_TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and in idle state.", + "TEXT_INPUT_SPEECH_LISTENING_PLACEHOLDER": "Listening…", + "_TEXT_INPUT_SPEECH_LISTENING_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and actively listening to user speech.", + "TEXT_INPUT_SPEECH_PROCESSING_PLACEHOLDER": "Processing…", + "_TEXT_INPUT_SPEECH_PROCESSING_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and processing the user's speech input.", + "TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER": "Speak to interrupt…", + "_TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and the bot is speaking.", "TEXT_INPUT_SEND_BUTTON_ALT": "Send", "TEXT_INPUT_SPEAK_BUTTON_ALT": "Speak", "TEXT_INPUT_UPLOAD_BUTTON_ALT": "Upload file", diff --git a/packages/component/src/Activity/StackedLayout.tsx b/packages/component/src/Activity/StackedLayout.tsx index f387eb41ad..9e173e36fb 100644 --- a/packages/component/src/Activity/StackedLayout.tsx +++ b/packages/component/src/Activity/StackedLayout.tsx @@ -3,7 +3,14 @@ import { hooks } from 'botframework-webchat-api'; import type { RenderAttachment } from 'botframework-webchat-api'; import { ActivityBorderDecorator } from 'botframework-webchat-api/decorator'; -import { getActivityLivestreamingMetadata, getOrgSchemaMessage, type WebChatActivity } from 'botframework-webchat-core'; +import { + getActivityLivestreamingMetadata, + getOrgSchemaMessage, + getVoiceActivityRole, + getVoiceActivityText, + isVoiceActivity, + type WebChatActivity +} from 'botframework-webchat-core'; import { useStyles } from '@msinternal/botframework-webchat-styles/react'; import cx from 'classnames'; import React, { memo, useCallback, useMemo, type ReactNode } from 'react'; @@ -124,7 +131,7 @@ const StackedLayout = ({ const isMessageOrTyping = activity.type === 'message' || activity.type === 'typing'; const attachments = useMemo(() => (isMessageOrTyping && activity.attachments) || [], [activity, isMessageOrTyping]); - const fromUser = activity.from.role === 'user'; + const fromUser = activity.from.role === 'user' || getVoiceActivityRole(activity) === 'user'; const messageBackDisplayText: string = (isMessageOrTyping && activity.channelData?.messageBack?.displayText) || ''; const messageThing = useMemo(() => getOrgSchemaMessage(activity.entities), [activity]); const isCollapsible = useMemo(() => messageThing?.keywords?.includes('Collapsible'), [messageThing]); @@ -134,7 +141,9 @@ const StackedLayout = ({ ? messageBackDisplayText || activity.text : isLivestreaming && 'text' in activity ? (activity.text as string) - : ''; + : isVoiceActivity(activity) + ? getVoiceActivityText(activity) + : ''; const initials = fromUser ? userInitials : botInitials; const nubOffset = fromUser ? bubbleFromUserNubOffset : bubbleNubOffset; diff --git a/packages/fluent-theme/src/components/icon/FluentIcon.module.css b/packages/fluent-theme/src/components/icon/FluentIcon.module.css index a091a1eee6..f2e8652e0e 100644 --- a/packages/fluent-theme/src/components/icon/FluentIcon.module.css +++ b/packages/fluent-theme/src/components/icon/FluentIcon.module.css @@ -50,4 +50,11 @@ --webchat__fluent-icon--mask: url('data:image/svg+xml;utf8,'); } +:global(.webchat) .icon--microphone { + --webchat__fluent-icon--mask: url('data:image/svg+xml;utf8,'); +} + +:global(.webchat) .icon--audio-playing { + --webchat__fluent-icon--mask: url('data:image/svg+xml;utf8,'); +} /* #endregion */ diff --git a/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx b/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx new file mode 100644 index 0000000000..a5e5a76dc5 --- /dev/null +++ b/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx @@ -0,0 +1,63 @@ +import { hooks } from 'botframework-webchat-api'; +import cx from 'classnames'; +import React, { memo, useCallback, useMemo } from 'react'; + +import { useStyles } from '../../styles'; +import testIds from '../../testIds'; +import { FluentIcon } from '../icon'; +import { ToolbarButton } from './Toolbar'; + +import styles from './Toolbar.module.css'; + +const { useSpeechToSpeech, useLocalizer } = hooks; + +function MicrophoneToolbarButton() { + const classNames = useStyles(styles); + const localize = useLocalizer(); + const [{ recording, setRecording, speechState }] = useSpeechToSpeech(); + + const handleClick = useCallback(() => { + setRecording(!recording); + }, [recording, setRecording]); + + const icon = useMemo(() => { + switch (speechState) { + case 'listening': + case 'processing': + return 'microphone'; + + case 'bot_speaking': + return 'audio-playing'; + + default: + return 'microphone'; + } + }, [speechState]); + + const ariaLabel = localize( + recording ? 'SPEECH_INPUT_MICROPHONE_BUTTON_OPEN_ALT' : 'SPEECH_INPUT_MICROPHONE_BUTTON_CLOSE_ALT' + ); + + const isBotSpeaking = speechState === 'bot_speaking'; + const isUserSpeaking = speechState === 'user_speaking'; + + return ( + + + + ); +} + +MicrophoneToolbarButton.displayName = 'SendBox.MicrophoneToolbarButton'; + +export default memo(MicrophoneToolbarButton); diff --git a/packages/fluent-theme/src/components/sendBox/SendBox.module.css b/packages/fluent-theme/src/components/sendBox/SendBox.module.css index 473a71e55e..ce5de5e2a1 100644 --- a/packages/fluent-theme/src/components/sendBox/SendBox.module.css +++ b/packages/fluent-theme/src/components/sendBox/SendBox.module.css @@ -77,6 +77,15 @@ } } +/* Speech-to-speech variant: disable focus animations and pointer events on the main box. */ +:global(.webchat-fluent) .sendbox__sendbox.sendbox__sendbox--speech { + &::after, + &:focus-within::after { + display: none; + } +} + + :global(.webchat-fluent) .sendbox__attachment-bar:global(.send-box-attachment-bar) { :global(.send-box-attachment-bar__box) { gap: var(--webchat-spacingVerticalXS) var(--webchat-spacingHorizontalXS); diff --git a/packages/fluent-theme/src/components/sendBox/SendBox.tsx b/packages/fluent-theme/src/components/sendBox/SendBox.tsx index 77c01d62b2..427a62e33a 100644 --- a/packages/fluent-theme/src/components/sendBox/SendBox.tsx +++ b/packages/fluent-theme/src/components/sendBox/SendBox.tsx @@ -4,6 +4,7 @@ import React, { memo, ReactNode, useCallback, + useMemo, useRef, useState, type FormEventHandler, @@ -19,12 +20,14 @@ import { SuggestedActions } from '../suggestedActions'; import { TelephoneKeypadSurrogate, useTelephoneKeypadShown, type DTMF } from '../telephoneKeypad'; import AddAttachmentButton from './AddAttachmentButton'; import ErrorMessage from './ErrorMessage'; +import useSpeechStateMessage from './private/useSpeechStateMessage'; import useSubmitError from './private/useSubmitError'; import useTranscriptNavigation from './private/useTranscriptNavigation'; import useUniqueId from './private/useUniqueId'; import styles from './SendBox.module.css'; import TelephoneKeypadToolbarButton from './TelephoneKeypadToolbarButton'; import { Toolbar, ToolbarButton, ToolbarSeparator } from './Toolbar'; +import MicrophoneToolbarButton from './MicrophoneToolbarButton'; const { useFocus, @@ -35,7 +38,8 @@ const { useSendBoxValue, useSendMessage, useStyleOptions, - useUIState + useUIState, + usePostActivity } = hooks; const { AttachmentBar, TextArea } = Components; @@ -48,7 +52,7 @@ type Props = Readonly<{ }>; function SendBox(props: Props) { - const [{ disableFileUpload, hideTelephoneKeypadButton, maxMessageLength }] = useStyleOptions(); + const [{ disableFileUpload, hideTelephoneKeypadButton, maxMessageLength, showMicrophoneButton }] = useStyleOptions(); const [attachments, setAttachments] = useSendBoxAttachments(); const [globalMessage, setGlobalMessage] = useSendBoxValue(); const [localMessage, setLocalMessage] = useState(''); @@ -62,6 +66,8 @@ function SendBox(props: Props) { const makeThumbnail = useMakeThumbnail(); const sendMessage = useSendMessage(); const setFocus = useFocus(); + const postActivity = usePostActivity(); + const speechStateMessage = useSpeechStateMessage(); const message = props.isPrimary ? globalMessage : localMessage; const setMessage = props.isPrimary ? setGlobalMessage : setLocalMessage; @@ -69,8 +75,15 @@ function SendBox(props: Props) { const [errorMessage, commitLatestError] = useSubmitError({ message, attachments }); const isMessageLengthExceeded = !!maxMessageLength && message.length > maxMessageLength; - const shouldShowMessageLength = - !isBlueprint && !telephoneKeypadShown && maxMessageLength && isFinite(maxMessageLength); + const shouldShowMessageLength = useMemo( + () => + !isBlueprint && + !telephoneKeypadShown && + !!maxMessageLength && + isFinite(maxMessageLength) && + !showMicrophoneButton, + [isBlueprint, telephoneKeypadShown, maxMessageLength, showMicrophoneButton] + ); const shouldShowTelephoneKeypad = !isBlueprint && telephoneKeypadShown; useRegisterFocusSendBox( @@ -171,9 +184,23 @@ function SendBox(props: Props) { ); const handleTelephoneKeypadButtonClick = useCallback( - // TODO: We need more official way of sending DTMF. - (dtmf: DTMF) => sendMessage(`/DTMFKey ${dtmf}`), - [sendMessage] + (dtmf: DTMF) => { + if (showMicrophoneButton) { + postActivity({ + type: 'event', + name: 'dtmf', + value: { + dtmf: { + value: dtmf + } + } + } as any); + } else { + // TODO: We need more official way of sending DTMF. + sendMessage(`/DTMFKey ${dtmf}`); + } + }, + [postActivity, sendMessage, showMicrophoneButton] ); const handleTranscriptNavigation = useTranscriptNavigation(); @@ -196,7 +223,9 @@ function SendBox(props: Props) { >
@@ -207,7 +236,10 @@ function SendBox(props: Props) { data-testid={testIds.sendBoxTextBox} hidden={shouldShowTelephoneKeypad} onInput={handleMessageChange} - placeholder={props.placeholder ?? localize('TEXT_INPUT_PLACEHOLDER')} + placeholder={ + props.placeholder ?? (showMicrophoneButton ? speechStateMessage : localize('TEXT_INPUT_PLACEHOLDER')) + } + readOnly={showMicrophoneButton} ref={inputRef} value={message} /> @@ -240,14 +272,17 @@ function SendBox(props: Props) { {!hideTelephoneKeypadButton && } {!disableFileUpload && } - - - + {showMicrophoneButton && } + {!showMicrophoneButton && ( + + + + )}
{!disableFileUpload && } diff --git a/packages/fluent-theme/src/components/sendBox/Toolbar.module.css b/packages/fluent-theme/src/components/sendBox/Toolbar.module.css index c60a842bb9..70ebedfd4a 100644 --- a/packages/fluent-theme/src/components/sendBox/Toolbar.module.css +++ b/packages/fluent-theme/src/components/sendBox/Toolbar.module.css @@ -46,6 +46,50 @@ color: var(--webchat-colorNeutralForegroundDisabled); cursor: not-allowed; } + + &.sendbox__toolbar-button--active { + --webchat__toolbar-button--pulse-start-size: 30px; + --webchat__toolbar-button--pulse-end-size: 58px; + --webchat__toolbar-button--pulse-opacity: 0.5; + --webchat__toolbar-button--background-gradient-opacity: 0.15; + + background-color: var(--webchat-colorNeutralForeground2BrandSelected); + border-radius: 50%; + color: var(--webchat-colorNeutralBackground1); + + @media (hover: hover) { + &:hover { + color: var(--webchat-colorNeutralBackground1); + } + } + } + + &.sendbox__toolbar-button--with-pulse::before { + animation: toolbar-button__pulse 1s linear infinite alternate; + background-color: var(--webchat-colorNeutralForeground2BrandSelected); + border-radius: 50%; + content: ''; + height: var(--webchat__toolbar-button--pulse-start-size); + opacity: var(--webchat__toolbar-button--pulse-opacity); + position: absolute; + width: var(--webchat__toolbar-button--pulse-start-size); + } + + &.sendbox__toolbar-button--with-gradient::after { + background: linear-gradient( + 90deg, + var(--webchat-colorBrandForeground1, #0078d4) 0%, + color-mix(in srgb, var(--webchat-colorBrandForeground1, #0078d4), #2db4ff) 33%, + color-mix(in srgb, var(--webchat-colorBrandForeground1, #0078d4), #d660ff) 66%, + color-mix(in srgb, var(--webchat-colorBrandForeground1, #0078d4), #fea874) 100% + ); + border-radius: 50%; + content: ''; + height: var(--webchat__toolbar-button--pulse-end-size); + opacity: var(--webchat__toolbar-button--background-gradient-opacity); + position: absolute; + width: var(--webchat__toolbar-button--pulse-end-size); + } } :global(.webchat-fluent) .sendbox__toolbar-separator { @@ -59,3 +103,15 @@ display: none; } } + +@keyframes toolbar-button__pulse { + 0% { + height: var(--webchat__toolbar-button--pulse-start-size); + width: var(--webchat__toolbar-button--pulse-start-size); + } + + 100% { + height: var(--webchat__toolbar-button--pulse-end-size); + width: var(--webchat__toolbar-button--pulse-end-size); + } +} diff --git a/packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts b/packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts new file mode 100644 index 0000000000..462cf31183 --- /dev/null +++ b/packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts @@ -0,0 +1,28 @@ +import { hooks } from 'botframework-webchat'; +import { useMemo } from 'react'; + +const { useLocalizer, useSpeechToSpeech } = hooks; + +export default function useSpeechPlaceholder(): string { + const localize = useLocalizer(); + const [{ speechState }] = useSpeechToSpeech(); + return useMemo(() => { + switch (speechState) { + case 'idle': + return localize('TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER'); + + case 'listening': + case 'user_speaking': + return localize('TEXT_INPUT_SPEECH_LISTENING_PLACEHOLDER'); + + case 'processing': + return localize('TEXT_INPUT_SPEECH_PROCESSING_PLACEHOLDER'); + + case 'bot_speaking': + return localize('TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER'); + + default: + return localize('TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER'); + } + }, [speechState, localize]); +} diff --git a/packages/fluent-theme/src/testIds.ts b/packages/fluent-theme/src/testIds.ts index 3eac5e83cf..ce6305a3ed 100644 --- a/packages/fluent-theme/src/testIds.ts +++ b/packages/fluent-theme/src/testIds.ts @@ -2,6 +2,7 @@ const testIds = { preChatMessageActivityStarterPromptsCardAction: 'pre-chat message activity starter prompts card action', sendBoxContainer: 'send box container', sendBoxDropZone: 'send box drop zone', + sendBoxMicrophoneButton: 'send box microphone button', sendBoxSendButton: 'send box send button', sendBoxSuggestedAction: 'send box suggested action', sendBoxTextBox: 'send box text area', From af1dd65213184af9746025e06cebdd6747c3e0c4 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Thu, 15 Jan 2026 15:31:36 +0000 Subject: [PATCH 08/32] test case added --- .../esm/speechToSpeech/mockAudioPlayback.js | 23 ++ .../esm/speechToSpeech/mockMediaDevices.js | 32 ++ __tests__/html2/speechToSpeech/barge.in.html | 184 ++++++++++ .../basic.sendbox.with.mic.html | 61 ++++ .../html2/speechToSpeech/csp.recording.html | 138 ++++++++ .../html2/speechToSpeech/dtmf.input.html | 207 ++++++++++++ .../html2/speechToSpeech/happy.path.html | 172 ++++++++++ .../html2/speechToSpeech/multiple.turns.html | 317 ++++++++++++++++++ .../outgoing.audio..interval.html | 137 ++++++++ packages/api/src/localization/en-US.json | 8 +- .../testHelpers/createDirectLineEmulator.js | 44 +++ 11 files changed, 1319 insertions(+), 4 deletions(-) create mode 100644 __tests__/assets/esm/speechToSpeech/mockAudioPlayback.js create mode 100644 __tests__/assets/esm/speechToSpeech/mockMediaDevices.js create mode 100644 __tests__/html2/speechToSpeech/barge.in.html create mode 100644 __tests__/html2/speechToSpeech/basic.sendbox.with.mic.html create mode 100644 __tests__/html2/speechToSpeech/csp.recording.html create mode 100644 __tests__/html2/speechToSpeech/dtmf.input.html create mode 100644 __tests__/html2/speechToSpeech/happy.path.html create mode 100644 __tests__/html2/speechToSpeech/multiple.turns.html create mode 100644 __tests__/html2/speechToSpeech/outgoing.audio..interval.html diff --git a/__tests__/assets/esm/speechToSpeech/mockAudioPlayback.js b/__tests__/assets/esm/speechToSpeech/mockAudioPlayback.js new file mode 100644 index 0000000000..f7bba9cbf5 --- /dev/null +++ b/__tests__/assets/esm/speechToSpeech/mockAudioPlayback.js @@ -0,0 +1,23 @@ +/* global AudioContext */ + +/** + * Mocks AudioContext.createBuffer to return buffers with minimum duration. + * + */ +export function setupMockAudioPlayback() { + const originalCreateBuffer = AudioContext.prototype.createBuffer; + + AudioContext.prototype.createBuffer = function (numberOfChannels, length, sampleRate) { + // Ensure minimum duration of 0.5 seconds for testing + const minSamples = Math.floor(sampleRate * 0.5); + const actualLength = Math.max(length, minSamples); + + return originalCreateBuffer.call(this, numberOfChannels, actualLength, sampleRate); + }; + + return { + restore: () => { + AudioContext.prototype.createBuffer = originalCreateBuffer; + } + }; +} diff --git a/__tests__/assets/esm/speechToSpeech/mockMediaDevices.js b/__tests__/assets/esm/speechToSpeech/mockMediaDevices.js new file mode 100644 index 0000000000..d4d25abbb4 --- /dev/null +++ b/__tests__/assets/esm/speechToSpeech/mockMediaDevices.js @@ -0,0 +1,32 @@ +/* global AudioContext, navigator */ + +/** + * Mocks navigator.mediaDevices.getUserMedia for testing speechToSpeech functionality. + */ +export function setupMockMediaDevices() { + if (!navigator.mediaDevices) { + navigator.mediaDevices = {}; + } + + navigator.mediaDevices.getUserMedia = constraints => { + const audioContext = new AudioContext({ sampleRate: constraints?.audio?.sampleRate || 24000 }); + const oscillator = audioContext.createOscillator(); + const destination = audioContext.createMediaStreamDestination(); + + oscillator.connect(destination); + oscillator.start(); + + const { stream } = destination; + + stream.getTracks().forEach(track => { + const originalStop = track.stop.bind(track); + track.stop = () => { + oscillator.stop(); + audioContext.close(); + originalStop(); + }; + }); + + return stream; + }; +} diff --git a/__tests__/html2/speechToSpeech/barge.in.html b/__tests__/html2/speechToSpeech/barge.in.html new file mode 100644 index 0000000000..9db66cc9ff --- /dev/null +++ b/__tests__/html2/speechToSpeech/barge.in.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + +
+ + + + + diff --git a/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html b/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html new file mode 100644 index 0000000000..48c020fa40 --- /dev/null +++ b/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html @@ -0,0 +1,61 @@ + + + + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/speechToSpeech/csp.recording.html b/__tests__/html2/speechToSpeech/csp.recording.html new file mode 100644 index 0000000000..95e7929196 --- /dev/null +++ b/__tests__/html2/speechToSpeech/csp.recording.html @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + +
+ + + + diff --git a/__tests__/html2/speechToSpeech/dtmf.input.html b/__tests__/html2/speechToSpeech/dtmf.input.html new file mode 100644 index 0000000000..17000d8797 --- /dev/null +++ b/__tests__/html2/speechToSpeech/dtmf.input.html @@ -0,0 +1,207 @@ + + + + + + + + + + + + + +
+ + + + + diff --git a/__tests__/html2/speechToSpeech/happy.path.html b/__tests__/html2/speechToSpeech/happy.path.html new file mode 100644 index 0000000000..768c178dfb --- /dev/null +++ b/__tests__/html2/speechToSpeech/happy.path.html @@ -0,0 +1,172 @@ + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/__tests__/html2/speechToSpeech/multiple.turns.html b/__tests__/html2/speechToSpeech/multiple.turns.html new file mode 100644 index 0000000000..856c17675c --- /dev/null +++ b/__tests__/html2/speechToSpeech/multiple.turns.html @@ -0,0 +1,317 @@ + + + + + + + + + + + + + +
+ + + + + diff --git a/__tests__/html2/speechToSpeech/outgoing.audio..interval.html b/__tests__/html2/speechToSpeech/outgoing.audio..interval.html new file mode 100644 index 0000000000..c9b66026d8 --- /dev/null +++ b/__tests__/html2/speechToSpeech/outgoing.audio..interval.html @@ -0,0 +1,137 @@ + + + + + + + + + + + + + +
+ + + + + diff --git a/packages/api/src/localization/en-US.json b/packages/api/src/localization/en-US.json index 5adafb7f9e..87dcda87ad 100644 --- a/packages/api/src/localization/en-US.json +++ b/packages/api/src/localization/en-US.json @@ -131,13 +131,13 @@ "TEXT_INPUT_ALT": "Message input box", "_TEXT_INPUT_ALT.comment": "This is for screen reader for the label of the message input box.", "TEXT_INPUT_PLACEHOLDER": "Type your message", - "TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER": "Start talking…", + "TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER": "Start talking...", "_TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and in idle state.", - "TEXT_INPUT_SPEECH_LISTENING_PLACEHOLDER": "Listening…", + "TEXT_INPUT_SPEECH_LISTENING_PLACEHOLDER": "Listening...", "_TEXT_INPUT_SPEECH_LISTENING_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and actively listening to user speech.", - "TEXT_INPUT_SPEECH_PROCESSING_PLACEHOLDER": "Processing…", + "TEXT_INPUT_SPEECH_PROCESSING_PLACEHOLDER": "Processing...", "_TEXT_INPUT_SPEECH_PROCESSING_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and processing the user's speech input.", - "TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER": "Speak to interrupt…", + "TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER": "Talk to interrupt...", "_TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER.comment": "This is the placeholder text shown in the message input box when speech-to-speech is enabled and the bot is speaking.", "TEXT_INPUT_SEND_BUTTON_ALT": "Send", "TEXT_INPUT_SPEAK_BUTTON_ALT": "Speak", diff --git a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js index 5ff5cca2b0..1a564b9923 100644 --- a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js +++ b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js @@ -42,6 +42,27 @@ export default function createDirectLineEmulator({ autoConnect = true, ponyfill const postActivity = outgoingActivity => { const returnPostActivityWithResolvers = withResolvers(); + // Auto-handle voice activities (continuous sending by mic) without requiring actPostActivity + // Voice activities are fire-and-forget and don't echo back + if ( + outgoingActivity.type === 'event' && + outgoingActivity.value && + (outgoingActivity.value.voice || outgoingActivity.value.dtmf) + ) { + const id = uniqueId(); + + return new Observable(observer => { + (function () { + try { + observer.next(id); + observer.complete(); + } catch (error) { + observer.error(error); + } + })(); + }); + } + const deferred = postActivityCallDeferreds.shift(); if (!deferred) { @@ -152,6 +173,29 @@ export default function createDirectLineEmulator({ autoConnect = true, ponyfill 1000 )); }, + emulateIncomingVoiceActivity: async (activity, { skipWait } = {}) => { + activity = updateIn(activity, ['from', 'role'], role => role || 'bot'); + activity = updateIn(activity, ['id'], id => id || uniqueId()); + activity = updateIn(activity, ['timestamp'], timestamp => + typeof timestamp === 'number' + ? new Date(now + timestamp).toISOString() + : 'timestamp' in activity + ? timestamp + : getTimestamp() + ); + activity = updateIn(activity, ['type'], type => type || 'event'); + + const { id } = activity; + + activityDeferredObservable.next(activity); + + skipWait || + (await became( + 'incoming voice activity appears in the voiceActivities store', + () => store.getState().voiceActivities?.find(activity => activity.id === id), + 1000 + )); + }, emulateOutgoingActivity: (activity, options) => { if (typeof activity === 'string') { activity = { From 8fac1b320790752e618798e1eefe7ecd37d15058 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Fri, 16 Jan 2026 09:51:01 +0000 Subject: [PATCH 09/32] screenshot added --- __tests__/html2/speechToSpeech/barge.in.html | 6 ++++ .../basic.sendbox.with.mic.html | 3 ++ .../basic.sendbox.with.mic.html.snap-1.png | Bin 0 -> 4126 bytes .../html2/speechToSpeech/dtmf.input.html | 7 +++++ .../speechToSpeech/dtmf.input.html.snap-1.png | Bin 0 -> 25262 bytes .../speechToSpeech/dtmf.input.html.snap-2.png | Bin 0 -> 20058 bytes .../html2/speechToSpeech/happy.path.html | 8 ++++++ .../speechToSpeech/happy.path.html.snap-1.png | Bin 0 -> 9172 bytes .../speechToSpeech/happy.path.html.snap-2.png | Bin 0 -> 12533 bytes .../html2/speechToSpeech/multiple.turns.html | 27 ++++++++++++++++++ .../multiple.turns.html.snap-1.png | Bin 0 -> 22155 bytes .../SpeechToSpeech/SpeechToSpeechComposer.tsx | 2 +- .../activity/PartGroupingDecorator.tsx | 5 ++-- .../src/components/sendBox/SendBox.tsx | 8 ++++-- 14 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 __tests__/html2/speechToSpeech/basic.sendbox.with.mic.html.snap-1.png create mode 100644 __tests__/html2/speechToSpeech/dtmf.input.html.snap-1.png create mode 100644 __tests__/html2/speechToSpeech/dtmf.input.html.snap-2.png create mode 100644 __tests__/html2/speechToSpeech/happy.path.html.snap-1.png create mode 100644 __tests__/html2/speechToSpeech/happy.path.html.snap-2.png create mode 100644 __tests__/html2/speechToSpeech/multiple.turns.html.snap-1.png diff --git a/__tests__/html2/speechToSpeech/barge.in.html b/__tests__/html2/speechToSpeech/barge.in.html index 9db66cc9ff..728bab53fd 100644 --- a/__tests__/html2/speechToSpeech/barge.in.html +++ b/__tests__/html2/speechToSpeech/barge.in.html @@ -98,6 +98,9 @@ 1000 ); + // VERIFY: Mic button has pulse animation during bot speaking + expect(micButton.className).toMatch(/with-pulse/); + // User barges in (server detects user speech) await directLine.emulateIncomingVoiceActivity({ type: 'event', @@ -113,6 +116,9 @@ 1000 ); + // VERIFY: Mic button still has pulse animation during user speaking + expect(micButton.className).toMatch(/with-pulse/); + // Server processes the user's interrupted request await directLine.emulateIncomingVoiceActivity({ type: 'event', diff --git a/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html b/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html index 48c020fa40..3066871343 100644 --- a/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html +++ b/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html @@ -55,6 +55,9 @@ // THEN: Send button should NOT be present const sendButton = document.querySelector(`[data-testid="${testIds.sendBoxSendButton}"]`); expect(sendButton).toBeFalsy(); + + // THEN: Should show sendbox with microphone and keypad buttons + await host.snapshot('local'); }); diff --git a/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html.snap-1.png b/__tests__/html2/speechToSpeech/basic.sendbox.with.mic.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..de8e85d3d3a40c129ed18bd25caabc0f2fb5d3fe GIT binary patch literal 4126 zcmeHKX*iqd8V*jSt(KXis;SVK(~T;b>Jf=8Ra(1&U1F?;WK7Q6eWfSa^{#F z>G;t0%YlQxEWo?pG!rtR*;&}*DJ4__dXt5Q9rSPc5Dxo6vx>B_7tpG8%H6D_r$Q2M1k&s1yw&qW|m1hL;5b z!Rh2Z?|D+qM6wgP&u@8-r}n&b^-EzMJa}y6yorEApdUpu^Gf6ztspa)nm`@LR0(<- z0aXAimnC?ScSt$O`I?%6_lY?4&_EHeQe5mmN{9uW~y<=b7+h+HD4ny;)(Q%wlPw%PE;uODpiT%W2d zUp}aqFFzGrUy}?|)AEuPY2;xa=)s+;hkiv!1~0Pa<-pMA8|$l0zz=kGcET9T7w{4G z;?OqDsC2jHg>KZw+7fp|G8_!v7duz?ITu3#5dc8twPVJipWY5&32OyucF~J$7nYR& zFuV&{m|hgQ25XXu0mQmsqmhv2>H#m4D^oo+14FY)y43UiWo{`cDI{$CHMe)rsF6_q z<0UR(BlFlr27nNFYHTQ|>Ncw!R^fYSyEWI<^h;+HXt1O{O zP!p0aykU^ZO5nyVjoO$iqhxdYQ%x&{MJ7U8FH`n=jTd76t!iG(Y#p(Xxy$?AgCE%h zbL#Urp+_M_f+oo3+w$U9{I^*Qqt$e%&z;E76Oxm>3*}hR|=wrg|31#Y3{jtH>3}(wIIl_34q_mrLh=N-K$ z#1^)EJG{@q8X$<;klW?aAo)$CS9Kt1*RsiIxC?Gkzz(16@LxmTvbD8sPE>)F-t8~U z@INWVt^wR0MQ5CMtAUpi3epCUi+zr;mmjZ(MNw*oIr$uD0dUqhGecJwfOi;*%a{jh zmb6OEi<7vuTSLMYK6h`(7P?arpYDhQhfK7`8_IM7@?vD;sVHZR=#fm!g5jJ%pJNk4SDd}r1;=noucSR}9zn6KE z5*T1Eok-&o1#fOC!RjU+g$>l?V1v%n816&*5R=H6uU~puA^5fBsrO`-BVS?-8GKS_ z*Lmmr{dT~6m7gm+zxvj9nTQ%Hy@7^|@#)BPShcOX(&FGrv7X zz7ZUzo1KKqek#Zy9(6k#)JweM)Wf=hm}_ho!X~?(V2GxCiTzNu&eCmW9DlptMVFW~ zjJjAqMNEl16%BS-P<~T06TAuUM_;S+v+A21@(@?EP|DUFccs_Lf6j2Z3EZouY zw`*rzsl4YR0aHyFAwSN}1{CGBYEAT1equ?kZ>yYVWdOUx(GK|x+GoC-P~WD<6|*fV zw%N|BKKu)<$q)^AU{Rc7K=-ln1bzRpk`*dvQrA8&T2Ne)m=$`0v_k_vlVUXXtxxgp z4)i2EX)D07=x0 z9DH=phWYwiC!oAm72mWZsV|MFqcA0}x&+JPso2Ko#fEDO6;10a6bc0yKKWlb+%C(2 z&(x*HO8F$Cz`>t@9G3WQ1z%|=gr<^#ssqe~G2f~I-mzy6g<)%90dMe(8Z`uZgig%8LP7zW@9O>srv}4!dlX$^mFYNU`^V!g-H>xl^x8e1KP0dz9wdI4=*98cO}X= za!?eM6WR&^qd+?t}H z`*c9tlF@855c%DG!0XGgO$_p#s{apztq z7nj;FK6Crj7N$3BI^AGy7*&q;Wx%3Z?x_LR4nc%?XT1V=b$(UxZ02&h8k19fd3t)< zWT71tXDmH6jFX6`sZB(iU=FQVK2i@ybf9d(-TJ`uAXBP%AV1#HU-ABJiXPlh0D(3( l?#5lT2Bv()Z{xiJ=&4no(mM411h4`+bIQ)D;-vTWKLBwt;x_;Q literal 0 HcmV?d00001 diff --git a/__tests__/html2/speechToSpeech/dtmf.input.html b/__tests__/html2/speechToSpeech/dtmf.input.html index 17000d8797..c8027da31b 100644 --- a/__tests__/html2/speechToSpeech/dtmf.input.html +++ b/__tests__/html2/speechToSpeech/dtmf.input.html @@ -104,6 +104,9 @@ expect(key2).toBeTruthy(); expect(key3).toBeTruthy(); expect(key4).toBeTruthy(); + + // THEN: Should show keypad open + await host.snapshot('local'); await host.click(key1); await host.click(key2); @@ -199,6 +202,10 @@ const finalActivities = pageElements.activityContents(); expect(finalActivities[5]).toHaveProperty('textContent', 'Thank you. Your PIN has been verified.'); + // THEN: Should show DTMF conversation + await pageConditions.scrollToBottomCompleted(); + await host.snapshot('local'); + await host.click(micButton); }); diff --git a/__tests__/html2/speechToSpeech/dtmf.input.html.snap-1.png b/__tests__/html2/speechToSpeech/dtmf.input.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..ff359efb4982e4c25d2157ee59c129b9f78a2d78 GIT binary patch literal 25262 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/speechToSpeech/dtmf.input.html.snap-2.png b/__tests__/html2/speechToSpeech/dtmf.input.html.snap-2.png new file mode 100644 index 0000000000000000000000000000000000000000..ec4f726d75e5e6ef2907901fec601d376fb39c32 GIT binary patch literal 20058 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 S%SGux5e83JKbLh*2~7Y6aFM|P literal 0 HcmV?d00001 diff --git a/__tests__/html2/speechToSpeech/happy.path.html b/__tests__/html2/speechToSpeech/happy.path.html index 768c178dfb..caea07fde9 100644 --- a/__tests__/html2/speechToSpeech/happy.path.html +++ b/__tests__/html2/speechToSpeech/happy.path.html @@ -110,6 +110,10 @@ 'What is the weather today?' ); + // THEN: Should show user message + await pageConditions.scrollToBottomCompleted(); + await host.snapshot('local'); + // WHEN: Server sends audio chunks await directLine.emulateIncomingVoiceActivity({ type: 'event', @@ -166,6 +170,10 @@ 1000 ); + // THEN: Should show happy path conversation + await pageConditions.scrollToBottomCompleted(); + await host.snapshot('local'); + }); diff --git a/__tests__/html2/speechToSpeech/happy.path.html.snap-1.png b/__tests__/html2/speechToSpeech/happy.path.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f9e16e326a8fa056e0042660c7d4cb3e8401174c GIT binary patch literal 9172 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/speechToSpeech/happy.path.html.snap-2.png b/__tests__/html2/speechToSpeech/happy.path.html.snap-2.png new file mode 100644 index 0000000000000000000000000000000000000000..8c2eee98a71f9e076992c77ab7a7effb6547e828 GIT binary patch literal 12533 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/speechToSpeech/multiple.turns.html b/__tests__/html2/speechToSpeech/multiple.turns.html index 856c17675c..1e2650e4b1 100644 --- a/__tests__/html2/speechToSpeech/multiple.turns.html +++ b/__tests__/html2/speechToSpeech/multiple.turns.html @@ -73,6 +73,12 @@ 1000 ); + // VERIFY: Mic button shows microphone icon and is active (but no pulse in listening state) + const micIcon = micButton.querySelector('[class*="icon--"]'); + expect(micIcon.className).toMatch(/icon--microphone/); + expect(micButton.className).toMatch(/active/); + expect(micButton.className).not.toMatch(/with-pulse/); + // ===== TURN 1: User speaks ===== // User speech detected await directLine.emulateIncomingVoiceActivity({ @@ -89,6 +95,10 @@ 1000 ); + // VERIFY: Mic button has pulse AND gradient during user speaking + expect(micButton.className).toMatch(/with-pulse/); + expect(micButton.className).toMatch(/with-gradient/); + // User speech processing await directLine.emulateIncomingVoiceActivity({ type: 'event', @@ -141,6 +151,11 @@ 1000 ); + // VERIFY: Mic button shows audio-playing icon with pulse animation during bot speaking + expect(micButton.querySelector('[class*="icon--"]').className).toMatch(/icon--audio-playing/); + expect(micButton.className).toMatch(/with-pulse/); + expect(micButton.className).not.toMatch(/with-gradient/); + // Bot transcript appears await directLine.emulateIncomingActivity({ type: 'event', @@ -246,6 +261,13 @@ value: { voice: { bot_state: 'voice.request.detected' } } }); + await directLine.emulateIncomingVoiceActivity({ + type: 'event', + name: 'session.update', + from: { role: 'bot' }, + value: { voice: { bot_state: 'voice.request.processing' } } + }); + await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', @@ -274,6 +296,7 @@ value: { voice: { contentUrl: 'AAAAAA==' } } }); + console.log(textArea.getAttribute('placeholder')); // Verify: State is "bot_speaking" await pageConditions.became( 'State: bot_speaking (Turn 3)', @@ -311,6 +334,10 @@ () => micButton.getAttribute('aria-label')?.includes('Microphone off'), 1000 ); + + // THEN: Should show multi-turn conversation + await pageConditions.scrollToBottomCompleted(); + await host.snapshot('local'); }); diff --git a/__tests__/html2/speechToSpeech/multiple.turns.html.snap-1.png b/__tests__/html2/speechToSpeech/multiple.turns.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..14a82218a63b3c07596e02412c85c134fad2bef0 GIT binary patch literal 22155 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 literal 0 HcmV?d00001 diff --git a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx index 634545482d..0c46ec4e07 100644 --- a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx +++ b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx @@ -104,7 +104,7 @@ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> handleVoiceActivity(activity); } - if (isPlaying && speechState !== 'bot_speaking') { + if (isPlaying && speechState !== 'bot_speaking' && speechState !== 'user_speaking') { setSpeechState('bot_speaking'); } else if (!isPlaying && speechState === 'bot_speaking') { setSpeechState('listening'); diff --git a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx index 77ba773625..3711327f09 100644 --- a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx +++ b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx @@ -38,9 +38,10 @@ function PartGroupingDecorator(props: PartGroupingDecoratorProps) { ); // S2S-both user and bot transcript comes from server (RT-LLM) hence need to check role explicitly. + // voiceActivityRole takes precedence over from.role since S2S activities always come from 'bot' const voiceActivityRole = activity && getVoiceActivityRole(activity); - const isFromUser = activity?.from?.role === 'user' || voiceActivityRole === 'user'; - const isFromBot = activity?.from?.role === 'bot' || voiceActivityRole === 'bot'; + const isFromUser = voiceActivityRole ? voiceActivityRole === 'user' : activity?.from?.role === 'user'; + const isFromBot = voiceActivityRole ? voiceActivityRole === 'bot' : activity?.from?.role === 'bot'; return (
{ - if (showMicrophoneButton) { + if (recording) { postActivity({ type: 'event', name: 'dtmf', @@ -200,7 +202,7 @@ function SendBox(props: Props) { sendMessage(`/DTMFKey ${dtmf}`); } }, - [postActivity, sendMessage, showMicrophoneButton] + [postActivity, recording, sendMessage] ); const handleTranscriptNavigation = useTranscriptNavigation(); From 0dcbd6376161d05a004ac14b302f8bf195bd232d Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Tue, 20 Jan 2026 13:39:19 +0000 Subject: [PATCH 10/32] refactor --- __tests__/html2/speechToSpeech/barge.in.html | 14 +++---- .../html2/speechToSpeech/dtmf.input.html | 12 +++--- .../speechToSpeech/dtmf.input.html.snap-1.png | Bin 25262 -> 25741 bytes .../speechToSpeech/dtmf.input.html.snap-2.png | Bin 20058 -> 24351 bytes .../html2/speechToSpeech/happy.path.html | 35 ++++++++++++----- .../speechToSpeech/happy.path.html.snap-2.png | Bin 12533 -> 13726 bytes .../html2/speechToSpeech/multiple.turns.html | 36 +++++++++--------- .../multiple.turns.html.snap-1.png | Bin 22155 -> 26857 bytes ...rval.html => outgoing.audio.interval.html} | 15 ++++---- .../ActivityBorderDecorator.tsx | 7 +++- .../ActivityBorderDecoratorRequestContext.ts | 10 +++++ packages/api/src/localization/en-US.json | 2 + .../SpeechToSpeech/SpeechToSpeechComposer.tsx | 16 ++++---- packages/core/src/types/WebChatActivity.ts | 1 + .../getVoiceActivityRole.spec.ts | 4 +- .../voiceActivity/getVoiceActivityRole.ts | 4 +- .../getVoiceActivityText.spec.ts | 8 ++-- .../voiceActivity/getVoiceActivityText.ts | 2 +- .../voiceActivity/isVoiceActivity.spec.ts | 14 +++---- .../utils/voiceActivity/isVoiceActivity.ts | 8 ++-- .../isVoiceTranscriptActivity.spec.ts | 18 ++++----- .../isVoiceTranscriptActivity.ts | 4 +- .../VoiceTranscriptActivityStatus.module.css | 20 ++++++++++ .../VoiceTranscriptActivityStatus.tsx | 36 ++++++++++++++++++ .../sendBox/MicrophoneToolbarButton.tsx | 22 ++--------- .../src/components/sendBox/SendBox.tsx | 2 +- .../src/private/FluentThemeProvider.tsx | 31 ++++++++++++++- .../testHelpers/createDirectLineEmulator.js | 4 +- 28 files changed, 214 insertions(+), 111 deletions(-) rename __tests__/html2/speechToSpeech/{outgoing.audio..interval.html => outgoing.audio.interval.html} (90%) create mode 100644 packages/fluent-theme/src/components/activityStatus/VoiceTranscriptActivityStatus.module.css create mode 100644 packages/fluent-theme/src/components/activityStatus/VoiceTranscriptActivityStatus.tsx diff --git a/__tests__/html2/speechToSpeech/barge.in.html b/__tests__/html2/speechToSpeech/barge.in.html index 728bab53fd..b229c837b4 100644 --- a/__tests__/html2/speechToSpeech/barge.in.html +++ b/__tests__/html2/speechToSpeech/barge.in.html @@ -81,14 +81,14 @@ type: 'event', name: 'stream.chunk', from: { role: 'bot' }, - value: { voice: { contentUrl: 'AAAAAA==' } } + payload: { voice: { content: 'AAAAAA==' } } }); await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'stream.chunk', from: { role: 'bot' }, - value: { voice: { contentUrl: 'AAAAAA==' } } + payload: { voice: { content: 'AAAAAA==' } } }); // VERIFY: State is "bot_speaking" (isPlaying = true) @@ -106,7 +106,7 @@ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.request.detected' } } + payload: { voice: { session: 'request.detected' } } }); // VERIFY: State changes to "user_speaking" - bot audio stopped @@ -124,7 +124,7 @@ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.request.processing' } } + payload: { voice: { session: 'request.processing' } } }); // VERIFY: State is "processing" @@ -140,7 +140,7 @@ name: 'stream.end', from: { role: 'bot' }, text: 'Stop! Change my destination.', - value: { voice: { transcription: 'Stop! Change my destination.', origin: 'user' } } + payload: { voice: { transcription: 'Stop! Change my destination.', origin: 'user' } } }); await pageConditions.numActivitiesShown(1); @@ -150,7 +150,7 @@ type: 'event', name: 'stream.chunk', from: { role: 'bot' }, - value: { voice: { contentUrl: 'AAAAAA==' } } + payload: { voice: { content: 'AAAAAA==' } } }); // VERIFY: State is "bot_speaking" again @@ -166,7 +166,7 @@ name: 'stream.end', from: { role: 'bot' }, text: 'Sure, where would you like to go instead?', - value: { voice: { transcription: 'Sure, where would you like to go instead?', origin: 'agent' } } + payload: { voice: { transcription: 'Sure, where would you like to go instead?', origin: 'agent' } } }); await pageConditions.numActivitiesShown(2); diff --git a/__tests__/html2/speechToSpeech/dtmf.input.html b/__tests__/html2/speechToSpeech/dtmf.input.html index c8027da31b..ec431f5619 100644 --- a/__tests__/html2/speechToSpeech/dtmf.input.html +++ b/__tests__/html2/speechToSpeech/dtmf.input.html @@ -71,7 +71,7 @@ name: 'stream.end', from: { role: 'bot' }, text: 'Please enter your 4-digit PIN using your keypad.', - value: { + payload: { voice: { transcription: 'Please enter your 4-digit PIN using your keypad.', origin: 'agent' @@ -133,7 +133,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: '/DTMFKey 1', origin: 'user' @@ -144,7 +144,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: '/DTMFKey 2', origin: 'user' @@ -155,7 +155,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: '/DTMFKey 3', origin: 'user' @@ -166,7 +166,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: '/DTMFKey 4', origin: 'user' @@ -189,7 +189,7 @@ type: 'event', name: 'stream.end', from: { role: 'bot' }, - value: { + payload: { voice: { transcription: 'Thank you. Your PIN has been verified.', origin: 'agent' diff --git a/__tests__/html2/speechToSpeech/dtmf.input.html.snap-1.png b/__tests__/html2/speechToSpeech/dtmf.input.html.snap-1.png index ff359efb4982e4c25d2157ee59c129b9f78a2d78..c29b07065a0ad478f19cf01784cfe8ca5e5dfdab 100644 GIT binary patch literal 25741 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 literal 25262 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 diff --git a/__tests__/html2/speechToSpeech/dtmf.input.html.snap-2.png b/__tests__/html2/speechToSpeech/dtmf.input.html.snap-2.png index ec4f726d75e5e6ef2907901fec601d376fb39c32..be9f100b5436ff460d71ebc1826263283cac526a 100644 GIT binary patch literal 24351 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 literal 20058 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 S%SGux5e83JKbLh*2~7Y6aFM|P diff --git a/__tests__/html2/speechToSpeech/happy.path.html b/__tests__/html2/speechToSpeech/happy.path.html index caea07fde9..d3214c6e5f 100644 --- a/__tests__/html2/speechToSpeech/happy.path.html +++ b/__tests__/html2/speechToSpeech/happy.path.html @@ -72,9 +72,9 @@ await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'session.update', - value: { + payload: { voice: { - bot_state: 'voice.request.detected' + session: 'request.detected' } } }); @@ -84,9 +84,9 @@ await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'session.update', - value: { + payload: { voice: { - bot_state: 'voice.request.processing' + session: 'request.processing' } } }); @@ -95,7 +95,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: 'What is the weather today?', origin: 'user' @@ -118,9 +118,9 @@ await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'stream.chunk', - value: { + payload: { voice: { - contentUrl: 'AAAAAA==' + content: 'AAAAAA==' } } }); @@ -129,9 +129,9 @@ type: 'event', name: 'stream.chunk', from: { role: 'bot' }, - value: { + payload: { voice: { - contentUrl: 'AAAAAA==' + content: 'AAAAAA==' } } }); @@ -141,7 +141,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: 'The weather today is sunny with a high of 75 degrees.', origin: 'agent' @@ -157,6 +157,21 @@ expect(activities[0]).toHaveProperty('textContent', 'What is the weather today?'); expect(activities[1]).toHaveProperty('textContent', 'The weather today is sunny with a high of 75 degrees.'); + // THEN: Verify activity status for voice transcripts + const activityStatuses = pageElements.activityStatuses(); + expect(activityStatuses.length).toBe(2); + + // THEN: User transcript should have timestamp but NO "Agent" label + const userActivityStatus = activityStatuses[0]; + expect(userActivityStatus.innerText).not.toContain('Agent'); + expect(userActivityStatus.innerText).toContain('Just now'); + + // THEN: Bot transcript should have "Agent" label AND timestamp + const botActivityStatus = activityStatuses[1]; + expect(botActivityStatus.innerText).toContain('Agent'); + expect(botActivityStatus.innerText).toContain('|'); + expect(botActivityStatus.innerText).toContain('Just now'); + // WHEN: User stops recording by clicking microphone button again await host.click(micButton); diff --git a/__tests__/html2/speechToSpeech/happy.path.html.snap-2.png b/__tests__/html2/speechToSpeech/happy.path.html.snap-2.png index 8c2eee98a71f9e076992c77ab7a7effb6547e828..d3a3724d2230b699405411f97482fe773bd9d5fc 100644 GIT binary patch literal 13726 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 R7(4@!msWXE`uvsO{{k8tb}j$_ literal 12533 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 diff --git a/__tests__/html2/speechToSpeech/multiple.turns.html b/__tests__/html2/speechToSpeech/multiple.turns.html index 1e2650e4b1..f117e10072 100644 --- a/__tests__/html2/speechToSpeech/multiple.turns.html +++ b/__tests__/html2/speechToSpeech/multiple.turns.html @@ -85,7 +85,7 @@ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.request.detected' } } + payload: { voice: { session: 'request.detected' } } }); // Verify: State is "user_speaking" @@ -104,7 +104,7 @@ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.request.processing' } } + payload: { voice: { session: 'request.processing' } } }); // Verify: State is "processing" @@ -118,7 +118,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: 'What time is my flight?', origin: 'user' @@ -133,7 +133,7 @@ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.response.available' } } + payload: { voice: { session: 'response.available' } } }); // Bot sends audio chunk (triggers playback) @@ -141,7 +141,7 @@ type: 'event', name: 'stream.chunk', from: { role: 'bot' }, - value: { voice: { contentUrl: 'AAAAAA==' } } + payload: { voice: { content: 'AAAAAA==' } } }); // Verify: State is "bot_speaking" @@ -160,7 +160,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: 'Your flight departs at 3:45 PM from Gate B7.', origin: 'agent' @@ -181,14 +181,14 @@ await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'session.update', - value: { voice: { bot_state: 'voice.request.detected' } } + payload: { voice: { session: 'request.detected' } } }); await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.request.processing' } } + payload: { voice: { session: 'request.processing' } } }); // Verify: State is "processing" @@ -201,7 +201,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: 'Is there a delay?', origin: 'user' @@ -215,7 +215,7 @@ await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'session.update', - value: { voice: { bot_state: 'voice.response.available' } } + payload: { voice: { session: 'response.available' } } }); // Bot sends audio chunk @@ -223,7 +223,7 @@ type: 'event', name: 'stream.chunk', from: { role: 'bot' }, - value: { voice: { contentUrl: 'AAAAAA==' } } + payload: { voice: { content: 'AAAAAA==' } } }); // Verify: State is "bot_speaking" @@ -236,7 +236,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: 'No delays reported. Your flight is on time.', origin: 'agent' @@ -258,20 +258,20 @@ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.request.detected' } } + payload: { voice: { session: 'request.detected' } } }); await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.request.processing' } } + payload: { voice: { session: 'request.processing' } } }); await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: 'Thank you!', origin: 'user' @@ -286,14 +286,14 @@ type: 'event', name: 'session.update', from: { role: 'bot' }, - value: { voice: { bot_state: 'voice.response.available' } } + payload: { voice: { session: 'response.available' } } }); await directLine.emulateIncomingVoiceActivity({ type: 'event', name: 'stream.chunk', from: { role: 'bot' }, - value: { voice: { contentUrl: 'AAAAAA==' } } + payload: { voice: { content: 'AAAAAA==' } } }); console.log(textArea.getAttribute('placeholder')); @@ -307,7 +307,7 @@ await directLine.emulateIncomingActivity({ type: 'event', name: 'stream.end', - value: { + payload: { voice: { transcription: "You're welcome! Have a safe flight.", origin: 'agent' diff --git a/__tests__/html2/speechToSpeech/multiple.turns.html.snap-1.png b/__tests__/html2/speechToSpeech/multiple.turns.html.snap-1.png index 14a82218a63b3c07596e02412c85c134fad2bef0..65531ebe9c5278daea764f0d885944eb2d951ee2 100644 GIT binary patch literal 26857 zcmeFZWl)@7ww*&|h0s(>(G`PFFyCt}Ln4R~3-Z^Kc z&aIldRrkxS$+vVj-Osc4+H0+!tS3_CjXXLEF$xqE6uP2!c+V`{i%CPmjj$hyRQX?HuD{Pp+;dGmI@SA08ea4~wkbjI5UP)6>gA zq#}rGf*?{FQX7;ZMPZ$iNUG?e!H}=SD2P-te7G1=5jKpZA&?mrK_sf;Tu1Oh>Hqt| z|GPZ@-vvbkx>*cTQn3@KnZG9rVpYsEYH$aHEP5E17LTf@lM6pq&b%;4u#zRAL17>w zCI&4s0)>D$*fGLw8U;~aQjLOZB5p#J7;B3f?fs};)*FVMu6sFLjB^SL{{V{+d70*j z4-wOiC`oU}WkbKs^$LoJNQ=vqikV@dAl_j*Dt`U?HK^-~!_0*%?$Tn46eCPQxsMT3 z`(2rqt*oGxPttR+E?j5s+(9r+-gjc_WWrbsZ3)6P=h`@Ve#%u zk7Owp&QM9~W)Ti;Y~BRbBAsT}S2q>G{^!IFRYdvgDBk!yITU#xd_V+Qwu%tKL0mtu1QG!knGoIp;*t zl^eD)uHySYSLNGh*{q=-NxVD1F-P>LIu!g0ClRi-{()6d=CR=Q;hibVR3=93YL1{; z?oa{`969&*+JMzb87$a*b=m=ZI#p%KB*{_`%{n{LI|VVacFSwVET$ z|6qIjaU{UV-C+e686`BhnJJCd(7+J(`dMU!OssOQ#EUJs0}4J-s1NgqeC zIO{kZd9AKYzokXFY-R|50A|C~l&3fLez@Mc9y@-n<-dKjtorJB|wKYF4}F_++Q4#QIYF@D`KeJ~lz5&W=!uxeOEaQKGn=Ny~y z;y2B_f|=D{PgN&X(ul(t-P4+Zz9GeWp59mYMOO~h1!ippbQ2~i%hmQn5v?m5wrB@a zN2^ErT@OC9wXWv*xw%EfiZdSytW!BW zt*P4Jw=-FKBJaLGd(qd!(%B`2dAztm=fEbZugW3%74zs4X+i9xfa*+Zdng#&JeH4)XT8#=a_V!zGGPeEb_SSrzZEf!!_6gxdqx+b)@(uQs{>F7-?5e0+n}8 zR^XD@44N&L&FGsP2h*6Q+N`tKsW)einKer`(#5;pKfgxTzdv57nweg%MAVV~dA^fu z9rK7yp9_iJ8#hDGL%a<8@p$?0atw_~CP*qem=m$&66rk)x*GJAzNld@YDE#CuEM4II^2BHYky$cYfDGJ~wz= zCyrJ}Dai=9%ukK<%trk*As!otEPWi={${k9k7)p&AW!Oqk> zpB-EimGqsZe5cQD&vq-fV;^I!us^;*a5;i_JeT(*VIHsk0%fOk2x$vuFm#IH$KEK- zG%Q7#UC&_j?y%ZHA(Rz9ai!%^aeu!8YgV%dzD0}Z8}Q}w5uJm36Tz?EDG$v%oBiu5 z7ha}HO9z2kgj%S#+pK@^uZ;IZB%Li?<0RPqQ=qLZv zdBs>rvSvqwdTHL zCyZ^Wefc5Z)3-a-Vzdt3Hom(&kwMT$hs!h62fMGNFctwZyx}cAZQ!kGXMG1pw*S+U z#@SmJhow@j76cWYvpPpq@6Goy0{TAsFl-o7*zgT#pP!9>dX7ZJH(ufX{^@)mm+U^2 zElv&<439AsTk;8u2YUd4y$?Hy@$zUMKdje`*%l%?V4#`)haF?Q6wGnw0eOL zU83EW5-B4|?a(yS70uip$v?rx0+`7fF<05`got+%&)2C|!Iajd<`nCnmm^xfRCLSy zhF4trf;qlP>9%3AohnU2#-y-_;QJzse=`{qv{e#nf;FmGXz7L4W@av`Sor2&Q9!xp zi0aw+I@KK_ibGq5O-8z1It9L=&c@z15^yAh&=_3Ie5 zbgpi{{(8vs9f}E2jers|Ihpc;J3ogywCjBL5Uv|nRs^l8pI4LS%CwkFjfuBPM;pCE ze>9Tl!ym5Kub4I-iqu)6Ca9iSblRX}@DZy5&Ud|Jxl{Z)F_LXm@;j*T>54W?4j5k5 z2u8pw#p+;{&;;eHrJ&m1ul3R&Lb`C**lf`@zKQ_Wqt+*k!*n6jf4EvP`eGSS2@T`E+;Wv-934n?b|r zN|QScHML&-d&Abp67Apb=PNhXJA!q@1`=ud>=u4(_C(K>8;S@DHW;`0Jw4oT z=+_;_k_c2DH8^dR@`78ZVu~c-Fe(M_uD1sUBVvZ(lZyMy_w^y7Ojeo8%kqVs-9%xM zixz2opFG{@QZ-p=bnQn&LJAn9e0RA&p{lCNqE*VM`(t~iq{3*?<#_q0R49sJD_(?P(}(M$jg5`*(EF={K5ezasSckP)DEl7V>uG?oBI=aGsT+D zPEMXzf4m${4(2L8F>C%_thK%U4ekJ)n76^_j(aiz8^GT0C;|ckX=wEhYvkM(5ji;k zH!E+l{5m{j#i0kJg3toW>tDZrGshT3o)7Aqf@aqG*t33mD#*6PSy@@s6LjMPl|pU)->*`Y&5lD zz5-UhJ%S*dgAhYVGeUFx|4V{l8X0k|Lb89UFI#}N#qtmv<2%7Q-&gF8IeSP_ze1JD z>Oj$iRZ@J={2$lSl$ieh{-PqrtT*AX<2JQ}2eQaik%;uxF(QwBP~8n(P$}nBNyN6D zRBckxAjZcHc5=-_66%$$tQZR%-@SX+AFlA5z)}|nm3#J{O`mew21j-fvU(;G}gf}A48@8qQEb{$H&J(kR;J|j~MQxnpc^# ztQfp;bqG`g=yz6|7B)_VF@RE0eBXbQPg_=RCMjrUCOMR^EQ_QlZlXc`hf$N}drg;| zW6F&!BxxChx0+zm_-5r{B%@q7WeBYVZZysJO8m~h!7r+)Cn0+}R|S9{rP0QhpOOk6 z=$tczn5UM>3oQI*_$dQdqPxM9yz+J{e2CON`V? z|L6~r7`U#bT3dqpVj`Zmmxl|^AOfi;=4)-WLA+;*ehDv?Z6Aq-e5XwbIBJvbE&Uruo4!2nGg*UMYe5-n$%M ze(TA6JQl5P?Jkha_=scA&vu4B?caPdUubf#=qW?MBxglkXVxxK$#p+j-5bqHHntp2 zJ3DE6=4WeuzalIkP~VU$BP-kDaR##@M@w8O*W`K-MlT6@H}GAj7B7xJZJL={ff z+sH!xe;x(ae4Gzv%Q)H|vC~IKM?bxuZ}zMX50?kYPWC1Jh9RC+H#oS#qfsu7j;Hfg z=1#So#isON%g9zrysmy5`#-rVC?KJf8aBVw->4u-#<-Kt`4oBtqoFl)%S_Fm5qGr5QGYyt2UBG4<3H@NL z?HNR0!mon^@5A{jaxt&0aS$M081VZBt12kv0WK=B6xHns$K# zwd#E$Mu*s$DDLZJD&Tp(E$Pk4U2nfc@9e0XD2J#r_(Hz9xp|mhMgY_vT5JlRQ)mOc z>Vr6*0IY~&$5=;70f*HTeN(>-34iez+$Bs(qT2$QwYC6y~sF%A%prFc_I34 zlr*yhlo=ZIJ)~IG7z{>^VTeI%yu=@!*#L1nFKbG!Gz=$<32ZCKeS8E(nN~DQ91F}* zM3Yt2DCVAkdVvx(UGixsbZmfH3^5Nm22G*C#8J3bh*U zj>O@@>}SHNN_vweoURqLE7``mBlQObpS8jDKr0b=Lc}88`v@JAj4w{>k;e4X@>3w zl0}>t=oHnKLt#U37c$2OV6g*gBNj;RAY^C{pkzwb?sS`@pds2>78K8;eBNr~^x_)F zieU9&G2l>gNVvUO^IyB1T#w2Waz=PZs7@9_xLSX;#5fK;u0Kv*z31|DHD@f?7%zUW zknf01Cm4kqvnpgYPO0OSW}OI&*9YI;AS=!eTTb0u=Ss2hYpO6U$T9KIf0k(&(SR*x zsoC@5D`I<y7EmQdR5A4un6xGopXK_-s+IXArwk=qD3Lg?}a zRi4wilH;-d2f=VV=um>;L%MLQ;=4eu{*aUS3Z4cAvTOg!|nn zT1%J}^DL=bh!Uu^Ebw!hi`<-u<0He&Az3iN{loQq-#{8j)A)j=Tm81Dd;+RE0E-vq z6FEJe1ug>xHY}D#c>xory#*3%FDe|CJ%0(}BrFXt-lH3@>PPblhxJMmpRd&~y`c#( zgHc)}@!Qiwi`ITR_r0Xs$9d@~BH0(})-IPo!BzRX4RoxPN`gW{9WnK4nDowlokDL!F2@iX+yRHYMto@o)5MGirHq#Nlys#_r(A6|YTQ-`aJlG9qNubR73x`j-E zX~)J_b3&FisRpi+Ee(sYY%&xWbM!)~c_|?wq$+8p++1#od(??Ox&#U*74E=`w;3Pn zvYFCyl*(Yy4Czo%qtV!8-lYjRkiSWsq#7}!*w-$a9cB$}Fd^q&BG|>-r@0#DeAitV5zt*bfovvv>$zBPzfGYfNljUGDje@Ge?_n}QEZ75JQQQ0kysmcdCKrY zd&{?DdlfEU2SG7hN7F<#p$ff$l95zJSBKDbbVtJmt}$r92uWv+8{c91k=jAjUyZ*p zaqfspWUuD@9bs3Ey%R_givxcFEtlLgM5|A2&V^kwxT`F?ZqsqY#b;zvZf5x+A7wSk zv0X@JuDcXOgs%oCq3Gw)<;F?A_}&%~VpSe-NmZ(+A@5r_em2!JcaA{Ch2G^V zFqRbV9;ZG`Sh9lg$0%@>V|38Dk4R z*XoeK5IluABip9IGlqw&-HOPcMM$Dg{|r2TgGdFb>HO za6h_+yrgtS^6cc2DJ4#Z?p%$~@9@B4?g$Mq4J}#t>HIDeG1H!voaSTT9R&+(XTt~9 zF=lprP|k8hlLx;^b|Y>KgU(I5G?yTvlN$2gmx(}=Dh%CM^-;uy$ABi&dCCkFpSS~t z0wl0_UvNxTprL&-<&`>5)59?-;(TOYK)8BXQOG0>$W*P+c+L>Mc;_O-KrS^xE<+;s zunA%iheLE$LTGFPj}!HYBKF~aGqeZdYEqojQT4;m&fo_MH%ZaZa2f+=UjZO0(p8<vUvbOixF)F1vD zODYLgIa@RlmS;hi^ao#@oQtqw1C}I`q77ta{NU>Rjq_bdVE!Zq2|i*-*UZe-M4o(& z2$G^6Cju-itf7HHjUJl@jWrtvVl)-n-EjZ@{yrnkxRA9AK>ipu;RQ<<4K`B!Btfa# zXks$bJKhnTmzh~vwQ@;XBBYzqzArZt76WJHdxLnnzx{}K7B@Ce*dT zB~d-$GLce8I#zO@;~jB!Q%`B2OJS3!A0@oZjiejUl%8+iS-#YSRd~gu8WIdiDgvPI zu_9qxAV7$*DEH*wT)=!vK$;HjfC_)E4yC!+W%TikbX6LkuS3OT~C(+R*YR+ubd*Wa%VQj3a;01{~RIO`le2ki(b zU)er|RZn(Hb+H0Jv6JSldF0e(DPzfwjgQshviVQW=Z7%Dgiq#yMf2e@rw8L;ZLtC zW*K=;#dAP#0d^;@LgltS5Vj`@4=^!v2UjX|q&;zDBIFW&2E`go5)u+R((tJGXc!pB zAUblTLVvs)^8-W)04LMm)#V{lN|p9b;72D-IC*WR8377CH(Wi12e+kOqE&W%v}FAA z1AHK610E_qtJPG&$egi%i_=yw=$!{Yi>owv-y9Rp%vWkx7~KlG9qQa&Ukf1i4gu;4 z5rb6FOLaW6>=b^8!ujzXoR%F)%DlbR74t}e^K)gn5e&rBI6lh`XpFS z6;Rpb+MK~l;#)Ey=AsihGpT-siz5g^`W9>tQv!Df3RMu~+}I8Y(E?^d#lgWr=@&Q# zVf8^9A(?=8 z8JiSF24bxdVS*l~2a(!bKP7$xM~$i@7HIL}C1mfPgoslKvqAzNg`(=N=!_o!cyIkGKXMH z#OZCA%+cHqe8$E(A|(5U#l_yazFRu;%SBDR)Iny0QZe$-FCpeMB7#5_BT-LVG6};_ zL&wWLrn;JETUy5#ngskB-T&ecamh?3N0iPlG*1aHsn#l~r6#RGP)rI`ME#!*k%184 z5cvd406&`dFNa7H0ug%XPpl~R-`#zJbTp1aQdbS!s#;nNKolNG=)}VBdXsjD6g{D^ z5m5nEL8M5${c^D6N?SgbasZ9hZlFXO$dNQ=W}Y*AWUfK90=&W@Ir%m^(?GgVmhcVXN7DukRnclXogG>O&q%hopM~-Ui8cqtLcM%Gos_iH zuF{`YXVjcsK4zbp7WMW&E!4TWjtLs0ajy@6($6r7EfGUe?Y*=s9Gl_G^{CIlu;+kq z+30;xpr8V7*V5VJOK7#Yf?Rc2UfA~WG>H!8gRxIDhc-&Ts zujoye&gc0K;mBhQ4EF_Mw*6Ww`Bty(ouhY3W#2!vh+s>@>vl&jI7{%P^Avm@j;)hi_TJ>Y+Ty%OKH zJDBY7EU^TH;tfis&jWd3(?y2<1HJyO_iml(Tk>-iI&bgo>p2iKy(``vU}R|@iZVL$ zSLgV1o z?yWEnZtwLUhm=@n!~lpg%e|CrpGbM$emfJnopv0`50KvQe*d z+Hi?YeUnj6v?}KEL*?%;fxwO+=K09F&(ym*Qu65mjVzVMJzH&u+2xlA)Fw6Rmj3V( z5zjlP*Pq^R4N82jvDThxatn(|*QbpO{8$=rwCfoKE= z-KLixf#Ku3TUSAWzO1b56Sw`>;NW2QmN06`4d8R?0DOUI=Ggro62d(~*MGbN`B$&c z@fjI$gc%qfF;S6!x<9yCSXfLI?Q*CH@W-ud4d|bbMU%6+Rs4{KNV&Svs(6Y_%z0Xua~g z`wrw`_Dmrna(t9pHU7X6Zm$;(R#VDt6(JuZ;X*ql)%epk^y^MMxYtit$@H;sNd@n{ z330Us^*sb%D=7)P-|#iT4*zgiYc8L#dHu5Il2C9uO4j*eF_jDU!R7dAC!q?bdT&t7 zd(s{AWUaOY+D+rn)V9-UE<${kPN@Y^i1p&MpZ0Fs+81P>9G*T{jH3n35+mumZT5lx zX*McgTvYFnl4Tq+FYwrN zBtBEAzZIlZLH7~$KG#`(`NLx9&*ho<4oyw(=paY7_{?K){9sDO_V%Hjp0lt(y`C${ z;Yt;HqwZdtA4&`sQmg_g$QtmlO)Y!jW!sxb&B3UJ$`)f;eWhq$vn7?u#r*LtoMK^9 zSoO)B5Or8?PMXhk{j!Dqs@CG2qWRuW9p{vh08bN^^!?&aG;E_A(qo0>MxuDv(B2s5 zF4a3nie)je95G)TE#%BkQ+;uiVdt9*Jghe%aEME~Ki`GLd>YNdl6x)5b*n3>oZVkR zTw_)3dh~MNFx0&y{r!huhrjgaDx$gr!FF-}yx5@-b(@_0SzTqe*enN+C@l|ZPHUa zt#?H!VpHaHpZ&JZ>*$~=Plxw}g`rqJnJnHI^DpI^$`I&gJB(~<66qYnU;FqXIyeCr zEwlD-zAN2It}Hgi0a6oFDr}RRi;WfswdmKAxwVLTR1h<8N3qV0PlRoHcq8h@FbTW=<~z4GaxkbCuCMB!g&~8sHWa7(jogSB76~ z+OxTiZbECFP~j9E7Z=BkjfI6pPEKwLLCA^@*4o?O-faJ*+J@!3f_MEkHl0 zyww~29fhPliyrEAV@sH>v{G_5DkP-%=58JohLbM%2E+)*(Yy$uvxZ`H8tC?4yN3%r! zYH>i%qKbX)uU|#`8^_4NW6Vid2lRh(aty;F;9T&ba}_2VMx+JE@c}f-v_Mi6XJUF{n{W?>cVM$PlUfC2802Av5Q=97vYot=XR9Dz^)^r73kJF!S# zEDHlb7g)l~BG$+emZiGA4a5~Bx%oC!W#zH)ah3Ei zxpf+Bx|b<}&bw%K5FJJ!cM17D3Z9#$>QqGi>%0FS+yq*B|DBs4RbY$x{~vAwV-Lyx z1Jg16I5mhHa`-grosn|n`U3}26)Y3}pf?`K%D+`0OKowfNmxWgM0j}LrhYk|>Xm7E zt}#$`3#VCext&r3Bbg%xD-4D!4Cvrs+~LLX11UYcSkxs3a_$up7G_55=H?dW6Or>*AscIE-O$`k%nBb|lV-tC}YGBQocTnV;$-{kI1vOx;ixH@hLu>drf0%gXFTcpO z+(?*ENh1;DcXxLO@JW!f;A>3&vgJ!#d_;^G;3kL+^l5fvt`S6&`+J}f&J7uu=Jcy5 zNx7=li}EGpkQ8+|e?X*DiW9MG|LrCqwBjXZB4wKXPd5QZR8Jyy)jw_mk9>pw%}rpI zENqA;g;a&~pJO2dPyDg}*aSLX1_CmLL$5|5AKGTN^e0gG6J3D6rvW4saQuCNbUX1? zmIL^8{vI1}HVD_~K^|pv{5{R|a8218N48X`OmS8>|HJYX$UN|>%AKg;@$t&w^p1Z^ zA-((zTneb?#{Y5?_+(O|kqOs;uPx}PTVG$dnJIocAL5`6)M;=u1z;AiM|s-~KYy|r zH46gUkCYfbW*eY8p6;)3B8LHq^7nYcX_${@3I!E0sItZZQt!KZAqutxArGK+0PBQ{ z+zqth!~rUXEGS74F=#-*7O?Pu`1w3O85 z$G`(sKomvcv6$iWWl8xzKe?yz03SrhbR$T64J2QsYk-9dNN*JWk5$VLfNe?4!wsm4 zEq^{-s0Nqidp^KmB^Qm)rhea)o?I;8$(TNK=v033d%91ul=tu^&1T zy)(eYFrffAj^XQBiu=u9zwSl^)|5W;vvG2&5SBFqYXMGp!GskCnea654e1IIQz|nx zli!LD?m9x&=_${iZq~MH+<#5Nzs*}f7IHfz+=XQfO#-5Hrl8YTpa&9$7wrM_L%DWE zw%Q@kD+Mtd*o*MVpx!MVp5ozZ?||S^Ffj(75WgP)lGPUZkDlb^MpxVENb>nsU+?X{ zBZk)2RzZk?)^tS!v#F`6V8X~}0r!Jhbi_Ef)kas;j3uC)=I4ldQrFimz)oR+tpVBZ z*YeK`KrW7a{C{)-7lcit2(pbFhUtYV%qtwo8XOlCmqsOx03>fHofSeo zP<}v#;j=~9ope2zl_YL`I2J+c0g}7vw#nRnH|HOL_sfhi5{@!3=1|^`*GmpuMU@=e zG|oVlk`6%H` zy(OAQo=H8tD)=hL@16+(EYgEx9q^ennf0Ksq<%@X;-`HJPDH_-?QCga3MiqVf(AR) z2lZYZF5pN73~3a;$pZV5{$~&wk=tgv=xC`v&lC`KE^co8Vm{F$?E{ymrvZ&@fOp*a zR+Nstrr7J3yDs=B@#hvcZtRn>pY<%V(=Dh!kZ};VsskxyvRVD%K7X}zyf+!V)?H!f z|HuxIAN}^T@dlQmeF@O+_YLW20$Ms`fb{L)?RFNEO zFGUg|l0z)8a-l?H8y+UqbHapkgX=W~b|JvJK8=c;xa^NZH}%Ry!Fg4)CX2Yg_mNTO zn&foP9YZ#s>oy2anuoWeAjPoZESYkVKbwiqj`C8m2dRh?`|!-x|*CbvWnC7fKJEPH~f%7XnUr=X+!E&Y?pg@%yUU z70X@(>JtBxLnq`~NHafq%ZOdkadSkiSW2+kbMm!R3p^-R;4 zz#JdiXzLbB0GG_vB>rJLViG%n=iQt10P8%9%?5~N!VWMomTd!7no#JiYX-LQlOUc> zj|#?YwtSUoT1Q%^La^%5_I3!Vj(&kEtc<`nA@k5VB)84>+_{&iTt%bVVkJJ&Jd`+A z*zAE~c%5@E_By)b4&WyOy)ry)wBB&*QRAq*c*MlSB)HDKRH{+Oa?iI!|5wytoorbx zH*m>#J>H(3Vwd4YA2jN_>{7|?E8@R~Mb3m5T#7*Igzrh!3Niu)v(Q{rf4Ejm4W-`e z_5OB+unWvRcmz=&L=Tj=cxJuoZftq5PVP2)KO#QJyv%wVj&J-_amK07gu}TXQr4SR zE2*e&m+#66ou*}57d^Evl*^YQwsP#d@UfHhM&=Ss{#*CWK`)a4Q}&6X@x z9q3D&>b+<_gwmak_*9f}6cp2~4R~smoxE!Ax@dRw@Gg z+e5(AW{?McN4N9`tIs{j#G>t1jG|GVDGjA8$&V23@cW@Tw<)fmQ&Y7(B2`4>P$pXk z?zIUs^(yqI+0uZ;!--e;TeVThe?BQ6FiDp7AGt(ajDD~;C;hgPV51Vk|5 zlR>nD!|fV>&;;hN#*8A_L{#{tQ2}%jTo&ShRisV|ok_vUi1hG+5{h9P$SJbsDs0Q= zZbysAd8R?W16AP-=XV!-JtR;qy~y(GICH3PgMRd4Q51wz-0079a3WX9(dXzm0kyhe zHCc>7NPIoa6yy{7@fFH}~6pO94`BQ-n^ zIvAn{TaVuY-5cbyMH{0Dhh!-}3|ACyZ6R}vbb%d$+)Mj4_%t4}*H_e~J&$#W5fNJR zmg?Q9)q1H^KV1=Ht97pnhV= zX+_luvNkbe$W=CH24MEkhA^5~3@iz#75$Zv9Zf*X;6p%5g^b#ZE2s6c`Q%l{4@X9P zM34K+@4#nE`d32^X3^9oJy#%&-FInpqyeHggt8HgfbL}No^QZ1sfyU?kU}uDwddsH z$tR8}w?{ezQP9v_oSY_XYE@!WY@Gyk&`kRgG33ENqCmNqc{GNNE-EicuWdy?CMDD$ zYZ-C*K+sbiusTnj+}vh~6@M;nK#UL7QNpJ&NIflB6^0NS2hfRx>AI=aF!I@7Q070e z2U;jd$fATR1Pba9-9@<(nkD`P4%a6Cj3VS)%|Q4agtW6snE-i!3+A=wWw?a5{X=nm zVbg+NBS%EaCZbv53?fo#{RerF_!WrG7Y91(&ab+EM}W`Aa{DMf7h3&?YCK1e_m66v zUqAy4-2850J3gSN0QZqD;$H5-qcR5I?g%%K&UfzXh{m$T4$Nd`{FHOV%bLxSfHpl( zN7@%p(FZdL`t8+j&B&-Iy+)T`(F7catT_M_|LsL9Z0nOjyL(2j4V3T^;MOnugoKG{ zTw|pQDkb(<)fx%qB%hJvXG(CvAH9|!G1=>GO_y83J-xK_{-ZL#2rJFfqA+byrGTzQFU zAj?+)r~z&gOce}{jbYBJbOgZzp4t0yUls5RpkrTaa55iEVRHRFjTHjHvC}7IP|oHh zL<2tg!AzlQA5>AFKt9{qX`osI`z@&RlIyVVdxGFm0h+%6hC_$thBMF%pBG@_9jtdSLbLlY)%QJ zPK@9S;3V$674~?n&??glgn|FtqFmP6&QY=h8N5TV+X90xacLF+E&yKui2{a8sB;5v zLb5tD0u=2X+MDc#$28PtB)ZPYBM*m0&9uJH8nZl?F(}yYFR;p^v`S<-v3aW7+Ma<( zkHt8W!lb@j4Ep524Ka{Io7_+I)|j@DxguJ;Z=}L1MFffaL-?p-$rQ%G3kd6{Tp{ znE&ge1}5tgt9N;nh-ZJiZczac}L_}^bhn= zwIXr`*1^F}po!=Eyp!eX2%BtFE4bc zG@I5VE+EjsEYIb=!f%F-kyyX1MKekf?%(CbdfceiImbU0NG$NkDu{70!wXSfYfi)~Mwuf-3y){nEY^l$A9>%FWh*t0TbJ`2BX5U1|6GcJrLv({>P?BOX) z$pjBJ5csag&PyxfH+^vRx}+tzIKimaWuuUdWYfGNUXNn2=@tI|Wbs6==8)xI4M`mD zRkP0@1Hw@0l5c;SsbLp90CJl#^=tLgmK z(-5?y>m0ZErs&?X#cVOBOYk&SqVJ4lriFS~vNo7Yt6x zb;l;HHoI94w~K4qcs<|G-Iw*T*VwI1yrtvFmI#g$ZT5Eu&jxU68%bwy`1w-P%}&q# z@iY*~?5Tc*WBMVKLR92_)S(^G|<4e%4EtY`>bNydIsXqyXDg|h+^Ry9CaswLrPGHl)4 zb_nZbTQ_V2gR){v{B!opO1r#Pt8e>yYjun|z79n7T)a1In*1V5vfbq`lpviW`6L%iH>NX5_aI+HM(ni*BwdNEPn&jP~dqT zx_&@i&2as_H>gc%+|kLsCzc~e=6(6(`8(tq-R5Ya&b2es6AV>J`F(1Il?pQUTe#~I zCtK3GC=Vu;u7Q58cQA;?BT5`UHSMA0qxmnAq3lc8*prpq*VT0t{MJ)%nhlpbvm1b9 zC?uo{rj*SAKdmkm6ihIhO@vRpIn`XN@b>QnTwF+4NX_~6V4Bd-?Lr$}?~i^G;H97y z3ff1Qb&>r5^zTVHrsFBB{o9RwjY*anTe3AoRLE|K$`YeRW62dQmQ<3mXJ<&IRhCxLh)_|(OqOU-TnUBH zs*AKK(({_@y6@j}-@kL;zjJ=id7kt9)j5;-8sG2d^ZvZwuWdF)ohW4dme{Ml+`P^A z0=TWmhSvsHD0RJ!GVGG+`VnsPa-p_y^E&%`3mjFluQIP)Q~?ip&s|@VkcvUk@bjgF zJx&(H#H1SXnvIZ+_W9hoT^$fHS*NRcM5E}KoQjId7I^E_Ei5e5*Aq=vug`T=zb_}Z zBYI29{1W9a{tuLRd&0S0e^m+h!awqw$=BI*ihaw}yLn%=!>Deafi{0phBa;fNg1NX z3;snJhIpE4p6??cv6ai*-6P#FcB)Kfv?27wQIFEJvSue94{0)XP&3++k0a({?4AY-L<_ga7Vp_wVII zS%vj@?3>XE&cHAVm1*Jmy6w**r$(JeS)9o)Uo3&Zffh_mOyoMnifsjN3D<5qrH6%6lQ4Q+Xey6gVw8x$=7hof%#_Zvuj)KW-4-(q~YP=upa;THnACS`2w?@ z^nU0peM5-o1UzIH`!&$;zYux~OR0(*n8!{tb91HS%h0Z8gc3$3e!#)D7A+}sZKbT6 zyWcbBOH1<{v3Y&zb~Q9=3Y*G{>#^|zhN?&c3Hk+MTbCz)YfdudcC)g&mBIFmYPf^1Ex*UND|QG z|Js4^tI9=UIQ}dxjC%$I@j8y9`KCLOu3%1OrXDCB2vfhq2Z!Pxeb?WkE5+0zlf{fv zJags@B(=s8*(@hbmja!LSDo{FNzAoVqwTvO^c`jER{72Q^LmF21Ec|L+6zSC;e4MO zv(wh+vo{-4shreifHIzU!&S`9X8cJ{&pKjb{>5IOo(;T}_W>&wyIkA>@hxZ#8|?5K6P6GG1NQHsaTH7&;Slkl|1#qr%y%a`rJYp`Hv4zDKxL|2BrYB5R zxw{oAF1H0h3~WEdj``{5=LaTZJ`Ak^<+R&7x-ZHYlhp{jn3b+JpH>yk4`sf-Zl`JWm)&^xN!X1&7zOF_Vq*@eO4)}*r3j8Q$G7TL-=#S_D@0OfMe{*_B`hfiKgjU1qtS@+oIl&b>7&}W zsoB0g*E>KVR6iTrKh zpLXM7j`Ubkj`!*Lk%<&Khm6e|ngXYx-rf=~!Wp2~%SlpS{O9 ziQybh;$a=T`^jZ7k9uUf4_~(Vz)a5`(wTTl3K7V5)JRFX>@RiHQs(X(e3bd}nMu8z z^@OB_d1Z^m5 z+%b#}z3ca#1Dp?t@!RLmCinGG{Bo3+CCALp&Q@-|W7yWO{&%}=^{&^e%P{@7=BUiT z&|GXrk9i9uAw_iFWf)i5muhMX2%;u#s1A19(vLyutc9$qBLfv}3>?S6MfXy!i**E( zdmiHmT{kB!jq>~p>Y`C#;DzRB#i11w4NIUn|K0<5z-o5VPLp!?I%X^|mSC5De(+bjc$XX8%d=A_MQ%(^*nen9&T@Z z&~n@bTVmWAkt#+Yv2(D%J9oZ*Sk&rsQ8YDd*ThBMkp_S_k4TxL~nrH~NXQe`*6Na`5=;}1!#W*LzwZ)(AiPRoK(e#;pw zR8Cg%DOjCLGOgVhxxDGec@L-?8ynwNf_1?AtTpfPO0P?@+I4^|ip(SUj?i6SwI3GV zW&X}d&A4AWQ0OirK9=6XcGZz!pxRrTdtdd-J}z1+nRLUiF@~yhK0!b>o}3UnE?HUw z_>IZRJ8l-{7xfv0Luqw@=%yQy=kzz1*o(M6rP6nbOGx}2J-mj|Vi>-a5?5i;n-R{c zSrp3mpt#fNFmu^wu~)#vd6FPF~UC%~oD1cHZ{hyrFz|Td&6(M(^7$-ZA*K* zvz39Hm7wZ=POR$Yq+%tV#rg^D3Z)L;3H)xl`VVwtr8`;D8laV9`&8!GPve)7inMqI zako{C!v=3>FPk5nuT*3h@VL3v7cPdm-h*r;9acv@kJR`c!BoU2V~5dqqYq4Bp; zL)7*td-3zipF6!)f+oN;MJJoMe5~H~F>XSa(jaXPV3R4SY0mGCo#9P0j@ZemkS zDPsG^llj%;_Ai63Yh1rx_wkRk_d~tad*4$#yq5W#UzZouyg^p7UgXW$!qY<5g!kqPtTO%$P5K)91>ndjO70n3rIL36A~K<@_`$M1T$WjgxiKG z{KFz?cd_$~CYhV3ja{Ow6TiqrubY&7^nmNrG#^@}A-Cxl2)P45{_e3ig*~l2&E!XI zi>^M%j7adazC+<7JJKdwE_uRBFPgd zYBRNEZIkP^h!7z^kykp@Ba}l6r1M$vt=ku689l{x5tv109a_8c(EQ8B&lM`o`)p$t@fpj}jql@7sF<-~iiK9?I zB)jYRTjBM2z6y?=vK@|(7DXGx$*0#(a*`{ zZP&l9{y3efH?A_SG8`HmyH$j59pR^~Q)h$h$^CUAe3oxSdc{_&NNy~QHdJ`qcU{jg zyWxW5>tsilfWYAt*Qt=w$Y3^AE?ILCt+};3;9a1$EYnd&(>5qIEV)J`uG}_XBho;* zd}*2v)I;LhM@a1=077%M z_GGgA*EDogO=+&blY5xql{EgYTXIDe{G6*xo@vw)oUfcM_cR@Ey;lB`E>Ql=`^WifYMDSRh$S#ZF?!Emh3~)h` z@)TzocR(L@6d+%cw>SG7)7bE2<6Lx6pTFEc`8lbVN3n1)vqI53~&9PpqVQx+gNSH%Ra)qhw2c}%=bU=}ZdD$L% z`U+!(vb;q{95|n%{cZEfe(ztPdN0JgKTVCTs_ta5Sdfy|rxg9C zgLC;GnRnsf%>2v2S>f|<9h`oLwcV1H&~&t%+$iF_-2~HXtsmeEZkrCduEqYZ+uQTC z#>5i1pwYI z=uwF(7~U{?y8NV=oywvO%%G+2iiZ%6tCr)P#Ne#%=^TcJ6(KggUw{vYDjGJRl}Gr^ z#>SX=C5ItI@n!!{nK*k!|LZ2sqo4k}O`Oie&91qzT#~3Zg+EZ0e-T=E;wcOkb`QXp zB!6^h{qJ#c`XC@FFMRjzlx0a@*>6~JqZ=EdtH9zPTfEs($%Bi?87}o+H?)n_#cH!> zc)S|8ePDz3sHm8zPRhd7r_vT}I)9GSHrV_&>L!QQx_j5I1<+nwj6Fk}B`bJ4o)F3x4Eq+j-Jzh)ju&5SUIe5ZM|7TptHQMEDx!b@KD*Bd0kH+ZgMT8GzCO^yl9lX;MmLOE|hE#q$DGUna#hO#p_RzeUX-~xrFeBEWZmg&(C3yntp zcz)~my`uYU#RJf~GsxqTIYP$%Zqz{G$Gaw8SZWSQyPYs`CYlQ7xrcazJ^hZ)E1bx@ zNI4W7ku`aNamXjpE}o#CEh(8Q$-S$2nwVqUB6>2mbID2 z`Qx;?c&WrMlF4+WUkU5+@cPu-BAP?jql{2eO^8!(OANN&cxGjsWO*^D_vt-f-u2Kd zL;7p4i2KK5t*A#Qq{u!o;WL8JF_p&>I2f8u%7$e3|0VM6?<`%fp0ZRHMncRE9@4fR zimO+z29|-Art^&DEz7YFKd#)vN$joe$5>iYZ^;t z)L5g{qD)>nRwbh>At~wDW{;l~Cr%NkfA8p(mP~dfN@!`i4Udm!C4@DKPy8!6%Ktkh zKf9E=35wYrfF-D|rcaHA91J+hEY70HSDn6SW&vLjMxL-? z!1u<4GqbJ#*50t|p*OqNpJ^sWNG=`j`hWu zi;Bz^NJ~p2E{hC;E*Xc2H%M%>7H2IYPeA>umH!2ji-UjysN$*?(;bWNAjxvoK#cxU z@g0+&K0SFGh2oZ=;d#zwUN`so<3#Yg5vc{V#4Qw4RqUutDD)Z6u$Jk1V3xzss{$jz zT5lvJ7c%J0dH7XupV$}=l?`d=OHz4ciL>E;+=QY{tX90Mc}Ej5Co5}X$S60l%|CWG zL>@q>0IvexQP$Xl_%N#8mt&Bb06#`miw_;raLup(LfhVprVm&g9@e{|p|e5i63b?0 zKRxWC(2Ssv_z6&faU--xS02*wJ56-!)7Q#iyFVr%Cz&ioDKr{-{`@&v4Y~ zv`o`Sk-erkx%0nIG<=dgrC~!zw@VZe9{&ymhd!73Gnd|q`w4tHb0` zs}Cy6_nDbe%dcLBYSWc8=O_r2pVk$;B zvTQNJb9;TcK!(-y5P!vkwyouEWfF<^#+*(*+@_^@KcCXfyLbdxJuS`>L(eF`-A+vQ zzdbx-;CViaVl^W_qHL9tnJH%V0_PLa#~CHU=(0?fNx9p6R_{H1wMGazjOY00TBC)g1A}6LE9j7asM(1^W?eTG3Zxag^e^&90u)(XkEi z0id<1RHeHp=WWS`w%K7}|MreW`Y!x^9RSm`|p<}`wc4>X|9cfpY z8XWaYADniEQLzi9Gv^xxBo`H_*)B=DB8nqsYs73S&N(PpH%Qx7;AH>*`Pz@VQ*!xP z_4_`Zr;32t{5S8czidm*Sg5Vdg~2Wd2LVP?|HyTX@l~UEU}M+U*IUHRHK4R0FLurN zQz_g+zuUg^AqUz7wA}2RwrUNSK`Lb!!|xLX?6L2RR$QLohV zxE3oq>gxv(Oi=4H7R&BN7h}LcL>+2GCWkY=y8{rUY`Qp?Aoa(r2H}-`h0TR0mIr5P z?WuPWC+U!PlbfW;lZDJkn5ZV#o;r1EY1oT_nh?*iYzK<)Xy$!SIaK)<1Of-5m2=$4 zU^~;v2pHR@RN}!`96We%qVd}q>Zb5@DGW1i35KFS-hbz$6$-WO@u8NVR@PfK#yz`sh@!<2c3ucxhGkzAR*rX(P% zR602iafVM~=bvyW-}A@7B3WTDC}H-1i?HYGaBpQa98tXN-LoHB&2&C_vJ2}@Dcey~ zvRARWii)h?6R$eVq|d;4vGGQvdIVyg+fMTJ#IyON&H;W^_cnceVa-ZlQXEf-N#uB1 z?VI8Z4#u(Kc`5to<0R3U_Ju|C2>`?h(3z*_EuYShJ8Je4Kqk`^=yBOaM=bs&L2VSI zNZ7BFi2tz=japEfG@NaIjzMz(!0!Oa0&BHwx%Sajpk+t1%P-Vy9! zK>oH3aWD+=Xf20K1yiCppua}2e@Ht<>Wh8JpKsFHe0vs@kWl~-_8H`*^b}%E^}9=? zgV#H{p9?pCp%)T?_&FS|>Eo#MiRZ{pIU=$}ILGME`uo>q1q7k#;dD}4F4-;|@N0WI8O z559lZ69kSp?L>DI)9A--F~9@;t;g8A_uJ4A9rmsz^tQmE4T}Tq%uztUOb*-q(`&$0 zVYR9BYt$u>L*l`nyop+V^3J2ZYhRdcNx|vj;N-+j3B@^e{*xWSIf7KlDfgO%SmlbJ4BETHui@fhZfp<&|o zy#LnFthbooptrbw9r$KqFVMHq++|f^?@s#N@!rVDci^Yx#D8UPUm^?+2PuGbJJpF4 z5KLrX1%%-LzWi?={BIrn?_==)^H4y717*dCoDff|l$H$(HCFkhtfQmj1`*Va7l)JK z_3`6lg~s6i>?oH*GCyKwWb7E?8#980z!fVC6W!d%SoVoY_8_zlM9^|3_TZ?*afhU1 zm_HjX_7!2Ztel|V-R&}#B!+k+4v8y2)-{VKuDiQ?upffow;LGbju}=zU|?bSTwk{n z2!xCONR06k$G~KHjjy@0^>bsxPFdW+@54i=2?lcQ;NXCYNOKC23x`BET<@SC8hkY- z2R?yMkQ(<*7ma_fL@?tKxw*eEj zwKznA?V*5*E`(?T*^>NSZjJFF7%9(UcuOX~#t3i0KD8fshCeP&k{|6oCDHZHW; zOStTr%50>U>+&Rf%J%eG*-zW5fSw;)215a2b{%^ID{(ZFPiNg!JY5yJ+$2(zpl^z` z_m1A#`fHTU=W5c*sNL*bo%3LA94TVMnN$h)S_8KYFHZ@$0xvEu`cyh?9;s;EnatwU zW8kokm?Vk%s~lAspAJQ*WH%9H@@qYLcOcaC=HxoE3wyJ!K9w@5#J`K0V36{z$#Ef3 z6^!GnxW>q!F>svhVtIEnHAH#L>{D5vx}Clr_>wA?ZvJ5J=d+JV)h{cL>)#RXFAF?@ z+YR5Z-E;(@II*c`e6b!UL28RjNRV@w%#SQt_>n2(;`rQ%x^^P3yDwx4rOm{$C4G!t z9)tsigDn<5PnWN_&KkdXk*bUCE7Rg-G)oQ?hz`GcQ&VI186E>sc#%wgN8$Yli%i-eir_+k$~xDm^!Ie{Fq; z1mXU?Ov_WFOKL@5ulw!$R#t* zK(LYWlbL4D%zN|k&)Vc!Grh7Y>)ge$bi5N?_0aELJs}c~0agfq|CZJZ=at7E$jQ2; z8~rl9hvwYvqM`WR{x%C_xsG^$L`Z;nt^S-|;GNVGYBVi%+ zdrmLyMK$Zae+`yR+jY7>}NUg`vGW8jC%+3ONvy#U%psaYUHYbYA&i$o5kv&46MDH5SAHEju z8m8V!)yL+DIxhbjnc=gd9f|!f zms9tnt*S5qXK8nJAv4D6m^sB1ROrPIZM^`4<5KK+)B-NJmN z`^9w3_S4)X_J;~LIlLwU+AMMP9~!yS8tIZFe}2!z&ldQn-ZS?W4W)6ssiQs13=BBh zdzr5t)E>CbHxFZW&1bqKRHQ4%1}8z^O#9ZmFg_ppmHaldj$N-5cQH7e$84L+++(}< z8%0!z*y;I*V;nq^#M|3$B*Agsb%>v}>qXgI9tSx1$B*a3_|G*nxFuw^`ZFKOcilvO ziAmJHVB^MfVpy&bvQ2Rs(}M{`cpmg;x9eoH=DuUmnEaxpdS^tjFvfHkzNMYLv%0EN z>caywYM_0xhoZ7RO4@7L>^FY0Bn82QK-1_cM{?b>R5v)%{uXSp1SwH{KDk zWxxZ$oprTd^ybBKiw}n;x?)La>qjw`2R5yo$9wE5vQ}13k9{szyAwhyU1}|!eblh6 zVow^Y8ttH3i3=Ht(;Lcew?1Ed*Y#q84k_`n+U~)HCMF;tKZ47$&aa?b9jF}BGTjH*{5a~+Fq~}`)Wu%YPnf7pbz&6;=iq!FJ*Y+X{ zKgH4W8srN;tKJ-3|FsoxcM$a=mY&0;{KrF0xUU#K8j+&!TTel1wo!}PKO39Gl6~E6 zt8z>2wAJgUl2v<@tGYqzjvKw_y=tMyjuR6`Debxl09VHvf2GadO;M5=5v0j zYb>YHTv!*|~U%;48(x3?{irImN) z?OuPWZ1FiV&y{umq4NnPbdX#6*)L(|D%ZXg|AqQI4P!~F+0v;ARYIOEzuQCkxKSEg z3zakqopN*WOi6#Ne6U|_NRI|@jy#*!^1U)Z9=c2ycU4TVJ*5)T%w^c@!t9v;`uQg4d2Bg47GL_wo0HGa zw=}cITxTKOT0C2txf~~X?ujXPl4Y1~`9P2&+T*KRWN4veEK{nh%Ko83XZ&3H zW+e9>JtY_B!g%@1;jDDiG$sSN=s2^g*PU!PSUy6d4gZ?3K-cyq4bHUEO?+La`}8Sa z{YJ=aWG-v;ncvM;=D{ZfVWH#6HF?<#9Qi&@87-HRzSz5_$LdL5kGxtEN-AvOdTL?% z?n-%^ULhO%Vtrc!R*{46x(_fZgZ3vv=%3v!$Aw?<(Uz|u*h{jugx{%Kz{TiT6>+XbVLP>jg! zv}=^WftXp`YYnxacE%%`Q&eE}!b+*5%TgPwS6 zsUZZ$Mr}0p|1N2iYsAfC!ig$oLb{DYq^%ku1hwL78~yid4oC;#CafFGn;Tq`2N2HT z8&cHQR5!QRv9Etu6c00IH2EjrdE9@`l72JR>6`Ha51BaPp{7v7m&& z1le^8T3T8M7L_j2&9z^?{1H8-7-w^U?1I|u7FL^=eNl$30w zhPD5!w8+4vbn^1@s4)0FymdcSY3{{OlxN_NymE{mi#USq)MS-$BQ}@ja1iubQX$Cr z1^t+Y2urDt&mhRka_W%!EK;G3+rpKUXULVp*fIx|h}#O-9Tq>(IcW2IGmanf&qzJf z#6wvLz%U1Sf{1>4lY$<3?mRIY<+NB3iRw6S?R_9ibEP8D@5+d7Qm1h|0#jNRlB8?W zNH!gD5OlBv2ixC5K}M!diAz>c6enU5ukj-vu?MPb_`g|zhd)lF%_$+#Kqj|MY={y) zZSn_VA|fIP#6g(a9qrgsUmg@`vtiM48Hb8+k3e;}dwCHTF0vMHmEQ}Dl7!pM&CPfU zYQk%O{={%B_Vi#LLkpxFoVCP1&R^Z!41LPo4PZipRb zg(yXtXIg8FEXBbhS`v?KQ+o2H2_iGpbKet@yy+-Oddd^E)11xuVU_)02KXl!KcwJ} zfFnhkxW8lfZZ;6g-_7};2k3xylQk@6tj z@V_st=S#&$r@IrP&hs0?=_h-0HJ5>Z=0#YhE35*Ke)bUm`MJFvk+nUVOL@@K5sV%| z$iS&@Tk~+v1REWpGkh?jQ8bxS3nj>BBvV@x(aJn;Y_|=r0+qlxQ z)kj>9>(OJM(-OI0G`(WY1cvte>)%v6K@JL9(3r@Kspv+aR_Ln%B@Qh8&h9hO_J>Q@48uFo8QHc%qYBGZKC2X~ zM_L&kch_gv!!%+pn(>VCmkMa;=qqjhQ7+5{_{N1mV^xwF5kmIEC3>H}cZOo;Gf!_v zUo;3;%irJM9OxFR0AElM_;9c0;qKm8Zo5$Dj6=%Gtydh47@1u$2v*r!s3*)OU&zVH zS?`VMnnIR@r;mMeH1eo;y*cQAG9qSaY1v;1>%zKonr`-T-RSGxUurHhs)&s&aa%*0 zT4AgNKHTxO--eWdN2W)sGRn|Qc4w=YeW34={ql8vaSTI`8|(>aM7!ak_$ByT!M9f@ z*qE5mH{N2{9OPVv+=gFf?-NqrrmZi^%7y>Tk+sX_AUy0-P)_vKYDl-z`s&kwHYr%cAa~@NP2$zv>$!TtV zbDUA>!NP|e?#&6Yh&oR10R;~9MIXm+AzxqLIC^PnwoE2vTr$Ljyy(YVi8ojgp^^EU zi@)lKM0q2F;`0` zzw@~lZU)2UQl==(M9OQ_YfAgety~w#+tUTt_D;26?t-JWaxnelhL;n?voc=$S#!`a zRK^U4?YWv4gb*yz#soc!rj;OZj-ij2@%J&u7iP#h0`}_Mpch*(k13$&p&PrmtE6rzMCOpOagf2w?2g@LYTS3IS zn8&PccyBM@{^|w3_vx`gnIS-2mFl2-AVNaI9geoC7rZ9bAGatw=!1t1zM2|XGOFRT zN?(!N`(|;!{~?PLL(Rm3;oglBo&rNb^vClRPW9qoskHfBF{&T019h~&($28F8B7pz zMMWdd+`wr+LuW+98LijVr(gPPO|bKELZ4}s4dxf+;bpam9qZW&%U0^oJZ$vR{Ir#+ z>7Q-*_F^B98$EKWjMax<-CFru<$uavZIIp-b&@xFA2FFi^yuJ_<@&P)_A%5kGaZJS z3y-^_J_hk-zP3w+?$-q@;_vaIm#?ObtU7;mX-1Kii1VWK^89e8aw8Y0`+5W7vuf)m zgGbrjG;70TR$svu?T6EdrBPyA@6C)cdZH**tx65bQt(SvFv2AzrJI=Tmt2;bUTPCb za_yPn%SPiSg}-EY&Dj3gq=uCnPqR^n)PwqEv^9(M1&jIzxm}sNQ$2|_RgYI=CYnKR zoq1@DuQwGYV7)?R5RFi*=YvTcsh5P7*zz)nIAdN*NQit2e3M@ zZ&|iBLN$@73k2a82x4aItySYo*G=}c;7{7wxOkvX97xNExe{IG5i^r|7rI}07vW3_ zjxzsAEzouPfRxhRjb*qED!V^INyb5$V3DdCe%zudv=xQ>a@_ z8x?>afw@kaZ7`45;0@8=ArM42r6{;x?L_Aa%X{i@<%~f`Igd&sAJE+~9hfQY>)E)r zw}&sZtRay$JWly7uH@^YoL8`xz?&`2KU`XRwV^iC$`L6kpr-E??f1BEjAA8crwp|T zzJ*NM^QKVrth$IKz)3d85AbX!3=UBm{>R$W+?ctxjl0uhy-)nd;~%`ecxp zt9FwSGRSbhRUKs^eN96_%PSdPb=vE&fsLc#8oA>eIm)-q}j&H$(ix-72qV&SJ(i$~G?RUI=72zotnWKG*f;m57 zIvw5#?kO>iQMq}rd(0f>`%(+mG*P!U>%{l7PxY7jf^~6CrplX?k?qa~fx#>5bPBJ% zw7!oF8u>Jq^$fE!Y&m)>%BA^yGQo|0Gb?kLX8oqqDir7La82>bKPJ%S(~vc*R4@Rid)!EitVsn9d*E?sJB_ zoPCS<4d3c=Q;3)#l!$7b@Z8WWB1fB|JixS9qw-2}nC5E=Yt!_;pP%$N+0tqZCd*=7 zL~ZC!!&x(56%HGis0+}U)j%la$&W1%p@$Elo5|&_MdD!mf}zUO!nlq3+~#XvB6wdi zbhT676yxC2ytL?grzDK3s@g%~^J(ck1cfa&N(eU)B%zI>B(Fyxjrd^wvnR6Sfb_lG zcOBMKqX0MqHjR=i&OFG8*I3}ka|%|vgtyZLj}HsSb@&;qg-u#Ct62ppnB~7R`Rikp zQ}{8o9-+M<=R#-FK1_h4e}^`)+FN*kPxG|qV#10Y!b!x?3#NU`zi~RVB`p_>V72bB zc2TXGJ}@ULM#IyMgFWACY^Y}@} z23AG8YJ2yIDB015Z8h67Tr#FmKj1o2eSq)o?2H#8YkflEd72tzKJD!sPos3-jyqKP zK3~ey(UGjFk<0AzmS?B#Q%+SbF}T)1kmcP~F^6bfKUeso33KT-kn13Mw>nS=PAhA_ zJ$_~&NjsG-;z;@1SM8u_R*M3#cp?GJ2wC|Mt4V+`}TWHj1N z9>shRUJyS^v17EK0|7pEG?k`J2~L5_EZsVhB+2rKyr?*_n_M1R8o7Wr|0?mS+_#ba zkKNuX!=M~Y7DyQi5%h$~g}KKn&}9*4Gyx0A1{Fxh$@XYqdnFS-uDM8-I5jR_ zk@0c}6=KS!^rN_zu~`XAIarhD%Z*JwWtr)Gkvv032<5cN*nJ71J`I6Gm3-|g`#b^a zapRlqSIaRiT+f8wu!xt-WRXQx9)@ZjI~VT6rX_vxZ5N=8rcxu(L?`aCF7I7*pm@y8 z@+$}*dXBNq-V{JASl;@Kj0*u$M^5&I{03UKCJ0hMv_?82Q7O^sQ8oR)z&lSO6rmvK zIV*27C%oIBV98+Z=I@T}pKaTJzsz1WqA2vMGS2te!-uM>?HRlo*r46}{kl}G^RPcM z;7RV=CnX^0IG)P$S~J=d3vz5yW2V^U3wII)WT-BO>k2~Us&ead-fI~dnOhz;1sgCV z4w5|nb|p3Z`Pvvan9)j985D`r;(eq59)`Sd@1GaX;HQphV+HnYP4XUHD=SvZFL_t^ zi7e)cBYRNS+}^zLJ>R4H16C-YjPCsOG`Fd#Nm4>WUZh~=r&}ci8GjIs4+evUQL__O zBAT0}Ccy^vn{TJ!@q`#$6%Zdp_}~f@IrauHDT2hU^J_%9dwRGLli*1iMtmn`UCyY> zgWq8|P*3^6;7Lpny!P%jC^Qd1q11=>C=P$4jQTkY) z^*itt%EB`ZVL)dnab%1`9~_l#2&};g8ggoo3_FKr9T`w0lkiJ7kRskIrRG;4vz*we zOid-Gf7)ygDX36DPi$|nX;2U5w;}_$se@=P;1rve@G^TV><Zu71q$uASVN#>LJ3#j?~`h(#dJNcU6pr z#(HEGGDPGBDa8ikEGaM))iBZ4VyV|cT~)z%RpUX{pH=Xo-PYZk9m)w$i z66yZrq_Hz2)iyHD-rz8vcW)is<00_#w6_j39>TaJ6a0|Pi9@E4=9lcWEc5Z5y4b3o z$h3&U&g)Ds$RO)@=v=dfnxcP~_1dGOk(f4TvoEHn zWe9<2hV!YomDt)3`F-0lGdxyI1vtEYAH;j6o>0Cb8#+0@5;7B9X?%Cry%x$Ov-W3G z#P|5(56!fLPTS6m#X`>G*J`sgKwquz%{A>#j(0K198FvbV0${3nKlQs!)&v&EmR2h zt`3(iU`D{zdcL_G3+|Mb6fV~<*rwFl8cq9ou>I-b9I#(sjQL-T9N=Xda4_rL`uRtk z?=My=RPFQ7WJ|kivdRQr+f4@L#Be4%m=rSkVVm?@-CWeV8owFeqw4otAAJ7N$^6?F z+x7XgL5lsUrnz0)z_1GZFPQ>XXD=9~cH_(5575Jm!^#FqkA-SX# z;}4|Kt!TYfbIREec`&j2CQ{<#s$W9EbMe4m-r3JEb7ZbxtelT1vS~Umv_AbNdDedO z&aw$VJ$7&5(H?GCXtxV%9IbiV;HM|`dpACN@TeEs&ev}m?-#z`wQ-s?zDhLw^RVcv zU+iRd!B+gUDDxtP+sOTPjPLo+{(ET>Hm&oaIanjq!<5IsJ3JH(*;cs7WKm1i<~187De^zs2t{jx%5R z37^UZ*=yaGzn!s+65AV$ml(>ImU`~rO*>!K z-S)k7`u5m1rL-oG$f>@wRLgv&#f>K&`g`#yStUPcYhN2b6B}n z4Q+osjN5iu#L;BD|;fZ+DKm zumvA=tS~${3OlrT><na@uLX2u{=7L7 z@Ag*j-%mLXhw_tOUC6$>M5am7^rb$fp0^b>n+SJo*0w}yKU5u%zMt)JJ;y2 zSQKk6=j1%Szw(N|@%D`%w1nILqcFjO^ieaLnogDJ2%vl9#meqyo(2n`SrV^r9Y9aECOYe@Rv)RPax+Dvq`i+}=K% z`)_e!t+vt>@Yed1;nN349Tv^3jit;P$Vt3V10j7RNo&B>k1s^xe3aU`a`>BoyEEQD zIzFwfI#g2s0EjT%G-1rS)fcTkM+yN3HLwXf8biecK;)FIY|awxfnxO~Pd__#r-o z^u#hxuQ;awFN&`P3|7NgrKHycG>OnRhW_Cs&$%}Eo_zrnJSer}Y)8nB1+9MN^w-DH zL@ujf7b~zlbmVhNqwjC~o?jwGS<0rDlomdFOLe6xRgaCI?2nZNPE6CO1kU|Nrt4gM zc8h#wEZq4lA)U0=@dT?|OKGwrl|0cwt}T-J)VVMx$I@j0^9m(LCSbD4{i~JX7omv^ zLYClBJb-+_b9wGf(RjcLHUe(be@DFhR|GeoRX+ZuxnFO;1wI9o#+~2YwV#lNpZU(` zc!!{Jjp4qgGUSc8nn%H@V&8_X&E1bN1L$~fyM>UrT6|jgZoy&dq8dJ?g%C@JRXhZX z7w~r^r0)F0zhtqoK_p$kT$&$)*Z@d>0RacCc5p!SSRc27LUeEdg>3;f8JI-cfg+-8 zoapD7X*@)+a+`~?Fqi^6(!GCw=Rds!`oF!z^!TZn$v+v50_>5WL2eC=ja02xSnt|M zSWG(~xgGng{rdH5V*_KV(#HJ|iyxSUbKUX&E~nPEx3_=){!Pge5?v0~R#AOngnbV= zQ-!jKvrjJK;d-22xC?+v!lR<15^=cZfmp|Q`2W*PL_C>OE=1$Nen!bi^y4&9PVi$c zQ&`vWehViH^>{5aJAR|q)Fo)=n<8fz6#w^UsP~XWq~(Ukr+=x5dx!r}6D-%`0gaZ4 z_+QPc16AlUgvH_cm?E@HzTpU<=>eyrHJ}M%c^L}Rq2CXx)p!*|k-C+NDwK6QVOT)t z*693dV`<8BBT`7xB?U|7!dn>XlxS^<|K%ond5KSzajH=7^dyc|A{+7<6R=f_>@a{I zEG+66m8_N)N&_MVC%I+ns0WA=L<*uboogINZcGZkBL6-;%6Gcv=jG)k54u7D<_!UY z=7xrThIcWo$1uQ0JiGocAF&adAXMcS&wY-o3a5`~iFtZ|%wrHrBMQ)F>7I!z?Xmpz5$l?OkKpWR`bcZz-uH8i z{%N;~dSEn>jTL|OMqvk&=Q0Vox?9qPBM}KX1V7yPZk~832Qeo_41#*9)`;6MPb)xx zWl=%w?C(z?8M-H+cZ5K?D1!#BB;r0{0EH7p{r6^|`*cAV3rs8Scj?AOMJ?=5>3w8F zOjx3mj|?ZEQ95~=4ina zL%?ORVY$^eDy|2>7y$a@KuDfb#!`#CO5!xYwa|DX-#(Bl+s^p#9N_fFYqrh&cKz|a zF*LtJodF*Hd?*DV!R3{tfK3=oVD1Cp`nMzu91?DmY8KnxXa%~cPbzdoS*_Z+=;Ef3=+p;AslL8<;n~UhzALNli7neC#I8Y52wXi?P6P!8OO} z#Y$j=gkGK;s^(XK{Nc1SODdggjo?vm&o;eve0K`aI%ee|6k8gL2f*pvTpYO0l+%44 zuY@UX1S>lm>KCfS1YB*V&VO_CI#{M-c$zI4_S$Xd)zs&aTv@9vD!@R@SOvxqn*m!a zU?a$9Tq(EUzlID07%|6j;Vqzp(v#YJ;ws&zzq%8F#N2KQ`35u z+Qy=h!~&YpC$1#%d!_;)yG<#7uFrluV4G8tMS+8+ zMWy@+MhqH#FL*`WzC4w=!noU5>xx)=I%mTy_VNeD^8#!@Sdr|m-Kf{tkGL^4d||hG zW8mlK=f(sWl;4YuLfW)vEnWxo!u9qe8M6ULKf@Nqe$Yb#5hQEyWIV$U*WZCi*9qN<0BdO1*}vJ(2-wEYW8QV6pIfQ8&5vv1}NmpxUHf{ zVh_H%y{rmQbwJ%(7%x=qA{t5Iq1nI*C-fnd6qXDg4vh_oO=D3f0kAoW@e;%oa8u@W zPU$8h{HZ|26aP3|@>+qh*EugxFk?rku!SGBKOdri`E(G|K+wg1&Q{q9l(=z!WOfJW zRwy>1%1Q{W9P7qyak2yqiGj}pqjqAKC^&`fFag^3siA@xc*%ccz^XNSwTl#pN6F700JSnEy9pfoyX@H-CH+?nzhI>_1vKv{F z;BL+?t{vF(p4`pv8mP)?9QSK_dU~QUKrEU(N&2Rot`^~E-r`M+shuJG5~%1gM~=;e z^A7K@yD&xVXuzET8~OA(KQu0sM8azw;D26keg3(~j z@f|scXLy-*M z3@LpL3~|$VopQ=_t6QK&Q2z#jJ244pTslpU|)$KOzeMDXL%KlVl$QW!ef7$7wl{lk3R9|MdPin}kq zXO;RFy?o!jut1|n5Dg+@*R$IrFqC9{kBW{ZR~L`{hOgzcqU{=Ys_WzXfFMio!=u~C zk55vyrA~pnUz-tB`*LECAWhVi={ue-R(iWeGN-8zFqS6R7#8Os237T}$rYtc%q)At zVOX}f%mgamYHEa@Sv&6*Vj)~K-t^)g5bt$IDpq`>w$ZU@@=(8_;9(Tgd1Q`eh6}F< z{vH}hH-lGzekOb}`9-*J-jM#^EI{xTlUQC5fMb4hIVt{5FZsl}Kb!JMX&!x@T-TdH zHCys6exQJATM`qqLO9euN0t!#79jMh-xjW`ml!$oQ%WEl4KO0rh<6B%ZANuFn z2-ab%VyOsb1&Z_WudYdT=<#zA3FUY?P|<+`b!bwRYlVIc3QK)M3}}gtL!7Z<7ztKak}r-2+B=?v5S$xt@FzP$rRsxOf7aVSHZaqINBI4 zWZgFy$N$J$@>QE;uY{(&@y)fxvrpOt45~Mv85I}1!KB^6WG+)l)@L>Hc%f*lT=s0k zLI{ypyT*d>FnmG~HL5Ho2WY61AzVwp@%3{LRq-Wcj5!VSgUc!)pAm1qXQ*$6{vU!m2L7XS6KYpQ9jcKDWD zd!F2bjQGLo#xy)`d}5g$Qwr_fsx@j-S$TMryr2nkWl`g_j5l~Iw+(eWeC@Spxz`6iJ56XmoXKP17SF!UygJ?Sfg1vYMBl^*pij6(w z%n9hL1D>m*$(p2P5hoGpUhylY@L7S)a8{UfK1rZCFmSVj7UURF2n1c1AM0cFAbDKJ z3&QxRSjAIleGy#1w6pRPJ;<`KllZdxEF?YetGg2X{*}Gd?to1O>0&H7vIXXsmAQ92~y3iy*oSGk$ zFXHAnPGim8ZetV4zqP1?t8ux|YS?6>(bvh(jL6t&uV~Atl>U1vRR(vWHFEa)XxEJ}Vjy*KVQ9&va&$ zT1_#ND7}CUb$6|O#3-gUPNMqXWB9@aDBRPjOdASP8uZF~en z$b1vpRUrEkLS!Rr+2RewHp;3N-$?(zRJxmSec+L=>ea5#NLo9Dm-7@d0{A#zD(O@zeVGhT}XjS@>e{Dhw<1(A6c9pN<$#lsO(AcOUqr_g_r9Ma*69Urajndlu30@}aT}oai}# zGINj)+4NK1JOG{G`)Jvp`GJLr9{b=gl3vjKi=^N4M#}z0(l-mTV|?8La^m6Qk~k3! z55D2kARJE+*n{N%o_wg?d>05XRLcGU@WA2Oi7(9t#M+IVg|=5Nw_6*^%gY;22zx64 zM5BIU9+z@GwR)(B_UdqjDg`O($T9VGz+Lj=)=Y?FFP%RoTn4usNSqpJp@)=GPvZzc z#x)$cuJlcn=71}XWiHI;7i$rq$RY)iP&qtueHgoVX>8(M;1=HyM+VL%I`=d?!Vyqg zL$IS~e&}}J(9qbqE@NJidCnz|c$)@<7k@I(pDgCvc8s$lVj$7SFTII7wRnM@_(j5B z2z~CE=`L&>cmie~W{I^uC!w-o&gg*=|81F$xIRwRwT})iHdKkq$Dd{2*6U3nki9RX zxZ{+G{;wks-PSvwi3&6eH6FD{OOKGy(b3gsw{Y7KcHMYrWiV}~7PgUkh9Tt<&wKC0 zrP$d|^KT5Iwyv(OzwJ(&bt6+(CDH>1lxJz0IN`>{)>R*rHBx%5K71S?Wz*uU$4g~@ z)P8nyMmOL5rVF>Hsou%syjvjMdwc8be<0$$^_}2WfN;-Nx&MjJp<9@)ka<4LA1EtZ zV{0MqUl7p91SD8zp2adq>Hx`o*NM1x)WE<8pXYdm>`oOXbtQ_0rkArPQLKI7KdDrb zqUEj6M>re(e_u~g_Z+wQo~We3y9OeW@@m7@3r(_R)8*|RC(9o;Ib#{Fi!`%DJ(YU7 z=e8>5B&{zSvT0_@&8jdW!LhNUIgi`?@8;nqc!yJA6KwV6cZyb%iK-6(>l>Z1W!>P_ zQG3E|(q;o>rq5j#SY+v?8b;@OitMg5ZoHfikYuHecdkVl6|PN z@@Rm~uMO7!3&B+gO!nV_m-5VesVA|hN4_Q>G$;+YTBJ&s=vZk7;PPzHOnkGPJcN~L z&)L7yoc|ICCmZihm|hf3QCCwFmAlKfxas^dQ3c#P<}#P>c&Rw~a`E=ZoZiD?JGSiRPO!9r!-;oJPS&u{R?6h`OHu0 zr5^*QOfFp~?E8&Nyi0-OC^-`MMn69e98>aA=o$>`c?^~4ve23vK)YqkA8wv~up1Cr zSo_g9!SSr9t_^QEzM@ZCZuV!NJ2L36+Rm6Cr%=^Uf-0_N)APGrLX9B(+@A93`i0QRO&w!bUk z|2!K?o%RxdWYN;ml}&!mY*(uqC=7>>>g-O;^V@;<=MBGV`=NW;Je1B z!g;!pX_@Ub=he~gT4B-D0NXsU-`&R{(J#4v*`#SA_R* zg%sfrU&~?FeK&JPn$gxTFm`Kkmio6rL^CKe|^9Mp;)Vfhy zbHhDdw|F8-Ok#t7TH}2ajs=YN?!r-BQx2dbA09P34Bxib0@Q$>yNueqh-HmdDRiu~ zs%)=dBqk+U-DXAGASjG2&aJF2p#w(AzHx3aC?Yd6bNuEx(Vtil=-6*_;|w`9H8sF- zx+}#+ft_mrb*H^*%UWGsl_L!Z2xx0-3+QC(U)@XMPe)w9F|fl-Ve-MT_cFX#s8c`& z!Cerh3?!{t_L;*JU#SAe@8lr)vapJqut{$bijTBv7C~}qQJQE2@d5A2z(dV?;%a_! z6R~;x8=klN1d;z4g--Mi$uc?vH14JE{ zE&<)YIcNHOvF|_*8sQx`&3OHgu!jt1J|aE$6Z)?hbWVY=HiGIO<@gFIpBvvz<%EO! z0a2+g4$PHBu910BYBp@wpNuxL@$};_7>`#=lA;0I($OJTIF6`GxhTL@uwkoyQYd=^ zfJ5I$Uu6}vk+xdm8%FW?vh8CLCre99m{4~hs>{HR0KltXqWET)$`_o7mU@QI+_@>F z@NVU?0U++TnP@=(z=dyFao=AaFkm4j16_?@N!HHBl$p5&i155uE?EBd}7ih-a9 z)_#aDL9wuq5#;iY`#_*XLc4iK&5~oy54rRKFI4SCrnPU`k(lbVTIoOOxO8@7(i0;pg!Bm+)hN&7AK}sKyi80*tLlBl*`%MJ`Wz zu8jXYK=^<(?{b5Cp?oM-6eXXE4L}q&Rg{Dsr=6Bt-i0WMc~ZoRI8KvsJj3u;$ek_K z`vkB?Jo4hFxyx0ys>EKq0ND{+@v}`qcy`H22Hv;GxL+QwRTXgr+#dDOOZ%+O&wY6J zd;06c?a3(c=GPnj`HuoFmb^q>O%nYADAxA$SF;d5?mcc=AZr}#7ELE*_++m7`4GVC z*fi4^^?}+{Pvg%=H1|_JjTBe1wq9MRcXdB=9)19_w!`T{Y#K>wxyArI6@K{x^cL9d zzqvVg2DtUPmq8vez^N9Rz4+>+rKS5~XfDoXtO~`feRcuJH(sDTl*|<|Fg-McM4OBeCZ z5~4iCC!mVq(Nsdku&(fAE+gQrCqO>$eXE-aklFqqrJ}!fK??9c&pf|q-n3JI^{L{{ zOIWq}0XY!C(25E^nZGH}g}>=yd)LWE_w`=!(!(McpFR#?<&CRQ(M_)A}4D1t^}OvtL+L)UawCJvr;cCa~FccwtAeQD_~w7NjD_ z!EbYScL!?*s)gPk%uLYRSXRb`uYcMzl*$)JEi$M9{fD38O*}Caby-Ao;xJP%K&62i zRU8CvEr13j18%+VEYmuHjlcixrMpwtDnO#8>=Xhp%dizG+vEURnU9AJrVa8Q$(EwT zN@&A4)uyE!MEf(8EhQ#sOQCEN0jAR_>WUyNoY#o}ZjfGD&L_BWzd-c3h{ul34jLJ5 z-8B#it13*!U2oA3Lr3=o^1T4rlJwXix(_^?GICJCw*a;plZIP!-yBmjGij0>x4&o0 z-kp+q5WINbwDz$!_|p*(dY1*b_ZtyAFdF6kduz3)>4MLJ47~W!{oT#_tDgw9zI6Mc z6avohD70-dMQQmE3?Nr7)~28-|Lu58@J>9|DX5 zLU~UC*P^7a0A#O$6g5*l@Ls-a0uH2V;-~L4!SL!G*QJ`zt#VfK0WD$0-oQE3C1> zwP^MEHk`}$lwNaYwqtSU&!44o3n`~{B5{#4Swl`IWpV5Ijmcoqq}>t{&xnA|7T3Az zN4*Qc83TMQbZxtf{Ut#{72qJn+k^(29^8#m({G&L$pqB&NthS+B~};%nCgM0tfjw?$Je?bOaDK;SxsL72gh&}it_sgOY5SPbQg zI-Az~sJ0*BtQWY=3lbCna;v8F_(CJvoz^Kdpg|xfFjQYOP~WkRNE>DT%&(7r750dK z&ZgFZ0hXs8rd)=^?!?CzK#q|V*DtNf`Vpj|A6t;<#AD)7F#av0v_#mJ!zMhAPL8rz zJNrG1ug~(*s5P0}gyb`Pw-vzjhdrxIodHUcrsVdNk3qXko&G`#<0*w^sCDGum79s4 zWr)=FCJ-PRQIA>r`yPGXUk}O*>MUe%UBh{>F^&?uwLx)QDR^U>K~9Vwg&rU^j4_x^i)XYiD1X8Zje96V{X{1ut>!3a907=R9=hsQDIc{IbkOB(V7s-cybI5>pgt> z$B@A&IvAc@yY&+VRiZ?n%R|^D@+-rVWHpULTcnBOi9b>xIL?Csd+QcBInoNm+ydbB zaj(=G9YynB(mA|i*K}v}O z)hPKxaB5z|iYyZ9$Fc@=H~9S=jy8v;`LONbhQOwcx2;0+yA#&q4sa@J9YT&4RYugt zyAlo+I~;uhWaVYdfQgX!N9ykoH_|+^o!`&IiE@IBH8VvC&T z&ay-tDd6aB!X)Eo+asA5TO%|Z5zWg5%6KqzL(b?U`#ZZX^wyvN7=}W0h0xnRP4c8oLLVChOgAr3G_>nI}k+9svwNdoOMpsfxN2q`4J zP#k>k;S?m<8;fc?oL&f;6X?t~Eua0a&8^xR&w5-XD0yw~)A<|kGi=N0Z z^{>Rb#Jr`Gw;}N`09{cwan^PHfAG9$!US(jsg^%V4YXV|4wVRhvIy(H+we&hPvZ;ynT0rwb@1SrIFJ?6<7)1v(rbO^>a-0zn<*nE*_yP@LdszsCdqL^p`?hA!?r37VXahzF_ z+-A|qU{mtoAv6Nt4_~9wd5o~u$6YFf-);;fsPkxHVPWTqj+MsdWDQ3V9h+7AM@2O?9w%gw z7K_`EwrttLlANykB83P}NvF~jX0o`d)#6UiMFaeov)#OC5?8;`(vVVnZT(J6!j{rS zc1-@TtuPFHl&pt+{lyhF0j(h=QtYDtiXlpp$;Y2ZT#4JT{(4c?UT_6;+IQvyaio&u zVJb~mR5f7liTq*PDV2(aE)*qh2ZOSmq^TAMF7L$`E{_*sm2v{&IbFPQJ$OWVa;3q9L-~(uNWS~zSboWFNOoH=kvoENB2o&%e;R}QB z`Gt>Efb?x^_9&^gMx;*cuYIc;g9;1SduqQAv@t;YQ@!)2qFc>6%Wb6_}iC8;vUq z3S?M^En}x)yJ!boO|0UevniqF@5O%x`TAWt@Zrhl53&s}+$5q36);)HY?Br=)>frA4E5PeFik#lB#wKe*<*~LzHfmH1nP|iQ}O9S4GGf;6Sli3Ci^=W0Uex;Ra8VaF9<9( zTCsp(Af1sE61~bG#K*@6lJFq@?VGJc)e^x<72^MC)&CKy{EJsTx=NWYx1ckC{zJ~T zPtpE@VE~s2BVhH|Y9G_}9&sPvx$kz$G15$pii%QXa%z(r8m!tF;Pxpp$q;jF$hC^- zjSsd?$E0W>KF;DHOG!#@C|Pm*mbu&rF)Il&aSK)SxaDN0Ot-9}tx*!V;upN+=(?An z==W@K)^YmUSq4lO)ycgwK zPZ3Iu_0a+q(~HhIYGxlioi&)nfo5syRBH76+-H;l7?u}9g81m7i+4p}v(nlKLZ|xm zt9}g+POi)xE?Qw8Sxo<B1W*d0s2BDW$->I+?oPQ zCsYFA^gTiw@M%4v1cpfb19kleSruh0riAWt8&;QI;~* zx0P(y$yy6NOJH;Ai`wue)YI;07ylCTT7Hu^%!+kKKKZY5zq%{-&aq|isW_dXR;VzC z%JaesK|?^Q!I7crOcK(>$?+taqf~vNscsFwA0;pUy1$IHghZL?@A-DpyYKA4n6Zas zrlmQJJpauw5cPaY$mLno%g6+SAQD_jG0ctRdZjdkSO7}n190)7S#*s?w|fAwMsjLn zsux5r2qaEzP&;M!w+8;!uC8+Tvertf4m9+*P~|Ld``?NGBoM^M3_Lv7fQ;Vj;EP!F z_j8QPkC_?=iP2flAaeA)jOdQiE#@BgjXWhe_Vz zCMmw1*F(H>cGZRjP#v&5Wp5It-%r8*9Wa;jIn%%8QIQkKC&MBqaawysI3%mMbD6B_TXJu5<6^WvUGEaKFXv(>mU-;iea*zJki_7=ZgG6|WRv5qW=pQ9em|bA zXB@D*+JLxSC<;Fm1G=u~;|=O&6#A7clRynvzHEr|%l6p#i)C!;)^z_uuYFHN?(7PB z>nZU&Py12CnKNf(q?!iL#T|ty*PFH=ry^Ty5y3`LiSXvcL^p09@T4__cTm|fX6ey9 z&SYXNQ#?aNkt(;1XUz>JC`gD```(OV>Gye;#RqaSm94(bkYVHsHCQL!LAfRbTJGKh zE#%~SW2O^oOv4}UDah=IJ^YKsA;FT2gF*W3= z@u5pOk)GwJWm+8G`~gpT(6ON!BHM~K?i7kFkrEl?Aw&sr&c*F>iBobK^g|UBD2TJ&Tp)Xm zW}4MdKBu(zlR+F?5(qqa{0oDHmK+m7cq2n{+)N}kCI)QbHb_I{YxpG#RF!#1z$kRY zi#R2QNQ&6(2k!s8$Zu+TItrohoMYsvxn%2Y)PrMI`yZE$jtxuOrX_L~sp0WrOb$xh zpHe*Cj+Z2SR4BFw>!PBm7Ti;J#7tu0awN`-#& zI{v186?eOOcpuMdZu0xCU!}BtZ+rmP6NR}7<6CE27(~e>g+S++QGe*KAoLcIquIr1 zl(kBa;n;v43O@UI`vvelKs!0$FS1Ictfv-hIWM({4&yS3M{+rD!Jkc!+#H2>yLV`* z`x?n4{A96Yd*B|EMUo{60kiVk?cA{WK?Y}M#6N`tHonu=9(vQB_vEVIIpck9*y(6l zP%;lBYP%J-LJw#V2sReP?85GB#8S&v(#CX(N%`|5@49r#q?>p{otGAs3=Ak#+vPQG zwY6k{M&%mr11SgEx_s=oyB*^cAKR#Ef#}`%e0en7(cv2J#eW@yGA(;psDdrX1aM|& zei^EymXsou7TH<(gVR{W7rpX73W)!CMNVwRx@VEThIwe?oV=>4s)mLJ!20C|1BQaj zgKQer0)Ok*O9G4t5L!&);++o{v%?_z8bK-&!jb6d5Bm@uUp@>m><yIhn`u{U{TcrOuIp@p diff --git a/__tests__/html2/speechToSpeech/outgoing.audio..interval.html b/__tests__/html2/speechToSpeech/outgoing.audio.interval.html similarity index 90% rename from __tests__/html2/speechToSpeech/outgoing.audio..interval.html rename to __tests__/html2/speechToSpeech/outgoing.audio.interval.html index c9b66026d8..6ebfbd99d1 100644 --- a/__tests__/html2/speechToSpeech/outgoing.audio..interval.html +++ b/__tests__/html2/speechToSpeech/outgoing.audio.interval.html @@ -17,10 +17,9 @@ This test validates: 1. Mic on → state becomes "listening" - 2. Audio chunks are sent with timestamps in value.voice.timestamp + 2. Audio chunks are sent with timestamps in payload.voice.timestamp 3. Verify ~100ms interval between chunk timestamps - 4. Verify chunk structure (type, name, from.role, value.voice) - 5. Mic off stops sending chunks + 4. Verify chunk structure (type, name, from.role, payload.voice) --> diff --git a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js index 7f73b69c9a..acdbe974fb 100644 --- a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js +++ b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js @@ -173,9 +173,7 @@ export default function createDirectLineEmulator({ autoConnect = true, ponyfill 1000 )); }, - emulateIncomingVoiceActivity: async (activity, { skipWait } = {}) => { - activity = updateIn(activity, ['from', 'role'], role => role || 'bot'); - activity = updateIn(activity, ['id'], id => id || uniqueId()); + emulateIncomingVoiceActivity: activity => { activity = updateIn(activity, ['timestamp'], timestamp => typeof timestamp === 'number' ? new Date(now + timestamp).toISOString() @@ -185,16 +183,7 @@ export default function createDirectLineEmulator({ autoConnect = true, ponyfill ); activity = updateIn(activity, ['type'], type => type || 'event'); - const { id } = activity; - activityDeferredObservable.next(activity); - - skipWait || - (await became( - 'incoming voice activity appears in the voiceActivities store', - () => store.getState().voiceActivities?.find(activity => activity.id === id), - 1000 - )); }, emulateOutgoingActivity: (activity, options) => { if (typeof activity === 'string') { From aceca000221ba6ef4b6566ace1f0d61b8d1cf9f1 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Fri, 23 Jan 2026 16:15:16 +0000 Subject: [PATCH 16/32] refactor as per comment --- .../html2/speechToSpeech/csp.recording.html | 2 +- .../html2/speechToSpeech/happy.path.html | 2 +- .../outgoing.audio.interval.html | 2 +- packages/api/src/boot/hook.ts | 7 +- packages/api/src/boot/internal.ts | 1 + .../ActivityBorderDecorator.tsx | 9 +- .../ActivityBorderDecoratorRequestContext.ts | 11 +- packages/api/src/defaultStyleOptions.ts | 2 +- packages/api/src/hooks/Composer.tsx | 23 ++-- packages/api/src/hooks/index.ts | 12 +- .../src/hooks/internal/WebChatAPIContext.ts | 9 +- .../hooks/internal/usePostVoiceActivity.ts | 18 +++ .../hooks/internal/useRegisterVoiceHandler.ts | 23 ++++ .../src/hooks/internal/useSetVoiceState.ts | 17 +++ .../api/src/hooks/internal/useSpeechState.ts | 15 --- .../api/src/hooks/internal/useVoiceHandler.ts | 9 -- .../src/hooks/internal/useVoiceHandlers.ts | 9 ++ .../src/hooks/internal/useVoiceRecording.ts | 8 -- .../api/src/hooks/usePostVoiceActivity.ts | 10 -- packages/api/src/hooks/useSpeechToSpeech.ts | 36 ------ packages/api/src/hooks/useStartVoice.ts | 9 ++ packages/api/src/hooks/useStopVoice.ts | 9 ++ packages/api/src/hooks/useVoiceState.ts | 17 +++ .../SpeechToSpeech/SpeechToSpeechComposer.tsx | 2 +- .../private/VoiceHandlerBridge.tsx | 16 +-- .../private/VoiceRecorderBridge.tsx | 33 ++--- .../private/useAudioPlayer.spec.tsx | 82 ++++++------ .../SpeechToSpeech/private/useAudioPlayer.ts | 20 +-- .../private/useRecorder.spec.tsx | 81 ++++++++---- .../SpeechToSpeech/private/useRecorder.ts | 120 ++++++++++-------- packages/api/src/types/SpeechToSpeech.ts | 9 -- .../bundle/src/boot/actual/hook/minimal.ts | 5 +- packages/bundle/src/boot/actual/internal.ts | 5 +- packages/component/src/TextArea/TextArea.tsx | 2 +- packages/component/src/boot/hook.ts | 7 +- .../core/src/actions/postVoiceActivity.ts | 21 +++ .../core/src/actions/registerVoiceHandler.ts | 24 ++++ packages/core/src/actions/setVoiceState.ts | 21 +++ .../core/src/actions/startVoiceRecording.ts | 17 +++ .../core/src/actions/stopVoiceRecording.ts | 17 +++ .../src/actions/unregisterVoiceHandler.ts | 19 +++ .../core/src/actions/voiceActivityActions.ts | 100 --------------- packages/core/src/index.ts | 34 ++--- packages/core/src/reducers/voiceActivity.ts | 81 ++++++++---- .../core/src/sagas/observeActivitySaga.ts | 22 ++-- .../core/src/sagas/postVoiceActivitySaga.ts | 4 +- .../sendBox/MicrophoneToolbarButton.tsx | 26 ++-- .../src/components/sendBox/SendBox.tsx | 9 +- .../sendBox/private/useSpeechStateMessage.ts | 8 +- .../botframework-webchat-api/internal.ts | 4 +- .../src/private/FluentThemeProvider.tsx | 2 +- 51 files changed, 574 insertions(+), 477 deletions(-) create mode 100644 packages/api/src/hooks/internal/usePostVoiceActivity.ts create mode 100644 packages/api/src/hooks/internal/useRegisterVoiceHandler.ts create mode 100644 packages/api/src/hooks/internal/useSetVoiceState.ts delete mode 100644 packages/api/src/hooks/internal/useSpeechState.ts delete mode 100644 packages/api/src/hooks/internal/useVoiceHandler.ts create mode 100644 packages/api/src/hooks/internal/useVoiceHandlers.ts delete mode 100644 packages/api/src/hooks/internal/useVoiceRecording.ts delete mode 100644 packages/api/src/hooks/usePostVoiceActivity.ts delete mode 100644 packages/api/src/hooks/useSpeechToSpeech.ts create mode 100644 packages/api/src/hooks/useStartVoice.ts create mode 100644 packages/api/src/hooks/useStopVoice.ts create mode 100644 packages/api/src/hooks/useVoiceState.ts delete mode 100644 packages/api/src/types/SpeechToSpeech.ts create mode 100644 packages/core/src/actions/postVoiceActivity.ts create mode 100644 packages/core/src/actions/registerVoiceHandler.ts create mode 100644 packages/core/src/actions/setVoiceState.ts create mode 100644 packages/core/src/actions/startVoiceRecording.ts create mode 100644 packages/core/src/actions/stopVoiceRecording.ts create mode 100644 packages/core/src/actions/unregisterVoiceHandler.ts delete mode 100644 packages/core/src/actions/voiceActivityActions.ts diff --git a/__tests__/html2/speechToSpeech/csp.recording.html b/__tests__/html2/speechToSpeech/csp.recording.html index cdcd93d4c8..8107506933 100644 --- a/__tests__/html2/speechToSpeech/csp.recording.html +++ b/__tests__/html2/speechToSpeech/csp.recording.html @@ -104,7 +104,7 @@ // THEN: Verify recording state is active (AudioWorklet is functioning) await pageConditions.became( 'Voice state is listening (recording active)', - () => store.getState().voice?.recording === true && store.getState().voice?.speechState === 'listening', + () => store.getState().voice?.voiceState === 'listening', 1000 ); diff --git a/__tests__/html2/speechToSpeech/happy.path.html b/__tests__/html2/speechToSpeech/happy.path.html index 0281382598..0b370e4e53 100644 --- a/__tests__/html2/speechToSpeech/happy.path.html +++ b/__tests__/html2/speechToSpeech/happy.path.html @@ -64,7 +64,7 @@ // THEN: Verify voice state is recording/listening await pageConditions.became( 'Voice state is listening', - () => store.getState().voice?.speechState === 'listening', + () => store.getState().voice?.voiceState === 'listening', 1000 ); diff --git a/__tests__/html2/speechToSpeech/outgoing.audio.interval.html b/__tests__/html2/speechToSpeech/outgoing.audio.interval.html index 0477b3d641..b4f946dd3c 100644 --- a/__tests__/html2/speechToSpeech/outgoing.audio.interval.html +++ b/__tests__/html2/speechToSpeech/outgoing.audio.interval.html @@ -45,7 +45,7 @@ const capturedChunks = []; const originalPostActivity = directLine.postActivity.bind(directLine); directLine.postActivity = (activity) => { - if (activity.name === 'stream.chunk' && activity.payload?.voice) { + if (activity.name === 'stream.chunk' && activity.payload?.voice?.content) { capturedChunks.push({ ...activity, capturedAt: Date.now() diff --git a/packages/api/src/boot/hook.ts b/packages/api/src/boot/hook.ts index a2036c2425..20b8c9d412 100644 --- a/packages/api/src/boot/hook.ts +++ b/packages/api/src/boot/hook.ts @@ -42,7 +42,6 @@ export { usePerformCardAction, usePonyfill, usePostActivity, - usePostVoiceActivity, useReferenceGrammarID, useRelativeTimeFormatter, useRenderAttachment, @@ -60,9 +59,10 @@ export { useSendTypingIndicator, useSetNotification, useShouldSpeakIncomingActivity, - useSpeechToSpeech, useStartDictate, + useStartVoice, useStopDictate, + useStopVoice, useStyleOptions, useSubmitSendBox, useSuggestedActions, @@ -75,5 +75,6 @@ export { useUIState, useUserID, useUsername, - useVoiceSelector + useVoiceSelector, + useVoiceState } from '../hooks/index'; diff --git a/packages/api/src/boot/internal.ts b/packages/api/src/boot/internal.ts index 1bb222c21f..1a5a031a02 100644 --- a/packages/api/src/boot/internal.ts +++ b/packages/api/src/boot/internal.ts @@ -1,4 +1,5 @@ export { default as LowPriorityDecoratorComposer } from '../decorator/internal/LowPriorityDecoratorComposer'; +export { default as usePostVoiceActivity } from '../hooks/internal/usePostVoiceActivity'; export { default as useSetDictateState } from '../hooks/internal/useSetDictateState'; export { LegacyActivityContextProvider, type LegacyActivityContextType } from '../legacy/LegacyActivityBridgeContext'; export { default as StyleOptionsComposer } from '../providers/StyleOptions/StyleOptionsComposer'; diff --git a/packages/api/src/decorator/ActivityBorder/ActivityBorderDecorator.tsx b/packages/api/src/decorator/ActivityBorder/ActivityBorderDecorator.tsx index 17925bcf4a..15b100540c 100644 --- a/packages/api/src/decorator/ActivityBorder/ActivityBorderDecorator.tsx +++ b/packages/api/src/decorator/ActivityBorder/ActivityBorderDecorator.tsx @@ -1,6 +1,7 @@ import { getActivityLivestreamingMetadata, getVoiceActivityRole, + isVoiceActivity, type WebChatActivity } from 'botframework-webchat-core'; import React, { memo, useMemo, type ReactNode } from 'react'; @@ -29,8 +30,12 @@ function ActivityBorderDecorator({ activity, children }: ActivityBorderDecorator const { type } = getActivityLivestreamingMetadata(activity) || {}; return { - from: supportedActivityRoles.includes(activity?.from?.role) ? activity?.from?.role : undefined, - voiceTranscriptRole: getVoiceActivityRole(activity), + from: isVoiceActivity(activity) + ? getVoiceActivityRole(activity) + : supportedActivityRoles.includes(activity?.from?.role) + ? activity?.from?.role + : undefined, + modality: new Set(isVoiceActivity(activity) ? ['audio', 'text'] : ['text']), livestreamingState: type === 'final activity' ? 'completing' diff --git a/packages/api/src/decorator/ActivityBorder/private/ActivityBorderDecoratorRequestContext.ts b/packages/api/src/decorator/ActivityBorder/private/ActivityBorderDecoratorRequestContext.ts index f968a98a4b..0c8e01453a 100644 --- a/packages/api/src/decorator/ActivityBorder/private/ActivityBorderDecoratorRequestContext.ts +++ b/packages/api/src/decorator/ActivityBorder/private/ActivityBorderDecoratorRequestContext.ts @@ -22,13 +22,12 @@ type ActivityBorderDecoratorRequest = Readonly<{ from: 'bot' | 'channel' | `user` | undefined; /** - * Gets the role of the voice transcript activity sender. + * Gets the modalities of the activity. * - * - `"bot"` - the voice transcript is from the bot/agent - * - `"user"` - the voice transcript is from the user - * - `undefined` - the activity is not a voice transcript + * - `'audio'` - the activity originated from audio/voice input + * - `'text'` - the activity originated from text input */ - voiceTranscriptRole: 'bot' | 'user' | undefined; + modality: Set<'audio' | 'text'>; }>; type ActivityBorderDecoratorRequestContextType = Readonly<{ @@ -39,7 +38,7 @@ const ActivityBorderDecoratorRequestContext = createContext(), livestreamingState: undefined }) }) diff --git a/packages/api/src/defaultStyleOptions.ts b/packages/api/src/defaultStyleOptions.ts index f64dd4a165..9ae298ae67 100644 --- a/packages/api/src/defaultStyleOptions.ts +++ b/packages/api/src/defaultStyleOptions.ts @@ -319,7 +319,7 @@ const DEFAULT_OPTIONS: Required = { sendBoxAttachmentBarMaxHeight: 114, sendBoxAttachmentBarMaxThumbnail: 3, - // S2S options + // Speech-to-speech options showMicrophoneButton: false }; diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 793e67e558..632769a20b 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -14,8 +14,6 @@ import { emitTypingIndicator, markActivity, postActivity, - postVoiceActivity, - registerVoiceHandler, sendEvent, sendFiles, sendMessage, @@ -29,7 +27,6 @@ import { setSendBoxAttachments, setSendTimeout, setSendTypingIndicator, - setVoiceState, singleToArray, startDictate, startSpeakingActivity, @@ -86,6 +83,7 @@ import isObject from '../utils/isObject'; import mapMap from '../utils/mapMap'; import normalizeLanguage from '../utils/normalizeLanguage'; import Tracker from './internal/Tracker'; +import useVoiceHandlers from './internal/useVoiceHandlers'; import WebChatAPIContext, { type WebChatAPIContextType } from './internal/WebChatAPIContext'; import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; import defaultSelectVoice from './internal/defaultSelectVoice'; @@ -108,8 +106,6 @@ const DISPATCHERS = { emitTypingIndicator, markActivity, postActivity, - postVoiceActivity, - registerVoiceHandler, sendEvent, sendFiles, sendMessage, @@ -123,11 +119,8 @@ const DISPATCHERS = { setSendTimeout, startDictate, startSpeakingActivity, - startVoiceRecording, - setVoiceState, stopDictate, stopSpeakingActivity, - stopVoiceRecording, submitSendBox }; @@ -307,6 +300,7 @@ const ComposerCore = ({ const [styleOptions] = useStyleOptions(); const dispatch = useDispatch(); const telemetryDimensionsRef = useRef({}); + const [voiceHandlers] = useVoiceHandlers(); const patchedDir = useMemo(() => (dir === 'ltr' || dir === 'rtl' ? dir : 'auto'), [dir]); const patchedGrammars = useMemo(() => grammars || [], [grammars]); @@ -377,6 +371,15 @@ const ComposerCore = ({ [dispatch] ); + const startVoice = useCallback(() => { + dispatch(startVoiceRecording()); + }, [dispatch]); + + const stopVoice = useCallback(() => { + voiceHandlers.forEach(handler => handler.stopAllAudio()); + dispatch(stopVoiceRecording()); + }, [dispatch, voiceHandlers]); + const patchedLocalizedStrings = useMemo( () => mergeStringsOverrides(getAllLocalizedStrings()[normalizeLanguage(locale)], locale, overrideLocalizedStrings), [locale, overrideLocalizedStrings] @@ -564,6 +567,8 @@ const ComposerCore = ({ scrollToEndButtonRenderer, selectVoice: patchedSelectVoice, sendTypingIndicator, + startVoice, + stopVoice, telemetryDimensionsRef, toastRenderer: patchedToastRenderer, trackDimension, @@ -593,6 +598,8 @@ const ComposerCore = ({ renderMarkdown, scrollToEndButtonRenderer, sendTypingIndicator, + startVoice, + stopVoice, telemetryDimensionsRef, trackDimension, uiState, diff --git a/packages/api/src/hooks/index.ts b/packages/api/src/hooks/index.ts index 19186d6469..fab9ab79d4 100644 --- a/packages/api/src/hooks/index.ts +++ b/packages/api/src/hooks/index.ts @@ -40,7 +40,6 @@ import useNotifications from './useNotifications'; import usePerformCardAction from './usePerformCardAction'; import usePonyfill from './usePonyfill'; import usePostActivity from './usePostActivity'; -import usePostVoiceActivity from './usePostVoiceActivity'; import useReferenceGrammarID from './useReferenceGrammarID'; import useRelativeTimeFormatter from './useRelativeTimeFormatter'; import useRenderAttachment from './useRenderAttachment'; @@ -58,9 +57,10 @@ import useSendTimeoutForActivity from './useSendTimeoutForActivity'; import useSendTypingIndicator from './useSendTypingIndicator'; import useSetNotification from './useSetNotification'; import useShouldSpeakIncomingActivity from './useShouldSpeakIncomingActivity'; -import useSpeechToSpeech from './useSpeechToSpeech'; import useStartDictate from './useStartDictate'; +import useStartVoice from './useStartVoice'; import useStopDictate from './useStopDictate'; +import useStopVoice from './useStopVoice'; import useStyleOptions from './useStyleOptions'; import useSubmitSendBox from './useSubmitSendBox'; import useSuggestedActions from './useSuggestedActions'; @@ -73,6 +73,7 @@ import useUIState from './useUIState'; import useUserID from './useUserID'; import useUsername from './useUsername'; import useVoiceSelector from './useVoiceSelector'; +import useVoiceState from './useVoiceState'; export { useBuildRenderActivityCallback } from '@msinternal/botframework-webchat-api-middleware'; export { useSuggestedActionsHooks } from '@msinternal/botframework-webchat-redux-store'; @@ -120,7 +121,6 @@ export { usePerformCardAction, usePonyfill, usePostActivity, - usePostVoiceActivity, useReferenceGrammarID, useRelativeTimeFormatter, useRenderAttachment, @@ -138,9 +138,10 @@ export { useSendTypingIndicator, useSetNotification, useShouldSpeakIncomingActivity, - useSpeechToSpeech, useStartDictate, + useStartVoice, useStopDictate, + useStopVoice, useStyleOptions, useSubmitSendBox, useSuggestedActions, @@ -152,5 +153,6 @@ export { useUIState, useUserID, useUsername, - useVoiceSelector + useVoiceSelector, + useVoiceState }; diff --git a/packages/api/src/hooks/internal/WebChatAPIContext.ts b/packages/api/src/hooks/internal/WebChatAPIContext.ts index 110443852d..a0bc434b51 100644 --- a/packages/api/src/hooks/internal/WebChatAPIContext.ts +++ b/packages/api/src/hooks/internal/WebChatAPIContext.ts @@ -1,7 +1,5 @@ import { type LegacyRenderAttachment } from '@msinternal/botframework-webchat-api-middleware/legacy'; import { - SpeechState, - VoiceHandler, type DirectLineJSBotConnection, type Observable, type WebChatActivity, @@ -49,8 +47,6 @@ export type WebChatAPIContextType = { onCardAction?: PerformCardAction; onTelemetry?: (event: TelemetryMeasurementEvent) => void; postActivity?: (activity: WebChatActivity) => Observable; - postVoiceActivity?: (activity: WebChatActivity) => void; - registerVoiceHandler?: (voiceHandler: VoiceHandler) => void; renderMarkdown?: ( markdown: string, newLineOptions: { markdownRespectCRLF: boolean }, @@ -75,11 +71,10 @@ export type WebChatAPIContextType = { setSendTimeout?: (timeout: number) => void; startDictate?: () => void; startSpeakingActivity?: () => void; - startVoiceRecording?: () => void; - setVoiceState?: (state: SpeechState) => void; + startVoice?: () => void; stopDictate?: () => void; stopSpeakingActivity?: () => void; - stopVoiceRecording?: () => void; + stopVoice?: () => void; submitSendBox?: (method?: string, { channelData }?: { channelData: any }) => void; telemetryDimensionsRef?: React.Ref; toastRenderer?: RenderToast; diff --git a/packages/api/src/hooks/internal/usePostVoiceActivity.ts b/packages/api/src/hooks/internal/usePostVoiceActivity.ts new file mode 100644 index 0000000000..18f735cff5 --- /dev/null +++ b/packages/api/src/hooks/internal/usePostVoiceActivity.ts @@ -0,0 +1,18 @@ +import { postVoiceActivity, type WebChatActivity } from 'botframework-webchat-core'; +import { useCallback } from 'react'; +import { useDispatch } from './WebChatReduxContext'; + +/** + * Hook to post voice activities (fire-and-forget, no echo back). + * Use this for DTMF and other voice-related event activities. + */ +export default function usePostVoiceActivity(): (activity: WebChatActivity) => void { + const dispatch = useDispatch(); + + return useCallback( + (activity: WebChatActivity) => { + dispatch(postVoiceActivity(activity)); + }, + [dispatch] + ); +} diff --git a/packages/api/src/hooks/internal/useRegisterVoiceHandler.ts b/packages/api/src/hooks/internal/useRegisterVoiceHandler.ts new file mode 100644 index 0000000000..149bd97f2a --- /dev/null +++ b/packages/api/src/hooks/internal/useRegisterVoiceHandler.ts @@ -0,0 +1,23 @@ +import { registerVoiceHandler, unregisterVoiceHandler, type VoiceHandler } from 'botframework-webchat-core'; +import { useCallback } from 'react'; +import randomId from '../../utils/randomId'; +import { useDispatch } from './WebChatReduxContext'; + +/** + * Internal hook to register a voice handler for audio playback. + * @returns A function that registers a voice handler and returns an unregister function. + */ +export default function useRegisterVoiceHandler(): (voiceHandler: VoiceHandler) => () => void { + const dispatch = useDispatch(); + + return useCallback( + (voiceHandler: VoiceHandler) => { + const id = randomId(); + dispatch(registerVoiceHandler(id, voiceHandler)); + return () => { + dispatch(unregisterVoiceHandler(id)); + }; + }, + [dispatch] + ); +} diff --git a/packages/api/src/hooks/internal/useSetVoiceState.ts b/packages/api/src/hooks/internal/useSetVoiceState.ts new file mode 100644 index 0000000000..875b6b4ecd --- /dev/null +++ b/packages/api/src/hooks/internal/useSetVoiceState.ts @@ -0,0 +1,17 @@ +import { setVoiceState, type VoiceState } from 'botframework-webchat-core'; +import { useCallback } from 'react'; +import { useDispatch } from './WebChatReduxContext'; + +/** + * Internal hook to set the voice state. + */ +export default function useSetVoiceState(): (state: VoiceState) => void { + const dispatch = useDispatch(); + + return useCallback( + (state: VoiceState) => { + dispatch(setVoiceState(state)); + }, + [dispatch] + ); +} diff --git a/packages/api/src/hooks/internal/useSpeechState.ts b/packages/api/src/hooks/internal/useSpeechState.ts deleted file mode 100644 index 174197a46f..0000000000 --- a/packages/api/src/hooks/internal/useSpeechState.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { SpeechState } from 'botframework-webchat-core'; -import { useSelector } from './WebChatReduxContext'; - -/** - * Hook to get the voice speech state. - * The speech state represents the current state of the speech-to-speech interaction: - * - 'idle': No active speech session - * - 'listening': Microphone is active - * - 'user_speaking': User is actively speaking - * - 'processing': User finished speaking, server is processing - * - 'bot_speaking': Bot is speaking (audio playback) - */ -export default function useSpeechState(): [SpeechState] { - return [useSelector(({ voice }) => voice.speechState)]; -} diff --git a/packages/api/src/hooks/internal/useVoiceHandler.ts b/packages/api/src/hooks/internal/useVoiceHandler.ts deleted file mode 100644 index f48a59a369..0000000000 --- a/packages/api/src/hooks/internal/useVoiceHandler.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { VoiceHandler } from 'botframework-webchat-core'; -import { useSelector } from './WebChatReduxContext'; - -/** - * Hook to get the current voice handler from Redux state. - */ -export default function useVoiceHandler(): [VoiceHandler | null] { - return [useSelector(({ voice }) => voice.voiceHandler)]; -} diff --git a/packages/api/src/hooks/internal/useVoiceHandlers.ts b/packages/api/src/hooks/internal/useVoiceHandlers.ts new file mode 100644 index 0000000000..ff1fac0452 --- /dev/null +++ b/packages/api/src/hooks/internal/useVoiceHandlers.ts @@ -0,0 +1,9 @@ +import type { VoiceHandler } from 'botframework-webchat-core'; +import { useSelector } from './WebChatReduxContext'; + +/** + * Internal hook to get all registered voice handlers from Redux state. + */ +export default function useVoiceHandlers(): [readonly VoiceHandler[]] { + return [useSelector((state: { voice: { voiceHandlers } }) => Array.from(state.voice.voiceHandlers.values()))]; +} diff --git a/packages/api/src/hooks/internal/useVoiceRecording.ts b/packages/api/src/hooks/internal/useVoiceRecording.ts deleted file mode 100644 index e96b6267e9..0000000000 --- a/packages/api/src/hooks/internal/useVoiceRecording.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useSelector } from './WebChatReduxContext'; - -/** - * Hook to get the voice recording state. - */ -export default function useVoiceRecording(): [boolean] { - return [useSelector(({ voice }) => voice.recording)]; -} diff --git a/packages/api/src/hooks/usePostVoiceActivity.ts b/packages/api/src/hooks/usePostVoiceActivity.ts deleted file mode 100644 index 0f02d9bc03..0000000000 --- a/packages/api/src/hooks/usePostVoiceActivity.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { type WebChatActivity } from 'botframework-webchat-core'; - -import useWebChatAPIContext from './internal/useWebChatAPIContext'; - -/** - * Hook to post voice activities (fire-and-forget, no echo back). - */ -export default function usePostVoiceActivity(): (activity: WebChatActivity) => void { - return useWebChatAPIContext().postVoiceActivity; -} diff --git a/packages/api/src/hooks/useSpeechToSpeech.ts b/packages/api/src/hooks/useSpeechToSpeech.ts deleted file mode 100644 index 186eb991ff..0000000000 --- a/packages/api/src/hooks/useSpeechToSpeech.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import useVoiceRecording from './internal/useVoiceRecording'; -import useSpeechState from './internal/useSpeechState'; -import { SpeechToSpeech } from '../types/SpeechToSpeech'; -import useWebChatAPIContext from './internal/useWebChatAPIContext'; - -/** - * Hook to access speech-to-speech state and controls. - */ -export default function useSpeechToSpeech(): readonly [SpeechToSpeech] { - const { startVoiceRecording, stopVoiceRecording } = useWebChatAPIContext(); - const [recording] = useVoiceRecording(); - const [speechState] = useSpeechState(); - - const setRecording = useCallback( - (shouldRecord: boolean) => { - if (shouldRecord) { - startVoiceRecording(); - } else { - stopVoiceRecording(); - } - }, - [startVoiceRecording, stopVoiceRecording] - ); - - return useMemo( - () => [ - { - recording, - setRecording, - speechState - } - ], - [recording, setRecording, speechState] - ); -} diff --git a/packages/api/src/hooks/useStartVoice.ts b/packages/api/src/hooks/useStartVoice.ts new file mode 100644 index 0000000000..952d2b9d38 --- /dev/null +++ b/packages/api/src/hooks/useStartVoice.ts @@ -0,0 +1,9 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +/** + * Hook to start voice mode (turns on microphone and enables audio synthesis). + * This starts speech-to-speech interaction. + */ +export default function useStartVoice(): () => void { + return useWebChatAPIContext().startVoice; +} diff --git a/packages/api/src/hooks/useStopVoice.ts b/packages/api/src/hooks/useStopVoice.ts new file mode 100644 index 0000000000..b7be0f5447 --- /dev/null +++ b/packages/api/src/hooks/useStopVoice.ts @@ -0,0 +1,9 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +/** + * Hook to stop voice mode (turns off microphone and stops audio playback). + * This ends speech-to-speech interaction. + */ +export default function useStopVoice(): () => void { + return useWebChatAPIContext().stopVoice; +} diff --git a/packages/api/src/hooks/useVoiceState.ts b/packages/api/src/hooks/useVoiceState.ts new file mode 100644 index 0000000000..ddd688d54b --- /dev/null +++ b/packages/api/src/hooks/useVoiceState.ts @@ -0,0 +1,17 @@ +import type { VoiceState } from 'botframework-webchat-core'; +import { useSelector } from './internal/WebChatReduxContext'; + +/** + * Hook to get the voice state. + * The voice state represents the current state of the speech-to-speech interaction: + * - 'idle': No active speech session, microphone and audio playback are off + * - 'listening': Microphone is active + * - 'user_speaking': User is actively speaking + * - 'processing': User finished speaking, server is processing + * - 'bot_speaking': Bot is speaking (audio playback) + */ +export default function useVoiceState(): [VoiceState] { + return [useSelector(({ voice }) => voice.voiceState)]; +} + +export type { VoiceState }; diff --git a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx index 9b0398b21b..da6ee79b7e 100644 --- a/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx +++ b/packages/api/src/providers/SpeechToSpeech/SpeechToSpeechComposer.tsx @@ -9,7 +9,7 @@ import { VoiceRecorderBridge } from './private/VoiceRecorderBridge'; * 1. VoiceHandlerBridge - registers audio player functions with Redux * 2. VoiceRecorderBridge - reacts to recording state and manages microphone * - * Use the `useSpeechToSpeech` hook to access state and controls. + * Use the `useVoiceState`, `useStartVoice`, and `useStopVoice` hooks to access state and controls. */ export const SpeechToSpeechComposer: React.FC<{ readonly children: ReactNode }> = ({ children }) => ( diff --git a/packages/api/src/providers/SpeechToSpeech/private/VoiceHandlerBridge.tsx b/packages/api/src/providers/SpeechToSpeech/private/VoiceHandlerBridge.tsx index 9262741c51..194d45c3a9 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/VoiceHandlerBridge.tsx +++ b/packages/api/src/providers/SpeechToSpeech/private/VoiceHandlerBridge.tsx @@ -1,28 +1,24 @@ import { useEffect } from 'react'; import useStyleOptions from '../../../hooks/useStyleOptions'; -import useWebChatAPIContext from '../../../hooks/internal/useWebChatAPIContext'; +import useRegisterVoiceHandler from '../../../hooks/internal/useRegisterVoiceHandler'; import { useAudioPlayer } from './useAudioPlayer'; /** * VoiceHandlerBridge is an invisible component that registers the audio player - * functions (playAudio, stopAudio) with Redux. + * functions (queueAudio, stopAllAudio) with Redux */ export const VoiceHandlerBridge = () => { - const { registerVoiceHandler } = useWebChatAPIContext(); - const { playAudio, stopAudio } = useAudioPlayer(); - + const registerVoiceHandler = useRegisterVoiceHandler(); + const { queueAudio, stopAllAudio } = useAudioPlayer(); const [{ showMicrophoneButton }] = useStyleOptions(); useEffect(() => { if (!showMicrophoneButton) { return; } - registerVoiceHandler({ playAudio, stopAudio }); - return () => { - registerVoiceHandler(null); - }; - }, [registerVoiceHandler, playAudio, stopAudio, showMicrophoneButton]); + return registerVoiceHandler({ queueAudio, stopAllAudio }); + }, [registerVoiceHandler, queueAudio, stopAllAudio, showMicrophoneButton]); return null; }; diff --git a/packages/api/src/providers/SpeechToSpeech/private/VoiceRecorderBridge.tsx b/packages/api/src/providers/SpeechToSpeech/private/VoiceRecorderBridge.tsx index bd99c0cb4b..f7f1e49c13 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/VoiceRecorderBridge.tsx +++ b/packages/api/src/providers/SpeechToSpeech/private/VoiceRecorderBridge.tsx @@ -1,18 +1,18 @@ -import { useEffect, useCallback, useRef } from 'react'; +import { useEffect, useCallback } from 'react'; import { useRecorder } from './useRecorder'; -import usePostVoiceActivity from '../../../hooks/usePostVoiceActivity'; -import useVoiceRecording from '../../../hooks/internal/useVoiceRecording'; -import useVoiceHandler from '../../../hooks/internal/useVoiceHandler'; +import usePostVoiceActivity from '../../../hooks/internal/usePostVoiceActivity'; +import useVoiceState from '../../../hooks/useVoiceState'; /** * VoiceRecorderBridge is an invisible component that bridges the Redux recording state * with the actual microphone recording functionality. */ export function VoiceRecorderBridge(): null { - const [recording] = useVoiceRecording(); - const [voiceHandler] = useVoiceHandler(); + const [voiceState] = useVoiceState(); const postVoiceActivity = usePostVoiceActivity(); - const prevRecordingRef = useRef(recording); + + // Derive recording state from voiceState - recording is active when not idle + const recording = voiceState !== 'idle'; const handleAudioChunk = useCallback( (base64: string, timestamp: string) => { @@ -31,24 +31,13 @@ export function VoiceRecorderBridge(): null { [postVoiceActivity] ); - const { startRecording, stopRecording } = useRecorder(handleAudioChunk); + const { record } = useRecorder(handleAudioChunk); useEffect(() => { - // This is to check transition of recording state, it it does not match then perorm actions - const wasRecording = prevRecordingRef.current; - prevRecordingRef.current = recording; - - if (recording && !wasRecording) { - startRecording(); - } else if (!recording && wasRecording) { - voiceHandler.stopAudio(); - stopRecording(); + if (recording) { + return record(); } - - return () => { - stopRecording(); - }; - }, [recording, startRecording, stopRecording, voiceHandler]); + }, [record, recording]); return null; } diff --git a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx index 60cc1f15ea..0c2a1c58c2 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx +++ b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.spec.tsx @@ -9,12 +9,10 @@ import { useAudioPlayer } from './useAudioPlayer'; // Mock setVoiceState function const mockSetVoiceState = jest.fn(); -// Mock useWebChatAPIContext hook -jest.mock('../../../hooks/internal/useWebChatAPIContext', () => ({ +// Mock useSetVoiceState hook +jest.mock('../../../hooks/internal/useSetVoiceState', () => ({ __esModule: true, - default: jest.fn(() => ({ - setVoiceState: mockSetVoiceState - })) + default: jest.fn(() => mockSetVoiceState) })); // Mock AudioContext and related APIs @@ -82,17 +80,17 @@ describe('useAudioPlayer', () => { }); describe('Initialization', () => { - test('should return playAudio and stopAudio functions', () => { + test('should return queueAudio and stopAllAudio functions', () => { render(); - expect(typeof hookData?.playAudio).toBe('function'); - expect(typeof hookData?.stopAudio).toBe('function'); + expect(typeof hookData?.queueAudio).toBe('function'); + expect(typeof hookData?.stopAllAudio).toBe('function'); }); - test('should create AudioContext on first playAudio call', async () => { + test('should create AudioContext on first queueAudio call', async () => { render(); - await hookData?.playAudio('dGVzdA=='); // base64 for 'test' + await hookData?.queueAudio('dGVzdA=='); // base64 for 'test' expect(AudioContext).toHaveBeenCalledWith({ sampleRate: 24000 }); }); @@ -100,8 +98,8 @@ describe('useAudioPlayer', () => { test('should reuse existing AudioContext on subsequent calls', async () => { render(); - await hookData?.playAudio('dGVzdA=='); - await hookData?.playAudio('dGVzdDI='); + await hookData?.queueAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdDI='); expect(AudioContext).toHaveBeenCalledTimes(1); }); @@ -113,7 +111,7 @@ describe('useAudioPlayer', () => { }); test('should process base64 audio data correctly', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); expect(global.atob).toHaveBeenCalledWith('dGVzdA=='); expect(mockAudioContext.createBuffer).toHaveBeenCalledWith(1, expect.any(Number), 24000); @@ -121,7 +119,7 @@ describe('useAudioPlayer', () => { }); test('should set up audio buffer source correctly', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); const [source] = createdBufferSources; expect(source.connect).toHaveBeenCalledWith(mockAudioContext.destination); @@ -130,7 +128,7 @@ describe('useAudioPlayer', () => { }); test('should resume AudioContext if needed', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); expect(mockAudioContext.resume).toHaveBeenCalled(); }); @@ -138,8 +136,8 @@ describe('useAudioPlayer', () => { test('should queue multiple audio chunks correctly', async () => { mockAudioBuffer.duration = 0.1; // 100ms - await hookData?.playAudio('dGVzdA=='); - await hookData?.playAudio('dGVzdDI='); + await hookData?.queueAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdDI='); expect(createdBufferSources).toHaveLength(2); // First chunk starts at currentTime (0), second at 0.1 @@ -156,7 +154,7 @@ describe('useAudioPlayer', () => { test('should set voice state to bot_speaking on first chunk', async () => { mockAudioContext.currentTime = 0; - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); expect(mockSetVoiceState).toHaveBeenCalledWith('bot_speaking'); }); @@ -165,16 +163,16 @@ describe('useAudioPlayer', () => { mockAudioContext.currentTime = 0; mockAudioBuffer.duration = 0.1; - await hookData?.playAudio('dGVzdA=='); // First chunk + await hookData?.queueAudio('dGVzdA=='); // First chunk mockSetVoiceState.mockClear(); - await hookData?.playAudio('dGVzdDI='); // Second chunk (while first is still playing) + await hookData?.queueAudio('dGVzdDI='); // Second chunk (while first is still playing) expect(mockSetVoiceState).not.toHaveBeenCalledWith('bot_speaking'); }); test('should set voice state to listening when last audio ends', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); mockSetVoiceState.mockClear(); // Simulate audio ended @@ -189,8 +187,8 @@ describe('useAudioPlayer', () => { test('should only trigger listening on the last source ended', async () => { mockAudioBuffer.duration = 0.1; - await hookData?.playAudio('dGVzdA=='); - await hookData?.playAudio('dGVzdDI='); + await hookData?.queueAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdDI='); mockSetVoiceState.mockClear(); const [firstSource, lastSource] = createdBufferSources; @@ -217,7 +215,7 @@ describe('useAudioPlayer', () => { }); test('should clean up buffer source on ended', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); const [source] = createdBufferSources; // Simulate audio ended @@ -230,23 +228,23 @@ describe('useAudioPlayer', () => { }); test('should stop all audio and close context', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); - hookData?.stopAudio(); + hookData?.stopAllAudio(); expect(mockAudioContext.close).toHaveBeenCalled(); }); test('should clear lastSourceRef onended callback on stop', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); const [source] = createdBufferSources; const onEndedBefore = source.onended; expect(onEndedBefore).not.toBeNull(); - hookData?.stopAudio(); + hookData?.stopAllAudio(); - // After stopAudio, the onended should be cleared + // After stopAllAudio, the onended should be cleared expect(source.onended).toBeNull(); }); }); @@ -258,7 +256,7 @@ describe('useAudioPlayer', () => { test('should handle invalid base64 data gracefully', async () => { await expect(async () => { - await hookData?.playAudio('invalid-base64!@#'); + await hookData?.queueAudio('invalid-base64!@#'); }).not.toThrow(); }); @@ -268,7 +266,7 @@ describe('useAudioPlayer', () => { }) as unknown as typeof AudioContext; await expect(async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); }).rejects.toThrow('AudioContext not supported'); }); }); @@ -282,7 +280,7 @@ describe('useAudioPlayer', () => { mockAudioBuffer.duration = 0.05; // 50ms chunks // Simulate streaming 5 chunks - await Promise.all(Array.from({ length: 5 }, (_, i) => hookData?.playAudio(`chunk${i}`))); + await Promise.all(Array.from({ length: 5 }, (_, i) => hookData?.queueAudio(`chunk${i}`))); expect(createdBufferSources).toHaveLength(5); createdBufferSources.forEach(source => { @@ -294,18 +292,18 @@ describe('useAudioPlayer', () => { }); test('should handle playback interruption', async () => { - await hookData?.playAudio('dGVzdA=='); + await hookData?.queueAudio('dGVzdA=='); - hookData?.stopAudio(); + hookData?.stopAllAudio(); expect(mockAudioContext.close).toHaveBeenCalled(); }); test('should handle resume after stop', async () => { // Play, stop, then play again - await hookData?.playAudio('dGVzdA=='); - hookData?.stopAudio(); - await hookData?.playAudio('dGVzdDI='); + await hookData?.queueAudio('dGVzdA=='); + hookData?.stopAllAudio(); + await hookData?.queueAudio('dGVzdDI='); expect(AudioContext).toHaveBeenCalledTimes(2); // New context after stop }); @@ -313,11 +311,11 @@ describe('useAudioPlayer', () => { test('should reset nextPlayTime after stop allowing immediate playback', async () => { mockAudioBuffer.duration = 0.1; - await hookData?.playAudio('dGVzdA=='); - hookData?.stopAudio(); + await hookData?.queueAudio('dGVzdA=='); + hookData?.stopAllAudio(); mockSetVoiceState.mockClear(); - await hookData?.playAudio('dGVzdDI='); + await hookData?.queueAudio('dGVzdDI='); // Should trigger bot_speaking again since it's a fresh start expect(mockSetVoiceState).toHaveBeenCalledWith('bot_speaking'); @@ -333,13 +331,13 @@ describe('useAudioPlayer', () => { const largeBase64 = 'A'.repeat(10000); await expect(async () => { - await hookData?.playAudio(largeBase64); + await hookData?.queueAudio(largeBase64); }).not.toThrow(); }); test('should handle rapid successive calls', async () => { // Ensure the mock "base64" data has an even length as Int16Array requires multiples of 2 bytes - await Promise.all(Array.from({ length: 100 }, (_, i) => hookData?.playAudio(`chunk${i}`.padEnd(8, ' ')))); + await Promise.all(Array.from({ length: 100 }, (_, i) => hookData?.queueAudio(`chunk${i}`.padEnd(8, ' ')))); expect(createdBufferSources).toHaveLength(100); createdBufferSources.forEach(source => { diff --git a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts index aa92309cef..b3f4f8752b 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts +++ b/packages/api/src/providers/SpeechToSpeech/private/useAudioPlayer.ts @@ -1,5 +1,5 @@ import { useRef, useCallback, useMemo } from 'react'; -import useWebChatAPIContext from '../../../hooks/internal/useWebChatAPIContext'; +import useSetVoiceState from '../../../hooks/internal/useSetVoiceState'; const DEFAULT_SAMPLE_RATE = 24000; const INT16_SCALE = 32768; @@ -8,9 +8,9 @@ export function useAudioPlayer() { const audioCtxRef = useRef(undefined); const nextPlayTimeRef = useRef(0); const lastSourceRef = useRef(undefined); - const { setVoiceState } = useWebChatAPIContext(); + const setVoiceState = useSetVoiceState(); - const playAudio = useCallback( + const queueAudio = useCallback( async (base64: string) => { if (!audioCtxRef.current) { audioCtxRef.current = new AudioContext({ sampleRate: DEFAULT_SAMPLE_RATE }); @@ -50,7 +50,7 @@ export function useAudioPlayer() { lastSourceRef.current = src; const isFirstChunk = nextPlayTimeRef.current <= audioCtx.currentTime; - // Only dispatch bot_speaking on first chunk, we are resetting refs on stopAudio (bargein, mic off) + // Only dispatch bot_speaking on first chunk, we are resetting refs on stopAllAudio (bargein, mic off) if (isFirstChunk) { setVoiceState('bot_speaking'); } @@ -65,23 +65,23 @@ export function useAudioPlayer() { [setVoiceState] ); - const stopAudio = useCallback(() => { + const stopAllAudio = useCallback(() => { nextPlayTimeRef.current = 0; if (lastSourceRef.current) { lastSourceRef.current.onended = null; - lastSourceRef.current = null; + lastSourceRef.current = undefined; } if (audioCtxRef.current) { audioCtxRef.current.close(); - audioCtxRef.current = null; + audioCtxRef.current = undefined; } }, []); return useMemo( () => ({ - playAudio, - stopAudio + queueAudio, + stopAllAudio }), - [playAudio, stopAudio] + [queueAudio, stopAllAudio] ); } diff --git a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx index 87a818537a..2560097b83 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx +++ b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.spec.tsx @@ -79,18 +79,22 @@ describe('useRecorder', () => { }; }); - test('should return startRecording and stopRecording functions', () => { + test('should return record function', () => { render(); - expect(typeof hookData?.startRecording).toBe('function'); - expect(typeof hookData?.stopRecording).toBe('function'); + expect(typeof hookData?.record).toBe('function'); }); - test('should start recording when startRecording is called', async () => { + test('should start recording when record is called', async () => { renderResult = render(); - await hookData?.startRecording(); + act(() => { + hookData?.record(); + }); + + await waitFor(() => { + expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledTimes(1); + }); - expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledTimes(1); expect(global.AudioContext).toHaveBeenCalledTimes(1); expect(mockAudioContext.audioWorklet.addModule).toHaveBeenCalledTimes(1); expect(global.AudioWorkletNode).toHaveBeenCalledWith(expect.anything(), 'audio-recorder', { @@ -100,15 +104,23 @@ describe('useRecorder', () => { expect(mockWorkletPort.postMessage).toHaveBeenCalledWith({ command: 'START' }); }); - test('should stop recording when stopRecording is called', async () => { + test('should stop recording when returned cleanup function is called', async () => { renderResult = render(); + let stopRecording: (() => void) | undefined; // Start recording - await hookData?.startRecording(); + act(() => { + stopRecording = hookData?.record(); + }); + + // Wait for async startRecording to complete + await waitFor(() => { + expect(mockWorkletPort.postMessage).toHaveBeenCalledWith({ command: 'START' }); + }); // Stop recording act(() => { - hookData?.stopRecording(); + stopRecording?.(); }); expect(mockWorkletPort.postMessage).toHaveBeenCalledWith({ command: 'STOP' }); @@ -119,7 +131,9 @@ describe('useRecorder', () => { test('should process audio chunks sent from the worklet', async () => { render(); - await hookData?.startRecording(); + act(() => { + hookData?.record(); + }); await waitFor(() => expect(mockWorkletPort.onmessage).not.toBeNull()); @@ -144,19 +158,38 @@ describe('useRecorder', () => { (mockAudioContext.state as string) = 'suspended'; render(); - await hookData?.startRecording(); + act(() => { + hookData?.record(); + }); - expect(mockAudioContext.resume).toHaveBeenCalledTimes(1); + await waitFor(() => { + expect(mockAudioContext.resume).toHaveBeenCalledTimes(1); + }); }); test('should reuse existing AudioContext on subsequent calls', async () => { render(); - await hookData?.startRecording(); + let stopRecording: (() => void) | undefined; + act(() => { + stopRecording = hookData?.record(); + }); - hookData?.stopRecording(); + await waitFor(() => { + expect(mockWorkletPort.postMessage).toHaveBeenCalledWith({ command: 'START' }); + }); - await hookData?.startRecording(); + act(() => { + stopRecording?.(); + }); + + act(() => { + hookData?.record(); + }); + + await waitFor(() => { + expect(mockWorkletPort.postMessage).toHaveBeenCalledTimes(3); // START, STOP, START + }); // AudioContext should only be created once expect(global.AudioContext).toHaveBeenCalledTimes(1); @@ -165,14 +198,18 @@ describe('useRecorder', () => { test('should request microphone with correct audio constraints', async () => { render(); - await hookData?.startRecording(); + act(() => { + hookData?.record(); + }); - expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledWith({ - audio: { - channelCount: 1, - sampleRate: 24000, - echoCancellation: true - } + await waitFor(() => { + expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledWith({ + audio: { + channelCount: 1, + sampleRate: 24000, + echoCancellation: true + } + }); }); }); }); diff --git a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts index cdc10fa027..1aecc2d5ab 100644 --- a/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts +++ b/packages/api/src/providers/SpeechToSpeech/private/useRecorder.ts @@ -1,49 +1,63 @@ import { useRef, useCallback, useMemo } from 'react'; import usePonyfill from '../../Ponyfill/usePonyfill'; +// Minimum AudioWorkletProcessor definition for TypeScript recognition +// adding reference of worker does not work +declare class AudioWorkletProcessor { + readonly port: MessagePort; + constructor(options?: AudioWorkletNodeOptions); + process(inputs: Float32Array[][], outputs: Float32Array[][], parameters: Record): boolean; +} +declare function registerProcessor(name: string, processorCtor: typeof AudioWorkletProcessor): void; + /** - * AudioWorklet processor code for recording audio. - * This code runs in a separate AudioWorklet context with its own globals - * (AudioWorkletProcessor, registerProcessor, etc.) - * - * IMPORTANT: This must be a plain string template to avoid transpiling issues - * as those don't exist in the AudioWorklet context. - * * CSP Compliant: check __tests__/html2/speechToSpeech/csp.recording.html for CSP compliance tests. */ -const audioProcessorCode = ` +const audioProcessorCode = `(${function () { + type RecorderState = { recording: boolean; buffer: number[]; bufferSize: number }; class AudioRecorderProcessor extends AudioWorkletProcessor { - constructor(options) { - super() - this.recording = false - this.buffer = [] - this.bufferSize = options.processorOptions.bufferSize - this.port.onmessage = e => { - if (e.data.command === 'START') this.recording = true - else if (e.data.command === 'STOP') { - this.recording = false - this.buffer = [] + constructor(options: AudioWorkletNodeOptions) { + super(); + const state: RecorderState = { + recording: false, + buffer: [], + bufferSize: options.processorOptions.bufferSize + }; + Object.assign(this, state); + + this.port.onmessage = (e: MessageEvent) => { + const state = this as unknown as RecorderState; + if (e.data.command === 'START') { + state.recording = true; + } else if (e.data.command === 'STOP') { + state.recording = false; + state.buffer = []; } - } + }; } + sendBuffer() { - while (this.buffer.length >= this.bufferSize) { - const chunk = this.buffer.splice(0, this.bufferSize) - this.port.postMessage({ - eventType: 'audio', - audioData: new Float32Array(chunk) - }) + const { buffer, bufferSize } = this as unknown as RecorderState; + while (buffer.length >= bufferSize) { + const chunk = buffer.splice(0, bufferSize); + this.port.postMessage({ eventType: 'audio', audioData: new Float32Array(chunk) }); } } - process(inputs) { - if (inputs[0]?.length && this.recording) { - this.buffer.push(...inputs[0][0]) - if (this.buffer.length >= this.bufferSize) this.sendBuffer() + + process(inputs: Float32Array[][]) { + const state = this as unknown as RecorderState; + if (inputs[0]?.length && state.recording) { + state.buffer.push(...inputs[0][0]); + if (state.buffer.length >= state.bufferSize) { + this.sendBuffer(); + } } - return true + return true; } } - registerProcessor('audio-recorder', AudioRecorderProcessor)`; + + registerProcessor('audio-recorder', AudioRecorderProcessor); +}})()`; const INT16_MIN = -32768; const INT16_MAX = 32767; @@ -53,11 +67,23 @@ const DEFAULT_CHUNK_SIZE_IN_MS = 100; const MS_IN_SECOND = 1000; export function useRecorder(onAudioChunk: (base64: string, timestamp: string) => void) { - const audioCtxRef = useRef(null); - const workletRef = useRef(null); - const streamRef = useRef(null); + const audioCtxRef = useRef(undefined); + const workletRef = useRef(undefined); + const streamRef = useRef(undefined); const [{ Date }] = usePonyfill(); + const stopRecording = useCallback(() => { + if (workletRef.current) { + workletRef.current.port.postMessage({ command: 'STOP' }); + workletRef.current.disconnect(); + workletRef.current = undefined; + } + if (streamRef.current) { + streamRef.current.getTracks().forEach(track => track.stop()); + streamRef.current = undefined; + } + }, []); + const initAudio = useCallback(async () => { if (audioCtxRef.current) { return; @@ -101,8 +127,7 @@ export function useRecorder(onAudioChunk: (base64: string, timestamp: string) => const float32 = e.data.audioData; const int16 = new Int16Array(float32.length); for (let i = 0; i < float32.length; i++) { - // eslint-disable-next-line security/detect-object-injection - int16[i] = Math.max(INT16_MIN, Math.min(INT16_MAX, float32[i] * INT16_SCALE)); + int16[+i] = Math.max(INT16_MIN, Math.min(INT16_MAX, float32.at(i) * INT16_SCALE)); } const base64 = btoa(String.fromCharCode(...new Uint8Array(int16.buffer))); onAudioChunk(base64, timestamp); @@ -115,23 +140,10 @@ export function useRecorder(onAudioChunk: (base64: string, timestamp: string) => workletRef.current = worklet; }, [Date, initAudio, onAudioChunk]); - const stopRecording = useCallback(() => { - if (workletRef.current) { - workletRef.current.port.postMessage({ command: 'STOP' }); - workletRef.current.disconnect(); - workletRef.current = null; - } - if (streamRef.current) { - streamRef.current.getTracks().forEach(track => track.stop()); - streamRef.current = null; - } - }, []); + const record = useCallback(() => { + startRecording(); + return stopRecording; + }, [startRecording, stopRecording]); - return useMemo( - () => ({ - startRecording, - stopRecording - }), - [startRecording, stopRecording] - ); + return useMemo(() => ({ record }), [record]); } diff --git a/packages/api/src/types/SpeechToSpeech.ts b/packages/api/src/types/SpeechToSpeech.ts deleted file mode 100644 index 4e700eaf1a..0000000000 --- a/packages/api/src/types/SpeechToSpeech.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { SpeechState } from 'botframework-webchat-core'; - -type SpeechToSpeech = { - recording: boolean; - setRecording: (recording: boolean) => void; - speechState: SpeechState; -}; - -export type { SpeechToSpeech }; diff --git a/packages/bundle/src/boot/actual/hook/minimal.ts b/packages/bundle/src/boot/actual/hook/minimal.ts index cc2bcb80ed..f0dd67e329 100644 --- a/packages/bundle/src/boot/actual/hook/minimal.ts +++ b/packages/bundle/src/boot/actual/hook/minimal.ts @@ -49,7 +49,6 @@ export { usePerformCardAction, usePonyfill, usePostActivity, - usePostVoiceActivity, useReferenceGrammarID, useRegisterFocusSendBox, useRelativeTimeFormatter, @@ -75,9 +74,10 @@ export { useSetNotification, useShouldReduceMotion, useShouldSpeakIncomingActivity, - useSpeechToSpeech, useStartDictate, + useStartVoice, useStopDictate, + useStopVoice, useStyleOptions, useStyleSet, useSubmitSendBox, @@ -96,6 +96,7 @@ export { useUserID, useUsername, useVoiceSelector, + useVoiceState, useWebSpeechPonyfill, type SendBoxFocusOptions } from 'botframework-webchat-component/hook'; diff --git a/packages/bundle/src/boot/actual/internal.ts b/packages/bundle/src/boot/actual/internal.ts index 0fcfbdc245..a7a99683c3 100644 --- a/packages/bundle/src/boot/actual/internal.ts +++ b/packages/bundle/src/boot/actual/internal.ts @@ -1,9 +1,10 @@ // We should review exports in this file to make sure 1P = 3P. export { type ActivityMiddleware, - type TypingIndicatorMiddleware, - type ActivityStatusMiddleware + type ActivityStatusMiddleware, + type TypingIndicatorMiddleware } from 'botframework-webchat-api'; +export { usePostVoiceActivity } from 'botframework-webchat-api/internal'; export { CodeHighlighterComposer, createIconComponent, diff --git a/packages/component/src/TextArea/TextArea.tsx b/packages/component/src/TextArea/TextArea.tsx index 491fcd9198..b6eed10f74 100644 --- a/packages/component/src/TextArea/TextArea.tsx +++ b/packages/component/src/TextArea/TextArea.tsx @@ -35,9 +35,9 @@ const TextArea = forwardRef< hidden?: boolean | undefined; onInput?: FormEventHandler | undefined; placeholder?: string | undefined; + readOnly?: boolean | undefined; startRows?: number | undefined; value?: string | undefined; - readOnly?: boolean | undefined; }> >((props, ref) => { const [uiState] = useUIState(); diff --git a/packages/component/src/boot/hook.ts b/packages/component/src/boot/hook.ts index 1fda9ea69b..e2ba678168 100644 --- a/packages/component/src/boot/hook.ts +++ b/packages/component/src/boot/hook.ts @@ -42,7 +42,6 @@ export { usePerformCardAction, usePonyfill, usePostActivity, - usePostVoiceActivity, useReferenceGrammarID, useRelativeTimeFormatter, useRenderAttachment, @@ -58,9 +57,10 @@ export { useSendTypingIndicator, useSetNotification, useShouldSpeakIncomingActivity, - useSpeechToSpeech, useStartDictate, + useStartVoice, useStopDictate, + useStopVoice, useStyleOptions, useSubmitSendBox, useSuggestedActions, @@ -73,7 +73,8 @@ export { useUIState, useUserID, useUsername, - useVoiceSelector + useVoiceSelector, + useVoiceState } from 'botframework-webchat-api/hook'; // #region Overrides diff --git a/packages/core/src/actions/postVoiceActivity.ts b/packages/core/src/actions/postVoiceActivity.ts new file mode 100644 index 0000000000..8ab7087012 --- /dev/null +++ b/packages/core/src/actions/postVoiceActivity.ts @@ -0,0 +1,21 @@ +import type { WebChatActivity } from '../types/WebChatActivity'; + +const VOICE_POST_ACTIVITY = 'WEB_CHAT/VOICE_POST_ACTIVITY' as const; + +type VoicePostActivityAction = { + type: typeof VOICE_POST_ACTIVITY; + payload: { activity: WebChatActivity }; +}; + +function postVoiceActivity(activity: WebChatActivity): VoicePostActivityAction { + return { + type: VOICE_POST_ACTIVITY, + payload: { activity } + }; +} + +export default postVoiceActivity; + +export { VOICE_POST_ACTIVITY }; + +export type { VoicePostActivityAction }; diff --git a/packages/core/src/actions/registerVoiceHandler.ts b/packages/core/src/actions/registerVoiceHandler.ts new file mode 100644 index 0000000000..3c0029835a --- /dev/null +++ b/packages/core/src/actions/registerVoiceHandler.ts @@ -0,0 +1,24 @@ +const VOICE_REGISTER_HANDLER = 'WEB_CHAT/VOICE_REGISTER_HANDLER' as const; + +type VoiceHandler = { + queueAudio: (base64: string) => void; + stopAllAudio: () => void; +}; + +type VoiceRegisterHandlerAction = { + type: typeof VOICE_REGISTER_HANDLER; + payload: { id: string; voiceHandler: VoiceHandler }; +}; + +function registerVoiceHandler(id: string, voiceHandler: VoiceHandler): VoiceRegisterHandlerAction { + return { + type: VOICE_REGISTER_HANDLER, + payload: { id, voiceHandler } + }; +} + +export default registerVoiceHandler; + +export { VOICE_REGISTER_HANDLER }; + +export type { VoiceHandler, VoiceRegisterHandlerAction }; diff --git a/packages/core/src/actions/setVoiceState.ts b/packages/core/src/actions/setVoiceState.ts new file mode 100644 index 0000000000..53fc12b7c2 --- /dev/null +++ b/packages/core/src/actions/setVoiceState.ts @@ -0,0 +1,21 @@ +const VOICE_SET_STATE = 'WEB_CHAT/VOICE_SET_STATE' as const; + +type VoiceState = 'idle' | 'listening' | 'user_speaking' | 'processing' | 'bot_speaking'; + +type VoiceSetStateAction = { + type: typeof VOICE_SET_STATE; + payload: { voiceState: VoiceState }; +}; + +function setVoiceState(voiceState: VoiceState): VoiceSetStateAction { + return { + type: VOICE_SET_STATE, + payload: { voiceState } + }; +} + +export default setVoiceState; + +export { VOICE_SET_STATE }; + +export type { VoiceState, VoiceSetStateAction }; diff --git a/packages/core/src/actions/startVoiceRecording.ts b/packages/core/src/actions/startVoiceRecording.ts new file mode 100644 index 0000000000..cbf050b392 --- /dev/null +++ b/packages/core/src/actions/startVoiceRecording.ts @@ -0,0 +1,17 @@ +const VOICE_START_RECORDING = 'WEB_CHAT/VOICE_START_RECORDING' as const; + +type VoiceStartRecordingAction = { + type: typeof VOICE_START_RECORDING; +}; + +function startVoiceRecording(): VoiceStartRecordingAction { + return { + type: VOICE_START_RECORDING + }; +} + +export default startVoiceRecording; + +export { VOICE_START_RECORDING }; + +export type { VoiceStartRecordingAction }; diff --git a/packages/core/src/actions/stopVoiceRecording.ts b/packages/core/src/actions/stopVoiceRecording.ts new file mode 100644 index 0000000000..f547fe9b81 --- /dev/null +++ b/packages/core/src/actions/stopVoiceRecording.ts @@ -0,0 +1,17 @@ +const VOICE_STOP_RECORDING = 'WEB_CHAT/VOICE_STOP_RECORDING' as const; + +type VoiceStopRecordingAction = { + type: typeof VOICE_STOP_RECORDING; +}; + +function stopVoiceRecording(): VoiceStopRecordingAction { + return { + type: VOICE_STOP_RECORDING + }; +} + +export default stopVoiceRecording; + +export { VOICE_STOP_RECORDING }; + +export type { VoiceStopRecordingAction }; diff --git a/packages/core/src/actions/unregisterVoiceHandler.ts b/packages/core/src/actions/unregisterVoiceHandler.ts new file mode 100644 index 0000000000..59fedcc27a --- /dev/null +++ b/packages/core/src/actions/unregisterVoiceHandler.ts @@ -0,0 +1,19 @@ +const VOICE_UNREGISTER_HANDLER = 'WEB_CHAT/VOICE_UNREGISTER_HANDLER' as const; + +type VoiceUnregisterHandlerAction = { + type: typeof VOICE_UNREGISTER_HANDLER; + payload: { id: string }; +}; + +function unregisterVoiceHandler(id: string): VoiceUnregisterHandlerAction { + return { + type: VOICE_UNREGISTER_HANDLER, + payload: { id } + }; +} + +export default unregisterVoiceHandler; + +export { VOICE_UNREGISTER_HANDLER }; + +export type { VoiceUnregisterHandlerAction }; diff --git a/packages/core/src/actions/voiceActivityActions.ts b/packages/core/src/actions/voiceActivityActions.ts deleted file mode 100644 index 2e4432ba9f..0000000000 --- a/packages/core/src/actions/voiceActivityActions.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { WebChatActivity } from '../types/WebChatActivity'; - -const VOICE_START_RECORDING = 'WEB_CHAT/VOICE_START_RECORDING' as const; -const VOICE_STOP_RECORDING = 'WEB_CHAT/VOICE_STOP_RECORDING' as const; -const VOICE_SET_STATE = 'WEB_CHAT/VOICE_SET_STATE' as const; -const VOICE_REGISTER_HANDLER = 'WEB_CHAT/VOICE_REGISTER_HANDLER' as const; -const VOICE_POST_ACTIVITY = 'WEB_CHAT/VOICE_POST_ACTIVITY' as const; - -type SpeechState = 'idle' | 'listening' | 'user_speaking' | 'processing' | 'bot_speaking'; -type VoiceHandler = { - playAudio: (base64: string) => void; - stopAudio: () => void; -} | null; - -type VoiceStartRecordingAction = { - type: typeof VOICE_START_RECORDING; -}; - -type VoiceStopRecordingAction = { - type: typeof VOICE_STOP_RECORDING; -}; - -type VoiceSetStateAction = { - type: typeof VOICE_SET_STATE; - payload: { speechState: SpeechState }; -}; - -type VoiceRegisterHandlerAction = { - type: typeof VOICE_REGISTER_HANDLER; - payload: { voiceHandler: VoiceHandler }; -}; - -type VoicePostActivityAction = { - type: typeof VOICE_POST_ACTIVITY; - payload: { activity: WebChatActivity }; -}; - -type VoiceActivityActions = - | VoiceStartRecordingAction - | VoiceStopRecordingAction - | VoiceSetStateAction - | VoiceRegisterHandlerAction - | VoicePostActivityAction; - -function startVoiceRecording(): VoiceStartRecordingAction { - return { - type: VOICE_START_RECORDING - }; -} - -function stopVoiceRecording(): VoiceStopRecordingAction { - return { - type: VOICE_STOP_RECORDING - }; -} - -function setVoiceState(speechState: SpeechState): VoiceSetStateAction { - return { - type: VOICE_SET_STATE, - payload: { speechState } - }; -} - -function registerVoiceHandler(voiceHandler: VoiceHandler): VoiceRegisterHandlerAction { - return { - type: VOICE_REGISTER_HANDLER, - payload: { voiceHandler } - }; -} - -function postVoiceActivity(activity: WebChatActivity): VoicePostActivityAction { - return { - type: VOICE_POST_ACTIVITY, - payload: { activity } - }; -} - -export { - VOICE_START_RECORDING, - VOICE_STOP_RECORDING, - VOICE_SET_STATE, - VOICE_REGISTER_HANDLER, - VOICE_POST_ACTIVITY, - startVoiceRecording, - stopVoiceRecording, - setVoiceState, - registerVoiceHandler, - postVoiceActivity -}; - -export type { - SpeechState, - VoiceHandler, - VoiceActivityActions, - VoiceStartRecordingAction, - VoiceStopRecordingAction, - VoiceSetStateAction, - VoiceRegisterHandlerAction, - VoicePostActivityAction -}; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7b47131a41..27fde76d63 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -44,23 +44,14 @@ import isVoiceActivity from './utils/voiceActivity/isVoiceActivity'; import isVoiceTranscriptActivity from './utils/voiceActivity/isVoiceTranscriptActivity'; import getVoiceActivityRole from './utils/voiceActivity/getVoiceActivityRole'; import getVoiceActivityText from './utils/voiceActivity/getVoiceActivityText'; -import { - startVoiceRecording, - stopVoiceRecording, - setVoiceState, - registerVoiceHandler, - postVoiceActivity -} from './actions/voiceActivityActions'; -import type { - SpeechState, - VoiceHandler, - VoiceActivityActions, - VoiceStartRecordingAction, - VoiceStopRecordingAction, - VoiceSetStateAction, - VoiceRegisterHandlerAction, - VoicePostActivityAction -} from './actions/voiceActivityActions'; +import startVoiceRecording from './actions/startVoiceRecording'; +import stopVoiceRecording from './actions/stopVoiceRecording'; +import setVoiceState from './actions/setVoiceState'; +import registerVoiceHandler from './actions/registerVoiceHandler'; +import unregisterVoiceHandler from './actions/unregisterVoiceHandler'; +import postVoiceActivity from './actions/postVoiceActivity'; +import type { VoiceState } from './actions/setVoiceState'; +import type { VoiceHandler } from './actions/registerVoiceHandler'; export { isForbiddenPropertyName, @@ -136,6 +127,7 @@ export { postActivity, postVoiceActivity, registerVoiceHandler, + unregisterVoiceHandler, sendEvent, sendFiles, sendMessage, @@ -185,14 +177,8 @@ export type { OrgSchemaThing, OrgSchemaUserReview, SendBoxAttachment, - SpeechState, - VoiceActivityActions, VoiceHandler, - VoicePostActivityAction, - VoiceRegisterHandlerAction, - VoiceSetStateAction, - VoiceStartRecordingAction, - VoiceStopRecordingAction, + VoiceState, WebChatActivity }; diff --git a/packages/core/src/reducers/voiceActivity.ts b/packages/core/src/reducers/voiceActivity.ts index 239186ca7e..d7f6953e49 100644 --- a/packages/core/src/reducers/voiceActivity.ts +++ b/packages/core/src/reducers/voiceActivity.ts @@ -1,50 +1,75 @@ -import { - VOICE_START_RECORDING, - VOICE_STOP_RECORDING, - VOICE_SET_STATE, - VOICE_REGISTER_HANDLER -} from '../actions/voiceActivityActions'; - -import type { SpeechState, VoiceHandler, VoiceActivityActions } from '../actions/voiceActivityActions'; - -interface VoiceState { - recording: boolean; - speechState: SpeechState; - voiceHandler: VoiceHandler; +import { VOICE_REGISTER_HANDLER } from '../actions/registerVoiceHandler'; +import { VOICE_SET_STATE } from '../actions/setVoiceState'; +import { VOICE_START_RECORDING } from '../actions/startVoiceRecording'; +import { VOICE_STOP_RECORDING } from '../actions/stopVoiceRecording'; +import { VOICE_UNREGISTER_HANDLER } from '../actions/unregisterVoiceHandler'; + +import type { VoiceHandler, VoiceRegisterHandlerAction } from '../actions/registerVoiceHandler'; +import type { VoiceSetStateAction, VoiceState } from '../actions/setVoiceState'; +import type { VoiceStartRecordingAction } from '../actions/startVoiceRecording'; +import type { VoiceStopRecordingAction } from '../actions/stopVoiceRecording'; +import type { VoiceUnregisterHandlerAction } from '../actions/unregisterVoiceHandler'; + +type VoiceActivityActions = + | VoiceRegisterHandlerAction + | VoiceSetStateAction + | VoiceStartRecordingAction + | VoiceStopRecordingAction + | VoiceUnregisterHandlerAction; + +interface VoiceActivityState { + voiceState: VoiceState; + voiceHandlers: Map; } -const DEFAULT_STATE: VoiceState = { - recording: false, - speechState: 'idle', - voiceHandler: null +const DEFAULT_STATE: VoiceActivityState = { + voiceState: 'idle', + voiceHandlers: new Map() }; -export default function voice(state: VoiceState = DEFAULT_STATE, action: VoiceActivityActions): VoiceState { +export default function voiceActivity( + state: VoiceActivityState = DEFAULT_STATE, + action: VoiceActivityActions +): VoiceActivityState { switch (action.type) { - case VOICE_START_RECORDING: + case VOICE_REGISTER_HANDLER: { + const newHandlers = new Map(state.voiceHandlers); + newHandlers.set(action.payload.id, action.payload.voiceHandler); return { ...state, - recording: true, - speechState: 'listening' + voiceHandlers: newHandlers }; + } - case VOICE_STOP_RECORDING: + case VOICE_UNREGISTER_HANDLER: { + const newHandlers = new Map(state.voiceHandlers); + newHandlers.delete(action.payload.id); return { ...state, - recording: false, - speechState: 'idle' + voiceHandlers: newHandlers }; + } case VOICE_SET_STATE: return { ...state, - speechState: action.payload.speechState + voiceState: action.payload.voiceState + }; + + case VOICE_START_RECORDING: + if (state.voiceState !== 'idle') { + console.warn(`botframework-webchat: Should not transit from "${state.voiceState}" to "listening"`); + } + + return { + ...state, + voiceState: 'listening' }; - case VOICE_REGISTER_HANDLER: + case VOICE_STOP_RECORDING: return { ...state, - voiceHandler: action.payload.voiceHandler + voiceState: 'idle' }; default: @@ -52,4 +77,4 @@ export default function voice(state: VoiceState = DEFAULT_STATE, action: VoiceAc } } -export type { VoiceState }; +export type { VoiceActivityState }; diff --git a/packages/core/src/sagas/observeActivitySaga.ts b/packages/core/src/sagas/observeActivitySaga.ts index 6c4eaa374e..baaed4592e 100644 --- a/packages/core/src/sagas/observeActivitySaga.ts +++ b/packages/core/src/sagas/observeActivitySaga.ts @@ -3,14 +3,13 @@ import updateIn from 'simple-update-in'; import observeEach from './effects/observeEach'; import queueIncomingActivity from '../actions/queueIncomingActivity'; -import { setVoiceState } from '../actions/voiceActivityActions'; +import setVoiceState from '../actions/setVoiceState'; import whileConnected from './effects/whileConnected'; import isVoiceActivity from '../utils/voiceActivity/isVoiceActivity'; import isVoiceTranscriptActivity from '../utils/voiceActivity/isVoiceTranscriptActivity'; import type { DirectLineActivity } from '../types/external/DirectLineActivity'; import type { DirectLineJSBotConnection } from '../types/external/DirectLineJSBotConnection'; import type { WebChatActivity } from '../types/WebChatActivity'; -import type { VoiceHandler } from '../actions/voiceActivityActions'; const PASSTHRU_FN = (value: unknown) => value; @@ -80,30 +79,31 @@ function patchFromName(activity: DirectLineActivity) { function* observeActivity({ directLine, userID }: { directLine: DirectLineJSBotConnection; userID?: string }) { yield observeEach(directLine.activity$, function* observeActivity(activity: DirectLineActivity) { // Handle voice activities separately - don't store them in Redux (except transcripts) - const directLineActivity = activity as DirectLineActivity; - if (isVoiceActivity(directLineActivity) && !isVoiceTranscriptActivity(directLineActivity)) { - const voiceHandler: VoiceHandler = yield select(state => state.voice?.voiceHandler); - const recording: boolean = yield select(state => state.voice?.recording); + if (isVoiceActivity(activity) && !isVoiceTranscriptActivity(activity)) { + const { recording, voiceHandlers } = yield select(state => ({ + recording: state.voice.voiceState !== 'idle', + voiceHandlers: state.voice.voiceHandlers + })); if (!recording) { return; } - switch (directLineActivity.name) { + switch (activity.name) { case 'stream.chunk': { - const audioContent = directLineActivity?.payload?.voice?.content; + const audioContent = activity?.payload?.voice?.content; if (audioContent) { - voiceHandler.playAudio(audioContent); + voiceHandlers.forEach(handler => handler.queueAudio(audioContent)); } break; } case 'session.update': { - const session = directLineActivity?.payload?.voice?.session; + const session = activity?.payload?.voice?.session; switch (session) { case 'request.detected': - voiceHandler.stopAudio(); + voiceHandlers.forEach(handler => handler.stopAllAudio()); yield put(setVoiceState('user_speaking')); break; diff --git a/packages/core/src/sagas/postVoiceActivitySaga.ts b/packages/core/src/sagas/postVoiceActivitySaga.ts index 004402e2d9..27b1f4bc32 100644 --- a/packages/core/src/sagas/postVoiceActivitySaga.ts +++ b/packages/core/src/sagas/postVoiceActivitySaga.ts @@ -1,5 +1,5 @@ import { select, takeEvery } from 'redux-saga/effects'; -import { VOICE_POST_ACTIVITY } from '../actions/voiceActivityActions'; +import { VOICE_POST_ACTIVITY } from '../actions/postVoiceActivity'; import languageSelector from '../selectors/language'; import dateToLocaleISOString from '../utils/dateToLocaleISOString'; import whileConnected from './effects/whileConnected'; @@ -8,7 +8,7 @@ import observeOnce from './effects/observeOnce'; import type { DirectLineJSBotConnection } from '../types/external/DirectLineJSBotConnection'; import type { DirectLineActivity } from '../types/external/DirectLineActivity'; import type { GlobalScopePonyfill } from '../types/GlobalScopePonyfill'; -import type { VoicePostActivityAction } from '../actions/voiceActivityActions'; +import type { VoicePostActivityAction } from '../actions/postVoiceActivity'; /** * Saga for handling outgoing voice activities. diff --git a/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx b/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx index 0fe1e62605..e3b0fdfc7f 100644 --- a/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx +++ b/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx @@ -1,4 +1,4 @@ -import { hooks } from 'botframework-webchat-api'; +import { hooks } from 'botframework-webchat'; import cx from 'classnames'; import React, { memo, useCallback } from 'react'; @@ -9,29 +9,37 @@ import { ToolbarButton } from './Toolbar'; import styles from './Toolbar.module.css'; -const { useSpeechToSpeech, useLocalizer } = hooks; +const { useVoiceState, useStartVoice, useStopVoice, useLocalizer } = hooks; function MicrophoneToolbarButton() { const classNames = useStyles(styles); const localize = useLocalizer(); - const [{ recording, setRecording, speechState }] = useSpeechToSpeech(); + const [voiceState] = useVoiceState(); + const startVoice = useStartVoice(); + const stopVoice = useStopVoice(); + + const recording = voiceState !== 'idle'; const handleMicrophoneClick = useCallback(() => { - setRecording(!recording); - }, [recording, setRecording]); + if (recording) { + stopVoice(); + } else { + startVoice(); + } + }, [recording, startVoice, stopVoice]); const ariaLabel = localize( recording ? 'SPEECH_INPUT_MICROPHONE_BUTTON_OPEN_ALT' : 'SPEECH_INPUT_MICROPHONE_BUTTON_CLOSE_ALT' ); - const isBotSpeaking = speechState === 'bot_speaking'; - const isUserSpeaking = speechState === 'user_speaking'; + const isBotSpeaking = voiceState === 'bot_speaking'; + const isUserSpeaking = voiceState === 'user_speaking'; return ( - + ); } diff --git a/packages/fluent-theme/src/components/sendBox/SendBox.tsx b/packages/fluent-theme/src/components/sendBox/SendBox.tsx index 59872782fe..bf8a790817 100644 --- a/packages/fluent-theme/src/components/sendBox/SendBox.tsx +++ b/packages/fluent-theme/src/components/sendBox/SendBox.tsx @@ -1,4 +1,5 @@ import { Components, hooks } from 'botframework-webchat'; +import { usePostVoiceActivity } from 'botframework-webchat/internal'; import cx from 'classnames'; import React, { memo, @@ -33,14 +34,13 @@ const { useFocus, useLocalizer, useMakeThumbnail, - usePostVoiceActivity, useRegisterFocusSendBox, useSendBoxAttachments, useSendBoxValue, useSendMessage, - useSpeechToSpeech, useStyleOptions, - useUIState + useUIState, + useVoiceState } = hooks; const { AttachmentBar, TextArea } = Components; @@ -69,8 +69,9 @@ function SendBox(props: Props) { const setFocus = useFocus(); const postVoiceActivity = usePostVoiceActivity(); const speechStateMessage = useSpeechStateMessage(); - const [{ recording }] = useSpeechToSpeech(); + const [voiceState] = useVoiceState(); + const recording = voiceState !== 'idle'; const message = props.isPrimary ? globalMessage : localMessage; const setMessage = props.isPrimary ? setGlobalMessage : setLocalMessage; const isBlueprint = uiState === 'blueprint'; diff --git a/packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts b/packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts index 462cf31183..6bfbc043ff 100644 --- a/packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts +++ b/packages/fluent-theme/src/components/sendBox/private/useSpeechStateMessage.ts @@ -1,13 +1,13 @@ import { hooks } from 'botframework-webchat'; import { useMemo } from 'react'; -const { useLocalizer, useSpeechToSpeech } = hooks; +const { useLocalizer, useVoiceState } = hooks; export default function useSpeechPlaceholder(): string { const localize = useLocalizer(); - const [{ speechState }] = useSpeechToSpeech(); + const [voiceState] = useVoiceState(); return useMemo(() => { - switch (speechState) { + switch (voiceState) { case 'idle': return localize('TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER'); @@ -24,5 +24,5 @@ export default function useSpeechPlaceholder(): string { default: return localize('TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER'); } - }, [speechState, localize]); + }, [voiceState, localize]); } diff --git a/packages/fluent-theme/src/external.umd/botframework-webchat-api/internal.ts b/packages/fluent-theme/src/external.umd/botframework-webchat-api/internal.ts index d3920b80ab..c2713f0336 100644 --- a/packages/fluent-theme/src/external.umd/botframework-webchat-api/internal.ts +++ b/packages/fluent-theme/src/external.umd/botframework-webchat-api/internal.ts @@ -1,5 +1,3 @@ /// -module.exports = { - internal: (globalThis as any).WebChat.internal -}; +module.exports = (globalThis as any).WebChat.internal; diff --git a/packages/fluent-theme/src/private/FluentThemeProvider.tsx b/packages/fluent-theme/src/private/FluentThemeProvider.tsx index dd907b28ff..13c7565eb7 100644 --- a/packages/fluent-theme/src/private/FluentThemeProvider.tsx +++ b/packages/fluent-theme/src/private/FluentThemeProvider.tsx @@ -72,7 +72,7 @@ const decoratorMiddleware: readonly DecoratorMiddleware[] = Object.freeze([ return next(request); }), createActivityBorderMiddleware(function FluentBorderFlair({ request, Next, ...props }) { - if (request.voiceTranscriptRole === 'bot') { + if (request.modality.has('audio') && request.from === 'bot') { return ( From 6f653ea49b994643fdd51ad1c361d5d88974b064 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Wed, 28 Jan 2026 13:51:39 +0000 Subject: [PATCH 17/32] review comment fixed --- __tests__/html2/activity/message-status.html | 1 + .../html2/simple/fatModule/fluentTheme.html | 1 + package-lock.json | 1 + .../src/hooks/internal/useVoiceHandlers.ts | 4 ++-- .../decorator/private/WebChatDecorator.tsx | 10 +++++++++ packages/core/src/createSagas.ts | 2 +- .../voiceActivity/getVoiceActivityRole.ts | 6 ++--- .../utils/voiceActivity/isVoiceActivity.ts | 4 ++-- .../isVoiceTranscriptActivity.ts | 4 ++-- packages/fluent-theme/package.json | 1 + .../activity/PartGroupingDecorator.tsx | 5 +++-- .../VoiceTranscriptActivityStatus.module.css | 6 ++--- .../src/components/icon/FluentIcon.module.css | 4 ++-- .../sendBox/MicrophoneToolbarButton.tsx | 6 ++--- .../src/components/sendBox/SendBox.module.css | 10 +-------- .../src/components/sendBox/SendBox.tsx | 15 ++++++------- .../src/components/sendBox/Toolbar.module.css | 12 ++++++---- .../sendBox/private/useSpeechStateMessage.ts | 9 ++++---- .../src/private/FluentThemeProvider.tsx | 19 ++++------------ .../testHelpers/createDirectLineEmulator.js | 22 +++++++++---------- 20 files changed, 69 insertions(+), 73 deletions(-) diff --git a/__tests__/html2/activity/message-status.html b/__tests__/html2/activity/message-status.html index c2ffadc3aa..ab8cb80aa4 100644 --- a/__tests__/html2/activity/message-status.html +++ b/__tests__/html2/activity/message-status.html @@ -15,6 +15,7 @@ "botframework-webchat/decorator": "/__dist__/packages/bundle/static/botframework-webchat/decorator.js", "botframework-webchat/hook": "/__dist__/packages/bundle/static/botframework-webchat/hook.js", "botframework-webchat/internal": "/__dist__/packages/bundle/static/botframework-webchat/internal.js", + "botframework-webchat-core": "/__dist__/packages/bundle/static/botframework-webchat-core.js", "botframework-webchat-fluent-theme": "/__dist__/packages/fluent-theme/static/botframework-webchat-fluent-theme.js", "react": "https://esm.sh/react@18", "react-dom": "https://esm.sh/react-dom@18", diff --git a/__tests__/html2/simple/fatModule/fluentTheme.html b/__tests__/html2/simple/fatModule/fluentTheme.html index fff45cf0ad..267d2601bd 100644 --- a/__tests__/html2/simple/fatModule/fluentTheme.html +++ b/__tests__/html2/simple/fatModule/fluentTheme.html @@ -22,6 +22,7 @@ "botframework-webchat/decorator": "/__dist__/packages/bundle/static/botframework-webchat/decorator.js", "botframework-webchat/hook": "/__dist__/packages/bundle/static/botframework-webchat/hook.js", "botframework-webchat/internal": "/__dist__/packages/bundle/static/botframework-webchat/internal.js", + "botframework-webchat-core": "/__dist__/packages/bundle/static/botframework-webchat-core.js", "botframework-webchat-fluent-theme": "/__dist__/packages/fluent-theme/static/botframework-webchat-fluent-theme.js", "react": "/__dist__/packages/bundle/static/react.js", "react-dom": "/__dist__/packages/bundle/static/react-dom.js", diff --git a/package-lock.json b/package-lock.json index 2bea880d81..81651d0729 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21008,6 +21008,7 @@ "license": "MIT", "dependencies": { "botframework-webchat": "0.0.0-0", + "botframework-webchat-core": "0.0.0-0", "classnames": "2.5.1", "inject-meta-tag": "0.0.1", "math-random": "2.0.1", diff --git a/packages/api/src/hooks/internal/useVoiceHandlers.ts b/packages/api/src/hooks/internal/useVoiceHandlers.ts index ff1fac0452..bdbc3e5115 100644 --- a/packages/api/src/hooks/internal/useVoiceHandlers.ts +++ b/packages/api/src/hooks/internal/useVoiceHandlers.ts @@ -4,6 +4,6 @@ import { useSelector } from './WebChatReduxContext'; /** * Internal hook to get all registered voice handlers from Redux state. */ -export default function useVoiceHandlers(): [readonly VoiceHandler[]] { - return [useSelector((state: { voice: { voiceHandlers } }) => Array.from(state.voice.voiceHandlers.values()))]; +export default function useVoiceHandlers(): [ReadonlyMap] { + return [useSelector((state: { voice: { voiceHandlers: Map } }) => state.voice.voiceHandlers)]; } diff --git a/packages/component/src/decorator/private/WebChatDecorator.tsx b/packages/component/src/decorator/private/WebChatDecorator.tsx index 33d76363ee..edce239b69 100644 --- a/packages/component/src/decorator/private/WebChatDecorator.tsx +++ b/packages/component/src/decorator/private/WebChatDecorator.tsx @@ -13,6 +13,16 @@ import BorderFlair from './BorderFlair'; import BorderLoader from './BorderLoader'; const middleware: readonly DecoratorMiddleware[] = Object.freeze([ + createActivityBorderMiddleware(function FluentBorderFlair({ request, Next, ...props }) { + if (request.modality.has('audio') && request.from === 'bot') { + return ( + + + + ); + } + return ; + }), createActivityBorderMiddleware(function BorderFlairDecorator({ request, Next, ...props }) { return ( diff --git a/packages/core/src/createSagas.ts b/packages/core/src/createSagas.ts index fe334d6e90..1fe2cac6e3 100644 --- a/packages/core/src/createSagas.ts +++ b/packages/core/src/createSagas.ts @@ -45,6 +45,7 @@ export default function createSagas({ ponyfill }: CreateSagasOptions): Saga { yield fork(markAllAsSpokenOnStopSpeakActivitySaga); yield fork(observeActivitySaga); yield fork(postActivitySaga, ponyfill); + yield fork(postVoiceActivitySaga, ponyfill); yield fork(queueIncomingActivitySaga, ponyfill); yield fork(sendEventToPostActivitySaga); yield fork(sendFilesToPostActivitySaga); @@ -58,6 +59,5 @@ export default function createSagas({ ponyfill }: CreateSagasOptions): Saga { yield fork(stopDictateOnCardActionSaga); yield fork(stopSpeakingActivityOnInputSaga); yield fork(submitSendBoxSaga); - yield fork(postVoiceActivitySaga, ponyfill); }; } diff --git a/packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts b/packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts index 07727a598f..ab34351686 100644 --- a/packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts +++ b/packages/core/src/utils/voiceActivity/getVoiceActivityRole.ts @@ -1,13 +1,11 @@ import { WebChatActivity } from '../../types/WebChatActivity'; import isVoiceTranscriptActivity from './isVoiceTranscriptActivity'; -const getVoiceActivityRole = (activity: WebChatActivity): 'user' | 'bot' | undefined => { +const getVoiceActivityRole = (activity: WebChatActivity): 'bot' | 'user' | undefined => { if (isVoiceTranscriptActivity(activity)) { if (activity.payload.voice.origin === 'agent') { return 'bot'; - } - - if (activity.payload.voice.origin === 'user') { + } else if (activity.payload.voice.origin === 'user') { return 'user'; } } diff --git a/packages/core/src/utils/voiceActivity/isVoiceActivity.ts b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts index 8aa8151c47..01cc023bab 100644 --- a/packages/core/src/utils/voiceActivity/isVoiceActivity.ts +++ b/packages/core/src/utils/voiceActivity/isVoiceActivity.ts @@ -8,10 +8,10 @@ const VoiceActivitySchema = object({ name: string(), payload: union([ object({ - voice: any() + dtmf: any() }), object({ - dtmf: any() + voice: any() }) ]), type: literal('event') diff --git a/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts index 0eac221d40..d82792c481 100644 --- a/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts +++ b/packages/core/src/utils/voiceActivity/isVoiceTranscriptActivity.ts @@ -6,7 +6,7 @@ const VoiceTranscriptActivitySchema = object({ name: literal('stream.end'), payload: object({ voice: object({ - origin: picklist(['user', 'agent']), + origin: picklist(['agent', 'user']), transcription: string() }) }), @@ -18,8 +18,8 @@ const isVoiceTranscriptActivity = ( ): activity is WebChatActivity & { payload: { voice: { + origin: 'agent' | 'user'; transcription: string; - origin: 'user' | 'agent'; }; }; } => safeParse(VoiceTranscriptActivitySchema, activity).success; diff --git a/packages/fluent-theme/package.json b/packages/fluent-theme/package.json index 36dee197c4..4351e4d821 100644 --- a/packages/fluent-theme/package.json +++ b/packages/fluent-theme/package.json @@ -85,6 +85,7 @@ }, "dependencies": { "botframework-webchat": "0.0.0-0", + "botframework-webchat-core": "0.0.0-0", "classnames": "2.5.1", "inject-meta-tag": "0.0.1", "math-random": "2.0.1", diff --git a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx index eacc92a1b7..dc06238ceb 100644 --- a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx +++ b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx @@ -1,4 +1,5 @@ import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot'; +import { getVoiceActivityRole } from 'botframework-webchat-core'; import { getOrgSchemaMessage, PartGrouping, type WebChatActivity } from 'botframework-webchat/internal'; import cx from 'classnames'; import React, { memo, useMemo, type ReactNode } from 'react'; @@ -7,7 +8,6 @@ import { array, custom, object, optional, pipe, readonly, safeParse } from 'vali import { useStyles, useVariantClassName } from '../../styles'; import styles from './PartGroupingDecorator.module.css'; -import { getVoiceActivityRole } from 'botframework-webchat-core'; const partGroupingDecoratorPropsSchema = pipe( object({ @@ -42,8 +42,9 @@ function PartGroupingDecorator(props: PartGroupingDecoratorProps) { // S2S-both user and bot transcript comes from server (RT-LLM) hence need to check role explicitly. // voiceActivityRole takes precedence over from.role since S2S activities always come from 'bot' const voiceActivityRole = activity && getVoiceActivityRole(activity); - const isFromUser = voiceActivityRole ? voiceActivityRole === 'user' : activity?.from?.role === 'user'; + const isFromBot = voiceActivityRole ? voiceActivityRole === 'bot' : activity?.from?.role === 'bot'; + const isFromUser = voiceActivityRole ? voiceActivityRole === 'user' : activity?.from?.role === 'user'; return (
'); + --webchat__fluent-icon--mask: url('data:image/svg+xml;utf8,'); } :global(.webchat) .icon--audio-playing { - --webchat__fluent-icon--mask: url('data:image/svg+xml;utf8,'); + --webchat__fluent-icon--mask: url('data:image/svg+xml;utf8,'); } /* #endregion */ diff --git a/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx b/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx index e3b0fdfc7f..946f2a5e88 100644 --- a/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx +++ b/packages/fluent-theme/src/components/sendBox/MicrophoneToolbarButton.tsx @@ -12,9 +12,9 @@ import styles from './Toolbar.module.css'; const { useVoiceState, useStartVoice, useStopVoice, useLocalizer } = hooks; function MicrophoneToolbarButton() { + const [voiceState] = useVoiceState(); const classNames = useStyles(styles); const localize = useLocalizer(); - const [voiceState] = useVoiceState(); const startVoice = useStartVoice(); const stopVoice = useStopVoice(); @@ -22,9 +22,9 @@ function MicrophoneToolbarButton() { const handleMicrophoneClick = useCallback(() => { if (recording) { - stopVoice(); + stopVoice(); // Stop recognition and synthesis. } else { - startVoice(); + startVoice(); // If it was stopped, will start recognition. It will synthesize when the bot respond. } }, [recording, startVoice, stopVoice]); diff --git a/packages/fluent-theme/src/components/sendBox/SendBox.module.css b/packages/fluent-theme/src/components/sendBox/SendBox.module.css index ce5de5e2a1..e8ad5744d5 100644 --- a/packages/fluent-theme/src/components/sendBox/SendBox.module.css +++ b/packages/fluent-theme/src/components/sendBox/SendBox.module.css @@ -55,7 +55,7 @@ transition: clip-path var(--webchat-durationUltraFast) var(--webchat-curveAccelerateMid); } - &:focus-within::after { + &:not(:has(textarea[readonly][aria-disabled='true'])):focus-within::after { clip-path: inset(calc(100% - var(--webchat-strokeWidthThicker)) 0 0 0); transition: clip-path var(--webchat-durationNormal) var(--webchat-curveDecelerateMid); } @@ -77,14 +77,6 @@ } } -/* Speech-to-speech variant: disable focus animations and pointer events on the main box. */ -:global(.webchat-fluent) .sendbox__sendbox.sendbox__sendbox--speech { - &::after, - &:focus-within::after { - display: none; - } -} - :global(.webchat-fluent) .sendbox__attachment-bar:global(.send-box-attachment-bar) { :global(.send-box-attachment-bar__box) { diff --git a/packages/fluent-theme/src/components/sendBox/SendBox.tsx b/packages/fluent-theme/src/components/sendBox/SendBox.tsx index 1aec1e4120..0b46f63800 100644 --- a/packages/fluent-theme/src/components/sendBox/SendBox.tsx +++ b/packages/fluent-theme/src/components/sendBox/SendBox.tsx @@ -59,20 +59,20 @@ function SendBox(props: Props) { const [localMessage, setLocalMessage] = useState(''); const [telephoneKeypadShown] = useTelephoneKeypadShown(); const [uiState] = useUIState(); + const [voiceState] = useVoiceState(); const classNames = useStyles(styles); const variantClassName = useVariantClassName(styles); const errorMessageId = useUniqueId('sendbox__error-message-id'); const inputRef = useRef(null); const localize = useLocalizer(); const makeThumbnail = useMakeThumbnail(); + const postVoiceActivity = usePostVoiceActivity(); const sendMessage = useSendMessage(); const setFocus = useFocus(); - const postVoiceActivity = usePostVoiceActivity(); const speechStateMessage = useSpeechStateMessage(); - const [voiceState] = useVoiceState(); - const recording = voiceState !== 'idle'; const message = props.isPrimary ? globalMessage : localMessage; + const recording = voiceState !== 'idle'; const setMessage = props.isPrimary ? setGlobalMessage : setLocalMessage; const isBlueprint = uiState === 'blueprint'; @@ -211,9 +211,7 @@ function SendBox(props: Props) { >
@@ -261,8 +259,9 @@ function SendBox(props: Props) { {!hideTelephoneKeypadButton && } {!disableFileUpload && } - {showMicrophoneButton && } - {!showMicrophoneButton && ( + {showMicrophoneButton ? ( + + ) : ( { switch (voiceState) { + case 'bot_speaking': + return localize('TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER'); + case 'idle': return localize('TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER'); @@ -18,9 +22,6 @@ export default function useSpeechPlaceholder(): string { case 'processing': return localize('TEXT_INPUT_SPEECH_PROCESSING_PLACEHOLDER'); - case 'bot_speaking': - return localize('TEXT_INPUT_SPEECH_BOT_SPEAKING_PLACEHOLDER'); - default: return localize('TEXT_INPUT_SPEECH_IDLE_PLACEHOLDER'); } diff --git a/packages/fluent-theme/src/private/FluentThemeProvider.tsx b/packages/fluent-theme/src/private/FluentThemeProvider.tsx index 13c7565eb7..58e3ba83b1 100644 --- a/packages/fluent-theme/src/private/FluentThemeProvider.tsx +++ b/packages/fluent-theme/src/private/FluentThemeProvider.tsx @@ -6,20 +6,18 @@ import { createActivityGroupingMiddleware, DecoratorComposer, WebChatDecorator, - BorderFlair, type DecoratorMiddleware } from 'botframework-webchat/decorator'; import { type ActivityMiddleware, - type TypingIndicatorMiddleware, - type ActivityStatusMiddleware + type ActivityStatusMiddleware, + type TypingIndicatorMiddleware } from 'botframework-webchat/internal'; +import { isVoiceTranscriptActivity } from 'botframework-webchat-core'; import React, { memo, useMemo } from 'react'; import { custom, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; -import { isVoiceTranscriptActivity } from 'botframework-webchat-core'; import ActivityLoader from '../components/activity/ActivityLoader'; -import VoiceTranscriptActivityStatus from '../components/activityStatus/VoiceTranscriptActivityStatus'; import PartGroupDecorator from '../components/activity/PartGroupingDecorator'; import AssetComposer from '../components/assets/AssetComposer'; import { isLinerMessageActivity, LinerMessageActivity } from '../components/linerActivity'; @@ -30,6 +28,7 @@ import { WebChatTheme } from '../components/theme'; import SlidingDotsTypingIndicator from '../components/typingIndicator/SlidingDotsTypingIndicator'; import FluentThemeStylesheet from '../stylesheet/FluentThemeStylesheet'; import VariantComposer, { variantNameSchema } from './VariantComposer'; +import VoiceTranscriptActivityStatus from '../components/activityStatus/VoiceTranscriptActivityStatus'; const fluentThemeProviderPropsSchema = pipe( object({ @@ -71,16 +70,6 @@ const decoratorMiddleware: readonly DecoratorMiddleware[] = Object.freeze([ } return next(request); }), - createActivityBorderMiddleware(function FluentBorderFlair({ request, Next, ...props }) { - if (request.modality.has('audio') && request.from === 'bot') { - return ( - - - - ); - } - return ; - }), createActivityBorderMiddleware(function FluentBorderLoader({ request, Next, ...props }) { return ( diff --git a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js index 69e49c9bb3..54868fe52e 100644 --- a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js +++ b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js @@ -40,29 +40,27 @@ export default function createDirectLineEmulator({ autoConnect = true, ponyfill const postActivityCallDeferreds = []; const postActivity = outgoingActivity => { - const returnPostActivityWithResolvers = withResolvers(); - // Auto-handle voice activities (continuous sending by mic) without requiring actPostActivity // Voice activities are fire-and-forget and don't echo back if ( - outgoingActivity.type === 'event' && outgoingActivity.payload && - (outgoingActivity.payload.voice || outgoingActivity.payload.dtmf) + (outgoingActivity.payload.voice || outgoingActivity.payload.dtmf) && + outgoingActivity.type === 'event' ) { const id = uniqueId(); return new Observable(observer => { - (function () { - try { - observer.next(id); - observer.complete(); - } catch (error) { - observer.error(error); - } - })(); + try { + observer.next(id); + observer.complete(); + } catch (error) { + observer.error(error); + } }); } + const returnPostActivityWithResolvers = withResolvers(); + const deferred = postActivityCallDeferreds.shift(); if (!deferred) { From 0253890d1b2be34db277223d052d1c6cfc5b6207 Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Wed, 28 Jan 2026 15:58:06 +0000 Subject: [PATCH 18/32] instead of core import from webchat internal --- __tests__/html2/activity/message-status.html | 1 - __tests__/html2/simple/fatModule/fluentTheme.html | 1 - package-lock.json | 1 - packages/bundle/src/boot/actual/internal.ts | 9 ++++++++- packages/fluent-theme/package.json | 1 - .../src/components/activity/PartGroupingDecorator.tsx | 8 ++++++-- .../activityStatus/VoiceTranscriptActivityStatus.tsx | 3 +-- .../fluent-theme/src/private/FluentThemeProvider.tsx | 2 +- 8 files changed, 16 insertions(+), 10 deletions(-) diff --git a/__tests__/html2/activity/message-status.html b/__tests__/html2/activity/message-status.html index ab8cb80aa4..c2ffadc3aa 100644 --- a/__tests__/html2/activity/message-status.html +++ b/__tests__/html2/activity/message-status.html @@ -15,7 +15,6 @@ "botframework-webchat/decorator": "/__dist__/packages/bundle/static/botframework-webchat/decorator.js", "botframework-webchat/hook": "/__dist__/packages/bundle/static/botframework-webchat/hook.js", "botframework-webchat/internal": "/__dist__/packages/bundle/static/botframework-webchat/internal.js", - "botframework-webchat-core": "/__dist__/packages/bundle/static/botframework-webchat-core.js", "botframework-webchat-fluent-theme": "/__dist__/packages/fluent-theme/static/botframework-webchat-fluent-theme.js", "react": "https://esm.sh/react@18", "react-dom": "https://esm.sh/react-dom@18", diff --git a/__tests__/html2/simple/fatModule/fluentTheme.html b/__tests__/html2/simple/fatModule/fluentTheme.html index 267d2601bd..fff45cf0ad 100644 --- a/__tests__/html2/simple/fatModule/fluentTheme.html +++ b/__tests__/html2/simple/fatModule/fluentTheme.html @@ -22,7 +22,6 @@ "botframework-webchat/decorator": "/__dist__/packages/bundle/static/botframework-webchat/decorator.js", "botframework-webchat/hook": "/__dist__/packages/bundle/static/botframework-webchat/hook.js", "botframework-webchat/internal": "/__dist__/packages/bundle/static/botframework-webchat/internal.js", - "botframework-webchat-core": "/__dist__/packages/bundle/static/botframework-webchat-core.js", "botframework-webchat-fluent-theme": "/__dist__/packages/fluent-theme/static/botframework-webchat-fluent-theme.js", "react": "/__dist__/packages/bundle/static/react.js", "react-dom": "/__dist__/packages/bundle/static/react-dom.js", diff --git a/package-lock.json b/package-lock.json index 81651d0729..2bea880d81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21008,7 +21008,6 @@ "license": "MIT", "dependencies": { "botframework-webchat": "0.0.0-0", - "botframework-webchat-core": "0.0.0-0", "classnames": "2.5.1", "inject-meta-tag": "0.0.1", "math-random": "2.0.1", diff --git a/packages/bundle/src/boot/actual/internal.ts b/packages/bundle/src/boot/actual/internal.ts index a7a99683c3..3a4331f54a 100644 --- a/packages/bundle/src/boot/actual/internal.ts +++ b/packages/bundle/src/boot/actual/internal.ts @@ -18,4 +18,11 @@ export { useLiveRegion, type HighlightCodeFn } from 'botframework-webchat-component/internal'; -export { getOrgSchemaMessage, type DirectLineCardAction, type WebChatActivity } from 'botframework-webchat-core'; +export { + getOrgSchemaMessage, + getVoiceActivityRole, + getVoiceActivityText, + isVoiceTranscriptActivity, + type DirectLineCardAction, + type WebChatActivity +} from 'botframework-webchat-core'; diff --git a/packages/fluent-theme/package.json b/packages/fluent-theme/package.json index 4351e4d821..36dee197c4 100644 --- a/packages/fluent-theme/package.json +++ b/packages/fluent-theme/package.json @@ -85,7 +85,6 @@ }, "dependencies": { "botframework-webchat": "0.0.0-0", - "botframework-webchat-core": "0.0.0-0", "classnames": "2.5.1", "inject-meta-tag": "0.0.1", "math-random": "2.0.1", diff --git a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx index dc06238ceb..31b4e6626d 100644 --- a/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx +++ b/packages/fluent-theme/src/components/activity/PartGroupingDecorator.tsx @@ -1,6 +1,10 @@ import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot'; -import { getVoiceActivityRole } from 'botframework-webchat-core'; -import { getOrgSchemaMessage, PartGrouping, type WebChatActivity } from 'botframework-webchat/internal'; +import { + getOrgSchemaMessage, + getVoiceActivityRole, + PartGrouping, + type WebChatActivity +} from 'botframework-webchat/internal'; import cx from 'classnames'; import React, { memo, useMemo, type ReactNode } from 'react'; import { array, custom, object, optional, pipe, readonly, safeParse } from 'valibot'; diff --git a/packages/fluent-theme/src/components/activityStatus/VoiceTranscriptActivityStatus.tsx b/packages/fluent-theme/src/components/activityStatus/VoiceTranscriptActivityStatus.tsx index f6d8039fab..28f9202f0b 100644 --- a/packages/fluent-theme/src/components/activityStatus/VoiceTranscriptActivityStatus.tsx +++ b/packages/fluent-theme/src/components/activityStatus/VoiceTranscriptActivityStatus.tsx @@ -1,7 +1,6 @@ import { hooks } from 'botframework-webchat'; import { Timestamp } from 'botframework-webchat/component'; -import { type WebChatActivity } from 'botframework-webchat/internal'; -import { getVoiceActivityRole, getVoiceActivityText } from 'botframework-webchat-core'; +import { getVoiceActivityRole, getVoiceActivityText, type WebChatActivity } from 'botframework-webchat/internal'; import React, { Fragment, memo } from 'react'; import { useStyles } from '../../styles'; diff --git a/packages/fluent-theme/src/private/FluentThemeProvider.tsx b/packages/fluent-theme/src/private/FluentThemeProvider.tsx index 58e3ba83b1..e93c37d24a 100644 --- a/packages/fluent-theme/src/private/FluentThemeProvider.tsx +++ b/packages/fluent-theme/src/private/FluentThemeProvider.tsx @@ -9,11 +9,11 @@ import { type DecoratorMiddleware } from 'botframework-webchat/decorator'; import { + isVoiceTranscriptActivity, type ActivityMiddleware, type ActivityStatusMiddleware, type TypingIndicatorMiddleware } from 'botframework-webchat/internal'; -import { isVoiceTranscriptActivity } from 'botframework-webchat-core'; import React, { memo, useMemo } from 'react'; import { custom, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; From 41de921b6c5aca8f0994cee3dc8ab4dd5c49766f Mon Sep 17 00:00:00 2001 From: Pranav Joshi Date: Wed, 28 Jan 2026 16:14:48 +0000 Subject: [PATCH 19/32] update screen shot --- .../autoScroll.afterSend.html.snap-1.png | Bin 31091 -> 31093 bytes .../html2/hooks/useTextBox.html.snap-1.png | Bin 41046 -> 41056 bytes .../html2/hooks/useTextBox.html.snap-2.png | Bin 31091 -> 31093 bytes ...rollToEndButton.visibility.html.snap-1.png | Bin 41046 -> 41056 bytes ...rollToEndButton.visibility.html.snap-2.png | Bin 42765 -> 42770 bytes ...rollToEndButton.visibility.html.snap-3.png | Bin 33472 -> 33490 bytes ...rollToEndButton.visibility.html.snap-4.png | Bin 41054 -> 41050 bytes 7 files changed, 0 insertions(+), 0 deletions(-) diff --git a/__tests__/html2/autoScroll/autoScroll.afterSend.html.snap-1.png b/__tests__/html2/autoScroll/autoScroll.afterSend.html.snap-1.png index e5721214f78b198b9e195bccafd706b34d8b8b0a..4273801616e0886c39e8e51cf2e74594e13e21a2 100644 GIT binary patch delta 9599 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 Axc~qF delta 9521 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 diff --git a/__tests__/html2/hooks/useTextBox.html.snap-1.png b/__tests__/html2/hooks/useTextBox.html.snap-1.png index b9400025bd568a873d4ea20ed2bd0a7dfbc688ce..e15519d2c7df7fa3f54d493d6c8dfeb28b06d8b7 100644 GIT binary patch delta 38030 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 Axc~qF delta 9521 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 diff --git a/__tests__/html2/scrollToEndButton/scrollToEndButton.visibility.html.snap-1.png b/__tests__/html2/scrollToEndButton/scrollToEndButton.visibility.html.snap-1.png index b9400025bd568a873d4ea20ed2bd0a7dfbc688ce..e15519d2c7df7fa3f54d493d6c8dfeb28b06d8b7 100644 GIT binary patch delta 38030 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

L;aK-wx~9(r}J3?My>>XvMQ< z>B}FD4|{**`#GbJy0}lK@l`R!PYrLUWeVR<-)5w4!M8HFSjF;cFZKpg$-d>2PMxN2 z@N=x+T;=?sl6gWB5gLG{6JS!uJH1OPxGIQ~Il1;Ybo2`0k<>BH`hSu%|I3~N>~cy< z!6YU~Oz303LW7m8!;hF0n}?$JU~+u{2Z4Lc8LB% zWbpsfzZ>P(7zM|-i!Kk>T1-vZ%vVio?{&a0Ac*E?7C%R$lHu(PaCFz+3Yngk0mamI zM>F{b!3{r7H$7GTZ2E?Mxz!$||M07qyO7GLwE&5Fn40I_3OxUUuthN)l(Kh&LkN9F zZ2zQ9zb%_F%k24DTA#~v_kMOfVt=xM#DlQYYZSOuzx}e--TM*%3m~~GQ})5_q{tWr zHiunc?BA8CLIsoGkPln@gFY|VFSV1RMm=?`KNmm#P&oj4z`1tzhssmF!{*husi39r zE%?AnQ5Rd1ZED-{Z1RRFChKw!Fd~;Yxqx)U|FVA!?)>vfgS|M>N%q=gVLVX`?A}|( z6V)yERg0W+l9QQJpKKl#Qcuz!j+vrm4;458?b}Bf2Z2%(C{OKtYe42XJnMxTV#GpS zJlA^LG1JuX)av4D5X#x;fJMmarq|feW3<1{N?O1u$%_4E2jr+vBV-5Ihnz=W zP8>3ccGGX__4b?vwCrs{fagtk^_|xy_UpW#W>Cr}%Y$5Yd<`hs=7SJht;;1+4c)jJ{MZ(VocMR zPc$U$;A6X7LA=q@dR=^S2Q!akWeS>7W2l!JqfgM&Vi&Gr;JCXS4<<~^AZNU=u@Z*( zHex=i-yV2&V!J4K^d|Udxgv5C%q_YxK{DuhJ%^t|6IE%n^$dj_f8%O2#AtiY4I+<{ zMj%dz?u1{;7|G0AyqOuZ%62j%(R*+%DOb9oC$vq){L3}9+d2gTf8!^gXAG zuTtRyr%QyoX6?TKAfgLR+k>b6c%V^MmGR4Kr-#Ks4GdjLeCJ5m|Jy=oLfUt zHB7)LMFWv+2IWBw8ewei7I39z}Vetb<{=;bfn7WV0Il%p5-`Bey~X zU`#H%fM5Nm1y%xDC4X9Ac-Q7Vk9>>~K9iXxI3E2j@q!JF1+)=JSKSyMyLFizJQX+7nBZ{3XOJflqc!Ht7D*Y=h`xkZV`3_4qQltaNp$5>tXxgS5SKKmo@GNO#~ zZJfmh_`h8`NYA?0wl)p*bBfwz0WKYswE$6}rlawO6@-q-Xc)o-_a}rO;$7xJa@CH` z3TMIBKlB9_R)V3pg0&e$IT|Lg@O#`cxus=j;D`zlzCe{BW{kC>k@HP&X9==z^_P74 zGM`hl&(N&<$v`ycpSeJtie?(rhe}H#&%pV3TY{d!-{w(;)1~VyUm_+dBy&s63;_MS zWZ(dWw2+05Gwtty&hA5(oLkehAT}uK4Px03U#zA0m_nGmd@_tt=aBsCuUmk_y*B@N zLF0$}FXuQ&jZ@7RMsniT?#1sk8p5Y7%?eeP#MPVbL46^Ix;?7*CUDYp75jzdlXX&R z0b5Txw)vaiO{wz+DQZ(3!t=;Uwf8d|Jb?SqM_AuSIwkW;2yB=ghos}U>5^e0ZG1tl*oy!awORD#=}r~=9wC7vU}xUxio z=%p$H%&5$WfjM?sJ-8wqVMV)3TG9=QmOp&GL0q$&c;exRB}uA4egN$UVu-=RAclC8 zdI??f;yn08K|zBd6pykr?4A%--oIS3bra}!!Eli-^#q_*wYCjfRj6EQxN2hA31v^4 zB0*lz4o9CZ{|iT^&pe6Zf&e#IL6Y40T-3PwnpBb@n8|_o6iE)GR4Yf!!8P4pR8Ldw z!1&f3Un&n?5`jL()kv3WlhPRRg;DYdij+66=VQ9Jp^ogJ|v!;XdVUG##Kz6U;GBx(a0OZY6r<|MY902C7Acj*KiW zS)IAL8D>1tN&g}$Mtowx5vx($c!1Ayh$#}JyWn5CEXHi@T0ObroYHtb-pNb<9FD5b zi+Kh8rOPN&E=x6f(lKu%>I3BA#;kwGxijx(Mt8fUll{1Q;)ll!t1nXIcl;aYGNgN$ zG-JxSaDbV97O`Agwb9-g(i!F#YVBptqN5vx>bmuj-ZbD8Fa|lzYRw2b<`Z+hr4i{An-@_>be+;A^t03$yOn!trFe&nfweM>>UjjG>_`!wr zDM(l-o+JT7Vv+HWGSNf0i@$<8UOiJ%0hv*Nj7XM@#te=sh5Bvd&AM(C_Jxyx?qKje z&pjoqAl8`dna_>W0UjGot4q+lgC66{RgzT3q(v9xe_X zU{gN!udnIGl75GLqwCF?wY)#XOaHAw1T|KZvi8RISbV4XkE~>o8GzIKst4=_4)K;m z);M??2g9j8nWMiic6xkSOsWbBeq!0%2hpL)Hz*=6&gO9P(Qs=fOXjg?f9D_n@Y}=* z88>zwMW=ICZZj!VxWU-(9+w}gHaO^0d&9=NxQvV8qw%;6X;CUIZ_snE=xvDNc||dd zKNhfd-%8)Sw6fN1VTtZ3cJZ+)BBhwQV2a6&$?g5Z-pri)T%JPId>!|F6(VSnNzGZE zB_M_Cl}rGfv|TECbo*TDyri8%BtP_#%SKJ$wyxt2j449D3)cu-xyMXLL=18oB3?P=bSNm#Jr^Rtoq^2w@jPwt&LYz&1wRlO&0&GRm6POlV zP=#QXB8z%wVX7)cfj!L}xOiWg@<$o%M4SGD59z<0JE*ejf)BBUpIYA?d^t-5<18!Z z853zxT|Q63pT)jF&*Xn;?%7fPa-ykM zWC?;IG^VY96H*?^avU*4!LfxH5 zG1F5{_FOdSCQ1`(EeyO-45Z%3l6k|$zurPB=o0ft_o!=Z;+x&IBAFoNYc=1z3k7tK zNRFQ#lT({5@XnFW!$WlM-{0z>v5i9Wm=aOF&C%w=MYcM*@lSO4=dXKSdg*ptQpak%HZPE zywIA*PpC0{UB#yKRjBpTrPI`3>qOv@bN+jtXw?JlU+6~zfPUoKU`JEvyZ3I5@sJJ= z&Ka6cGzDLsSyZ4CD2$~6p6|}o6R(}K?y671y$>w8t_U2`-rf@1E^Q5U z>X=2+KQg_~Cprt0?%xL$Cz?AS8Vs6Dr%Rp& z_#V(zKA6P#rH-9Pv**>YrrUKM_sggCDSuND%PaEYC70@6i$m^KZ0mg#b$!^+IInxV z>e;I;ES_^c1U{&@LZ2l^e0A3|3jpSb{k!CO(?t9OB%R8eM>dGF{>eYwOeNf!ef4*Y z`1+;U6)WzAH~tzxmvl8E74RNYn%Wsrz)>WCtsLbUc{#uR$Ni!mIg#n)*H)6%CU%^lEVt%pt?ox+iTrgDLTePY`>%BM zyC;j7`Pw!H{rZ}@eo>J}_Azt2=08(?R`+tfLD1 zENYD%Aynjat$hsK-D;{LdHDYKg!*U@L2uPKIY%U>ryrQ#&J|v7yb7lqhCOhOumVyz zW9EVR{mts-e9+oWEe@c{nQY=dydx|8h0j$}gd1{qN69FVxi4Y59Mk?wKe522qN~>| z&Yu<+(f@x^L!@l-7=h~wgWB=US3DAr5*v^tjY1zml68T(fR*xtsJZN$4Jt+08$7%3 zFM$hG?eOJv+!?1Ce=B$RbPL%SE|6joI*9IOnzPc?ddTR<38R3b z@65yJ)&=09XJJV3=OBg4CLa?n%_1-S7*`1>f&DXMiEIWp3xWBj$3*{PZbrn#yRIR5 z9q@_)Yy&(x6W=J!cPn3nC}@~}ERpC=3V`~QOOKR^aS#xZk}Ay|Efn2;^S4qaS0Mz; zO7qqNqMA;4t8byTvA*n^RBc&(m<5r$=UD_Md6Xlk4KE(0GHu--{kIq13o9=pkG*I4 za1P-}Bv!mcEvpBJ6XChVU3<-oj&xrT5d49Yq~#tMZNgN9#$DiQAzQ!XV&S^bMIeV#U*Zhx1jEya~o%-$*fBTe-IeM z>URg@m~|cgx&;Jh0n+H=ufW4(JlF4^x6+bd?P(zqwHx~yQX3o$1OVzTJw*UFEpuEg~o%m*NNhyFAwIcUC*=tzy-dnxXJNrEhw1Ds|^V#&shbg zGc9u3FS8rWt{MKo{2qp=42hOWR95n03$yS^lRH1Pg83=vLp9&9K2v}zVaiBm|ABr+ z3>zF4ENZTz@XSmp4GiMxbK0rGKgAfC;L->h?D1b3AjT1Hqq1@aDdAFgD|TjOBLZ}f z`cCQH(2KdGE;9x~=C7fdpi`VRZwF(bMg}M8P)43jTHHz8aQVH^;F4SimI+^w**`An zSR1IZWY_(DNAT@jbN?286^ok`%onk+ACK$kSjxyXb2yt4oj2c;Zyz+_;LRI3yB*q> zPfx@rdhVA$L;PeQkMv>X)N;g_C%dx8&#vBgY=%-|HTi;YJ$j%aR6o)&CaZm* zm59bV&}-d=rEYcxu|M1Q0WcEPC5DIT&{Jy!pAX6enJhWcFA77xa!-`36COmYRimmOVSxq<$l+OB&3PFM(;RpO|I~_iaT+gKEqvBd z0i$?5UtN#!;A$|gV9P{nu&r*qJ&VMKZzr75BpU!>@!;$ag$0i*WuS&85N^r?({-!0 zS+W-%su7DXOkMs5S;Ow;rPk4TM5Ke{X;_TU z0cX?k@2y>3zH1dufn()&d&S() zEX*1k%)zjK^|u5{&{S15H4(n2KZjW~Sdty2;%)=$LO?u&c_H9u)^oK|$)l^7hq}CI zB%fq`q#bUO{H7g33v$%2hUy5ibYrui4o8M{4N-r5)!SmpUsySMCe|XYPL2zI^ZJ+J z3dl2oVKRB-hfRb*M1vDMQ3HvqRaJ;LlR|ConA8NUEw4GyYpl1o+dvil?ltm&ny(@* z<7+z%TRfavbT!fTN)Z?U6D;_-fZMu+=+)Fg5g|gi7LQ1_6Yk_3EkUCY zuz!K(KO})h)BKqtUFpYCH~Ra)l%`uN{S;VzC#XM}jSjuVrxo}*g+g!6Uvf#kc}SKo zy;+`gpO|W8FL}P2`!*V7ermZV7>qBnp$U-C3@ucZ-5bXK4{Ooi`{!*5WY}9k@9C?I za#E7k0W+A`)O?GX0IX0M`Z(_RwhYH>=HIl_~+ zBcP$hpuf+^820j#Ph~IKL45o6ZNBKxw{KwFr9KsKNeaCvsi^kBqzENtAVo2>`wkuS z9C~yLo7r1SO9u{!yF;y%CoH8Fg5>jrH7OGnWFWgQu?yf8X z*WQCY^yy47q8TMX`-xT<#4NY#V!JLFgK$L#O%s6ZQ55y3qkW<6`C|F`yPE2R1Xi z%Uf|yXxXu=4JF}9!mNjs@c#EMf`}ZBb9qG5G!SwC>>e)n-GxQ-!9&f9AM)7rVqp(L zb+0bxb91(=xncB#|L&WeZQaxvEVyBz6`$YhvvB85oXInzPk(_)hVws`GceImFB*$m z7xvrMJ(xb&&wi%ZZG2UjJNyk-1{`9+EqH&Y(DHA2xg~$RE9#}dANFj1y02Z@#eI7j9xgW@ zph}_gj)hpB1AAnp$`&cgLmE*n_d@_`d}zWl21ts5set0=eQMLSoy4PHZx~M~!=MPH zi+76q7SLo-WrmdF69D4)ryvd(Bb)a)vJl1AL_*=uFa^zSEgzf|KMUkJ@^@T$l=UDr zD}w(e!Guc}O+qU7XfAybbbf%bTI2Agx-=eI@_eSiet#cEFQ7AUJ@BC9_m%;23&>T1 zjt#1_tyiyeJHi9lfCQ%(;R?IGiq_0{3v4z)r4Y`^S5|_d!hB{VzdE58dGaBKmz+Nn z^gz!A%@C)>qD&#Ey3Z3I7LGTaY|h&; zzXg7`zmBDO{-SNQl>Td+jiKp<#n@U^)i)ko%)%wkNN-%smqvR>eNY|dSsEaQ764=t zy=(fc3CO^ez+ChY`Rj{kNO!PcPyr#bC4FSpYT^^A$PyyS<)NlOZki_$-`I5@G_~fp zW8fwtS(i~uzY_A7h8@TCM==v*3j&jTaEWOr3ysFd=m3b*w;{N)BRufZ6sjlSwi0yk z;Bb*p!D1p158N35wF`I?1zMV`&_AwtU$w7{Os4tgP$%L8t_1UTDSts0-a;si|KRgM zIT5C0nD8W*umeoWjeSCD5Ho{MOcFB^ZFX5-o8f}M?&Z`pQp7Ps9t_ZC~NNv?nFBj^ZkkT+(z>Qi(AmQ?mU11*duz0W1c>I3829HC*VTOOqYLMQ^0T97$q zrF)Tss0N;GQv3qj;^-u?4s}p+6aDOSadic-+=HNVjk2{ zzej9EKp@Q~@R49?jI*J4fz4=huQyX6)yR5u|I?a;*)gQ8uyeYLcZXZ*I2Tq9iHWRM@*~EH5ZM8mj zR*P#L_Vsr>yP*#5k1f%tk%4S%tm^uwE72Jz;XzMUo}at0aD%H=8QkL{LUGYg9h)P- z6ux9SLNgfCl97=q%2U(M-85G5Ys5=Wj0jJ@+S@6GFy~)fQ4`~U{*29=Gt<$o1}nCr zWO~@pQ8`%a5Oj)u54i~PCX~f7Isx1^1l#Nvg+4JtFh74UCWx&gA9uh9AFTv=>}}+Q zTxIHL@&EE=8mFY+u6f>58u}gG^Jlv*_n2>y*6W_KLhhd(59P`42i5&A{e@ORR^2g= z;k!UY@0o?or>{Q#5!zqbV^bzAk*q$I;C;vl5%g;uM!?QYNJ4n}46=3Egq4w6;5e-i zovLDJ&(3XT3YC=_Z_f8y2t?@1!4QL(Mj!aN?$~|@@m>W&o{{d+gBYQErS}PvF!rBl zm-MwQ5Rlm-S)i#?2Uw-GnBgc{a-Sf`DZh-AgpMr#NJeKa>Fli>w25U)K!_`sSqCk9jZ|!H&=16%`ew>+Yr-9z`tcb4dUB`z&xCrDvKxk$z9=Z-IJI?eOhzjfLA^SxbscVU|N4!W= z!;(2NJI}|Zl`5G2qY?Wkt5-@=O6p3+Hc0WLe> zYEs<9W+bqgoz&qf5*vE3I31&E22t6R^aZSrPK>Hc>a7H&1x00KLC9x}M7`{K$}%L) zY$xGlAc`e6tFl?6LC%ApkT^H{iXc0x&>C=;z>;{YSNBvd%;y0n`gR$+;vre~Ew*(` zcsTi`&XIU9xwQ2%IqN8Ip3WO#OM-hRfyh6My)bTNw3o$47cFSAw3#rn;~5dO1^k9S zMJ{OVkkTQ*L0`d7_W>wfcqT*`3o?ax2B?-UJ;r8V8I|T#vaj={oJGw5*C?OlBzxD}Kt2aSn2OkX(%t2F%n<3 zph9A*yIB}ZiX*=Mt_0IQoNu7OO~^*_ZjB(pZ+jr^|7q+zqnd2GHH=b1FVdw2q)Q3C z_xdVbN&u0f;43w>03s#yCPh#JA{~@o1Ps!V5)c7F=~6-ykS>T4$Qjpnew_2~dwwQs zWzBjrv-dss%-)xX$#)sQt7AM8&iAx@w}!AJ_#}=^rDy?&) zIWl@C_neIr*Pgef)!tK8DGkcD_2&q>E=LvG^?T#x?tFa91v3Af(NRQX=%oz6O`K8q(bJah~ccp|$QC@bf``AL>9kb;Zx5TVI_cG)8CVN|e3wzka5S`*;4;0XGK^uZfaE2Sxb{ zEK#QrdBv!)$I;{#t04~`O1ZpDgikJ|3*gZ5j#3>S3li-~Y2(Ciax(%8Ji}4sVMZBG z9uogLV~asVDY)-hnO?HOj|<-gZ05Tae^u z3$mXoJq_w!L~hv6Q6-R{!{3?0a}^ z!^Q4mV3LwP-`)qJ2Q)5zPD(PquUQQB-R*sJM0s@b*kmABy~FkQn~WQb@}7+~n_oI~ zI9~7F&$WFM>w4?5HDJoLOZ_}tSHml?*{W(9I^{85*b}7lUL$yWsod&gx$#|_x}|{S z7fZRbOSIQz$$N{6iU3S<=HmQU$@-^UIS%zFn69p63Oid{V>GM??8XNM29QYPG-)n1%06HtR<2II0Gx;#rLHuugoNzuX<$(xp3`v1w+Hi{y@v{( z<|+AypRGXr{f{f|yuR1@WELPu1=dfJs0E*Vd?5~KzzI7W8`kuV!0MngFwR$Hclq2E z5s{bl-1Mb<4F#>@C^jN|~gs}dBt41mPU;R+f;LI!|K-2MO% zYjHfjegI!x@HJv6Wnm@o)OLXzzPzWE7N((U@A zufRe4Q`wUYhAnZo>Fi~ug04ViW#!S)(a6w4sD8IfIs1s8g@uK?`}XnXm_aHhg+`aj zD`h%vRpAJ`V0KSpROEM`T_?e^($eMYPN86QxD)Uc-7w3Us<9`Wt)^{lZN2kZLIwqC z1nqIw&Hx~&uq7PM_CP>b*znFB|L({u7+Kw00c6a~%)YKeSge_ah0FTCEtuHTlM}s9 zAo4W(EO7_%-n>aw(Yrq56;5ub*!cjQe!-logc@ZGr@`I%`%?2}4*BOyP$_`D%LL(r z9kbg2T24&4g6o~@>eRrQQlTqY#7|oK)J;2n9io>G+FOv8yTId}CZx)wPz?FqEAh<= zGBWc3%R2};brr?H7#J8_k)%{T`jh3x22ZcYdaM-F#bAeqv{c+i&{7^#Vk5|45-Jw4 z$k`wSLi1-2MHmTbEWzXETAC6mHVE2-g2jh$@+}AbMKp5&0Cj>Zln2miaq84R4ZIzt zv0|W@y*R+2F6Gm=+A;6N#ag#;`MoZbrOEe7+JB9HzBj>2fuxU9XB*>L)ShV3dAaf9 z2DS7;40!nsKzCzr_-Uu-W z)D!4Qts#q$IU@1yEPZ0dm4bJxNr(qfh#|RVd;JwTt#X#o6}}=XgaktVNr0bUlt!;f zY!*b7R+f3*@ZoaIjH|Qr;Z9wb_Fcu5r6SF{qAAhtlt+pQlJrKOBM29)WUAuE^?qq0 zKQ{{^Xt|V`Y@@5I#YkAi+6{(@_aZww)Y^%j^xe|UmT(v?&=@-eYhF!}fa_0QnS(w@ z{QPdt#0Tpc{+K0l2S#9shKiz;p_V8_A-%xx@G$mcVY6Y#&z)(yL#n1#0LLybF9%nx zMtX+Hha2jnzLRZnY(y4*A|He!Sxy>~mE;nPms<;I*N7JxM?ZwYgq3c6pder&C>;)|=a&wJSEkLK_0uj(MU%{CH{5vettO+%kF=9}4j*}t%ZC8EHXFky$ z;t#e0)o=OQdcwFt-9$5S->xAK!jb)+HinMqcFE;KfVXjn2nrT#gnBrN?#~wRbL#F! z#+0~)j9r$R#lGQUy4 zcB>Jf_~_a$DrIl6c7s9I|DQ^d|5t^drE6qFZ2-EhLH?9!{H69N(f(KLp8x#bVlP;E zzL)slXfzubfpv|Yoc99y2089#^pYv0ysQimw2kfT-W$J^2eV-?jpx_N$vPO$@baeb zLT8x0gG1N?#ur4aGq{C?AHXad7#O5N6Y40!xeWpW0zib%aVO&7c!|Maii`QcH)AP3 zet7Oh_l&IyOGvO(kO|=-GgoVvZ<4}i*a&s!SU-F8$Ye02&OUs_ef%hD`<3dbWVkS z^Wf-?Ph#u60KMJS)iuWOF9>)5V7Cvo+K{`JmX`S%5#b`Xy>0JT?)_yIB>tK_}DN6bu2cs#!LUPn>_wUDfWf>tscD!Ny1#sc_ z7FuQadfq-9EAB+0P-k89+FW_OYHD0LkHk<49#bjLh4}dkKRG))=N%NJmC&%Tuvlen zZf@THuB)#tWjj;`1rX0=IF{E!h=gWKvPalt>X$YndRFZu&ajORZ(e6 zPf!0RQ&8^F1iz%@*wPXYWt6knUbN+5fpul!>4lI2bx_LD$cWJ?!-qfXAG1O7?rQ-v zzO5~^zgAE`VN1G4;()up|JqKi)-=pQ)k=$yJEzQg#2S6HmKHE=GR(XFg)qi6I#iV_C zpetqb@KY`+sgnN&bydjbC|8zFB;rw@2YL}ac`&EG3B}Q9Jqhfa;$mFBTIl%Y@USm= zDh)X~0*Tbu=;qWaJ;-3B9NzoZCN&Dw%qNK}8P_f-9|XQnJyS*bUpYq^L0Z<=*QJbM zOdu2|y{;%L3j|p1rSNkvkm1=@p{yw4Nnt z%ii62y~f@Ax|gIfB<0suxxKYPBtJ|Y74>&h^ijMO;Kl|ImH^L8CqT=m$hWH}Bve#9 z`nC6MMNn5)xBYE1x|HiC=U#yfZJ+$H>Y3b zSIs$ZhN67iiq66IYfC%5X{e44vbVQ4IWzq*v(8qWKy=(bJV418D|&jJoxOo(DqI#F z))z<>3q@+)*A<6YTU)2gFR*G;2y@vbFGl`xa(OFj=DJSg7rDly&72{j`B2H(n}asv zd)LV_eMW@kMePlB9eC5#+tJXnB=-dSL!**dD09?5B(A8FDBg-6>2|;0iGpaTM;>{X z$eUW;ADhlw?0_SrqMwGN9Y+`+Ai!y=aQHLIOdT|@BC#dKA|*dX7^Ejoi0-3gevwlM zqdCTs6ld@pGG>J@IkQk8Zslmtrb{l2Lm%IHZ4!2{3@*FVNl7E#0u8L!6q{)Yr)38k zo%Jy_ExGK~>`R~xW@eXvbSE-uXf%HIEcxSL@TBFyq0`A+l=C-eRDWwFlCPI80)Hme z7=X|$tSELs6T7xZ4N1|M(c~B&W@Z(XRns>NfjB_F53Pzxk71;wr)AZUId`YIo%*84 zt&4V05K*8WM&FesIfzrWs3ccjX4Mo)XVH4sJy=oCSpt!k^_+oaWM}2(4)YUj$C>Hj z@x}YJR$YGsz>F%~I)%ji=pN@;O;1k`EIq->*=Cu*XOjfSP#WmydR^?m`|#f0-q?vA zURG0{`Z5xIkiX&-H^^ehj@d8KSWBGdhFlh8kDBEU!tV^vx6d_?4NBN9Y-@0+u^fg0T2~R~x>6Y1K5I-^pCk|%hWBtUR-~-pqt7;r+w?m# z*GGuRD7~*J_v%ycF|h}?B->0g6mTS%719<{Ly51W+L?b|-47mziIRUPVr_q6B} zh3f3q1lg`%IWt&E`RYd=^0|g5XKO=@{PD2EnTVasUrP}gqcP&K!ce+C!H5u;4a3@v zm63^JYBq$}Iy8`^iRr)eu&IXmEC4FK@03o*YRv< z>`^t470Zitx>JGq5)Wk$07uXomuJLwk!aFNUl0eHJ*G!rsjzyCV3RH`&-dwdtBahR z67hofz+6_>6oD}{FeSu5jl{HlsLfL#aIH0U!u+&??!kGyQN8?+UO44I6f8AX+^)fe zbb!M4u{-dq^Y8E)WM%a z9aYIY2U6Jm!5#w(5xUFI4Ra!@X`Mon(Q)HfCT8&3%<%KTohjblcrATz79<53rLVL_ z5LnQ)qoTCnQa4dMVN14A3|L8VO1*z*gaYEz%M7NB@$*kfw4Ti3vkBI8U8~^z!%5-> zQFzsf%eAR%eKxUu@n>>0QP57$?}Y!ZdGCL2a^vZUhzNul&9AqJKyLY)T8N3N{2Saw T$z&J6Cq)0~ndsJPJ4O8utYq!C literal 42765 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 delta 6259 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 z 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�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 Qfk#-*p#CtgFh%431Mad;3jhEB literal 41054 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