pub enum Action {
Show 51 variants
InsertChar(char),
Backspace,
DeleteForward,
MoveLeft,
MoveRight,
MoveHome,
MoveEnd,
Newline,
ClearComposerLine,
Submit(String),
ScrollUp,
ScrollDown,
ToggleTheme,
OpenHistorySearch,
HistorySearchType(char),
HistorySearchBackspace,
HistorySearchNext,
HistorySearchPrev,
HistorySearchConfirm,
HistorySearchCancel,
VimSetMode(VimMode),
VimMoveLeft,
VimMoveRight,
VimMoveHome,
VimMoveEnd,
VimDeleteChar,
VimDeleteLine,
RequestExternalEditor,
ExternalEditorResult(String),
ExternalEditorFailed(String),
PasteImage(String),
ShowApprovalModal(PendingApprovalRequest),
ResolveApproval(ApprovalOutcome),
ShowChildApprovalModal(PendingChildApproval),
ResolveChildApproval(ApprovalOutcome),
ShowElicitationModal(PendingElicitation),
ElicitationType(char),
ElicitationBackspace,
ResolveElicitationAccept,
ResolveElicitationDecline,
ResolveElicitationCancel,
ShowOAuthModal(PendingOAuthDisplay),
DismissOAuthModal,
AppendStreamingDelta(String),
FinalizeStreaming,
PushTranscript(TranscriptEntry),
SetModelLabel(String),
SetTurnActive(bool),
ArmQuit,
Quit,
Noop,
}Expand description
A pure description of a state transition — the output of
TuiState::handle_key and the input to TuiState::apply. Not
Clone/PartialEq-derived as a whole: the Show*Modal variants embed
a one-shot reply channel (std::sync::mpsc::Sender/
tokio::sync::oneshot::Sender, neither of which is PartialEq) — tests
assert on the resulting TuiState, not on raw Action equality.
Variants§
InsertChar(char)
Insert one character at the cursor.
Backspace
Delete the character before the cursor.
DeleteForward
Delete the character at (after) the cursor.
MoveLeft
Move the cursor one character left.
MoveRight
Move the cursor one character right.
MoveHome
Move the cursor to the start of the composer.
MoveEnd
Move the cursor to the end of the composer.
Newline
Insert a newline without submitting (multi-line composing).
ClearComposerLine
Clear the composer buffer without submitting (non-empty-line
Ctrl+C, and vim dd).
Submit(String)
The composer’s contents were submitted — apply clears the
composer, appends the text to history + the transcript. The CLI
event loop is the one that actually calls agent.send(text); it
sees this variant in handle_key’s returned Vec<Action> BEFORE
calling apply (see the module doc comment on the render layer).
ScrollUp
Scroll the transcript up one page.
ScrollDown
Scroll the transcript down one page.
ToggleTheme
Toggle the dark/light theme.
OpenHistorySearch
Enter Ctrl+R cross-session prompt-history search.
HistorySearchType(char)
Type one character into the history-search query.
HistorySearchBackspace
Delete the last character of the history-search query.
HistorySearchNext
Select the next (older) matching history entry.
HistorySearchPrev
Select the previous (more recent) matching history entry.
HistorySearchConfirm
Accept the selected history entry into the composer.
HistorySearchCancel
Leave history search without changing the composer.
VimSetMode(VimMode)
Switch vim sub-mode (Normal/Insert).
VimMoveLeft
Vim h — move left.
VimMoveRight
Vim l — move right.
VimMoveHome
Vim 0 — move to line start.
VimMoveEnd
Vim $ — move to line end.
VimDeleteChar
Vim x — delete the character under the cursor.
VimDeleteLine
Vim dd (approximated as one keystroke — see VimMode’s doc
comment) — clear the composer line.
RequestExternalEditor
The CLI layer should shell out to $EDITOR — apply only flips a
flag (TuiState::external_editor_requested); the actual process
spawn is terminal I/O, out of the view-model’s scope.
ExternalEditorResult(String)
The CLI layer’s $EDITOR invocation finished — replaces the
composer with the edited text.
ExternalEditorFailed(String)
F9 (Fable-5 adversarial review — LOW): the CLI layer’s $EDITOR
invocation failed to spawn (editor not found, exec error, …) —
clears TuiState::external_editor_requested (same as
ExternalEditorResult, so run_loop doesn’t keep retrying it
every tick) WITHOUT touching the composer, and surfaces message
as a system transcript notice so the session stays alive and the
user actually sees why nothing happened, instead of the whole TUI
process exiting out from under them.
PasteImage(String)
An image was pasted/attached (path or a data reference) — appended
to the composer as a placeholder token and recorded in
TuiState::pending_images for the CLI layer to route into the
multimodal read path.
ShowApprovalModal(PendingApprovalRequest)
A new top-level Ask-tier approval request arrived — show (or
queue) it as a modal.
ResolveApproval(ApprovalOutcome)
The user resolved the active approval modal.
ShowChildApprovalModal(PendingChildApproval)
A new background-child approval request arrived — show (or queue) it as a modal.
ResolveChildApproval(ApprovalOutcome)
The user resolved the active child-approval modal.
ShowElicitationModal(PendingElicitation)
A new MCP elicitation request arrived — show (or queue) it as a modal.
ElicitationType(char)
Type one character into the elicitation answer buffer.
ElicitationBackspace
Delete the last character of the elicitation answer buffer.
ResolveElicitationAccept
Accept the elicitation with the typed answer.
ResolveElicitationDecline
Decline the elicitation.
ResolveElicitationCancel
Cancel/dismiss the elicitation without a decision.
ShowOAuthModal(PendingOAuthDisplay)
A new OAuth device-code display arrived — show (or queue) it.
DismissOAuthModal
Dismiss the OAuth device-code modal (no reply — see
PendingOAuthDisplay’s doc comment).
AppendStreamingDelta(String)
A chunk of streaming assistant text arrived.
FinalizeStreaming
The in-progress streaming turn is done — move it into the transcript.
PushTranscript(TranscriptEntry)
Append one entry directly to the transcript (tool events, system notices raised outside a modal resolution).
SetModelLabel(String)
Update the status line’s model label.
SetTurnActive(bool)
Update the status line’s turn-in-flight indicator.
ArmQuit
First Ctrl+C on an empty, non-modal composer — arms the “press again to exit” notice without quitting yet.
Quit
Second consecutive Ctrl+C — actually quit.
Noop
A key the current focus/modal doesn’t bind to anything — carries no
mutation; apply is a no-op for it. handle_key prefers returning
an empty Vec over this where possible; it exists for the rare
case a caller wants an explicit “nothing happened” marker (e.g. a
disabled modal option).