@@ -16,8 +16,9 @@ use coro_core::ResolvedLlmConfig;
1616use iocraft:: prelude:: * ;
1717use std:: cmp:: min;
1818use std:: path:: PathBuf ;
19+ use std:: sync:: Arc ;
1920use std:: time:: { Duration , Instant } ;
20- use tokio:: sync:: broadcast;
21+ use tokio:: sync:: { broadcast, Mutex } ;
2122use unicode_width:: UnicodeWidthStr ;
2223
2324/// Find the nearest character boundary at or before the given byte position
@@ -117,17 +118,19 @@ impl Default for InputSectionProps {
117118 ) ,
118119 project_path : PathBuf :: new ( ) ,
119120 ui_sender : tokio:: sync:: broadcast:: channel ( 1 ) . 0 ,
121+ agent : Arc :: new ( Mutex :: new ( None ) ) ,
120122 } ,
121123 }
122124 }
123125}
124126
125127/// Context for the input section component
126- #[ derive( Debug , Clone ) ]
128+ #[ derive( Clone ) ]
127129pub struct InputSectionContext {
128130 pub llm_config : ResolvedLlmConfig ,
129131 pub project_path : PathBuf ,
130132 pub ui_sender : broadcast:: Sender < AppMessage > ,
133+ pub agent : Arc < Mutex < Option < coro_core:: agent:: AgentCore > > > ,
131134}
132135
133136/// Enhanced text input component that wraps iocraft's TextInput with submit handling
@@ -912,6 +915,69 @@ pub fn spawn_ui_agent_task(
912915 } ) ;
913916}
914917
918+ /// Spawn agent task execution with persistent agent for conversation continuity
919+ pub fn spawn_ui_agent_task_with_context (
920+ input : String ,
921+ llm_config : ResolvedLlmConfig ,
922+ project_path : PathBuf ,
923+ ui_sender : broadcast:: Sender < AppMessage > ,
924+ agent : Arc < Mutex < Option < coro_core:: agent:: AgentCore > > > ,
925+ ) {
926+ use crate :: interactive:: message_handler:: get_random_status_word;
927+ use crate :: interactive:: task_executor:: execute_agent_task_with_context;
928+
929+ // Start with a random status word
930+ let _ = ui_sender. send ( AppMessage :: AgentTaskStarted {
931+ operation : get_random_status_word ( ) ,
932+ } ) ;
933+
934+ // Create a cancellation token for the timer
935+ let ( cancel_sender, mut cancel_receiver) = tokio:: sync:: oneshot:: channel :: < ( ) > ( ) ;
936+
937+ // Change status word once after 1 second (unless cancelled)
938+ let ui_sender_timer = ui_sender. clone ( ) ;
939+ tokio:: spawn ( async move {
940+ tokio:: select! {
941+ _ = tokio:: time:: sleep( tokio:: time:: Duration :: from_secs( 1 ) ) => {
942+ let _ = ui_sender_timer. send( AppMessage :: AgentTaskStarted {
943+ operation: get_random_status_word( ) ,
944+ } ) ;
945+ }
946+ _ = & mut cancel_receiver => {
947+ // Timer cancelled, do nothing
948+ }
949+ }
950+ } ) ;
951+
952+ // Execute agent task with persistent context
953+ tokio:: spawn ( async move {
954+ match execute_agent_task_with_context (
955+ input,
956+ llm_config,
957+ project_path,
958+ ui_sender. clone ( ) ,
959+ agent,
960+ )
961+ . await
962+ {
963+ Ok ( _) => {
964+ let _ = cancel_sender. send ( ( ) ) ; // Cancel the timer
965+ let _ = ui_sender. send ( AppMessage :: AgentExecutionCompleted ) ;
966+ }
967+ Err ( e) => {
968+ let _ = cancel_sender. send ( ( ) ) ; // Cancel the timer
969+ // Check if it's an interruption error
970+ if e. to_string ( ) . contains ( "Task interrupted by user" ) {
971+ // Don't show error message for user interruptions
972+ } else {
973+ let _ = ui_sender. send ( AppMessage :: SystemMessage ( format ! ( "Error: {}" , e) ) ) ;
974+ }
975+ let _ = ui_sender. send ( AppMessage :: AgentExecutionCompleted ) ;
976+ }
977+ }
978+ } ) ;
979+ }
980+
915981/// Input Section Component - Fixed bottom area for input and status
916982#[ component]
917983pub fn InputSection ( mut hooks : Hooks , props : & InputSectionProps ) -> impl Into < AnyElement < ' static > > {
@@ -1105,6 +1171,7 @@ pub fn InputSection(mut hooks: Hooks, props: &InputSectionProps) -> impl Into<An
11051171 let ui_sender = ui_sender. clone( ) ;
11061172 let llm_config = llm_config. clone( ) ;
11071173 let project_path = project_path. clone( ) ;
1174+ let agent = context. agent. clone( ) ;
11081175 move |input: String | {
11091176 if input. trim( ) . is_empty( ) {
11101177 return ;
@@ -1137,6 +1204,7 @@ pub fn InputSection(mut hooks: Hooks, props: &InputSectionProps) -> impl Into<An
11371204 llm_config. clone( ) ,
11381205 project_path. clone( ) ,
11391206 ui_sender. clone( ) ,
1207+ agent. clone( ) ,
11401208 ) ;
11411209 }
11421210 } ,
0 commit comments