@@ -3647,6 +3647,48 @@ impl EventLoop {
36473647 }
36483648 } ) ;
36493649 }
3650+
3651+ ToolEvent :: AgentGenerated {
3652+ name,
3653+ path,
3654+ location,
3655+ } => {
3656+ // Agent was generated and saved successfully
3657+ tracing:: info!(
3658+ "Agent generated: {} (location: {}, path: {})" ,
3659+ name,
3660+ location,
3661+ path
3662+ ) ;
3663+
3664+ // Show success message
3665+ self . app_state
3666+ . toasts
3667+ . success ( format ! ( "Agent @{} created!" , name) ) ;
3668+
3669+ // Add system message about the created agent
3670+ self . inject_agent_created_event ( & name) ;
3671+
3672+ // Refresh the agents list in interactive mode
3673+ let cwd = std:: env:: current_dir ( ) . ok ( ) ;
3674+ let terminal_height = self . app_state . terminal_size . 1 ;
3675+ let interactive = crate :: interactive:: builders:: build_agents_selector (
3676+ cwd. as_deref ( ) ,
3677+ Some ( terminal_height) ,
3678+ ) ;
3679+ self . app_state . enter_interactive_mode ( interactive) ;
3680+ }
3681+
3682+ ToolEvent :: AgentGenerationFailed { error } => {
3683+ // Agent generation failed
3684+ tracing:: error!( "Agent generation failed: {}" , error) ;
3685+
3686+ // Show error message
3687+ self . app_state . toasts . error ( & error) ;
3688+
3689+ // Exit interactive mode (user can try again with /agents)
3690+ self . app_state . exit_interactive_mode ( ) ;
3691+ }
36503692 }
36513693 }
36523694
@@ -6666,6 +6708,7 @@ impl EventLoop {
66666708 }
66676709 action if action. starts_with ( "agent-ai-create:" ) => {
66686710 // AI-assisted agent creation from inline form
6711+ // Fully automated: generate agent with LLM and save directly
66696712 let location_str = action. strip_prefix ( "agent-ai-create:" ) . unwrap_or ( "project" ) ;
66706713 let description = values. get ( "description" ) . cloned ( ) . unwrap_or_default ( ) ;
66716714
@@ -6683,21 +6726,104 @@ impl EventLoop {
66836726 _ => AgentLocation :: Project ,
66846727 } ;
66856728
6686- // Store location for later use
6687- self . app_state . agent_creation_location = Some ( location) ;
6688- // Set mode to AI and store the description for processing
6689- self . app_state . agent_creation_mode = Some ( "ai" . to_string ( ) ) ;
6729+ // Spawn async task for AI agent generation
6730+ let tx = self . tool_event_tx . clone ( ) ;
6731+ let location_clone = location;
6732+ let description_clone = description. clone ( ) ;
6733+
6734+ tokio:: spawn ( async move {
6735+ use cortex_engine:: agent:: AgentGenerator ;
6736+
6737+ // Generate agent configuration using AI
6738+ let generator = AgentGenerator :: new ( ) . with_model ( "gpt-4o" ) ;
6739+
6740+ match generator. generate ( & description_clone) . await {
6741+ Ok ( generated) => {
6742+ // Determine save directory based on location
6743+ let dir = match location_clone {
6744+ AgentLocation :: Project => {
6745+ match std:: env:: current_dir ( ) {
6746+ Ok ( cwd) => cwd. join ( ".cortex/agents" ) ,
6747+ Err ( e) => {
6748+ let _ = tx. send ( crate :: events:: ToolEvent :: AgentGenerationFailed {
6749+ error : format ! ( "Could not determine current directory: {}" , e) ,
6750+ } ) . await ;
6751+ return ;
6752+ }
6753+ }
6754+ }
6755+ AgentLocation :: Global => {
6756+ match dirs:: home_dir ( ) {
6757+ Some ( home) => home. join ( ".cortex/agents" ) ,
6758+ None => {
6759+ let _ = tx. send ( crate :: events:: ToolEvent :: AgentGenerationFailed {
6760+ error : "Could not determine home directory" . to_string ( ) ,
6761+ } ) . await ;
6762+ return ;
6763+ }
6764+ }
6765+ }
6766+ } ;
66906767
6691- // Insert the description into the input box and trigger AI generation
6692- let prompt = format ! ( "Create an agent with this description: {}" , description) ;
6693- self . app_state . input . set_text ( & prompt) ;
6768+ // Create directory if it doesn't exist
6769+ if let Err ( e) = std:: fs:: create_dir_all ( & dir) {
6770+ let _ = tx
6771+ . send ( crate :: events:: ToolEvent :: AgentGenerationFailed {
6772+ error : format ! ( "Failed to create agents directory: {}" , e) ,
6773+ } )
6774+ . await ;
6775+ return ;
6776+ }
66946777
6695- self . app_state
6696- . toasts
6697- . info ( "Generating agent configuration..." ) ;
6778+ // Save agent file
6779+ let filepath = dir . join ( generated . filename ( ) ) ;
6780+ let content = generated . to_markdown ( ) ;
66986781
6699- // Exit interactive mode - the description will be processed
6700- false
6782+ if let Err ( e) = std:: fs:: write ( & filepath, & content) {
6783+ let _ = tx
6784+ . send ( crate :: events:: ToolEvent :: AgentGenerationFailed {
6785+ error : format ! ( "Failed to save agent file: {}" , e) ,
6786+ } )
6787+ . await ;
6788+ return ;
6789+ }
6790+
6791+ // Send success event
6792+ let _ = tx
6793+ . send ( crate :: events:: ToolEvent :: AgentGenerated {
6794+ name : generated. identifier . clone ( ) ,
6795+ path : filepath. display ( ) . to_string ( ) ,
6796+ location : match location_clone {
6797+ AgentLocation :: Project => "project" . to_string ( ) ,
6798+ AgentLocation :: Global => "global" . to_string ( ) ,
6799+ } ,
6800+ } )
6801+ . await ;
6802+ }
6803+ Err ( e) => {
6804+ let _ = tx
6805+ . send ( crate :: events:: ToolEvent :: AgentGenerationFailed {
6806+ error : format ! ( "Failed to generate agent: {}" , e) ,
6807+ } )
6808+ . await ;
6809+ }
6810+ }
6811+ } ) ;
6812+
6813+ // Clear creation state
6814+ self . app_state . agent_creation_location = None ;
6815+ self . app_state . agent_creation_mode = None ;
6816+
6817+ // Stay in interactive mode - will be updated when generation completes
6818+ // Show a loading state in the agents panel
6819+ let cwd = std:: env:: current_dir ( ) . ok ( ) ;
6820+ let terminal_height = self . app_state . terminal_size . 1 ;
6821+ let interactive = crate :: interactive:: builders:: build_agents_selector (
6822+ cwd. as_deref ( ) ,
6823+ Some ( terminal_height) ,
6824+ ) ;
6825+ self . app_state . enter_interactive_mode ( interactive) ;
6826+ true // Stay in interactive mode showing agents list
67016827 }
67026828 _ => {
67036829 tracing:: warn!( "Unhandled inline form submission: {}" , action_id) ;
0 commit comments