@@ -25,7 +25,8 @@ import {
2525 LiveServerContent ,
2626 LiveServerGoingAwayNotice ,
2727 LiveServerToolCall ,
28- LiveServerToolCallCancellation
28+ LiveServerToolCallCancellation ,
29+ LiveSessionResumptionUpdate
2930} from '../types' ;
3031import { LiveSession } from './live-session' ;
3132import { WebSocketHandler } from '../websocket' ;
@@ -83,7 +84,15 @@ describe('LiveSession', () => {
8384 beforeEach ( ( ) => {
8485 mockHandler = new MockWebSocketHandler ( ) ;
8586 serverMessagesGenerator = mockHandler . listen ( ) ;
86- session = new LiveSession ( mockHandler , serverMessagesGenerator ) ;
87+ session = new LiveSession (
88+ mockHandler ,
89+ serverMessagesGenerator ,
90+ async ( resumptionConfig ) => {
91+ // mock reconnector that replaces the handler
92+ mockHandler = new MockWebSocketHandler ( ) ;
93+ return mockHandler . listen ( ) ;
94+ }
95+ ) ;
8796 } ) ;
8897
8998 describe ( 'send()' , ( ) => {
@@ -220,6 +229,27 @@ describe('LiveSession', () => {
220229 } ) ;
221230 } ) ;
222231
232+ describe ( 'resumeSession()' , ( ) => {
233+ it ( 'should close existing session and start a new one using reconnector' , async ( ) => {
234+ expect ( session . isClosed ) . to . be . false ;
235+
236+ const oldServerMessages = ( session as any ) . serverMessages ;
237+ await session . resumeSession ( { handle : 'testHandle' } ) ;
238+
239+ expect ( mockHandler . close ) . to . have . been . calledOnce ;
240+ expect ( session . isClosed ) . to . be . false ;
241+ expect ( ( session as any ) . serverMessages ) . to . not . equal ( oldServerMessages ) ;
242+ } ) ;
243+
244+ it ( 'should throw if reconnector is not provided' , async ( ) => {
245+ const basicSession = new LiveSession ( mockHandler , serverMessagesGenerator ) ;
246+ await expect ( basicSession . resumeSession ( ) ) . to . be . rejectedWith (
247+ AIError ,
248+ / r e s u m e S e s s i o n i s n o t s u p p o r t e d o n t h i s s e s s i o n /
249+ ) ;
250+ } ) ;
251+ } ) ;
252+
223253 describe ( 'receive()' , ( ) => {
224254 it ( 'should correctly parse and transform all server message types' , async ( ) => {
225255 const receivePromise = ( async ( ) => {
@@ -242,14 +272,17 @@ describe('LiveSession', () => {
242272 mockHandler . simulateServerMessage ( {
243273 goAway : { timeLeft : '30s' }
244274 } ) ;
275+ mockHandler . simulateServerMessage ( {
276+ sessionResumptionUpdate : { newHandle : 'test' , resumable : true , lastConsumedClientMessageIndex : 5 }
277+ } ) ;
245278 mockHandler . simulateServerMessage ( {
246279 serverContent : { turnComplete : true }
247280 } ) ;
248281 await new Promise < void > ( r => setTimeout ( ( ) => r ( ) , 10 ) ) ; // Wait for the listener to process messages
249282 mockHandler . endStream ( ) ;
250283
251284 const responses = await receivePromise ;
252- expect ( responses ) . to . have . lengthOf ( 5 ) ;
285+ expect ( responses ) . to . have . lengthOf ( 6 ) ;
253286 expect ( responses [ 0 ] ) . to . deep . equal ( {
254287 type : LiveResponseType . SERVER_CONTENT ,
255288 modelTurn : { parts : [ { text : 'response 1' } ] }
@@ -267,6 +300,12 @@ describe('LiveSession', () => {
267300 timeLeft : 30
268301 } as LiveServerGoingAwayNotice ) ;
269302 expect ( responses [ 4 ] ) . to . deep . equal ( {
303+ type : LiveResponseType . SESSION_RESUMPTION_UPDATE ,
304+ newHandle : 'test' ,
305+ resumable : true ,
306+ lastConsumedClientMessageIndex : 5
307+ } as LiveSessionResumptionUpdate ) ;
308+ expect ( responses [ 5 ] ) . to . deep . equal ( {
270309 type : LiveResponseType . SERVER_CONTENT ,
271310 turnComplete : true
272311 } as LiveServerContent ) ;
0 commit comments