@@ -69,10 +69,11 @@ describe("summarizeConversation", () => {
6969 // Reset mocks
7070 jest . clearAllMocks ( )
7171
72- // Setup mock stream
72+ // Setup mock stream with usage information
7373 mockStream = ( async function * ( ) {
7474 yield { type : "text" as const , text : "This is " }
7575 yield { type : "text" as const , text : "a summary" }
76+ yield { type : "usage" as const , totalCost : 0.05 , outputTokens : 150 }
7677 } ) ( )
7778
7879 // Setup mock API handler
@@ -103,7 +104,10 @@ describe("summarizeConversation", () => {
103104 ]
104105
105106 const result = await summarizeConversation ( messages , mockApiHandler )
106- expect ( result ) . toEqual ( messages )
107+ expect ( result . messages ) . toEqual ( messages )
108+ expect ( result . cost ) . toBe ( 0 )
109+ expect ( result . summary ) . toBe ( "" )
110+ expect ( result . newContextTokens ) . toBeUndefined ( )
107111 expect ( mockApiHandler . createMessage ) . not . toHaveBeenCalled ( )
108112 } )
109113
@@ -119,7 +123,10 @@ describe("summarizeConversation", () => {
119123 ]
120124
121125 const result = await summarizeConversation ( messages , mockApiHandler )
122- expect ( result ) . toEqual ( messages )
126+ expect ( result . messages ) . toEqual ( messages )
127+ expect ( result . cost ) . toBe ( 0 )
128+ expect ( result . summary ) . toBe ( "" )
129+ expect ( result . newContextTokens ) . toBeUndefined ( )
123130 expect ( mockApiHandler . createMessage ) . not . toHaveBeenCalled ( )
124131 } )
125132
@@ -142,17 +149,22 @@ describe("summarizeConversation", () => {
142149
143150 // Verify the structure of the result
144151 // The result should be: original messages (except last N) + summary + last N messages
145- expect ( result . length ) . toBe ( messages . length + 1 ) // Original + summary
152+ expect ( result . messages . length ) . toBe ( messages . length + 1 ) // Original + summary
146153
147154 // Check that the summary message was inserted correctly
148- const summaryMessage = result [ result . length - N_MESSAGES_TO_KEEP - 1 ]
155+ const summaryMessage = result . messages [ result . messages . length - N_MESSAGES_TO_KEEP - 1 ]
149156 expect ( summaryMessage . role ) . toBe ( "assistant" )
150157 expect ( summaryMessage . content ) . toBe ( "This is a summary" )
151158 expect ( summaryMessage . isSummary ) . toBe ( true )
152159
153160 // Check that the last N_MESSAGES_TO_KEEP messages are preserved
154161 const lastMessages = messages . slice ( - N_MESSAGES_TO_KEEP )
155- expect ( result . slice ( - N_MESSAGES_TO_KEEP ) ) . toEqual ( lastMessages )
162+ expect ( result . messages . slice ( - N_MESSAGES_TO_KEEP ) ) . toEqual ( lastMessages )
163+
164+ // Check the cost and token counts
165+ expect ( result . cost ) . toBe ( 0.05 )
166+ expect ( result . summary ) . toBe ( "This is a summary" )
167+ expect ( result . newContextTokens ) . toBe ( 250 ) // 150 output tokens + 100 from countTokens
156168 } )
157169
158170 it ( "should handle empty summary response" , async ( ) => {
@@ -172,9 +184,10 @@ describe("summarizeConversation", () => {
172184 const mockWarn = jest . fn ( )
173185 console . warn = mockWarn
174186
175- // Setup empty summary response
187+ // Setup empty summary response with usage information
176188 const emptyStream = ( async function * ( ) {
177189 yield { type : "text" as const , text : "" }
190+ yield { type : "usage" as const , totalCost : 0.02 , outputTokens : 0 }
178191 } ) ( )
179192
180193 // Create a new mock for createMessage that returns empty stream
@@ -189,7 +202,9 @@ describe("summarizeConversation", () => {
189202 const result = await summarizeConversation ( messages , mockApiHandler )
190203
191204 // Should return original messages when summary is empty
192- expect ( result ) . toEqual ( messages )
205+ expect ( result . messages ) . toEqual ( messages )
206+ expect ( result . cost ) . toBe ( 0.02 )
207+ expect ( result . summary ) . toBe ( "" )
193208 expect ( mockWarn ) . toHaveBeenCalledWith ( "Received empty summary from API" )
194209
195210 // Restore console.warn
@@ -225,4 +240,37 @@ describe("summarizeConversation", () => {
225240 const mockCallArgs = ( maybeRemoveImageBlocks as jest . Mock ) . mock . calls [ 0 ] [ 0 ] as any [ ]
226241 expect ( mockCallArgs [ mockCallArgs . length - 1 ] ) . toEqual ( expectedFinalMessage )
227242 } )
243+
244+ it ( "should calculate newContextTokens correctly with systemPrompt" , async ( ) => {
245+ const messages : ApiMessage [ ] = [
246+ { role : "user" , content : "Hello" , ts : 1 } ,
247+ { role : "assistant" , content : "Hi there" , ts : 2 } ,
248+ { role : "user" , content : "How are you?" , ts : 3 } ,
249+ { role : "assistant" , content : "I'm good" , ts : 4 } ,
250+ { role : "user" , content : "What's new?" , ts : 5 } ,
251+ { role : "assistant" , content : "Not much" , ts : 6 } ,
252+ { role : "user" , content : "Tell me more" , ts : 7 } ,
253+ ]
254+
255+ const systemPrompt = "You are a helpful assistant."
256+
257+ // Create a stream with usage information
258+ const streamWithUsage = ( async function * ( ) {
259+ yield { type : "text" as const , text : "This is a summary with system prompt" }
260+ yield { type : "usage" as const , totalCost : 0.06 , outputTokens : 200 }
261+ } ) ( )
262+
263+ // Override the mock for this test
264+ mockApiHandler . createMessage = jest . fn ( ) . mockReturnValue ( streamWithUsage ) as any
265+
266+ const result = await summarizeConversation ( messages , mockApiHandler , systemPrompt )
267+
268+ // Verify that countTokens was called with the correct messages including system prompt
269+ expect ( mockApiHandler . countTokens ) . toHaveBeenCalled ( )
270+
271+ // Check the newContextTokens calculation includes system prompt
272+ expect ( result . newContextTokens ) . toBe ( 300 ) // 200 output tokens + 100 from countTokens
273+ expect ( result . cost ) . toBe ( 0.06 )
274+ expect ( result . summary ) . toBe ( "This is a summary with system prompt" )
275+ } )
228276} )
0 commit comments