1- use clap:: Args ;
1+ use clap:: {
2+ Args ,
3+ Subcommand ,
4+ } ;
25use crossterm:: execute;
36use crossterm:: style:: {
47 self ,
@@ -14,9 +17,33 @@ use crate::database::settings::Setting;
1417use crate :: os:: Os ;
1518
1619#[ derive( Debug , PartialEq , Args ) ]
17- pub struct TangentArgs ;
20+ pub struct TangentArgs {
21+ #[ command( subcommand) ]
22+ pub subcommand : Option < TangentSubcommand > ,
23+ }
24+
25+ #[ derive( Debug , PartialEq , Subcommand ) ]
26+ pub enum TangentSubcommand {
27+ /// Exit tangent mode and keep the last conversation entry (user question + assistant response)
28+ Tail ,
29+ }
1830
1931impl TangentArgs {
32+ async fn send_tangent_telemetry ( os : & Os , session : & ChatSession , duration_seconds : i64 ) {
33+ if let Err ( err) = os
34+ . telemetry
35+ . send_tangent_mode_session (
36+ & os. database ,
37+ session. conversation . conversation_id ( ) . to_string ( ) ,
38+ crate :: telemetry:: TelemetryResult :: Succeeded ,
39+ crate :: telemetry:: core:: TangentModeSessionArgs { duration_seconds } ,
40+ )
41+ . await
42+ {
43+ tracing:: warn!( ?err, "Failed to send tangent mode session telemetry" ) ;
44+ }
45+ }
46+
2047 pub async fn execute ( self , os : & Os , session : & mut ChatSession ) -> Result < ChatState , ChatError > {
2148 // Check if tangent mode is enabled
2249 if !os
@@ -35,69 +62,86 @@ impl TangentArgs {
3562 skip_printing_tools : true ,
3663 } ) ;
3764 }
38- if session. conversation . is_in_tangent_mode ( ) {
39- // Get duration before exiting tangent mode
40- let duration_seconds = session. conversation . get_tangent_duration_seconds ( ) . unwrap_or ( 0 ) ;
41-
42- session. conversation . exit_tangent_mode ( ) ;
43-
44- // Send telemetry for tangent mode session
45- if let Err ( err) = os
46- . telemetry
47- . send_tangent_mode_session (
48- & os. database ,
49- session. conversation . conversation_id ( ) . to_string ( ) ,
50- crate :: telemetry:: TelemetryResult :: Succeeded ,
51- crate :: telemetry:: core:: TangentModeSessionArgs { duration_seconds } ,
52- )
53- . await
54- {
55- tracing:: warn!( ?err, "Failed to send tangent mode session telemetry" ) ;
56- }
5765
58- execute ! (
59- session. stderr,
60- style:: SetForegroundColor ( Color :: DarkGrey ) ,
61- style:: Print ( "Restored conversation from checkpoint (" ) ,
62- style:: SetForegroundColor ( Color :: Yellow ) ,
63- style:: Print ( "↯" ) ,
64- style:: SetForegroundColor ( Color :: DarkGrey ) ,
65- style:: Print ( "). - Returned to main conversation.\n " ) ,
66- style:: SetForegroundColor ( Color :: Reset )
67- ) ?;
68- } else {
69- session. conversation . enter_tangent_mode ( ) ;
70-
71- // Get the configured tangent mode key for display
72- let tangent_key_char = match os
73- . database
74- . settings
75- . get_string ( crate :: database:: settings:: Setting :: TangentModeKey )
76- {
77- Some ( key) if key. len ( ) == 1 => key. chars ( ) . next ( ) . unwrap_or ( 't' ) ,
78- _ => 't' , // Default to 't' if setting is missing or invalid
79- } ;
80- let tangent_key_display = format ! ( "ctrl + {}" , tangent_key_char. to_lowercase( ) ) ;
66+ match self . subcommand {
67+ Some ( TangentSubcommand :: Tail ) => {
68+ if session. conversation . is_in_tangent_mode ( ) {
69+ let duration_seconds = session. conversation . get_tangent_duration_seconds ( ) . unwrap_or ( 0 ) ;
70+ session. conversation . exit_tangent_mode_with_tail ( ) ;
71+ Self :: send_tangent_telemetry ( os, session, duration_seconds) . await ;
8172
82- execute ! (
83- session. stderr,
84- style:: SetForegroundColor ( Color :: DarkGrey ) ,
85- style:: Print ( "Created a conversation checkpoint (" ) ,
86- style:: SetForegroundColor ( Color :: Yellow ) ,
87- style:: Print ( "↯" ) ,
88- style:: SetForegroundColor ( Color :: DarkGrey ) ,
89- style:: Print ( "). Use " ) ,
90- style:: SetForegroundColor ( Color :: Green ) ,
91- style:: Print ( & tangent_key_display) ,
92- style:: SetForegroundColor ( Color :: DarkGrey ) ,
93- style:: Print ( " or " ) ,
94- style:: SetForegroundColor ( Color :: Green ) ,
95- style:: Print ( "/tangent" ) ,
96- style:: SetForegroundColor ( Color :: DarkGrey ) ,
97- style:: Print ( " to restore the conversation later.\n " ) ,
98- style:: Print ( "Note: this functionality is experimental and may change or be removed in the future.\n " ) ,
99- style:: SetForegroundColor ( Color :: Reset )
100- ) ?;
73+ execute ! (
74+ session. stderr,
75+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
76+ style:: Print ( "Restored conversation from checkpoint (" ) ,
77+ style:: SetForegroundColor ( Color :: Yellow ) ,
78+ style:: Print ( "↯" ) ,
79+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
80+ style:: Print ( ") with last conversation entry preserved.\n " ) ,
81+ style:: SetForegroundColor ( Color :: Reset )
82+ ) ?;
83+ } else {
84+ execute ! (
85+ session. stderr,
86+ style:: SetForegroundColor ( Color :: Red ) ,
87+ style:: Print ( "You need to be in tangent mode to use tail.\n " ) ,
88+ style:: SetForegroundColor ( Color :: Reset )
89+ ) ?;
90+ }
91+ } ,
92+ None => {
93+ if session. conversation . is_in_tangent_mode ( ) {
94+ let duration_seconds = session. conversation . get_tangent_duration_seconds ( ) . unwrap_or ( 0 ) ;
95+ session. conversation . exit_tangent_mode ( ) ;
96+ Self :: send_tangent_telemetry ( os, session, duration_seconds) . await ;
97+
98+ execute ! (
99+ session. stderr,
100+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
101+ style:: Print ( "Restored conversation from checkpoint (" ) ,
102+ style:: SetForegroundColor ( Color :: Yellow ) ,
103+ style:: Print ( "↯" ) ,
104+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
105+ style:: Print ( "). - Returned to main conversation.\n " ) ,
106+ style:: SetForegroundColor ( Color :: Reset )
107+ ) ?;
108+ } else {
109+ session. conversation . enter_tangent_mode ( ) ;
110+
111+ // Get the configured tangent mode key for display
112+ let tangent_key_char = match os
113+ . database
114+ . settings
115+ . get_string ( crate :: database:: settings:: Setting :: TangentModeKey )
116+ {
117+ Some ( key) if key. len ( ) == 1 => key. chars ( ) . next ( ) . unwrap_or ( 't' ) ,
118+ _ => 't' , // Default to 't' if setting is missing or invalid
119+ } ;
120+ let tangent_key_display = format ! ( "ctrl + {}" , tangent_key_char. to_lowercase( ) ) ;
121+
122+ execute ! (
123+ session. stderr,
124+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
125+ style:: Print ( "Created a conversation checkpoint (" ) ,
126+ style:: SetForegroundColor ( Color :: Yellow ) ,
127+ style:: Print ( "↯" ) ,
128+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
129+ style:: Print ( "). Use " ) ,
130+ style:: SetForegroundColor ( Color :: Green ) ,
131+ style:: Print ( & tangent_key_display) ,
132+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
133+ style:: Print ( " or " ) ,
134+ style:: SetForegroundColor ( Color :: Green ) ,
135+ style:: Print ( "/tangent" ) ,
136+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
137+ style:: Print ( " to restore the conversation later.\n " ) ,
138+ style:: Print (
139+ "Note: this functionality is experimental and may change or be removed in the future.\n "
140+ ) ,
141+ style:: SetForegroundColor ( Color :: Reset )
142+ ) ?;
143+ }
144+ } ,
101145 }
102146
103147 Ok ( ChatState :: PromptUser {
0 commit comments