diff options
| author | Michelle Tilley <michelle@michelletilley.net> | 2026-04-21 15:30:46 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-21 15:30:46 -0700 |
| commit | 8dec33f5f9a972a38978b5600fde5bc292fb6401 (patch) | |
| tree | 19708731284c8ba810a5acede4720d3396f9e5a2 /crates/atuin-ai/src/fsm/tools.rs | |
| parent | fix: shell tool preview stuck as Running after completion (#3436) (diff) | |
| download | atuin-8dec33f5f9a972a38978b5600fde5bc292fb6401.zip | |
feat: shell tool execution timeouts (#3437)
Diffstat (limited to 'crates/atuin-ai/src/fsm/tools.rs')
| -rw-r--r-- | crates/atuin-ai/src/fsm/tools.rs | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/crates/atuin-ai/src/fsm/tools.rs b/crates/atuin-ai/src/fsm/tools.rs index a6b2e9ae..96348672 100644 --- a/crates/atuin-ai/src/fsm/tools.rs +++ b/crates/atuin-ai/src/fsm/tools.rs @@ -7,6 +7,15 @@ use crate::diff::{EditPreview, WritePreview}; use crate::tools::ClientToolCall; +/// Why a tool execution was interrupted. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum InterruptReason { + /// User pressed Ctrl+C or Esc during execution. + User, + /// The LLM-specified execution timeout expired. + Timeout(u64), +} + /// Per-tool lifecycle state. #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum ToolState { @@ -29,7 +38,7 @@ pub(crate) enum ToolPreviewData { Shell { lines: Vec<String>, exit_code: Option<i32>, - interrupted: bool, + interrupted: Option<InterruptReason>, }, /// File edit diff preview. Edit(EditPreview), @@ -45,6 +54,9 @@ pub(crate) struct TrackedTool { pub state: ToolState, /// Cached preview data for rendering (populated during/after execution). pub preview: Option<ToolPreviewData>, + /// Set by the FSM when it emits AbortTool, so that ToolExecutionDone + /// can distinguish user interrupts from timeouts. + pub interrupt_reason: Option<InterruptReason>, } impl TrackedTool { @@ -63,7 +75,7 @@ impl TrackedTool { }) => Some(crate::tools::ToolPreview { lines: lines.clone(), exit_code: *exit_code, - interrupted: *interrupted, + interrupted: interrupted.clone(), }), _ => None, } @@ -109,6 +121,7 @@ impl ToolManager { tool, state: ToolState::CheckingPermission, preview: None, + interrupt_reason: None, }); } |
