Overlap plugin and model discovery during startup

This commit is contained in:
Charlie Marsh
2026-06-04 17:46:24 -04:00
parent 409e0170dd
commit 78ae0c5dfa
5 changed files with 63 additions and 14 deletions
+9 -4
View File
@@ -16,6 +16,7 @@ use crate::app_event::RealtimeAudioDeviceKind;
#[cfg(target_os = "windows")]
use crate::app_event::WindowsSandboxEnableMode;
use crate::app_event_sender::AppEventSender;
use crate::app_server_session::AppServerBootstrap;
use crate::app_server_session::AppServerSession;
use crate::app_server_session::AppServerStartedThread;
use crate::app_server_session::TurnPermissionsOverride;
@@ -727,6 +728,8 @@ impl App {
app_server_target: AppServerTarget,
state_db: Option<StateDbHandle>,
environment_manager: Arc<EnvironmentManager>,
startup_elapsed_before_app: Duration,
startup_bootstrap: Option<AppServerBootstrap>,
startup_hooks_browser: Option<HooksListEntry>,
) -> Result<AppExitInfo> {
use tokio_stream::StreamExt;
@@ -774,9 +777,11 @@ impl App {
});
}
};
let bootstrap_started_at = Instant::now();
let bootstrap = app_server.bootstrap(&config).await?;
let bootstrap_ms = bootstrap_started_at.elapsed().as_millis();
let bootstrap = match startup_bootstrap {
Some(bootstrap) => bootstrap,
None => app_server.bootstrap(&config).await?,
};
let bootstrap_ms = bootstrap.duration.as_millis();
let mut model = bootstrap.default_model;
let available_models = bootstrap.available_models;
let remote_connection = crate::status::remote_connection::remote_connection_status_value(
@@ -1085,7 +1090,7 @@ See the Codex keymap documentation for supported actions and examples."
tui.frame_requester().schedule_frame();
tracing::info!(
duration_ms = %startup_started_at.elapsed().as_millis(),
duration_ms = %(startup_elapsed_before_app + startup_started_at.elapsed()).as_millis(),
bootstrap_ms = %bootstrap_ms,
runtime_model_provider_ms = %runtime_model_provider_ms,
thread_and_widget_ms = %thread_and_widget_ms,
+5
View File
@@ -127,6 +127,8 @@ use color_eyre::eyre::Result;
use color_eyre::eyre::WrapErr;
use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Duration;
use std::time::Instant;
use uuid::Uuid;
const JSONRPC_INVALID_REQUEST: i64 = -32600;
@@ -150,6 +152,7 @@ fn is_thread_settings_update_unsupported(source: &JSONRPCErrorError) -> bool {
/// fetched asynchronously after bootstrap returns so that the TUI can render
/// its first frame without waiting for the rate-limit round-trip.
pub(crate) struct AppServerBootstrap {
pub(crate) duration: Duration,
pub(crate) account_email: Option<String>,
pub(crate) auth_mode: Option<TelemetryAuthMode>,
pub(crate) status_account_display: Option<StatusAccountDisplay>,
@@ -239,6 +242,7 @@ impl AppServerSession {
}
pub(crate) async fn bootstrap(&mut self, config: &Config) -> Result<AppServerBootstrap> {
let started_at = Instant::now();
let account = self.read_account().await?;
let model_request_id = self.next_request_id();
let models: ModelListResponse = self
@@ -314,6 +318,7 @@ impl AppServerSession {
None => (None, None, None, None, FeedbackAudience::External, false),
};
Ok(AppServerBootstrap {
duration: started_at.elapsed(),
account_email,
auth_mode,
status_account_display,
@@ -25,7 +25,7 @@ pub(crate) enum ExternalAgentConfigMigrationStartupOutcome {
ExitRequested,
}
fn should_show_external_agent_config_migration_prompt(
pub(crate) fn should_show_external_agent_config_migration_prompt(
config: &Config,
entered_trust_nux: bool,
) -> bool {
+26
View File
@@ -71,6 +71,7 @@ use std::fs::OpenOptions;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Instant;
pub use token_usage::TokenUsage;
use tracing::Level;
use tracing::error;
@@ -276,6 +277,7 @@ pub(crate) mod test_support;
use crate::onboarding::onboarding_screen::OnboardingScreenArgs;
use crate::onboarding::onboarding_screen::run_onboarding_app;
use crate::startup_hooks_review::StartupHooksReviewOutcome;
use crate::startup_hooks_review::load_startup_hooks_review_entry;
use crate::startup_hooks_review::maybe_run_startup_hooks_review;
use crate::tui::Tui;
pub use cli::Cli;
@@ -1781,11 +1783,33 @@ async fn run_ratatui_app(
resume_picker::SessionSelection::Resume(_)
);
let bypass_hook_trust_for_startup_review = config.bypass_hook_trust && !is_persistent_resume;
let hooks_request_handle = app_server.request_handle();
let hooks_cwd = config.cwd.to_path_buf();
let startup_prefetch_started_at = Instant::now();
let should_defer_bootstrap =
external_agent_config_migration_startup::should_show_external_agent_config_migration_prompt(
&config,
should_show_trust_screen_flag,
);
let (startup_bootstrap, startup_hooks_entry) = if should_defer_bootstrap {
(
None,
load_startup_hooks_review_entry(hooks_request_handle, hooks_cwd).await,
)
} else {
let (bootstrap, entry) = tokio::join!(
app_server.bootstrap(&config),
load_startup_hooks_review_entry(hooks_request_handle, hooks_cwd),
);
(Some(bootstrap?), entry)
};
let startup_elapsed_before_app = startup_prefetch_started_at.elapsed();
let startup_hooks_browser = match maybe_run_startup_hooks_review(
&mut app_server,
&mut tui,
&config,
bypass_hook_trust_for_startup_review,
startup_hooks_entry,
)
.await?
{
@@ -1810,6 +1834,8 @@ async fn run_ratatui_app(
app_server_target,
state_db,
environment_manager,
startup_elapsed_before_app,
startup_bootstrap,
startup_hooks_browser,
)
.await;
+22 -9
View File
@@ -28,7 +28,9 @@ use crate::render::renderable::ColumnRenderable;
use crate::render::renderable::Renderable;
use crate::tui::Tui;
use crate::tui::TuiEvent;
use codex_app_server_client::AppServerRequestHandle;
use codex_app_server_protocol::HooksListEntry;
use std::path::PathBuf;
pub(crate) enum StartupHooksReviewOutcome {
Continue,
@@ -42,21 +44,32 @@ enum StartupHooksReviewSelection {
ContinueWithoutTrusting,
}
pub(crate) async fn load_startup_hooks_review_entry(
request_handle: AppServerRequestHandle,
cwd: PathBuf,
) -> HooksListEntry {
let response = match fetch_hooks_list(request_handle, cwd.clone()).await {
Ok(response) => response,
Err(err) => {
tracing::warn!("failed to load startup hook review state: {err:#}");
return HooksListEntry {
cwd,
hooks: Vec::new(),
warnings: Vec::new(),
errors: Vec::new(),
};
}
};
hooks_list_entry_for_cwd(response, &cwd)
}
pub(crate) async fn maybe_run_startup_hooks_review(
app_server: &mut AppServerSession,
tui: &mut Tui,
config: &Config,
bypass_hook_trust: bool,
entry: HooksListEntry,
) -> Result<StartupHooksReviewOutcome> {
let cwd = config.cwd.to_path_buf();
let response = match fetch_hooks_list(app_server.request_handle(), cwd.clone()).await {
Ok(response) => response,
Err(err) => {
tracing::warn!("failed to load startup hook review state: {err:#}");
return Ok(StartupHooksReviewOutcome::Continue);
}
};
let entry = hooks_list_entry_for_cwd(response, &cwd);
if !review_is_needed(bypass_hook_trust, &entry) {
return Ok(StartupHooksReviewOutcome::Continue);
}