Files
codex/codex-rs/tui/src/bottom_pane/bottom_pane_view.rs
T
Matthew Zeng 45b7763c3f [apps] Improve app loading. (#10994)
There are two concepts of apps that we load in the harness:

- Directory apps, which is all the apps that the user can install.
- Accessible apps, which is what the user actually installed and can be
$ inserted and be used by the model. These are extracted from the tools
that are loaded through the gateway MCP.

Previously we wait for both sets of apps before returning the full apps
list. Which causes many issues because accessible apps won't be
available to the UI or the model if directory apps aren't loaded or
failed to load.

In this PR we are separating them so that accessible apps can be loaded
separately and are instantly available to be shown in the UI and to be
provided in model context. We also added an app-server event so that
clients can subscribe to also get accessible apps without being blocked
on the full app list.

- [x] Separate accessible apps and directory apps loading.
- [x] `app/list` request will also emit `app/list/updated` notifications
that app-server clients can subscribe. Which allows clients to get
accessible apps list to render in the $ menu without being blocked by
directory apps.
- [x] Cache both accessible and directory apps with 1 hour TTL to avoid
reloading them when creating new threads.
- [x] TUI improvements to redraw $ menu and /apps menu when app list is
updated.
2026-02-08 15:24:56 -08:00

75 lines
2.3 KiB
Rust

use crate::bottom_pane::ApprovalRequest;
use crate::render::renderable::Renderable;
use codex_protocol::request_user_input::RequestUserInputEvent;
use crossterm::event::KeyEvent;
use super::CancellationEvent;
/// Trait implemented by every view that can be shown in the bottom pane.
pub(crate) trait BottomPaneView: Renderable {
/// Handle a key event while the view is active. A redraw is always
/// scheduled after this call.
fn handle_key_event(&mut self, _key_event: KeyEvent) {}
/// Return `true` if the view has finished and should be removed.
fn is_complete(&self) -> bool {
false
}
/// Stable identifier for views that need external refreshes while open.
fn view_id(&self) -> Option<&'static str> {
None
}
/// Handle Ctrl-C while this view is active.
fn on_ctrl_c(&mut self) -> CancellationEvent {
CancellationEvent::NotHandled
}
/// Return true if Esc should be routed through `handle_key_event` instead
/// of the `on_ctrl_c` cancellation path.
fn prefer_esc_to_handle_key_event(&self) -> bool {
false
}
/// Optional paste handler. Return true if the view modified its state and
/// needs a redraw.
fn handle_paste(&mut self, _pasted: String) -> bool {
false
}
/// Flush any pending paste-burst state. Return true if state changed.
///
/// This lets a modal that reuses `ChatComposer` participate in the same
/// time-based paste burst flushing as the primary composer.
fn flush_paste_burst_if_due(&mut self) -> bool {
false
}
/// Whether the view is currently holding paste-burst transient state.
///
/// When `true`, the bottom pane will schedule a short delayed redraw to
/// give the burst time window a chance to flush.
fn is_in_paste_burst(&self) -> bool {
false
}
/// Try to handle approval request; return the original value if not
/// consumed.
fn try_consume_approval_request(
&mut self,
request: ApprovalRequest,
) -> Option<ApprovalRequest> {
Some(request)
}
/// Try to handle request_user_input; return the original value if not
/// consumed.
fn try_consume_user_input_request(
&mut self,
request: RequestUserInputEvent,
) -> Option<RequestUserInputEvent> {
Some(request)
}
}