@@ -660,12 +660,10 @@ export class RealtimeSession extends llm.RealtimeSession {
660660 for ( const f of this . resampleAudio ( frame ) ) {
661661 for ( const nf of this . bstream . write ( f . data . buffer as ArrayBuffer ) ) {
662662 const realtimeInput : types . LiveClientRealtimeInput = {
663- mediaChunks : [
664- {
665- mimeType : 'audio/pcm' ,
666- data : Buffer . from ( nf . data . buffer ) . toString ( 'base64' ) ,
667- } ,
668- ] ,
663+ audio : {
664+ mimeType : 'audio/pcm' ,
665+ data : Buffer . from ( nf . data . buffer ) . toString ( 'base64' ) ,
666+ } ,
669667 } ;
670668 this . sendClientEvent ( {
671669 type : 'realtime_input' ,
@@ -704,26 +702,12 @@ export class RealtimeSession extends llm.RealtimeSession {
704702 this . inUserActivity = false ;
705703 }
706704
707- // Gemini requires the last message to end with user's turn
708- // so we need to add a placeholder user turn in order to trigger a new generation
709- const turns : types . Content [ ] = [ ] ;
710- if ( instructions !== undefined ) {
711- turns . push ( {
712- parts : [ { text : instructions } ] ,
713- role : 'model' ,
714- } ) ;
715- }
716- turns . push ( {
717- parts : [ { text : '.' } ] ,
718- role : 'user' ,
719- } ) ;
720-
705+ // Trigger generation via realtime text input.
706+ // Gemini 3.1+ rejects sendClientContent — sendRealtimeInput({ text }) works on all Live models.
707+ // Instructions are included in the text so the model uses them as context for the next reply.
721708 this . sendClientEvent ( {
722- type : 'content' ,
723- value : {
724- turns,
725- turnComplete : true ,
726- } ,
709+ type : 'realtime_input' ,
710+ value : { text : instructions ?? '.' } ,
727711 } ) ;
728712
729713 const timeoutHandle = setTimeout ( ( ) => {
@@ -992,12 +976,10 @@ export class RealtimeSession extends llm.RealtimeSession {
992976 }
993977 break ;
994978 case 'realtime_input' :
995- const { mediaChunks , activityStart, activityEnd, text } = msg . value ;
979+ const { audio , activityStart, activityEnd, text } = msg . value ;
996980 if ( this . pendingToolCallIds . size > 0 ) break ;
997- if ( mediaChunks ) {
998- for ( const mediaChunk of mediaChunks ) {
999- await session . sendRealtimeInput ( { media : mediaChunk } ) ;
1000- }
981+ if ( audio ) {
982+ await session . sendRealtimeInput ( { audio } ) ;
1001983 }
1002984 if ( text ) {
1003985 await session . sendRealtimeInput ( { text } ) ;
@@ -1141,15 +1123,14 @@ export class RealtimeSession extends llm.RealtimeSession {
11411123 maxLength : number = 30 ,
11421124 ) : Record < string , unknown > {
11431125 const obj : any = { ...event } ;
1144- if ( obj . type === 'realtime_input' && obj . value ?. mediaChunks ) {
1126+ if ( obj . type === 'realtime_input' && obj . value ?. audio ) {
1127+ const mc = obj . value . audio as { mimeType ?: string ; data ?: string } ;
11451128 obj . value = {
11461129 ...obj . value ,
1147- mediaChunks : ( obj . value . mediaChunks as Array < { mimeType ?: string ; data ?: string } > ) . map (
1148- ( mc ) => ( {
1149- ...mc ,
1150- data : typeof mc . data === 'string' ? this . truncateString ( mc . data , maxLength ) : mc . data ,
1151- } ) ,
1152- ) ,
1130+ audio : {
1131+ ...mc ,
1132+ data : typeof mc . data === 'string' ? this . truncateString ( mc . data , maxLength ) : mc . data ,
1133+ } ,
11531134 } ;
11541135 }
11551136 return obj ;
@@ -1265,17 +1246,15 @@ export class RealtimeSession extends llm.RealtimeSession {
12651246 } ,
12661247 languageCode : opts . language ,
12671248 } ,
1268- tools : [
1269- {
1270- functionDeclarations : this . geminiDeclarations ,
1271- ...this . options . geminiTools ,
1272- } ,
1273- ] ,
1249+ tools :
1250+ this . geminiDeclarations . length > 0 || this . options . geminiTools
1251+ ? [ { functionDeclarations : this . geminiDeclarations , ...this . options . geminiTools } ]
1252+ : undefined ,
12741253 inputAudioTranscription : opts . inputAudioTranscription ,
12751254 outputAudioTranscription : opts . outputAudioTranscription ,
1276- sessionResumption : {
1277- handle : this . sessionResumptionHandle ,
1278- } ,
1255+ sessionResumption : this . sessionResumptionHandle
1256+ ? { handle : this . sessionResumptionHandle }
1257+ : undefined ,
12791258 } ;
12801259
12811260 // Add generation fields at TOP LEVEL (NO generationConfig!)
0 commit comments