@@ -300,4 +300,157 @@ describe("VsCodeLmHandler", () => {
300300 await expect ( promise ) . rejects . toThrow ( "VSCode LM completion error: Completion failed" )
301301 } )
302302 } )
303+
304+ describe ( "session tracking" , ( ) => {
305+ it ( "should start a new session" , ( ) => {
306+ const sessionId = handler . startSession ( )
307+ expect ( sessionId ) . toBeDefined ( )
308+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 0 )
309+ } )
310+
311+ it ( "should use provided session ID" , ( ) => {
312+ const customSessionId = "custom-session-123"
313+ const sessionId = handler . startSession ( customSessionId )
314+ expect ( sessionId ) . toBe ( customSessionId )
315+ expect ( handler [ "currentSessionId" ] ) . toBe ( customSessionId )
316+ } )
317+
318+ it ( "should track message count in session" , async ( ) => {
319+ const mockModel = { ...mockLanguageModelChat }
320+ ; ( vscode . lm . selectChatModels as Mock ) . mockResolvedValueOnce ( [ mockModel ] )
321+ handler [ "client" ] = mockLanguageModelChat
322+ mockLanguageModelChat . countTokens . mockResolvedValue ( 10 )
323+
324+ const sessionId = handler . startSession ( )
325+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 0 )
326+
327+ // Mock the sendRequest to return a simple stream
328+ mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
329+ stream : ( async function * ( ) {
330+ yield new vscode . LanguageModelTextPart ( "Response 1" )
331+ return
332+ } ) ( ) ,
333+ text : ( async function * ( ) {
334+ yield "Response 1"
335+ return
336+ } ) ( ) ,
337+ } )
338+
339+ // First message
340+ const stream1 = handler . createMessage ( "System prompt" , [ { role : "user" as const , content : "Message 1" } ] , {
341+ taskId : sessionId ,
342+ } )
343+ for await ( const _chunk of stream1 ) {
344+ // Consume stream
345+ }
346+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 1 )
347+
348+ // Mock the sendRequest for second message
349+ mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
350+ stream : ( async function * ( ) {
351+ yield new vscode . LanguageModelTextPart ( "Response 2" )
352+ return
353+ } ) ( ) ,
354+ text : ( async function * ( ) {
355+ yield "Response 2"
356+ return
357+ } ) ( ) ,
358+ } )
359+
360+ // Second message
361+ const stream2 = handler . createMessage ( "System prompt" , [ { role : "user" as const , content : "Message 2" } ] , {
362+ taskId : sessionId ,
363+ } )
364+ for await ( const _chunk of stream2 ) {
365+ // Consume stream
366+ }
367+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 2 )
368+ } )
369+
370+ it ( "should end session and clear message count" , ( ) => {
371+ const sessionId = handler . startSession ( )
372+
373+ // Simulate some messages
374+ handler [ "sessionMessageCount" ] . set ( sessionId , 5 )
375+ handler [ "currentSessionId" ] = sessionId
376+
377+ handler . endSession ( )
378+
379+ expect ( handler [ "currentSessionId" ] ) . toBeNull ( )
380+ expect ( handler [ "sessionMessageCount" ] . has ( sessionId ) ) . toBe ( false )
381+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 0 )
382+ } )
383+
384+ it ( "should track different sessions independently" , async ( ) => {
385+ const mockModel = { ...mockLanguageModelChat }
386+ ; ( vscode . lm . selectChatModels as Mock ) . mockResolvedValueOnce ( [ mockModel ] )
387+ handler [ "client" ] = mockLanguageModelChat
388+ mockLanguageModelChat . countTokens . mockResolvedValue ( 10 )
389+
390+ // Start first session
391+ const session1 = "session-1"
392+ handler . startSession ( session1 )
393+
394+ // Mock the sendRequest
395+ mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
396+ stream : ( async function * ( ) {
397+ yield new vscode . LanguageModelTextPart ( "Response" )
398+ return
399+ } ) ( ) ,
400+ text : ( async function * ( ) {
401+ yield "Response"
402+ return
403+ } ) ( ) ,
404+ } )
405+
406+ // Send message in first session
407+ const stream1 = handler . createMessage ( "System prompt" , [ { role : "user" as const , content : "Message" } ] , {
408+ taskId : session1 ,
409+ } )
410+ for await ( const _chunk of stream1 ) {
411+ // Consume stream
412+ }
413+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 1 )
414+
415+ // Switch to second session
416+ const session2 = "session-2"
417+ handler . startSession ( session2 )
418+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 0 ) // New session starts at 0
419+
420+ // Mock the sendRequest for second session
421+ mockLanguageModelChat . sendRequest . mockResolvedValueOnce ( {
422+ stream : ( async function * ( ) {
423+ yield new vscode . LanguageModelTextPart ( "Response" )
424+ return
425+ } ) ( ) ,
426+ text : ( async function * ( ) {
427+ yield "Response"
428+ return
429+ } ) ( ) ,
430+ } )
431+
432+ // Send message in second session
433+ const stream2 = handler . createMessage ( "System prompt" , [ { role : "user" as const , content : "Message" } ] , {
434+ taskId : session2 ,
435+ } )
436+ for await ( const _chunk of stream2 ) {
437+ // Consume stream
438+ }
439+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 1 )
440+
441+ // Verify first session still has its count
442+ handler [ "currentSessionId" ] = session1
443+ expect ( handler . getSessionMessageCount ( ) ) . toBe ( 1 )
444+ } )
445+
446+ it ( "should clean up sessions on dispose" , ( ) => {
447+ const sessionId = handler . startSession ( )
448+ handler [ "sessionMessageCount" ] . set ( sessionId , 3 )
449+
450+ handler . dispose ( )
451+
452+ expect ( handler [ "currentSessionId" ] ) . toBeNull ( )
453+ expect ( handler [ "sessionMessageCount" ] . size ) . toBe ( 0 )
454+ } )
455+ } )
303456} )
0 commit comments