Skip to content

feat(ui): flag agents awaiting a response, curate themes, fix theme-blind colors - #224

Open
BunsDev wants to merge 4 commits into
mainfrom
feat/agent-status-and-ui-polish
Open

feat(ui): flag agents awaiting a response, curate themes, fix theme-blind colors#224
BunsDev wants to merge 4 commits into
mainfrom
feat/agent-status-and-ui-polish

Conversation

@BunsDev

@BunsDev BunsDev commented Jul 26, 2026

Copy link
Copy Markdown
Member

Description

Three passes over the app's UI surfaces, from a review of the interface against the Phase 1 design contract. They share files (tab.rs, workspace/view.rs, ai/conversation_status_ui.rs each carry hunks from more than one pass), so they land together rather than as three PRs whose diffs would have to be split hunk-by-hunk.

1. Show when an agent is waiting on you

Why: a tab gave no signal when an agent in one of its panes was blocked awaiting a response, so a background tab could sit unanswered indefinitely.

How: TerminalView::is_awaiting_user_response is the shared predicate; PaneGroup::panes_awaiting_user_response counts blocked panes; the tab bar gains an Indicator::NeedsResponse { pane_count } and the pane header a "Needs response" chip.

The blocked state has two independent sources and both have to be checked. Checking only the Oz conversation is not enough, because selected_conversation_status_for_display returns None for a conversation that is blocked but empty — so the CLI-agent session path is checked first.

No new re-render plumbing was needed: Workspace and TerminalView already subscribe to BlocklistAIHistoryModel and CLIAgentSessionsModel and notify on status change.

2. Bundled themes reduced 24 → 6

Why: the catalog included ten background-image themes, three gradients, and two referral-reward themes that are unreachable in an OSS build.

How: kept CastCodes Dark, Dark, Light, Dracula, Solarized Dark, Gruvbox Dark.

Back-compat is deliberate: retired ThemeKind variants stay in the enum so existing settings still deserialize and the chooser's discriminant-ordered sort is preserved. They are hidden with #[schemars(skip)] and resolve through a new retired_replacement() to a theme of the same lightness, so a user on a retired theme is not flipped from dark to light. Covered by retired_theme_kinds_still_deserialize and retired_themes_resolve_to_a_same_lightness_replacement.

3. Colors that only worked on one background lightness

These are correctness bugs, not styling preferences — each hard-codes a color that disappears or fails contrast on the other themes:

Surface Was Now
Settings working-dir input ColorU::black() on surface_2() — invisible on every dark theme main_text_color(surface_2())
Tab bar icons (×3) ColorU::white() fallback — invisible on Light active_ui_text_color()
Account avatar black on the #7c3aed accent — fails contrast active_highlighted_text_color()
Shared-block overflow icon fixed #b3bab8; 5px radius nonactive_ui_text_color(); 4px
Command palette statics 2 dead translucent-white consts deleted

active_highlighted_text_color() now reads the primary_foreground token, which was defined in castcodes_ui_tokens but never consumed; the accessor itself had zero callers before this, so the change carries no regression risk elsewhere. Themes without a ui block keep the previously derived value.

Adds app/src/ui_components/design.rs — the radius, spacing, type and motion steps from the contract. Colors were already tokenized; sizing had no code representation, so every call site wrote a bare literal and review had nothing to check against.

Deliberately not changed, after verifying each:

  • icon_with_status.rs draws a black glyph on a fixed brand-purple ambient badge — not a theme surface, so black is contrast-correct.
  • traffic_lights.rs uses white on WINDOWS_BRIGHT_RED for the Windows close-button hover — platform convention.
  • login_slide.rs copy reads as hosted-service marketing, but the login gate is unreachable in OSS builds (root_view.rs requires ChannelState::cloud_services_available(); auth_state.rs returns early without it). Retoning it would be churn on a dead path.
  • 48 radii across 37 inherited Warp files sit outside the 4/6/8 scale, mostly 1–3px hairlines on badges and glyphs. A blind sweep is what the rebrand guard warns against and is visually unverifiable, so these migrate as views are touched.

Linked Issue

Closes #223

  • The linked issue is labeled ready-to-spec or ready-to-implement.

Neither label exists in this repo (gh api repos/OpenCoven/cast-codes/labels returns only aardvark, bug, codex, documentation, duplicate, enhancement, external-contributor, good first issue, help wanted, invalid, question, wontfix), so the box is left unchecked rather than claimed falsely. #223 is labeled bug + enhancement.

  • Where appropriate, screenshots or a short video of the implementation are included below.

Testing

Automated:

  • cargo check -p warp-app --bin cast-codes --features gui — clean, zero warnings (the design module's unused steps are covered by a scoped, documented #![allow(dead_code)]).
  • cargo test -p warp_core ui::theme — 33 pass, including two new tests for the primary_foreground wiring and its fallback.
  • cargo test -p warp-app --features gui --lib themes:: — 42 pass, including three new tests for the six-theme curation and retired-kind back-compat.
  • cargo test -p warp-app --features gui --lib settings_view:: — 163 pass.
  • New unit test is_awaiting_user_response_tracks_cli_session_blocked_status covers the CLI-session blocked path (it sets listener: Some(..); the pre-existing test at view_tests.rs uses listener: None and only exercises the conversation path).
  • ./script/check_ai_attribution and ./script/check_rebrand — pass.
  • Final presubmit-equivalent verification — pass: cargo fmt, full-workspace clippy, clang-format, wgslfmt, PSScriptAnalyzer, workspace nextest (6,561 pass; 87 configured skips), warp_completer v2 nextest (107 pass; 4 skips), and doc tests. The wrapper reached PSScriptAnalyzer on the final diff but hit its known intermittent null-reference despite zero violations; a clean analyzer retry and the exact remaining nextest/doc-test commands all passed.

Not done, so a reviewer should treat these as open:

  • I have manually tested my changes locally with ./script/run

./script/run built, bundled, and launched the public OSS app, but it aborted during existing macOS menu construction before the changed UI could be inspected (app/src/app_menus.rs:104: action should have a name: ReferAFriend). A follow-up reached the same baseline defect class at ToggleWarpDrive. That startup defect is tracked separately; the tab indicator, response chip, and six themes still need a visual eyeball before merge. macOS Computer Use permissions were also unavailable.

Full workspace nextest and doc tests passed with the exact commands used by ./script/presubmit. No integration test was added — the change is covered by unit tests at the model/predicate level.

Screenshots / Videos

None — see the note above. Happy to add them if someone can capture a run.

Agent Mode

CHANGELOG-IMPROVEMENT: Tabs and pane headers now show when an agent is waiting on your response.
CHANGELOG-IMPROVEMENT: Reduced the bundled theme catalog to six curated themes.
CHANGELOG-BUG-FIX: Fixed text and icons that were invisible or low contrast on some themes, including the settings working-directory input on dark themes and tab bar icons on light themes.

…lind colors

Three passes over the app's UI surfaces.

Agent needs-response indicators

A tab gave no signal when an agent in one of its panes was blocked waiting on
the user, so a background tab could sit unanswered indefinitely. Tabs now show
a needs-response indicator when any pane is blocked, and pane headers carry a
matching chip.

The state has two independent sources that both have to be checked: a
plugin-backed CLI agent session and the Oz conversation. The conversation path
alone is not sufficient, because selected_conversation_status_for_display
returns None for a blocked-but-empty conversation.

Bundled themes reduced to six

The catalog had grown to 24, including ten background-image themes, three
gradients, and two referral rewards that are unreachable in an OSS build. Kept
CastCodes Dark, Dark, Light, Dracula, Solarized Dark and Gruvbox Dark.

Retired ThemeKind variants stay in the enum so existing settings still
deserialize and the chooser's sort order is preserved; they are hidden from the
schema and resolve to a replacement of the same lightness.

Theme-blind color literals

Several render sites hard-coded a color that only works against one background
lightness. The settings working-directory input drew black text on surface_2(),
invisible in every dark theme; three tab bar icons fell back to white,
invisible in Light; the account avatar used black initials on the accent fill.
These now use the semantic accessors.

active_highlighted_text_color() reads the primary_foreground token, which was
defined in castcodes_ui_tokens but never consumed. Two dead translucent-white
statics in the command palette were removed rather than re-themed.

Adds app/src/ui_components/design.rs with the radius, spacing, type and motion
steps from the Phase 1 contract. Colors were already tokenized; sizing had no
code representation, so every call site wrote a bare literal. Inherited Warp
views are migrated as they are touched rather than in one sweep, which would
churn hundreds of visually unverifiable call sites.
Copilot AI review requested due to automatic review settings July 26, 2026 11:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes a set of UI-focused improvements aligned with the Phase 1 design contract: it surfaces “agent awaiting your response” state in both tabs and pane chrome, curates the bundled theme set down to the intended six, and fixes several theme-dependent contrast issues by routing through semantic theme accessors and adding a shared sizing scale.

Changes:

  • Add a shared “awaiting user response” predicate for terminal panes, then surface it via a new tab-bar indicator and a “Needs response” chip in pane headers.
  • Reduce bundled themes from 24 → 6 while preserving backwards-compatible deserialization for retired ThemeKind values via a same-lightness replacement mapping.
  • Fix several hard-coded colors that broke on light/dark themes and introduce ui_components::design constants for radius/spacing/type/motion.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
DESIGN-CHANGES.md Documents the theme curation, contrast fixes, and the new sizing scale.
crates/warp_core/src/ui/theme/theme_tests.rs Adds coverage for active_highlighted_text_color token fallback/override behavior.
crates/warp_core/src/ui/theme/color.rs Updates active_highlighted_text_color() to prefer UiTokens::primary_foreground when present.
app/src/workspace/view/vertical_tabs.rs Reuses shared “status pill with label” renderer for consistent status chips.
app/src/workspace/view.rs Resets theme deletion to ThemeKind::default(); fixes avatar text color + font size via design scale.
app/src/ui_components/mod.rs Exposes design module and ties shared border radius to the design scale.
app/src/ui_components/design.rs Introduces a code-level sizing/type/motion vocabulary for Phase 1 contract values.
app/src/themes/theme.rs Retires non-curated themes (schema-hidden, still deserializable), adds bundled-set helpers and replacement mapping, and limits preload to six themes.
app/src/themes/theme_tests.rs Updates rendering invariants for the reduced built-in set; adds tests for curated set and retired-kind compatibility.
app/src/themes/theme_chooser.rs Removes referral-theme filtering from the chooser item generation.
app/src/themes/mod.rs Updates onboarding theme picker to draw from the curated bundled set.
app/src/themes/default_themes.rs Removes definitions for retired decorative/referral themes; adds module docs explaining the curated set.
app/src/terminal/view/pane_impl.rs Adds “Needs response” chip to pane headers; implements TerminalView::is_awaiting_user_response().
app/src/terminal/view_tests.rs Adds unit test covering CLI-agent-session blocked status path for is_awaiting_user_response().
app/src/tab.rs Adds Indicator::NeedsResponse and tooltip; fixes tab icon fallback colors for Light theme; adopts design radius for tab rounding.
app/src/settings/initializer.rs Removes the “DefaultAdeberryTheme” new-user override now that Adeberry is retired.
app/src/settings_view/show_blocks_view.rs Fixes overflow icon color to use a semantic theme accessor; aligns radius to 4px.
app/src/settings_view/features/working_directory.rs Fixes input text color to be theme-correct on dark surfaces.
app/src/search/command_search/view.rs Removes dead translucent-white color constants.
app/src/pane_group/mod.rs Adds pane-group helper to count panes awaiting user response.
app/src/env_vars/env_var_collection_block.rs Aligns env-var collection radius to the 8px contract maximum via a named constant.
app/src/auth/login_slide.rs Simplifies visual selection mapping now that retired themes are no longer offered.
app/src/ai/document/orchestration_config_block.rs Uses percentage radius for pill toggle track to express intent and keep pixel-identical appearance.
app/src/ai/conversation_status_ui.rs Adds shared “status pill with label” renderer and adopts design scale constants for padding/radius/font size.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/src/themes/theme_chooser.rs Outdated
Copilot AI review requested due to automatic review settings July 26, 2026 13:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.

Comment thread app/src/tab.rs
Comment on lines +831 to +837
/// Returns the needs-response indicator when any visible pane in this tab
/// (focused or not, Oz conversation or CLI agent session) is blocked
/// awaiting the user's response, so the user can spot it from the tab bar.
fn needs_response_indicator(tab: &TabData, ctx: &AppContext) -> Option<Indicator> {
let pane_count = tab.pane_group.as_ref(ctx).panes_awaiting_user_response(ctx);
(pane_count > 0).then_some(Indicator::NeedsResponse { pane_count })
}
Comment thread app/src/tab.rs Outdated
Comment thread app/src/ai/conversation_status_ui.rs
Comment thread app/src/settings_view/show_blocks_view.rs Outdated
Copilot AI review requested due to automatic review settings July 26, 2026 13:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 24 out of 24 changed files in this pull request and generated no new comments.

Keep OSC 9/777 notifications enabled in OSS builds so local agent blocked states can reach the needs-response indicators. Add a channel-level regression test for the feature gate.

Signed-off-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 27, 2026 15:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.

Comment thread app/src/tab.rs
Comment on lines +831 to +837
/// Returns the needs-response indicator when any visible pane in this tab
/// (focused or not, Oz conversation or CLI agent session) is blocked
/// awaiting the user's response, so the user can spot it from the tab bar.
fn needs_response_indicator(tab: &TabData, ctx: &AppContext) -> Option<Indicator> {
let pane_count = tab.pane_group.as_ref(ctx).panes_awaiting_user_response(ctx);
(pane_count > 0).then_some(Indicator::NeedsResponse { pane_count })
}
@BunsDev BunsDev self-assigned this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent-waiting state is invisible, theme catalog too large, and colors hard-coded to one background lightness

2 participants