pub struct App {
pub state: UiState,
pub buf: Buffer,
pub menu: MenuState,
pub active_modal: Option<Box<dyn Modal>>,
pub message_queue: VecDeque<QueuedMessage>,
pub think: ThinkStripper,
pub pending_tools: HashMap<String, (String, String, bool)>,
pub exit_pending: Option<Instant>,
pub fixissue_pending: Option<IssueRef>,
pub fixissue_buffer: String,
pub reasoning_buffer: String,
pub setup_hint_shown: bool,
}Expand description
All the per-session UI state that flows through key/event handlers.
Before this aggregation, handlers took 7–9 &mut parameters each
and the call sites filled a paragraph. Now the handlers take
(&mut App, &mut LoopCtx, &mut dyn Renderer, …event) — the LoopCtx
stays separate because the tokio select! in run_loop needs to
borrow ctx.input_rx, ctx.runtime_event_rx, ctx.wake_rx
independently, and bundling them into App would fight the borrow
checker on every arm.
Fields§
§state: UiState§buf: Buffer§active_modal: Option<Box<dyn Modal>>Exactly one overlay at a time — /model, /provider, /resume all
push into the same slot. The Modal trait owns draw + key handling
so adding a fourth overlay is Some(Box::new(X)), not a new
field + new dispatch branch.
message_queue: VecDeque<QueuedMessage>Messages the user submitted while a turn was already running. Drained one-at-a-time from the head whenever the current turn finishes. Matches CC’s “type-ahead” UX — queue the next prompt while the model is still thinking and it fires automatically.
think: ThinkStripperStreaming-state <think>…</think> stripper. Kept on App (not
a local in the streaming arm) because it carries state across
agent events — a tag straddling two chunks would break if the
stripper were re-constructed each event.
pending_tools: HashMap<String, (String, String, bool)>call_id → (tool_name, detail, call_rendered). Populated on
ToolCallStarted, read by ApprovalNeeded (which renders the
▸ Tool(detail) line eagerly so the user sees what they’re
being asked to approve), and consumed on ToolCallResult. The
call_rendered flag prevents rendering the tool-call line
twice when ApprovalNeeded fired first.
exit_pending: Option<Instant>Timestamp of the first Ctrl+C press on an empty idle buffer.
Requires a second press within CTRL_C_EXIT_WINDOW to actually
exit — protects against accidental single-tap exits.
fixissue_pending: Option<IssueRef>Set by /fixissue <url> while the agent is resolving that issue.
On TurnComplete the text buffered in fixissue_buffer is posted
back as an issue comment + the fixed label is applied. Cleared
on TurnComplete / TurnCancelled / Error so a subsequent normal
message doesn’t accidentally trigger a post-back.
fixissue_buffer: StringAccumulates every visible AssistantText delta produced during a
fixissue turn, verbatim. Sent as the AtomGit comment body on
successful completion.
reasoning_buffer: StringAccumulates reasoning/thinking content for display in verbose mode. Flushed on newline or when buffer exceeds threshold.
setup_hint_shown: boolGuards the one-shot /setup hint so it fires at most once per
session. Flipped to true after the first render; subsequent
redraws skip the check entirely.
Auto Trait Implementations§
impl Freeze for App
impl !RefUnwindSafe for App
impl Send for App
impl !Sync for App
impl Unpin for App
impl UnsafeUnpin for App
impl !UnwindSafe for App
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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