@@ -73,6 +73,7 @@ use hooks::{
73
73
HookTrigger ,
74
74
} ;
75
75
use summarization_state:: {
76
+ CONTEXT_WINDOW_SIZE ,
76
77
SummarizationState ,
77
78
TokenWarningLevel ,
78
79
} ;
@@ -205,6 +206,7 @@ const HELP_TEXT: &str = color_print::cstr! {"
205
206
<em>rm</em> <black!>Remove file(s) from context [--global]</black!>
206
207
<em>clear</em> <black!>Clear all files from current context [--global]</black!>
207
208
<em>hooks</em> <black!>View and manage context hooks</black!>
209
+ <em>/usage</em> <black!>Show current session's context window usage</black!>
208
210
209
211
<cyan,em>Tips:</cyan,em>
210
212
<em>!{command}</em> <black!>Quickly execute a command in your current session</black!>
@@ -1899,6 +1901,157 @@ where
1899
1901
// during PromptUser.
1900
1902
execute ! ( self . output, style:: Print ( "\n \n " ) , ) ?;
1901
1903
1904
+ ChatState :: PromptUser {
1905
+ tool_uses : Some ( tool_uses) ,
1906
+ pending_tool_index,
1907
+ skip_printing_tools : true ,
1908
+ }
1909
+ } ,
1910
+ Command :: Usage => {
1911
+ let context_messages = self . conversation_state . context_messages ( None ) . await ;
1912
+ let chat_history = self . conversation_state . get_chat_history ( ) ;
1913
+ let assistant_messages = chat_history
1914
+ . iter ( )
1915
+ . filter_map ( |message| {
1916
+ if let fig_api_client:: model:: ChatMessage :: AssistantResponseMessage ( msg) = message {
1917
+ Some ( msg)
1918
+ } else {
1919
+ None
1920
+ }
1921
+ } )
1922
+ . collect :: < Vec < _ > > ( ) ;
1923
+
1924
+ let user_messages = chat_history
1925
+ . iter ( )
1926
+ . filter_map ( |message| {
1927
+ if let fig_api_client:: model:: ChatMessage :: UserInputMessage ( msg) = message {
1928
+ Some ( msg)
1929
+ } else {
1930
+ None
1931
+ }
1932
+ } )
1933
+ . collect :: < Vec < _ > > ( ) ;
1934
+
1935
+ let context_token_count = context_messages
1936
+ . iter ( )
1937
+ . map ( |msg| TokenCounter :: count_tokens ( & msg. 0 . content ) )
1938
+ . sum :: < usize > ( ) ;
1939
+
1940
+ let assistant_token_count = assistant_messages
1941
+ . iter ( )
1942
+ . map ( |msg| TokenCounter :: count_tokens ( & msg. content ) )
1943
+ . sum :: < usize > ( ) ;
1944
+
1945
+ let user_token_count = user_messages
1946
+ . iter ( )
1947
+ . map ( |msg| TokenCounter :: count_tokens ( & msg. content ) )
1948
+ . sum :: < usize > ( ) ;
1949
+
1950
+ let total_token_used: usize = context_token_count + assistant_token_count + user_token_count;
1951
+
1952
+ let window_width = self . terminal_width ( ) ;
1953
+ let progress_bar_width = std:: cmp:: min ( window_width, 80 ) ; // set a max width for the progress bar for better aesthetic
1954
+
1955
+ let context_width =
1956
+ ( ( context_token_count as f64 / CONTEXT_WINDOW_SIZE as f64 ) * progress_bar_width as f64 ) as usize ;
1957
+ let assistant_width =
1958
+ ( ( assistant_token_count as f64 / CONTEXT_WINDOW_SIZE as f64 ) * progress_bar_width as f64 ) as usize ;
1959
+ let user_width =
1960
+ ( ( user_token_count as f64 / CONTEXT_WINDOW_SIZE as f64 ) * progress_bar_width as f64 ) as usize ;
1961
+
1962
+ let left_over_width = progress_bar_width
1963
+ - std:: cmp:: min ( context_width + assistant_width + user_width, progress_bar_width) ;
1964
+
1965
+ queue ! (
1966
+ self . output,
1967
+ style:: Print ( format!(
1968
+ "\n Current context window ({} of {}k tokens used)\n " ,
1969
+ total_token_used,
1970
+ CONTEXT_WINDOW_SIZE / 1000
1971
+ ) ) ,
1972
+ style:: SetForegroundColor ( Color :: DarkCyan ) ,
1973
+ // add a nice visual to mimic "tiny" progress, so the overral progress bar doesn't look too empty
1974
+ style:: Print ( "|" . repeat( if context_width == 0 && context_token_count > 0 {
1975
+ 1
1976
+ } else {
1977
+ 0
1978
+ } ) ) ,
1979
+ style:: Print ( "█" . repeat( context_width) ) ,
1980
+ style:: SetForegroundColor ( Color :: Blue ) ,
1981
+ style:: Print ( "|" . repeat( if assistant_width == 0 && assistant_token_count > 0 {
1982
+ 1
1983
+ } else {
1984
+ 0
1985
+ } ) ) ,
1986
+ style:: Print ( "█" . repeat( assistant_width) ) ,
1987
+ style:: SetForegroundColor ( Color :: Magenta ) ,
1988
+ style:: Print ( "|" . repeat( if user_width == 0 && user_token_count > 0 { 1 } else { 0 } ) ) ,
1989
+ style:: Print ( "█" . repeat( user_width) ) ,
1990
+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
1991
+ style:: Print ( "█" . repeat( left_over_width) ) ,
1992
+ style:: Print ( " " ) ,
1993
+ style:: SetForegroundColor ( Color :: Reset ) ,
1994
+ style:: Print ( format!(
1995
+ "{:.2}%" ,
1996
+ ( total_token_used as f32 / CONTEXT_WINDOW_SIZE as f32 ) * 100.0
1997
+ ) ) ,
1998
+ ) ?;
1999
+
2000
+ queue ! ( self . output, style:: Print ( "\n \n " ) ) ?;
2001
+ self . output . flush ( ) ?;
2002
+
2003
+ queue ! (
2004
+ self . output,
2005
+ style:: SetForegroundColor ( Color :: DarkCyan ) ,
2006
+ style:: Print ( "█ Context files: " ) ,
2007
+ style:: SetForegroundColor ( Color :: Reset ) ,
2008
+ style:: Print ( format!(
2009
+ "~{} tokens ({:.2}%)\n " ,
2010
+ context_token_count,
2011
+ ( context_token_count as f32 / CONTEXT_WINDOW_SIZE as f32 ) * 100.0
2012
+ ) ) ,
2013
+ style:: SetForegroundColor ( Color :: Blue ) ,
2014
+ style:: Print ( "█ Q responses: " ) ,
2015
+ style:: SetForegroundColor ( Color :: Reset ) ,
2016
+ style:: Print ( format!(
2017
+ " ~{} tokens ({:.2}%)\n " ,
2018
+ assistant_token_count,
2019
+ ( assistant_token_count as f32 / CONTEXT_WINDOW_SIZE as f32 ) * 100.0
2020
+ ) ) ,
2021
+ style:: SetForegroundColor ( Color :: Magenta ) ,
2022
+ style:: Print ( "█ Your prompts: " ) ,
2023
+ style:: SetForegroundColor ( Color :: Reset ) ,
2024
+ style:: Print ( format!(
2025
+ " ~{} tokens ({:.2}%)\n \n " ,
2026
+ user_token_count,
2027
+ ( user_token_count as f32 / CONTEXT_WINDOW_SIZE as f32 ) * 100.0
2028
+ ) ) ,
2029
+ ) ?;
2030
+
2031
+ queue ! (
2032
+ self . output,
2033
+ style:: SetAttribute ( Attribute :: Bold ) ,
2034
+ style:: Print ( "\n 💡 Pro Tips:\n " ) ,
2035
+ style:: SetAttribute ( Attribute :: Reset ) ,
2036
+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
2037
+ style:: Print ( "Run " ) ,
2038
+ style:: SetForegroundColor ( Color :: DarkGreen ) ,
2039
+ style:: Print ( "/compact" ) ,
2040
+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
2041
+ style:: Print ( " to replace the conversation history with its summary\n " ) ,
2042
+ style:: Print ( "Run " ) ,
2043
+ style:: SetForegroundColor ( Color :: DarkGreen ) ,
2044
+ style:: Print ( "/clear" ) ,
2045
+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
2046
+ style:: Print ( " to erase the entire chat history\n " ) ,
2047
+ style:: Print ( "Run " ) ,
2048
+ style:: SetForegroundColor ( Color :: DarkGreen ) ,
2049
+ style:: Print ( "/context show" ) ,
2050
+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
2051
+ style:: Print ( " to see tokens per context file\n \n " ) ,
2052
+ style:: SetForegroundColor ( Color :: Reset ) ,
2053
+ ) ?;
2054
+
1902
2055
ChatState :: PromptUser {
1903
2056
tool_uses : Some ( tool_uses) ,
1904
2057
pending_tool_index,
0 commit comments