fix(tui): make topbar route segment interactive - #5763
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @Hmbown's task in 3m 10s —— View job Review: fix(tui): make topbar route segment interactiveSummary: This is a clean, well-scoped fix. It correctly unifies the topbar's route/model segment click (and new Correctness
Provider/model/route safety (EPIC #2608 invariant)No violation. The picker itself remains the sole authority for catalog/readiness/apply; the topbar and Reuse/simplification
TestsThe new tests are appropriately targeted: SecurityNo secret handling, shell/exec, or input-validation surface touched. Note: I was not able to run |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 55fb926277
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| route: hitboxes | ||
| .iter() | ||
| .find(|hitbox| hitbox.id == TopbarSegmentId::Model) | ||
| .map(|hitbox| hitbox.area), |
There was a problem hiding this comment.
Derive the route target from the shed layout
When an active Run, Pod, or Whales segment is removed at narrower widths, Topbar::render moves the Model segment left using shed_pass, but topbar_hitboxes() still positions it after every original segment. Taking the route rectangle from that list therefore registers HEADER_ROUTE over the wrong cells: clicking the painted route can do nothing, while clicking cells to its right can unexpectedly open the provider picker. Compute the interaction rectangle from the same kept-segment geometry used for rendering.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Codewhale review
PR makes the topbar route/model segment interactive by click or F3 and delegates to the existing provider picker through a new shared helper. The design direction is sound, but the diff appears to call the new helper from sibling modules without importing it, and the new ViewEvent/F3 routing path is only partially tested.
Findings
- [ERROR]
open_provider_pickermay be unresolved inhandlers.rs(crates/tui/src/tui/ui/handlers.rs:1913)
The newViewEvent::TopbarRoutePickerRequestedarm callsopen_provider_picker, but that helper is defined in the siblingoverlaysmodule. This diff does not add an import for it. Unless the file already has a glob import such asuse super::overlays::*, this will fail to compile with an unresolved-name error. - [ERROR]
open_provider_pickermay be unresolved inapply.rs(crates/tui/src/tui/ui/apply.rs:1719)
AppAction::OpenProviderPickernow callsopen_provider_picker, but the helper is defined in the siblingoverlaysmodule and no new import is added in the diff. Without an existing glob or re-export import, this will fail to compile. - [INFO]
TopbarRoutePickerRequestedhandler is not directly tested (crates/tui/src/tui/ui/handlers.rs:1913)
The PR tests that a mouse click emitsTopbarRoutePickerRequestedand that F3 is recognized, but there is no test asserting thathandle_view_eventsactually handles this variant by opening the provider picker. A regression in this arm could otherwise go unnoticed. - [INFO] F3 event-loop routing is not directly tested (
crates/tui/src/tui/ui/event_loop.rs)
The new F3 branch inrun_event_loopis central to the keyboard entry point, but the added tests only coveris_provider_route_shortcut. There is no test proving that an F3 key event with an empty view stack dispatchesTopbarRoutePickerRequestedand continues without leaking into launch-surface key handling.
Suggestions
-
crates/tui/src/tui/ui/handlers.rs:1913— Use the fully qualified path to the new sibling helper; the diff adds this call without a correspondinguse, so the unqualified name may not resolve.crate::tui::ui::overlays::open_provider_picker(app, config, engine_handle).await; -
crates/tui/src/tui/ui/apply.rs:1719— Use the fully qualified path to the new sibling helper; the diff adds this call without a correspondinguse, so the unqualified name may not resolve.crate::tui::ui::overlays::open_provider_picker(app, config, engine_handle).await;
Assessment
The PR cleanly consolidates provider-picker opening and makes the topbar route segment truthful. Before merge, confirm that the new open_provider_picker helper resolves in both call sites and add direct coverage for the ViewEvent and F3 event-loop dispatch paths.
Advisory review by Codewhale (codewhale review --pr 5763 --post, head 55fb926277f274ccf801048f3848676ec6a12575). Line-specific findings are also posted as inline review comments; mechanical fixes arrive as committable suggestions you can apply from the Files tab. CODEOWNERS approval still governs merge.
| app.needs_redraw = true; | ||
| } | ||
| ViewEvent::TopbarRoutePickerRequested => { | ||
| open_provider_picker(app, config, engine_handle).await; |
There was a problem hiding this comment.
[ERROR] open_provider_picker may be unresolved in handlers.rs
The new ViewEvent::TopbarRoutePickerRequested arm calls open_provider_picker, but that helper is defined in the sibling overlays module. This diff does not add an import for it. Unless the file already has a glob import such as use super::overlays::*, this will fail to compile with an unresolved-name error.
| .with_provider_health(&app.provider_health), | ||
| ); | ||
| } | ||
| open_provider_picker(app, config, engine_handle).await; |
There was a problem hiding this comment.
[ERROR] open_provider_picker may be unresolved in apply.rs
AppAction::OpenProviderPicker now calls open_provider_picker, but the helper is defined in the sibling overlays module and no new import is added in the diff. Without an existing glob or re-export import, this will fail to compile.
| app.needs_redraw = true; | ||
| } | ||
| ViewEvent::TopbarRoutePickerRequested => { | ||
| open_provider_picker(app, config, engine_handle).await; |
There was a problem hiding this comment.
[INFO] TopbarRoutePickerRequested handler is not directly tested
The PR tests that a mouse click emits TopbarRoutePickerRequested and that F3 is recognized, but there is no test asserting that handle_view_events actually handles this variant by opening the provider picker. A regression in this arm could otherwise go unnoticed.
| app.needs_redraw = true; | ||
| } | ||
| ViewEvent::TopbarRoutePickerRequested => { | ||
| open_provider_picker(app, config, engine_handle).await; |
There was a problem hiding this comment.
Use the fully qualified path to the new sibling helper; the diff adds this call without a corresponding use, so the unqualified name may not resolve.
| open_provider_picker(app, config, engine_handle).await; | |
| crate::tui::ui::overlays::open_provider_picker(app, config, engine_handle).await; |
| .with_provider_health(&app.provider_health), | ||
| ); | ||
| } | ||
| open_provider_picker(app, config, engine_handle).await; |
There was a problem hiding this comment.
Use the fully qualified path to the new sibling helper; the diff adds this call without a corresponding use, so the unqualified name may not resolve.
| open_provider_picker(app, config, engine_handle).await; | |
| crate::tui::ui::overlays::open_provider_picker(app, config, engine_handle).await; |
|
Claude finished @Hmbown's task in 3m 25s —— View job Review: fix(tui): make topbar route segment interactive
Summary: The design is sound and matches Confirmed bug: route hitbox can misalign at narrow widths
This bug lives in The new False positives — disregard Codewhale-agent's two ERROR findingsCodewhale-agent flagged
No import is missing; no fully-qualified path is needed. Everything else
AssessmentFix the shed/hitbox mismatch before merge — it's a real, user-visible correctness bug in the exact control this PR makes interactive. Everything else in the diff (provider/model/route safety, dedup, F3 gating behind onboarding/view-stack state) checks out. |
There was a problem hiding this comment.
Codewhale review
The PR makes the topbar route/model segment interactive by mouse and F3, and centralizes provider picker entry through a shared open_provider_picker helper. The structure is sound, but the new key routing path is under-tested and the refactor appears to drop an existing duplicate-modal guard.
Findings
- [WARNING] F3 event-loop path lacks a direct integration test (
crates/tui/src/tui/ui/event_loop.rs:4410)
The PR adds a non-trivial async branch in run_event_loop that converts F3 into ViewEvent::TopbarRoutePickerRequested, but the added tests only cover is_provider_route_shortcut and binding catalog strings. No test asserts that an F3 key event with an empty view stack emits the route-picker event or opens the picker. This is the primary new user-visible control, so it should be covered. - [WARNING] Reused picker helper may drop the existing duplicate-modal guard (
crates/tui/src/tui/ui/overlays.rs)
The previous AppAction::OpenProviderPicker implementation would only push ProviderPickerView when app.view_stack.top_kind() != Some(ModalKind::ProviderPicker). The new open_provider_picker delegates to open_launch_provider_picker without an explicit equivalent guard. If open_launch_provider_picker does not already perform that check, repeated /provider invocations or a stale topbar route target can stack duplicate picker views.
Assessment
The refactor is logically clean and improves the topbar from decorative text to a typed control with shared entry points. Before merge, add direct event-loop coverage for F3 and confirm or restore the duplicate provider-picker guard.
Advisory review by Codewhale (codewhale review --pr 5763 --post, head d9bd021fe6d8339060a619101f9dba663c881d3e). Line-specific findings are also posted as inline review comments; mechanical fixes arrive as committable suggestions you can apply from the Files tab. CODEOWNERS approval still governs merge.
| continue; | ||
| } | ||
|
|
||
| // F3 is the non-printable keyboard counterpart to the clickable |
There was a problem hiding this comment.
[WARNING] F3 event-loop path lacks a direct integration test
The PR adds a non-trivial async branch in run_event_loop that converts F3 into ViewEvent::TopbarRoutePickerRequested, but the added tests only cover is_provider_route_shortcut and binding catalog strings. No test asserts that an F3 key event with an empty view stack emits the route-picker event or opens the picker. This is the primary new user-visible control, so it should be covered.
Closes #5756
Product change
The painted route/model segment now opens the existing provider picker by click or F3. Both entry points delegate to the same picker/apply path as
/provider; the header owns neither catalog data nor route authority.Verification
cargo fmt --all -- --checkgit diff --checkBoundary
This makes the visible control truthful. It does not resolve #5755, the wider single-authority provider/runtime/catalog lifecycle problem.