Skip to main content

App

Struct App 

Source
pub struct App {
Show 38 fields pub prompt: PromptInputState, pub blocks: Vec<TranscriptBlock>, pub should_quit: bool, pub session_id: Option<String>, pub connected: bool, pub scroll_offset: u16, pub screen: AppScreen, pub start_time: Instant, pub usage: UsageStats, pub turn: TurnState, pub turn_count: u64, pub pending_latency_ms: Option<u64>, pub model_name: String, pub spinner_frame: usize, pub modals: Vec<Modal>, pub commands: CommandRegistry, pub tool_catalog: Vec<(String, String)>, pub command_menu_selected: Option<usize>, pub planning_mode_on: bool, pub plan_awaiting_approval: bool, pub plan_mode_request_pending: bool, pub double_press: DoublePressTracker, pub atfile_query: String, pub atfile_suggestions: Vec<String>, pub atfile_selected: Option<usize>, pub hsearch_query: String, pub hsearch_matches: Vec<usize>, pub hsearch_selected: usize, pub pending_permission: Option<PendingPermission>, pub auto_allowed_tools: HashSet<String>, pub permission_hook_enabled: Arc<AtomicBool>, pub current_todos: Vec<TodoItem>, pub active_goal: Option<GoalState>, pub workspace_path: PathBuf, pub theme: &'static Theme, pub last_printed_idx: usize, pub print_queue: Vec<Vec<Line<'static>>>, pub modal_scroll: u16,
}

Fields§

§prompt: PromptInputState

Multi-mode input state (Goal 145).

§blocks: Vec<TranscriptBlock>§should_quit: bool§session_id: Option<String>§connected: bool§scroll_offset: u16§screen: AppScreen§start_time: Instant

Tracks when the TUI session started. Used by /status to report uptime.

§usage: UsageStats§turn: TurnState§turn_count: u64§pending_latency_ms: Option<u64>§model_name: String§spinner_frame: usize§modals: Vec<Modal>

Goal-146: stack of overlay modals. The topmost (last) modal receives keys; an empty stack means chat keys are active.

§commands: CommandRegistry

Goal-146: registry of /-prefixed slash commands. Lazily initialised in App::new with [CommandRegistry::default_set].

§tool_catalog: Vec<(String, String)>

Goal-146: list of tools the runtime has registered. Populated by main.rs from Backend::tool_specs() after the worker boots, and read by the /tools command. Defaults to a static list when running offline.

§command_menu_selected: Option<usize>

Goal-146: cursor / selected index into the command-menu completion popup. None means the user hasn’t navigated (Enter executes the literal buffer).

§planning_mode_on: bool

Goal-146: planning-mode flag mirrored on the UI side. Reflects the latest /plan on|off invocation. Used to render an indicator and to seed /status.

§plan_awaiting_approval: bool

Set when the agent has proposed a plan via exit_plan_mode and we are waiting for the user to approve or reject it. Cleared by PlanConfirmed / PlanRejected events. Used to show a status-bar indicator so the user knows input is expected.

§plan_mode_request_pending: bool

Goal-202: set when the agent has called request_plan_mode and we are waiting for the user to allow or skip planning. Cleared by PlanModeApproved / PlanModeRejected events.

§double_press: DoublePressTracker

Goal-147: tracks the most recent Esc / Ctrl+C presses so the second press within double_press_window can promote a soft action (interrupt / clear) into a real exit. See App::handle_key.

§atfile_query: String

The text the user has typed after @ while in AtFile mode.

§atfile_suggestions: Vec<String>

Candidate file paths matching [atfile_query]. Refreshed on every keystroke in AtFile mode. Contains at most MAX_ATFILE_SUGGESTIONS entries.

§atfile_selected: Option<usize>

Currently highlighted row in the AtFile popup. None means nothing is highlighted yet (typing narrows the list).

§hsearch_query: String

Current search query in HistorySearch mode.

§hsearch_matches: Vec<usize>

Indices into prompt.history that match [hsearch_query], in priority order (prefix matches first). Capped at MAX_HSEARCH_RESULTS.

§hsearch_selected: usize

Currently highlighted row in the history-search popup.

§pending_permission: Option<PendingPermission>

A pending tool-permission request delivered from the backend worker via the side-channel. None means no permission dialog is open. When Some, the modal is rendered and all keys are routed to handle_permission_key.

§auto_allowed_tools: HashSet<String>

Set of tool names the user has chosen to “Allow All” for the current session. Requests for these tools skip the modal.

§permission_hook_enabled: Arc<AtomicBool>

Whether the runtime permission hook is currently active. Toggled by /permissions on|off. Shared with the backend worker.

§current_todos: Vec<TodoItem>

Goal-167: current task list maintained by todo_write calls. Empty when no task list has been set this session.

§active_goal: Option<GoalState>

Goal-168: mirrored goal state, updated by UiEvent::Goal* events.

§workspace_path: PathBuf

Goal-171: workspace root path, used by /resume to list sessions.

§theme: &'static Theme

Goal-174: active colour palette. Defaults to [DARK]; switchable via /theme <name> without restart.

§last_printed_idx: usize

Blocks from self.blocks[0..last_printed_idx] have already been flushed to the terminal’s scrollback buffer via terminal.insert_before(). The inline viewport only renders blocks at index >= last_printed_idx (in-flight content).

§print_queue: Vec<Vec<Line<'static>>>

Queue of rendered lines waiting to be pushed to the scrollback buffer in the next event-loop iteration. Drained by the main loop using terminal.insert_before().

§modal_scroll: u16

Vertical scroll offset (in lines) for the currently-active modal. Reset to 0 whenever a new modal is pushed. For list-based modals (ResumePicker, McpServers, Journal) the key handler auto-updates this to keep the selection visible.

Implementations§

Source§

impl App

Source

pub fn handle_key(&mut self, key: KeyEvent) -> Option<UserAction>

Process one key event. Returns an optional UserAction that the caller must forward to the backend worker.

Source

pub fn handle_command_menu_key( &mut self, key: KeyEvent, ) -> Option<Option<UserAction>>

Handle a key in command-completion-menu context. Returns Some(action) (with action itself optional) if the key was consumed; the outer None means “fall through to the regular chat key path”.

Source

pub fn handle_atfile_key(&mut self, key: KeyEvent) -> Option<UserAction>

Handle a key when InputMode::AtFile is active.

Source

pub fn handle_history_search_key(&mut self, key: KeyEvent) -> Option<UserAction>

Handle a key when InputMode::HistorySearch is active.

Source

pub fn handle_permission_key(&mut self, key: KeyEvent) -> Option<UserAction>

Handle a key while a permission modal is active.

  • y / Y / Enter → allow once
  • n / N / Esc → deny
  • a / A → allow + add tool to auto-allow list
Source

pub fn handle_modal_key_action(&mut self, key: KeyEvent) -> Option<UserAction>

Handle a key event when at least one modal is on the stack. Returns Some(action) if the modal layer wants to forward a UserAction to the backend (currently only the PlanReview modal does this). The outer key dispatcher should not also process this key against the chat layer.

Source

pub fn handle_modal_key(&mut self, key: KeyEvent) -> bool

Handle a key event when at least one modal is on the stack. Returns true if the key was consumed by the modal layer (so the caller should skip the chat key path).

Source§

impl App

Source

pub fn handle_ui_event(&mut self, event: UiEvent)

Apply an event coming from the backend worker.

Source

pub fn flush_ready_blocks(&mut self)

Scan blocks[last_printed_idx..] and push any “finalized” blocks into print_queue so the main loop can flush them to the terminal’s scrollback buffer via terminal.insert_before().

A block is considered finalized when:

  • User — always
  • Assistant — when !streaming
  • ToolCall — when result.is_some()
  • Reasoning — only when the immediately following block is NOT a streaming Assistant (prevents the reasoning from being separated from its answer in the scrollback)
  • All other variants — always

This is idempotent and safe to call after every event.

Source§

impl App

Source

pub fn new() -> Self

Source

pub fn push_modal(&mut self, modal: Modal)

Push a modal onto the stack and reset the modal scroll to the top.

Source

pub fn input(&self) -> &str

Backwards-compat shim for legacy code paths that still expect a single input string. Reads the prompt buffer.

Source

pub fn set_input<S: Into<String>>(&mut self, value: S)

Replace the prompt buffer (used by PlanReview’s e-edit path and a handful of unit tests). Resets cursor to end and mode to Prompt.

Source

pub fn scroll_to_bottom(&mut self)

Source

pub fn push_system(&mut self, text: impl Into<String>)

Push a System block onto the transcript and scroll to bottom. Public so [crate::commands] handlers can use it directly.

Source

pub fn push_error(&mut self, text: impl Into<String>)

Push an Error block onto the transcript and scroll to bottom.

Source

pub fn reset_transcript(&mut self)

Reset the transcript to a single fresh welcome block and zero out per-session usage. Called by /clear.

Source

pub fn set_pending_permission(&mut self, req: PermissionRequest)

Receive a pending permission request from the backend side-channel. Auto-allow if the tool is in the auto_allowed_tools set; otherwise store it so the UI can display the modal on the next render.

Trait Implementations§

Source§

impl Default for App

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for App

§

impl !UnwindSafe for App

§

impl Freeze for App

§

impl Send for App

§

impl Sync for App

§

impl Unpin for App

§

impl UnsafeUnpin for App

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more