aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-ai/src/tui/components/atuin_ai.rs
diff options
context:
space:
mode:
authorMichelle Tilley <michelle@michelletilley.net>2026-04-10 13:24:57 -0700
committerGitHub <noreply@github.com>2026-04-10 20:24:57 +0000
commit09279a428659cf41824737d3e0c97bcc19a8885a (patch)
tree64731502c065df2483e8dd680d46c5559f3094f2 /crates/atuin-ai/src/tui/components/atuin_ai.rs
parentfeat: add strip_trailing_whitespace, on by default (#3390) (diff)
downloadatuin-09279a428659cf41824737d3e0c97bcc19a8885a.zip
feat: Client-tool execution + permission system (#3370)
Adds client-side tool execution to Atuin AI, starting with `atuin_history`. The server can request tool calls, which are executed locally with a permission system, and results are sent back to continue the conversation.
Diffstat (limited to 'crates/atuin-ai/src/tui/components/atuin_ai.rs')
-rw-r--r--crates/atuin-ai/src/tui/components/atuin_ai.rs16
1 files changed, 13 insertions, 3 deletions
diff --git a/crates/atuin-ai/src/tui/components/atuin_ai.rs b/crates/atuin-ai/src/tui/components/atuin_ai.rs
index fab29502..c04ac722 100644
--- a/crates/atuin-ai/src/tui/components/atuin_ai.rs
+++ b/crates/atuin-ai/src/tui/components/atuin_ai.rs
@@ -22,10 +22,11 @@ pub(crate) struct AtuinAi {
pub has_command: bool,
pub is_input_blank: bool,
pub pending_confirmation: bool,
+ pub has_executing_preview: bool,
}
#[derive(Default)]
-pub struct AtuinAiState {
+pub(crate) struct AtuinAiState {
tx: Option<mpsc::Sender<AiTuiEvent>>,
}
@@ -55,15 +56,24 @@ fn atuin_ai(
return EventResult::Ignored;
};
- // Ctrl+C always exits
+ // Ctrl+C — interrupt executing command or exit
if modifiers.contains(KeyModifiers::CONTROL) && *code == KeyCode::Char('c') {
- let _ = tx.send(AiTuiEvent::Exit);
+ if props.has_executing_preview {
+ let _ = tx.send(AiTuiEvent::InterruptToolExecution);
+ } else {
+ let _ = tx.send(AiTuiEvent::Exit);
+ }
return EventResult::Consumed;
}
match props.mode {
AppMode::Input => match code {
KeyCode::Esc => {
+ if props.has_executing_preview {
+ let _ = tx.send(AiTuiEvent::InterruptToolExecution);
+ return EventResult::Consumed;
+ }
+
if props.pending_confirmation {
let _ = tx.send(AiTuiEvent::CancelConfirmation);
return EventResult::Consumed;