diff options
| author | Michelle Tilley <michelle@michelletilley.net> | 2026-04-14 16:03:08 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-15 00:03:08 +0100 |
| commit | fd188da879d977ca847f10708c39dd4801a204c4 (patch) | |
| tree | 592bfe2644f8bd9be3563f176eabf29e55fa9a9b /crates/atuin-ai/src/tui/components/input_box.rs | |
| parent | fix: dependency fix (#3414) (diff) | |
| download | atuin-fd188da879d977ca847f10708c39dd4801a204c4.zip | |
feat: Allow resuming previous AI sessions (#3407)
This PR introduces session continuation to Atuin AI.
* Conversations with Atuin AI are stored in a local SQLite database
* Upon startup, Atuin AI tries to find a session to resume based on its
directory/workspace and the time since the last event
* If found, Atuin AI will show a note that the session has been resumed,
and an event is added to help the LLM know where the invocation
boundaries are
* If not, Atuin AI will create a new conversation
* The user can create a new conversation with `/new`
* The new setting `ai.session_continue_minutes`, which defaults to `60`,
controls how old the last event in a session can be before it's no
longer considered for automatic resuming.
<img width="1055" height="593" alt="image"
src="https://github.com/user-attachments/assets/3f9ff01a-ef64-44a9-b0e2-3a4252c5746f"
/>
## Architecture
A new `SessionService` trait defines an API contract for a service that
can manage session data. `LocalSessionService` implements this, with
`DaemonSessionService` a possible future extension point.
`SessionManager` owns a `dyn SessionService` and delegates as
appropriate.
Diffstat (limited to 'crates/atuin-ai/src/tui/components/input_box.rs')
| -rw-r--r-- | crates/atuin-ai/src/tui/components/input_box.rs | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/crates/atuin-ai/src/tui/components/input_box.rs b/crates/atuin-ai/src/tui/components/input_box.rs index f5e0fe2b..6e041418 100644 --- a/crates/atuin-ai/src/tui/components/input_box.rs +++ b/crates/atuin-ai/src/tui/components/input_box.rs @@ -19,7 +19,7 @@ use ratatui_core::{ }; use tui_textarea::TextArea; -use crate::tui::events::AiTuiEvent; +use crate::tui::{events::AiTuiEvent, slash::SlashCommandSearchResult}; /// A bordered text input box backed by tui-textarea. /// @@ -35,6 +35,8 @@ pub(crate) struct InputBox { pub footer: String, /// Whether the input is currently active (shows cursor, accepts input) pub active: bool, + /// If the user has typed a slash command, this holds the best match for it. + pub slash_suggestion: Option<SlashCommandSearchResult>, } pub(crate) struct InputBoxState { @@ -129,6 +131,18 @@ fn input_box( textarea.insert_newline(); return EventResult::Consumed; } + crossterm::event::KeyCode::Tab if props.slash_suggestion.is_some() => { + // If there's a slash command suggestion, Tab accepts it. + if let Some(suggestion) = &props.slash_suggestion { + textarea.clear(); + textarea.insert_str(format!("/{}", suggestion.command.name)); + // Manually trigger an input update event so the slash suggestion box can update immediately + if let Some(ref tx) = state.tx { + let _ = tx.send(AiTuiEvent::InputUpdated(textarea.lines().join("\n"))); + } + return EventResult::Consumed; + } + } crossterm::event::KeyCode::Enter => { if key.modifiers.contains(KeyModifiers::SHIFT) { textarea.insert_newline(); |
