Compare commits

...

1 Commits

Author SHA1 Message Date
Michael Neale
ff7dd542c8 control C wasn't working 2026-01-26 10:54:40 +11:00
3 changed files with 28 additions and 19 deletions

View File

@@ -156,7 +156,10 @@ pub async fn handle_command<W: UiWriter>(
} else { } else {
G3Status::progress(&format!("loading {}", file_path)); G3Status::progress(&format!("loading {}", file_path));
G3Status::done(); G3Status::done();
execute_task_with_retry(agent, prompt, show_prompt, show_code, output).await; let completed = execute_task_with_retry(agent, prompt, show_prompt, show_code, output).await;
if !completed {
return Ok(false);
}
} }
} }
Err(e) => { Err(e) => {
@@ -383,7 +386,10 @@ pub async fn handle_command<W: UiWriter>(
// Auto-submit the project status prompt // Auto-submit the project status prompt
let prompt = "what is the current state of the project? and what is your suggested next best step?"; let prompt = "what is the current state of the project? and what is your suggested next best step?";
execute_task_with_retry(agent, prompt, show_prompt, show_code, output).await; let completed = execute_task_with_retry(agent, prompt, show_prompt, show_code, output).await;
if !completed {
return Ok(false);
}
} else { } else {
output.print("❌ Failed to set project content in agent context."); output.print("❌ Failed to set project content in agent context.");
} }

View File

@@ -210,7 +210,7 @@ pub async fn run_interactive<W: UiWriter>(
} }
// Process the multiline input // Process the multiline input
execute_task_with_retry( let completed = execute_task_with_retry(
&mut agent, &mut agent,
&input, &input,
show_prompt, show_prompt,
@@ -218,6 +218,9 @@ pub async fn run_interactive<W: UiWriter>(
&output, &output,
) )
.await; .await;
if !completed {
break;
}
// Send auto-memory reminder if enabled and tools were called // Send auto-memory reminder if enabled and tools were called
// Skip per-turn reminders when from_agent_mode - we'll send once on exit // Skip per-turn reminders when from_agent_mode - we'll send once on exit
@@ -243,13 +246,16 @@ pub async fn run_interactive<W: UiWriter>(
// Check for control commands // Check for control commands
if input.starts_with('/') { if input.starts_with('/') {
if handle_command(&input, &mut agent, workspace_path, &output, &mut active_project, &mut rl, show_prompt, show_code).await? { let should_continue = handle_command(&input, &mut agent, workspace_path, &output, &mut active_project, &mut rl, show_prompt, show_code).await?;
if should_continue {
continue; continue;
} else {
break;
} }
} }
// Process the single line input // Process the single line input
execute_task_with_retry( let completed = execute_task_with_retry(
&mut agent, &mut agent,
&input, &input,
show_prompt, show_prompt,
@@ -257,6 +263,9 @@ pub async fn run_interactive<W: UiWriter>(
&output, &output,
) )
.await; .await;
if !completed {
break;
}
// Send auto-memory reminder if enabled and tools were called // Send auto-memory reminder if enabled and tools were called
// Skip per-turn reminders when from_agent_mode - we'll send once on exit // Skip per-turn reminders when from_agent_mode - we'll send once on exit
@@ -269,15 +278,8 @@ pub async fn run_interactive<W: UiWriter>(
} }
Err(ReadlineError::Interrupted) => { Err(ReadlineError::Interrupted) => {
// Ctrl-C pressed // Ctrl-C pressed
if in_multiline { output.print("");
// Cancel multiline input break;
output.print("Multi-line input cancelled");
multiline_buffer.clear();
in_multiline = false;
} else {
output.print("CTRL-C");
}
continue;
} }
Err(ReadlineError::Eof) => { Err(ReadlineError::Eof) => {
output.print("CTRL-D"); output.print("CTRL-D");

View File

@@ -26,13 +26,14 @@ fn recoverable_error_name(err: &RecoverableError) -> &'static str {
} }
/// Execute a task with retry logic for recoverable errors. /// Execute a task with retry logic for recoverable errors.
/// Returns `true` if the task completed normally, `false` if cancelled by Ctrl+C.
pub async fn execute_task_with_retry<W: UiWriter>( pub async fn execute_task_with_retry<W: UiWriter>(
agent: &mut Agent<W>, agent: &mut Agent<W>,
input: &str, input: &str,
show_prompt: bool, show_prompt: bool,
show_code: bool, show_code: bool,
output: &SimpleOutput, output: &SimpleOutput,
) { ) -> bool {
let mut attempt = 0; let mut attempt = 0;
output.print("🤔 Thinking..."); output.print("🤔 Thinking...");
@@ -54,7 +55,7 @@ pub async fn execute_task_with_retry<W: UiWriter>(
_ = tokio::signal::ctrl_c() => { _ = tokio::signal::ctrl_c() => {
cancel_token_clone.cancel(); cancel_token_clone.cancel();
output.print("\n⚠️ Operation cancelled by user (Ctrl+C)"); output.print("\n⚠️ Operation cancelled by user (Ctrl+C)");
return; return false;
} }
}; };
@@ -64,12 +65,12 @@ pub async fn execute_task_with_retry<W: UiWriter>(
output.print(&format!("✅ Request succeeded after {} attempts", attempt)); output.print(&format!("✅ Request succeeded after {} attempts", attempt));
} }
// Response was already displayed during streaming - don't print again // Response was already displayed during streaming - don't print again
return; return true;
} }
Err(e) => { Err(e) => {
if e.to_string().contains("cancelled") { if e.to_string().contains("cancelled") {
output.print("⚠️ Operation cancelled by user"); output.print("⚠️ Operation cancelled by user");
return; return false;
} }
// Check if this is a recoverable error that we should retry // Check if this is a recoverable error that we should retry
@@ -99,7 +100,7 @@ pub async fn execute_task_with_retry<W: UiWriter>(
// For non-recoverable errors or after max retries // For non-recoverable errors or after max retries
handle_execution_error(&e, input, output, attempt); handle_execution_error(&e, input, output, attempt);
return; return true;
} }
} }
} }