@@ -183,17 +183,67 @@ describe("AutoApprovalHandler", () => {
183183 expect ( result3 . requiresApproval ) . toBe ( true )
184184 } )
185185
186- it ( "should not reset cost to zero on approval" , async ( ) => {
186+ it ( "should reset cost tracking on approval" , async ( ) => {
187+ const messages : ClineMessage [ ] = [
188+ { type : "say" , say : "api_req_started" , text : '{"cost": 3.0}' , ts : 1000 } ,
189+ { type : "say" , say : "api_req_started" , text : '{"cost": 3.0}' , ts : 2000 } ,
190+ ]
191+
192+ // First check - cost exceeds limit (6.0 > 5.0)
193+ mockGetApiMetrics . mockReturnValue ( { totalCost : 6.0 } )
194+ mockAskForApproval . mockResolvedValue ( { response : "yesButtonClicked" } )
195+
196+ const result1 = await handler . checkAutoApprovalLimits ( mockState , messages , mockAskForApproval )
197+ expect ( result1 . shouldProceed ) . toBe ( true )
198+ expect ( result1 . requiresApproval ) . toBe ( true )
199+
200+ // Add more messages after reset
201+ messages . push (
202+ { type : "say" , say : "api_req_started" , text : '{"cost": 2.0}' , ts : 3000 } ,
203+ { type : "say" , say : "api_req_started" , text : '{"cost": 1.0}' , ts : 4000 } ,
204+ )
205+
206+ // Second check - should only count messages after reset (3.0 < 5.0)
207+ mockGetApiMetrics . mockReturnValue ( { totalCost : 3.0 } )
208+ const result2 = await handler . checkAutoApprovalLimits ( mockState , messages , mockAskForApproval )
209+
210+ // Should not require approval since cost after reset is under limit
211+ expect ( result2 . shouldProceed ) . toBe ( true )
212+ expect ( result2 . requiresApproval ) . toBe ( false )
213+
214+ // Verify it's only calculating cost from messages after reset point
215+ expect ( mockGetApiMetrics ) . toHaveBeenLastCalledWith ( messages . slice ( 2 ) )
216+ } )
217+
218+ it ( "should track multiple cost resets correctly" , async ( ) => {
187219 const messages : ClineMessage [ ] = [ ]
188220
221+ // First cost limit hit
222+ messages . push ( { type : "say" , say : "api_req_started" , text : '{"cost": 6.0}' , ts : 1000 } )
189223 mockGetApiMetrics . mockReturnValue ( { totalCost : 6.0 } )
190224 mockAskForApproval . mockResolvedValue ( { response : "yesButtonClicked" } )
191225
192226 await handler . checkAutoApprovalLimits ( mockState , messages , mockAskForApproval )
193227
194- // Cost should still be calculated from messages, not reset
195- const state = handler . getApprovalState ( )
196- expect ( state . currentCost ) . toBe ( 6.0 )
228+ // Add more messages
229+ messages . push (
230+ { type : "say" , say : "api_req_started" , text : '{"cost": 3.0}' , ts : 2000 } ,
231+ { type : "say" , say : "api_req_started" , text : '{"cost": 3.0}' , ts : 3000 } ,
232+ )
233+
234+ // Second cost limit hit (only counting from index 1)
235+ mockGetApiMetrics . mockReturnValue ( { totalCost : 6.0 } )
236+ await handler . checkAutoApprovalLimits ( mockState , messages , mockAskForApproval )
237+
238+ // Add more messages after second reset
239+ messages . push ( { type : "say" , say : "api_req_started" , text : '{"cost": 2.0}' , ts : 4000 } )
240+
241+ // Third check - should only count from last reset
242+ mockGetApiMetrics . mockReturnValue ( { totalCost : 2.0 } )
243+ const result = await handler . checkAutoApprovalLimits ( mockState , messages , mockAskForApproval )
244+
245+ expect ( result . requiresApproval ) . toBe ( false )
246+ expect ( mockGetApiMetrics ) . toHaveBeenLastCalledWith ( messages . slice ( 3 ) )
197247 } )
198248 } )
199249
0 commit comments