diff --git a/codex-rs/tui/BUILD.bazel b/codex-rs/tui/BUILD.bazel index d0aab0805a..bfa3a4bbb4 100644 --- a/codex-rs/tui/BUILD.bazel +++ b/codex-rs/tui/BUILD.bazel @@ -16,6 +16,7 @@ codex_rust_crate( "//codex-rs/collaboration-mode-templates:templates/plan.md", ], test_data_extra = glob([ + "pets/assets/**", "src/**/*.rs", "src/**/snapshots/**", ]) + ["//codex-rs/core:model_availability_nux_fixtures"], diff --git a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__chatwidget_tall.snap b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__chatwidget_tall.snap index 44a143a0d0..9642be5f12 100644 --- a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__chatwidget_tall.snap +++ b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__chatwidget_tall.snap @@ -23,6 +23,6 @@ expression: normalize_snapshot_paths(term.backend().vt100().screen().contents()) ↳ Hello, world! 14 ↳ Hello, world! 15 -› Ask Codex to do anything Running - Thinking +› Ask Codex to do anything + gpt-5.5 default · /tmp/project diff --git a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__guardian_parallel_reviews_render_aggregate_status.snap b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__guardian_parallel_reviews_render_aggregate_status.snap index 04bc3e962e..653a48e949 100644 --- a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__guardian_parallel_reviews_render_aggregate_status.snap +++ b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__guardian_parallel_reviews_render_aggregate_status.snap @@ -7,6 +7,6 @@ expression: normalize_snapshot_paths(rendered) • rm -rf '/tmp/guardian target 2' -› Ask Codex to do anything Running - Thinking +› Ask Codex to do anything + gpt-5.5 default · /tmp/project diff --git a/codex-rs/tui/src/chatwidget/tests/helpers.rs b/codex-rs/tui/src/chatwidget/tests/helpers.rs index 18947c2c01..6a3ab2c462 100644 --- a/codex-rs/tui/src/chatwidget/tests/helpers.rs +++ b/codex-rs/tui/src/chatwidget/tests/helpers.rs @@ -17,6 +17,7 @@ pub(super) async fn test_config() -> Config { config.sqlite_home = codex_home.clone(); config.log_dir = codex_home.join("log"); config.cwd = PathBuf::from(test_path_display("/tmp/project")).abs(); + config.tui_pet = Some(crate::pets::DISABLED_PET_ID.to_string()); config.config_layer_stack = ConfigLayerStack::default(); config.startup_warnings.clear(); config.user_instructions = None; diff --git a/codex-rs/tui/src/chatwidget/tests/slash_commands.rs b/codex-rs/tui/src/chatwidget/tests/slash_commands.rs index 849a87a316..45517bac96 100644 --- a/codex-rs/tui/src/chatwidget/tests/slash_commands.rs +++ b/codex-rs/tui/src/chatwidget/tests/slash_commands.rs @@ -9,6 +9,10 @@ fn force_pet_image_support(chat: &mut ChatWidget) { )); } +fn enable_default_pet_for_test(chat: &mut ChatWidget) { + chat.set_tui_pet(/*pet*/ None); +} + fn force_tmux_pet_image_unsupported(chat: &mut ChatWidget) { chat.set_pet_image_support_for_tests(crate::pets::PetImageSupport::Unsupported( crate::pets::PetImageUnsupportedReason::Tmux, @@ -1807,6 +1811,7 @@ async fn slash_resume_with_arg_requests_named_session() { #[serial] async fn slash_pets_opens_picker() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); force_pet_image_support(&mut chat); chat.dispatch_command(SlashCommand::Pets); @@ -1822,6 +1827,7 @@ async fn slash_pets_opens_picker() { #[serial] async fn slash_pets_with_arg_selects_named_pet() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); force_pet_image_support(&mut chat); chat.bottom_pane diff --git a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs index 5611e09288..c1d58a6ff7 100644 --- a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs +++ b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs @@ -10,6 +10,10 @@ fn force_pet_image_support(chat: &mut ChatWidget) { )); } +fn enable_default_pet_for_test(chat: &mut ChatWidget) { + chat.set_tui_pet(/*pet*/ None); +} + /// Receiving a token usage update without usage clears the context indicator. #[tokio::test] async fn token_count_none_resets_context_indicator() { @@ -1212,6 +1216,7 @@ async fn ambient_pet_defaults_to_codex_and_anchors_to_composer_bottom() { use ratatui::layout::Rect; let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); force_pet_image_support(&mut chat); assert_eq!( chat.ambient_pet @@ -1254,6 +1259,7 @@ async fn ambient_pet_screen_bottom_anchor_uses_terminal_bottom() { use ratatui::layout::Rect; let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); force_pet_image_support(&mut chat); let terminal_area = Rect::new( @@ -1276,6 +1282,7 @@ async fn ambient_pet_screen_bottom_anchor_uses_terminal_bottom() { #[serial] async fn ambient_pet_can_be_disabled() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); chat.set_tui_pet(Some(crate::pets::DISABLED_PET_ID.to_string())); @@ -1286,6 +1293,7 @@ async fn ambient_pet_can_be_disabled() { #[serial] async fn ambient_pet_reserves_history_wrap_width() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); force_pet_image_support(&mut chat); assert_eq!(chat.history_wrap_width(/*width*/ 80), 69); @@ -1302,6 +1310,7 @@ async fn ambient_pet_reduces_stream_width_and_composer_text_width() { let (mut with_pet, _with_pet_rx, _with_pet_op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut with_pet); force_pet_image_support(&mut with_pet); with_pet.last_rendered_width.set(Some(80)); let stream_width_with_pet = with_pet.current_stream_width(/*reserved_cols*/ 2); @@ -1372,6 +1381,7 @@ async fn ambient_pet_draw_uses_terminal_screen_area_not_short_inline_viewport() use ratatui::layout::Rect; let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); force_pet_image_support(&mut chat); assert!( @@ -1404,6 +1414,7 @@ async fn ambient_pet_uses_the_app_notification_labels() { use ratatui::backend::TestBackend; let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + enable_default_pet_for_test(&mut chat); force_pet_image_support(&mut chat); for (kind, label) in [ (crate::pets::PetNotificationKind::Running, "Running"), diff --git a/codex-rs/tui/src/pets/catalog.rs b/codex-rs/tui/src/pets/catalog.rs index a4febdde46..837dc83e6b 100644 --- a/codex-rs/tui/src/pets/catalog.rs +++ b/codex-rs/tui/src/pets/catalog.rs @@ -74,8 +74,29 @@ pub(super) fn builtin_pet(id: &str) -> Option { } pub(super) fn builtin_spritesheet_path(file: &str) -> PathBuf { - Path::new(env!("CARGO_MANIFEST_DIR")) + let cargo_path = Path::new(env!("CARGO_MANIFEST_DIR")) .join("pets") .join("assets") - .join(file) + .join(file); + if cargo_path.is_file() { + return cargo_path; + } + + if let Some(bazel_package) = option_env!("BAZEL_PACKAGE") + && let Ok(current_dir) = std::env::current_dir() + { + let package = bazel_package + .strip_prefix("codex-rs/") + .unwrap_or(bazel_package); + let bazel_path = current_dir + .join(package) + .join("pets") + .join("assets") + .join(file); + if bazel_path.is_file() { + return bazel_path; + } + } + + cargo_path }