mirror of
https://github.com/openai/codex.git
synced 2026-10-31 19:28:49 +00:00
Add local image thumbnails to the TUI composer (#58261)
## What changed - Show draft attachment thumbnails in reference order in inline and fullscreen views on supported terminals with local workspaces. Display a `+N` count for attachments that do not fit, and preserve editable image references when previews are unavailable or space is limited. - Refresh previews when attached files change, apply image orientation metadata, and clear frame graphics before terminal handoffs, screen switches, and shutdown. - Finish CLI subcommand dispatch before polling interactive TUI events. ## Testing Add a regression test and snapshot covering thumbnail order, overflow, resizing, attachment deletion, file replacement, and fallback behavior in both inline and fullscreen views. GitOrigin-RevId: 1ea7c89e089cecc390e145c1790b6ede8bad8d5e
This commit is contained in:
+35
-37
@@ -1036,16 +1036,18 @@ fn main() -> anyhow::Result<()> {
|
||||
codex_build_info::initialize!();
|
||||
let remote_control_disabled = codex_app_server::take_remote_control_disabled_env();
|
||||
arg0_dispatch_or_else(move |arg0_paths: Arg0DispatchPaths| async move {
|
||||
// Keep the CLI dispatcher off the runtime's stack while the TUI rebuilds a thread.
|
||||
Box::pin(cli_main(arg0_paths, remote_control_disabled)).await?;
|
||||
// Finish polling the large subcommand dispatcher before polling interactive TUI events.
|
||||
if let Some(tui) = Box::pin(dispatch_cli(arg0_paths, remote_control_disabled)).await? {
|
||||
tui.await?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
async fn cli_main(
|
||||
async fn dispatch_cli(
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
remote_control_disabled: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
) -> anyhow::Result<Option<impl Future<Output = anyhow::Result<()>>>> {
|
||||
let MultitoolCli {
|
||||
config_overrides: mut root_config_overrides,
|
||||
feature_toggles,
|
||||
@@ -1097,6 +1099,11 @@ async fn cli_main(
|
||||
profile_v2_for_subcommand(&interactive, subcommand)?;
|
||||
}
|
||||
|
||||
let launch_tui = move |interactive, remote, auth_token_env, arg0_paths| async move {
|
||||
let exit_info =
|
||||
run_interactive_tui(interactive, remote, auth_token_env, arg0_paths).await?;
|
||||
handle_app_exit(exit_info, daemon_cli_executable.as_deref())
|
||||
};
|
||||
let open_agents_overview = matches!(&subcommand, Some(Subcommand::Agents(_)));
|
||||
match subcommand {
|
||||
None | Some(Subcommand::Agents(_)) => {
|
||||
@@ -1129,17 +1136,15 @@ async fn cli_main(
|
||||
}
|
||||
interactive.agents_overview = true;
|
||||
}
|
||||
let exit_info = run_interactive_tui(
|
||||
return Ok(Some(launch_tui(
|
||||
interactive,
|
||||
root_remote.clone(),
|
||||
root_remote_auth_token_env.clone(),
|
||||
arg0_paths.clone(),
|
||||
)
|
||||
.await?;
|
||||
handle_app_exit(exit_info, daemon_cli_executable.as_deref())?;
|
||||
root_remote,
|
||||
root_remote_auth_token_env,
|
||||
arg0_paths,
|
||||
)));
|
||||
}
|
||||
Some(Subcommand::TcpTunnel(args)) => {
|
||||
return codex_tcp_tunnel::run(args).await;
|
||||
codex_tcp_tunnel::run(args).await?;
|
||||
}
|
||||
Some(Subcommand::Exec(mut exec_cli)) => {
|
||||
reject_remote_mode_for_subcommand(
|
||||
@@ -1252,15 +1257,15 @@ async fn cli_main(
|
||||
subcommand.is_none(),
|
||||
"--print-startup-config cannot run a subcommand"
|
||||
);
|
||||
return codex_app_server::print_startup_config(
|
||||
codex_app_server::print_startup_config(
|
||||
arg0_paths,
|
||||
root_config_overrides,
|
||||
LoaderOverrides::default(),
|
||||
strict_config,
|
||||
startup_config,
|
||||
)
|
||||
.await
|
||||
.map_err(Into::into);
|
||||
.await?;
|
||||
return Ok(None);
|
||||
}
|
||||
match subcommand {
|
||||
None => {
|
||||
@@ -1405,7 +1410,7 @@ async fn cli_main(
|
||||
AppServerDaemonSubcommand::PidUpdateLoop {
|
||||
check_package_ownership: true,
|
||||
..
|
||||
} => return Ok(()),
|
||||
} => return Ok(None),
|
||||
AppServerDaemonSubcommand::Update {
|
||||
from_cli: false, ..
|
||||
}
|
||||
@@ -1528,16 +1533,12 @@ async fn cli_main(
|
||||
include_non_interactive,
|
||||
config_overrides,
|
||||
);
|
||||
let exit_info = run_interactive_tui(
|
||||
return Ok(Some(launch_tui(
|
||||
interactive,
|
||||
remote.remote.or(root_remote.clone()),
|
||||
remote
|
||||
.remote_auth_token_env
|
||||
.or(root_remote_auth_token_env.clone()),
|
||||
arg0_paths.clone(),
|
||||
)
|
||||
.await?;
|
||||
handle_app_exit(exit_info, daemon_cli_executable.as_deref())?;
|
||||
remote.remote.or(root_remote),
|
||||
remote.remote_auth_token_env.or(root_remote_auth_token_env),
|
||||
arg0_paths,
|
||||
)));
|
||||
}
|
||||
Some(Subcommand::Archive(cmd)) => {
|
||||
let output = run_session_archive_cli_command(
|
||||
@@ -1628,16 +1629,12 @@ async fn cli_main(
|
||||
all,
|
||||
config_overrides,
|
||||
);
|
||||
let exit_info = run_interactive_tui(
|
||||
return Ok(Some(launch_tui(
|
||||
interactive,
|
||||
remote.remote.or(root_remote.clone()),
|
||||
remote
|
||||
.remote_auth_token_env
|
||||
.or(root_remote_auth_token_env.clone()),
|
||||
arg0_paths.clone(),
|
||||
)
|
||||
.await?;
|
||||
handle_app_exit(exit_info, daemon_cli_executable.as_deref())?;
|
||||
remote.remote.or(root_remote),
|
||||
remote.remote_auth_token_env.or(root_remote_auth_token_env),
|
||||
arg0_paths,
|
||||
)));
|
||||
}
|
||||
Some(Subcommand::Login(mut login_cli)) => {
|
||||
reject_remote_mode_for_subcommand(
|
||||
@@ -1762,7 +1759,7 @@ async fn cli_main(
|
||||
.parse_overrides()
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
sandbox_setup::run(setup_cli, config_profile.cloned(), cli_overrides).await?;
|
||||
return Ok(());
|
||||
return Ok(None);
|
||||
}
|
||||
reject_remote_mode_for_subcommand(
|
||||
root_remote.as_deref(),
|
||||
@@ -1770,7 +1767,8 @@ async fn cli_main(
|
||||
"sandbox",
|
||||
)?;
|
||||
if let Some(SandboxSubcommand::Uninstall(command)) = subcommand {
|
||||
return command.run();
|
||||
command.run()?;
|
||||
return Ok(None);
|
||||
}
|
||||
let loader_overrides = loader_overrides_for_profile(config_profile)?;
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -1950,7 +1948,7 @@ async fn cli_main(
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn profile_v2_for_subcommand<'a>(
|
||||
|
||||
Reference in New Issue
Block a user