1+ use spinners:: {
2+ Spinner ,
3+ Spinners ,
4+ } ;
5+
16use crate :: theme:: StyledText ;
27use crate :: util:: ui:: should_send_structured_message;
38pub mod cli;
49mod consts;
510pub mod context;
611mod conversation;
7- mod custom_spinner;
812mod input_source;
913mod message;
1014mod parse;
@@ -83,7 +87,6 @@ use crossterm::{
8387 style,
8488 terminal,
8589} ;
86- use custom_spinner:: Spinners ;
8790use eyre:: {
8891 Report ,
8992 Result ,
@@ -576,7 +579,7 @@ pub struct ChatSession {
576579 input_source : InputSource ,
577580 /// Width of the terminal, required for [ParseState].
578581 terminal_width_provider : fn ( ) -> Option < usize > ,
579- spinner : Option < Spinners > ,
582+ spinner : Option < Spinner > ,
580583 /// [ConversationState].
581584 conversation : ConversationState ,
582585 /// Tool uses requested by the model that are actively being handled.
@@ -829,6 +832,11 @@ impl ChatSession {
829832
830833 if self . spinner . is_some ( ) {
831834 drop ( self . spinner . take ( ) ) ;
835+ queue ! (
836+ self . stderr,
837+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
838+ cursor:: MoveToColumn ( 0 ) ,
839+ ) ?;
832840 }
833841
834842 let ( context, report, display_err_message) = match err {
@@ -1138,6 +1146,10 @@ impl ChatSession {
11381146
11391147impl Drop for ChatSession {
11401148 fn drop ( & mut self ) {
1149+ if let Some ( spinner) = & mut self . spinner {
1150+ spinner. stop ( ) ;
1151+ }
1152+
11411153 execute ! (
11421154 self . stderr,
11431155 cursor:: MoveToColumn ( 0 ) ,
@@ -1435,7 +1447,7 @@ impl ChatSession {
14351447 . await ?;
14361448
14371449 if self . interactive {
1438- self . spinner = Some ( Spinners :: new ( "Creating summary..." . to_string ( ) ) ) ;
1450+ self . spinner = Some ( Spinner :: new ( Spinners :: Dots , "Creating summary..." . to_string ( ) ) ) ;
14391451 }
14401452
14411453 let mut response = match self
@@ -1451,6 +1463,12 @@ impl ChatSession {
14511463 Err ( err) => {
14521464 if self . interactive {
14531465 self . spinner . take ( ) ;
1466+ execute ! (
1467+ self . stderr,
1468+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
1469+ cursor:: MoveToColumn ( 0 ) ,
1470+ StyledText :: reset_attributes( )
1471+ ) ?;
14541472 }
14551473
14561474 // If the request fails due to context window overflow, then we'll see if it's
@@ -1548,6 +1566,11 @@ impl ChatSession {
15481566
15491567 if self . spinner . is_some ( ) {
15501568 drop ( self . spinner . take ( ) ) ;
1569+ queue ! (
1570+ self . stderr,
1571+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
1572+ cursor:: MoveToColumn ( 0 ) ,
1573+ ) ?;
15511574 }
15521575
15531576 self . conversation
@@ -1718,10 +1741,10 @@ impl ChatSession {
17181741
17191742 if self . interactive {
17201743 execute ! ( self . stderr, cursor:: Hide , style:: Print ( "\n " ) ) ?;
1721- self . spinner = Some ( Spinners :: new ( format ! (
1722- "Generating agent config for '{}'..." ,
1723- agent_name
1724- ) ) ) ;
1744+ self . spinner = Some ( Spinner :: new (
1745+ Spinners :: Dots ,
1746+ format ! ( "Generating agent config for '{}'..." , agent_name) ,
1747+ ) ) ;
17251748 }
17261749
17271750 let mut response = match self
@@ -1737,6 +1760,12 @@ impl ChatSession {
17371760 Err ( err) => {
17381761 if self . interactive {
17391762 self . spinner . take ( ) ;
1763+ execute ! (
1764+ self . stderr,
1765+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
1766+ cursor:: MoveToColumn ( 0 ) ,
1767+ StyledText :: reset_attributes( )
1768+ ) ?;
17401769 }
17411770 return Err ( err) ;
17421771 } ,
@@ -1783,6 +1812,11 @@ impl ChatSession {
17831812
17841813 if self . spinner . is_some ( ) {
17851814 drop ( self . spinner . take ( ) ) ;
1815+ queue ! (
1816+ self . stderr,
1817+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
1818+ cursor:: MoveToColumn ( 0 ) ,
1819+ ) ?;
17861820 }
17871821 // Parse and validate the initial generated config
17881822 let initial_agent_config = match serde_json:: from_str :: < Agent > ( & agent_config_json) {
@@ -2174,7 +2208,7 @@ impl ChatSession {
21742208 queue ! ( self . stderr, cursor:: Hide ) ?;
21752209
21762210 if self . interactive {
2177- self . spinner = Some ( Spinners :: new ( "Thinking..." . to_owned ( ) ) ) ;
2211+ self . spinner = Some ( Spinner :: new ( Spinners :: Dots , "Thinking..." . to_owned ( ) ) ) ;
21782212 }
21792213
21802214 Ok ( ChatState :: HandleResponseStream ( conv_state) )
@@ -2326,6 +2360,12 @@ impl ChatSession {
23262360
23272361 if let Some ( spinner) = self . spinner . take ( ) {
23282362 drop ( spinner) ;
2363+ queue ! (
2364+ self . stderr,
2365+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
2366+ cursor:: MoveToColumn ( 0 ) ,
2367+ cursor:: Show
2368+ ) ?;
23292369 }
23302370
23312371 // Handle checkpoint after tool execution - store tag for later display
@@ -2601,7 +2641,7 @@ impl ChatSession {
26012641 execute ! ( self . stderr, cursor:: Hide ) ?;
26022642 execute ! ( self . stderr, style:: Print ( "\n " ) , StyledText :: reset_attributes( ) ) ?;
26032643 if self . interactive {
2604- self . spinner = Some ( Spinners :: new ( "Thinking..." . to_string ( ) ) ) ;
2644+ self . spinner = Some ( Spinner :: new ( Spinners :: Dots , "Thinking..." . to_string ( ) ) ) ;
26052645 }
26062646
26072647 self . send_chat_telemetry ( os, TelemetryResult :: Succeeded , None , None , None , false )
@@ -2657,6 +2697,11 @@ impl ChatSession {
26572697
26582698 if self . spinner . is_some ( ) {
26592699 drop ( self . spinner . take ( ) ) ;
2700+ queue ! (
2701+ self . stderr,
2702+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
2703+ cursor:: MoveToColumn ( 0 ) ,
2704+ ) ?;
26602705 }
26612706
26622707 loop {
@@ -2699,6 +2744,11 @@ impl ChatSession {
26992744 parser:: ResponseEvent :: ToolUse ( tool_use) => {
27002745 if self . spinner . is_some ( ) {
27012746 drop ( self . spinner . take ( ) ) ;
2747+ queue ! (
2748+ self . stderr,
2749+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
2750+ cursor:: MoveToColumn ( 0 ) ,
2751+ ) ?;
27022752 }
27032753 tool_uses. push ( tool_use) ;
27042754 tool_name_being_recvd = None ;
@@ -2748,7 +2798,7 @@ impl ChatSession {
27482798 ) ;
27492799
27502800 execute ! ( self . stderr, cursor:: Hide ) ?;
2751- self . spinner = Some ( Spinners :: new ( "Dividing up the work..." . to_string ( ) ) ) ;
2801+ self . spinner = Some ( Spinner :: new ( Spinners :: Dots , "Dividing up the work..." . to_string ( ) ) ) ;
27522802
27532803 // For stream timeouts, we'll tell the model to try and split its response into
27542804 // smaller chunks.
@@ -2887,6 +2937,12 @@ impl ChatSession {
28872937
28882938 if tool_name_being_recvd. is_none ( ) && !buf. is_empty ( ) && self . spinner . is_some ( ) {
28892939 drop ( self . spinner . take ( ) ) ;
2940+ queue ! (
2941+ self . stderr,
2942+ terminal:: Clear ( terminal:: ClearType :: CurrentLine ) ,
2943+ cursor:: MoveToColumn ( 0 ) ,
2944+ cursor:: Show
2945+ ) ?;
28902946 }
28912947
28922948 info ! ( "## control end: buf: {:?}" , buf) ;
@@ -2940,7 +2996,7 @@ impl ChatSession {
29402996 if tool_name_being_recvd. is_some ( ) {
29412997 queue ! ( self . stderr, cursor:: Hide ) ?;
29422998 if self . interactive {
2943- self . spinner = Some ( Spinners :: new ( "Thinking..." . to_string ( ) ) ) ;
2999+ self . spinner = Some ( Spinner :: new ( Spinners :: Dots , "Thinking..." . to_string ( ) ) ) ;
29443000 }
29453001 }
29463002
@@ -3263,7 +3319,7 @@ impl ChatSession {
32633319 }
32643320
32653321 if self . interactive {
3266- self . spinner = Some ( Spinners :: new ( "Thinking..." . to_owned ( ) ) ) ;
3322+ self . spinner = Some ( Spinner :: new ( Spinners :: Dots , "Thinking..." . to_owned ( ) ) ) ;
32673323 }
32683324
32693325 Ok ( ChatState :: HandleResponseStream (
@@ -3708,7 +3764,7 @@ where
37083764 Fut : std:: future:: Future < Output = Result < T , E > > ,
37093765{
37103766 queue ! ( output, cursor:: Hide , ) . ok ( ) ;
3711- let spinner = Spinners :: new ( spinner_text. to_owned ( ) ) ;
3767+ let spinner = Spinner :: new ( Spinners :: Dots , spinner_text. to_owned ( ) ) ;
37123768
37133769 let result = f ( ) . await ;
37143770
0 commit comments