@@ -582,6 +582,55 @@ func TestLoop_TokenBasedCompaction(t *testing.T) {
582582 }
583583}
584584
585+ func TestLoop_BudgetExceeded (t * testing.T ) {
586+ mp := & mockProvider {
587+ responses : []* provider.ChatResponse {
588+ {
589+ Content : []provider.ContentBlock {{Type : provider .ContentText , Text : "Partial result" }},
590+ StopReason : provider .StopEndTurn ,
591+ Usage : provider.Usage {InputTokens : 1_000_000 , OutputTokens : 1_000_000 },
592+ },
593+ },
594+ }
595+ exec := & mockExecutor {results : map [string ]string {}}
596+ bt := NewBudgetTracker (0.001 , nil ) // $0.001 budget — 1M tokens of sonnet costs $18
597+ a := New (mp , "claude-sonnet-4-6" , exec , WithUsageRecorder (bt ), WithBudgetChecker (bt ))
598+
599+ result , err := a .Run (context .Background (), "test" )
600+ if err == nil {
601+ t .Fatal ("expected budget exceeded error" )
602+ }
603+ if ! strings .Contains (err .Error (), "budget exceeded" ) {
604+ t .Errorf ("error = %q, want budget exceeded" , err .Error ())
605+ }
606+ if result != "Partial result" {
607+ t .Errorf ("result = %q, want partial text returned" , result )
608+ }
609+ }
610+
611+ func TestLoop_BudgetNotExceeded (t * testing.T ) {
612+ mp := & mockProvider {
613+ responses : []* provider.ChatResponse {
614+ {
615+ Content : []provider.ContentBlock {{Type : provider .ContentText , Text : "Full result" }},
616+ StopReason : provider .StopEndTurn ,
617+ Usage : provider.Usage {InputTokens : 100 , OutputTokens : 100 },
618+ },
619+ },
620+ }
621+ exec := & mockExecutor {results : map [string ]string {}}
622+ bt := NewBudgetTracker (10.0 , nil ) // $10 budget — more than enough
623+ a := New (mp , "claude-sonnet-4-6" , exec , WithUsageRecorder (bt ), WithBudgetChecker (bt ))
624+
625+ result , err := a .Run (context .Background (), "test" )
626+ if err != nil {
627+ t .Fatalf ("unexpected error: %v" , err )
628+ }
629+ if result != "Full result" {
630+ t .Errorf ("result = %q, want Full result" , result )
631+ }
632+ }
633+
585634func TestLoop_TracksLastInputTokens (t * testing.T ) {
586635 mp := & mockProvider {
587636 responses : []* provider.ChatResponse {
0 commit comments