@@ -30,6 +30,7 @@ import {
3030 MIN_SILENCE_DURATION_MS ,
3131 type TurnDetectionEvent ,
3232} from '../inference/eot/base.js' ;
33+ import { type LanguageCode , asLanguageCode } from '../language.js' ;
3334import { ChatContext } from '../llm/chat_context.js' ;
3435import { initializeLogger } from '../log.js' ;
3536import { Future } from '../utils.js' ;
@@ -55,6 +56,7 @@ interface RecognitionInternals {
5556 turnDetectorLatePredictionWarned : boolean ;
5657 lastEmittedEotPrediction ?: TurnDetectionEvent ;
5758 lastSpeakingTime ?: number ;
59+ lastLanguage ?: LanguageCode ;
5860 audioTranscript : string ;
5961 audioInterimTranscript : string ;
6062 audioPreflightTranscript : string ;
@@ -68,6 +70,7 @@ interface RecognitionInternals {
6870 runEOUDetection : ( chatCtx : ChatContext , trigger ?: 'vad' | 'stt' | 'manual' ) => void ;
6971 createVadTask : ( vad : VAD | undefined , signal : AbortSignal ) => Promise < void > ;
7072 checkVadSilenceRequirement : ( detector ?: _TurnDetector | BaseStreamingTurnDetector ) => void ;
73+ updateLastLanguage : ( language : LanguageCode , transcript : string ) => void ;
7174 updateTurnDetector : ( detector : _TurnDetector | BaseStreamingTurnDetector | undefined ) => void ;
7275 clearUserTurn : ( ) => void ;
7376}
@@ -221,6 +224,35 @@ function flush(): Promise<void> {
221224 return new Promise ( ( resolve ) => setImmediate ( resolve ) ) ;
222225}
223226
227+ describe ( 'TestLanguageTracking' , ( ) => {
228+ it ( 'does not replace a concrete language with a non-specific language' , ( ) => {
229+ const { internals } = makeRecognition ( ) ;
230+ internals . lastLanguage = asLanguageCode ( 'en' ) ;
231+
232+ internals . updateLastLanguage ( asLanguageCode ( 'multi' ) , 'ambiguous phrase' ) ;
233+
234+ expect ( internals . lastLanguage ) . toBe ( asLanguageCode ( 'en' ) ) ;
235+ } ) ;
236+
237+ it ( 'does not initialize language with a non-specific language' , ( ) => {
238+ const { internals } = makeRecognition ( ) ;
239+ internals . lastLanguage = undefined ;
240+
241+ internals . updateLastLanguage ( asLanguageCode ( 'multi' ) , 'we' ) ;
242+
243+ expect ( internals . lastLanguage ) . toBeUndefined ( ) ;
244+ } ) ;
245+
246+ it ( 'still updates concrete language after a long transcript' , ( ) => {
247+ const { internals } = makeRecognition ( ) ;
248+ internals . lastLanguage = asLanguageCode ( 'en' ) ;
249+
250+ internals . updateLastLanguage ( asLanguageCode ( 'fr' ) , 'bonjour' ) ;
251+
252+ expect ( internals . lastLanguage ) . toBe ( asLanguageCode ( 'fr' ) ) ;
253+ } ) ;
254+ } ) ;
255+
224256/**
225257 * Drive `createVadTask` against a scripted VAD stream so VAD events flow
226258 * through the real handler. `feed()` resolves once the event has been processed
0 commit comments