From f148b2c0336fefb713c83cc4982ad92e78d80e7f Mon Sep 17 00:00:00 2001 From: Oz Date: Fri, 26 Jun 2026 17:22:24 +0000 Subject: [PATCH 1/4] Flip context window circle to represent context remaining MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The context-window usage circle's solid (white) marks previously represented the amount of context *used*, while the tooltip already read "X% context remaining" — so a near-full context window showed a mostly white/full circle labeled with a low remaining %, which read as "used", not "remaining". Flip the color semantics so the white marks represent the context *remaining*: - empty conversation -> all-white circle, "100% context remaining" - full context window -> all-grey circle, "0% context remaining" The tooltip text is unchanged (it was already remaining-based). Both surfaces that show the circle (the agent input footer and the conversation usage footer) funnel through the pure `icon_for_context_window_usage`, so the single mapping change fixes both; the static placeholder icons default to the full-white (100% remaining) state. The >= 80%-used red warning tint is preserved. Co-Authored-By: Warp --- .../agent_view/agent_input_footer/mod.rs | 5 +- .../agent_input_footer/toolbar_item.rs | 5 +- app/src/ai/blocklist/usage/mod.rs | 35 +++++--- app/src/ai/blocklist/usage/mod_tests.rs | 80 +++++++++++++++++++ 4 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 app/src/ai/blocklist/usage/mod_tests.rs diff --git a/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs b/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs index cf8ee68873..90b52ff18f 100644 --- a/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs +++ b/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs @@ -609,7 +609,10 @@ impl AgentInputFooter { let context_window_button = ctx.add_typed_action_view(|_ctx| { ActionButton::new("", AgentInputButtonTheme) - .with_icon(Icon::ConversationContext0) + // Placeholder before live usage loads: a fresh conversation is + // at 100% context remaining, i.e. an all-white circle. The real + // level is set by `update_context_window_button`. + .with_icon(Icon::ConversationContext100) .with_tooltip("Context window usage") .with_size(button_size) .with_tooltip_alignment(TooltipAlignment::Left) diff --git a/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs b/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs index 4d813f620d..ef22b1c6c0 100644 --- a/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs +++ b/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs @@ -138,7 +138,10 @@ impl AgentToolbarItemKind { Self::NLDToggle => Some(Icon::NLD), Self::VoiceInput => Some(Icon::Microphone), Self::FileAttach => Some(Icon::Plus), - Self::ContextWindowUsage => Some(Icon::ConversationContext0), + // Full-white circle as the representative/placeholder icon: under + // the remaining-context semantics a fresh conversation is at 100% + // remaining, and live usage replaces this via the render fn. + Self::ContextWindowUsage => Some(Icon::ConversationContext100), Self::FileExplorer => Some(Icon::FileCopy), Self::RichInput => Some(Icon::TextInput), Self::ShareSession => Some(Icon::Phone01), diff --git a/app/src/ai/blocklist/usage/mod.rs b/app/src/ai/blocklist/usage/mod.rs index c066b12051..46e50ba6b9 100644 --- a/app/src/ai/blocklist/usage/mod.rs +++ b/app/src/ai/blocklist/usage/mod.rs @@ -6,26 +6,32 @@ pub mod conversation_usage_view; pub mod rollup; pub fn icon_for_context_window_usage(context_window_usage: f32) -> Icon { - // Match the context window usage to the nearest 10% icon. - if context_window_usage >= 0.95 { + // The circle's solid (white) marks represent the context *remaining*, not + // the amount used: an empty conversation shows an all-white circle (100% + // remaining) and counts down to an all-grey circle as the context window + // fills up (0% remaining). So match the *remaining* fraction + // (`1 - usage`) to the nearest 10% icon, where `ConversationContextN` + // brightens N% of the ring. + let context_window_remaining = 1.0 - context_window_usage; + if context_window_remaining >= 0.95 { Icon::ConversationContext100 - } else if context_window_usage >= 0.85 { + } else if context_window_remaining >= 0.85 { Icon::ConversationContext90 - } else if context_window_usage >= 0.75 { + } else if context_window_remaining >= 0.75 { Icon::ConversationContext80 - } else if context_window_usage >= 0.65 { + } else if context_window_remaining >= 0.65 { Icon::ConversationContext70 - } else if context_window_usage >= 0.55 { + } else if context_window_remaining >= 0.55 { Icon::ConversationContext60 - } else if context_window_usage >= 0.45 { + } else if context_window_remaining >= 0.45 { Icon::ConversationContext50 - } else if context_window_usage >= 0.35 { + } else if context_window_remaining >= 0.35 { Icon::ConversationContext40 - } else if context_window_usage >= 0.25 { + } else if context_window_remaining >= 0.25 { Icon::ConversationContext30 - } else if context_window_usage >= 0.15 { + } else if context_window_remaining >= 0.15 { Icon::ConversationContext20 - } else if context_window_usage >= 0.05 { + } else if context_window_remaining >= 0.05 { Icon::ConversationContext10 } else { Icon::ConversationContext0 @@ -39,6 +45,9 @@ pub fn render_context_window_usage_icon( ) -> Box { let icon = icon_for_context_window_usage(context_window_usage); + // Independent of the white/grey fill level, tint the whole circle red once + // the context window is nearly full (>= 80% used) to warn that the + // conversation is running out of context. let fill = if context_window_usage >= 0.8 { Fill::Solid(theme.ansi_fg_red()) } else { @@ -47,3 +56,7 @@ pub fn render_context_window_usage_icon( icon.to_warpui_icon(fill).finish() } + +#[cfg(test)] +#[path = "mod_tests.rs"] +mod tests; diff --git a/app/src/ai/blocklist/usage/mod_tests.rs b/app/src/ai/blocklist/usage/mod_tests.rs new file mode 100644 index 0000000000..8e0f931986 --- /dev/null +++ b/app/src/ai/blocklist/usage/mod_tests.rs @@ -0,0 +1,80 @@ +//! Tests for the context-window usage circle icon mapping. +//! +//! Regression guard for the color semantics of the context-window circle: +//! the solid (white) marks represent the context *remaining*, not the amount +//! used. An empty conversation (0% used → 100% remaining) shows a full white +//! circle and it counts down to an all-grey circle as the window fills up +//! (100% used → 0% remaining). + +use warp_core::ui::Icon; + +use super::icon_for_context_window_usage; + +#[test] +fn empty_conversation_shows_full_white_circle() { + // 0% used == 100% remaining -> all-white circle. + assert_eq!( + icon_for_context_window_usage(0.0), + Icon::ConversationContext100 + ); +} + +#[test] +fn full_context_window_shows_all_grey_circle() { + // 100% used == 0% remaining -> all-grey circle. + assert_eq!( + icon_for_context_window_usage(1.0), + Icon::ConversationContext0 + ); +} + +#[test] +fn icon_brightness_tracks_remaining_not_used() { + // Lightly-used conversation: lots of context remaining -> mostly white. + assert_eq!( + icon_for_context_window_usage(0.1), + Icon::ConversationContext90 + ); + // Half used -> half white. + assert_eq!( + icon_for_context_window_usage(0.5), + Icon::ConversationContext50 + ); + // Heavily used (the original report's 88%): little remaining -> mostly grey. + assert_eq!( + icon_for_context_window_usage(0.88), + Icon::ConversationContext10 + ); +} + +#[test] +fn mapping_is_monotonic_more_usage_never_brightens_the_circle() { + // As usage increases, the number of bright (remaining) marks must be + // non-increasing — the circle only ever empties as context fills. + let icon_rank = |usage: f32| match icon_for_context_window_usage(usage) { + Icon::ConversationContext0 => 0, + Icon::ConversationContext10 => 10, + Icon::ConversationContext20 => 20, + Icon::ConversationContext30 => 30, + Icon::ConversationContext40 => 40, + Icon::ConversationContext50 => 50, + Icon::ConversationContext60 => 60, + Icon::ConversationContext70 => 70, + Icon::ConversationContext80 => 80, + Icon::ConversationContext90 => 90, + Icon::ConversationContext100 => 100, + other => panic!("unexpected icon: {other:?}"), + }; + + let mut usage = 0.0; + let mut previous = icon_rank(usage); + while usage <= 1.0 { + let current = icon_rank(usage); + assert!( + current <= previous, + "icon brightness increased as usage rose to {usage}: {previous} -> {current}" + ); + previous = current; + usage += 0.05; + } +} From 5585ce3411119383b3dbf681de5226649d5ba2ac Mon Sep 17 00:00:00 2001 From: Oz Date: Fri, 26 Jun 2026 17:59:53 +0000 Subject: [PATCH 2/4] Rename context-window circle assets/icons to remaining-based names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per review feedback, align the asset and icon-enum names with how the circle is displayed (context remaining). Rename the SVG assets conversation-context-{0..100}.svg -> context-remaining-{0..100}.svg and the Icon::ConversationContext{0..100} variants -> Icon::ContextRemaining{0..100}, and update all references. The number denotes the bright fill level, which now maps directly to the percentage of context remaining (e.g. context-remaining-100 = full white circle on an empty conversation). Pure rename — no behavior or rendering change. Co-Authored-By: Warp --- ...-context-0.svg => context-remaining-0.svg} | 0 ...ontext-10.svg => context-remaining-10.svg} | 0 ...text-100.svg => context-remaining-100.svg} | 0 ...ontext-20.svg => context-remaining-20.svg} | 0 ...ontext-30.svg => context-remaining-30.svg} | 0 ...ontext-40.svg => context-remaining-40.svg} | 0 ...ontext-50.svg => context-remaining-50.svg} | 0 ...ontext-60.svg => context-remaining-60.svg} | 0 ...ontext-70.svg => context-remaining-70.svg} | 0 ...ontext-80.svg => context-remaining-80.svg} | 0 ...ontext-90.svg => context-remaining-90.svg} | 0 .../agent_view/agent_input_footer/mod.rs | 2 +- .../agent_input_footer/toolbar_item.rs | 2 +- app/src/ai/blocklist/usage/mod.rs | 24 +++++----- app/src/ai/blocklist/usage/mod_tests.rs | 41 +++++++---------- crates/warp_core/src/ui/icons.rs | 44 +++++++++---------- 16 files changed, 52 insertions(+), 61 deletions(-) rename app/assets/bundled/svg/{conversation-context-0.svg => context-remaining-0.svg} (100%) rename app/assets/bundled/svg/{conversation-context-10.svg => context-remaining-10.svg} (100%) rename app/assets/bundled/svg/{conversation-context-100.svg => context-remaining-100.svg} (100%) rename app/assets/bundled/svg/{conversation-context-20.svg => context-remaining-20.svg} (100%) rename app/assets/bundled/svg/{conversation-context-30.svg => context-remaining-30.svg} (100%) rename app/assets/bundled/svg/{conversation-context-40.svg => context-remaining-40.svg} (100%) rename app/assets/bundled/svg/{conversation-context-50.svg => context-remaining-50.svg} (100%) rename app/assets/bundled/svg/{conversation-context-60.svg => context-remaining-60.svg} (100%) rename app/assets/bundled/svg/{conversation-context-70.svg => context-remaining-70.svg} (100%) rename app/assets/bundled/svg/{conversation-context-80.svg => context-remaining-80.svg} (100%) rename app/assets/bundled/svg/{conversation-context-90.svg => context-remaining-90.svg} (100%) diff --git a/app/assets/bundled/svg/conversation-context-0.svg b/app/assets/bundled/svg/context-remaining-0.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-0.svg rename to app/assets/bundled/svg/context-remaining-0.svg diff --git a/app/assets/bundled/svg/conversation-context-10.svg b/app/assets/bundled/svg/context-remaining-10.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-10.svg rename to app/assets/bundled/svg/context-remaining-10.svg diff --git a/app/assets/bundled/svg/conversation-context-100.svg b/app/assets/bundled/svg/context-remaining-100.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-100.svg rename to app/assets/bundled/svg/context-remaining-100.svg diff --git a/app/assets/bundled/svg/conversation-context-20.svg b/app/assets/bundled/svg/context-remaining-20.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-20.svg rename to app/assets/bundled/svg/context-remaining-20.svg diff --git a/app/assets/bundled/svg/conversation-context-30.svg b/app/assets/bundled/svg/context-remaining-30.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-30.svg rename to app/assets/bundled/svg/context-remaining-30.svg diff --git a/app/assets/bundled/svg/conversation-context-40.svg b/app/assets/bundled/svg/context-remaining-40.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-40.svg rename to app/assets/bundled/svg/context-remaining-40.svg diff --git a/app/assets/bundled/svg/conversation-context-50.svg b/app/assets/bundled/svg/context-remaining-50.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-50.svg rename to app/assets/bundled/svg/context-remaining-50.svg diff --git a/app/assets/bundled/svg/conversation-context-60.svg b/app/assets/bundled/svg/context-remaining-60.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-60.svg rename to app/assets/bundled/svg/context-remaining-60.svg diff --git a/app/assets/bundled/svg/conversation-context-70.svg b/app/assets/bundled/svg/context-remaining-70.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-70.svg rename to app/assets/bundled/svg/context-remaining-70.svg diff --git a/app/assets/bundled/svg/conversation-context-80.svg b/app/assets/bundled/svg/context-remaining-80.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-80.svg rename to app/assets/bundled/svg/context-remaining-80.svg diff --git a/app/assets/bundled/svg/conversation-context-90.svg b/app/assets/bundled/svg/context-remaining-90.svg similarity index 100% rename from app/assets/bundled/svg/conversation-context-90.svg rename to app/assets/bundled/svg/context-remaining-90.svg diff --git a/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs b/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs index 90b52ff18f..6584379aff 100644 --- a/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs +++ b/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs @@ -612,7 +612,7 @@ impl AgentInputFooter { // Placeholder before live usage loads: a fresh conversation is // at 100% context remaining, i.e. an all-white circle. The real // level is set by `update_context_window_button`. - .with_icon(Icon::ConversationContext100) + .with_icon(Icon::ContextRemaining100) .with_tooltip("Context window usage") .with_size(button_size) .with_tooltip_alignment(TooltipAlignment::Left) diff --git a/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs b/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs index ef22b1c6c0..f065812784 100644 --- a/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs +++ b/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs @@ -141,7 +141,7 @@ impl AgentToolbarItemKind { // Full-white circle as the representative/placeholder icon: under // the remaining-context semantics a fresh conversation is at 100% // remaining, and live usage replaces this via the render fn. - Self::ContextWindowUsage => Some(Icon::ConversationContext100), + Self::ContextWindowUsage => Some(Icon::ContextRemaining100), Self::FileExplorer => Some(Icon::FileCopy), Self::RichInput => Some(Icon::TextInput), Self::ShareSession => Some(Icon::Phone01), diff --git a/app/src/ai/blocklist/usage/mod.rs b/app/src/ai/blocklist/usage/mod.rs index 46e50ba6b9..9a31e35862 100644 --- a/app/src/ai/blocklist/usage/mod.rs +++ b/app/src/ai/blocklist/usage/mod.rs @@ -10,31 +10,31 @@ pub fn icon_for_context_window_usage(context_window_usage: f32) -> Icon { // the amount used: an empty conversation shows an all-white circle (100% // remaining) and counts down to an all-grey circle as the context window // fills up (0% remaining). So match the *remaining* fraction - // (`1 - usage`) to the nearest 10% icon, where `ConversationContextN` + // (`1 - usage`) to the nearest 10% icon, where `ContextRemainingN` // brightens N% of the ring. let context_window_remaining = 1.0 - context_window_usage; if context_window_remaining >= 0.95 { - Icon::ConversationContext100 + Icon::ContextRemaining100 } else if context_window_remaining >= 0.85 { - Icon::ConversationContext90 + Icon::ContextRemaining90 } else if context_window_remaining >= 0.75 { - Icon::ConversationContext80 + Icon::ContextRemaining80 } else if context_window_remaining >= 0.65 { - Icon::ConversationContext70 + Icon::ContextRemaining70 } else if context_window_remaining >= 0.55 { - Icon::ConversationContext60 + Icon::ContextRemaining60 } else if context_window_remaining >= 0.45 { - Icon::ConversationContext50 + Icon::ContextRemaining50 } else if context_window_remaining >= 0.35 { - Icon::ConversationContext40 + Icon::ContextRemaining40 } else if context_window_remaining >= 0.25 { - Icon::ConversationContext30 + Icon::ContextRemaining30 } else if context_window_remaining >= 0.15 { - Icon::ConversationContext20 + Icon::ContextRemaining20 } else if context_window_remaining >= 0.05 { - Icon::ConversationContext10 + Icon::ContextRemaining10 } else { - Icon::ConversationContext0 + Icon::ContextRemaining0 } } diff --git a/app/src/ai/blocklist/usage/mod_tests.rs b/app/src/ai/blocklist/usage/mod_tests.rs index 8e0f931986..dbe71cb31e 100644 --- a/app/src/ai/blocklist/usage/mod_tests.rs +++ b/app/src/ai/blocklist/usage/mod_tests.rs @@ -15,35 +15,26 @@ fn empty_conversation_shows_full_white_circle() { // 0% used == 100% remaining -> all-white circle. assert_eq!( icon_for_context_window_usage(0.0), - Icon::ConversationContext100 + Icon::ContextRemaining100 ); } #[test] fn full_context_window_shows_all_grey_circle() { // 100% used == 0% remaining -> all-grey circle. - assert_eq!( - icon_for_context_window_usage(1.0), - Icon::ConversationContext0 - ); + assert_eq!(icon_for_context_window_usage(1.0), Icon::ContextRemaining0); } #[test] fn icon_brightness_tracks_remaining_not_used() { // Lightly-used conversation: lots of context remaining -> mostly white. - assert_eq!( - icon_for_context_window_usage(0.1), - Icon::ConversationContext90 - ); + assert_eq!(icon_for_context_window_usage(0.1), Icon::ContextRemaining90); // Half used -> half white. - assert_eq!( - icon_for_context_window_usage(0.5), - Icon::ConversationContext50 - ); + assert_eq!(icon_for_context_window_usage(0.5), Icon::ContextRemaining50); // Heavily used (the original report's 88%): little remaining -> mostly grey. assert_eq!( icon_for_context_window_usage(0.88), - Icon::ConversationContext10 + Icon::ContextRemaining10 ); } @@ -52,17 +43,17 @@ fn mapping_is_monotonic_more_usage_never_brightens_the_circle() { // As usage increases, the number of bright (remaining) marks must be // non-increasing — the circle only ever empties as context fills. let icon_rank = |usage: f32| match icon_for_context_window_usage(usage) { - Icon::ConversationContext0 => 0, - Icon::ConversationContext10 => 10, - Icon::ConversationContext20 => 20, - Icon::ConversationContext30 => 30, - Icon::ConversationContext40 => 40, - Icon::ConversationContext50 => 50, - Icon::ConversationContext60 => 60, - Icon::ConversationContext70 => 70, - Icon::ConversationContext80 => 80, - Icon::ConversationContext90 => 90, - Icon::ConversationContext100 => 100, + Icon::ContextRemaining0 => 0, + Icon::ContextRemaining10 => 10, + Icon::ContextRemaining20 => 20, + Icon::ContextRemaining30 => 30, + Icon::ContextRemaining40 => 40, + Icon::ContextRemaining50 => 50, + Icon::ContextRemaining60 => 60, + Icon::ContextRemaining70 => 70, + Icon::ContextRemaining80 => 80, + Icon::ContextRemaining90 => 90, + Icon::ContextRemaining100 => 100, other => panic!("unexpected icon: {other:?}"), }; diff --git a/crates/warp_core/src/ui/icons.rs b/crates/warp_core/src/ui/icons.rs index 1d4eebd2b2..21dce9d97f 100644 --- a/crates/warp_core/src/ui/icons.rs +++ b/crates/warp_core/src/ui/icons.rs @@ -240,17 +240,17 @@ pub enum Icon { ContextWindowSixtyPct, ContextWindowWarning, ContextWindowSummarized, - ConversationContext0, - ConversationContext10, - ConversationContext20, - ConversationContext30, - ConversationContext40, - ConversationContext50, - ConversationContext60, - ConversationContext70, - ConversationContext80, - ConversationContext90, - ConversationContext100, + ContextRemaining0, + ContextRemaining10, + ContextRemaining20, + ContextRemaining30, + ContextRemaining40, + ContextRemaining50, + ContextRemaining60, + ContextRemaining70, + ContextRemaining80, + ContextRemaining90, + ContextRemaining100, LeftSidebarOpen, LeftSidebarClose, Diff, @@ -577,17 +577,17 @@ impl From for &'static str { Icon::ContextWindowSixtyPct => "bundled/svg/context-window-60-pct.svg", Icon::ContextWindowWarning => "bundled/svg/context-window-warning.svg", Icon::ContextWindowSummarized => "bundled/svg/context-window-summarized.svg", - Icon::ConversationContext0 => "bundled/svg/conversation-context-0.svg", - Icon::ConversationContext10 => "bundled/svg/conversation-context-10.svg", - Icon::ConversationContext20 => "bundled/svg/conversation-context-20.svg", - Icon::ConversationContext30 => "bundled/svg/conversation-context-30.svg", - Icon::ConversationContext40 => "bundled/svg/conversation-context-40.svg", - Icon::ConversationContext50 => "bundled/svg/conversation-context-50.svg", - Icon::ConversationContext60 => "bundled/svg/conversation-context-60.svg", - Icon::ConversationContext70 => "bundled/svg/conversation-context-70.svg", - Icon::ConversationContext80 => "bundled/svg/conversation-context-80.svg", - Icon::ConversationContext90 => "bundled/svg/conversation-context-90.svg", - Icon::ConversationContext100 => "bundled/svg/conversation-context-100.svg", + Icon::ContextRemaining0 => "bundled/svg/context-remaining-0.svg", + Icon::ContextRemaining10 => "bundled/svg/context-remaining-10.svg", + Icon::ContextRemaining20 => "bundled/svg/context-remaining-20.svg", + Icon::ContextRemaining30 => "bundled/svg/context-remaining-30.svg", + Icon::ContextRemaining40 => "bundled/svg/context-remaining-40.svg", + Icon::ContextRemaining50 => "bundled/svg/context-remaining-50.svg", + Icon::ContextRemaining60 => "bundled/svg/context-remaining-60.svg", + Icon::ContextRemaining70 => "bundled/svg/context-remaining-70.svg", + Icon::ContextRemaining80 => "bundled/svg/context-remaining-80.svg", + Icon::ContextRemaining90 => "bundled/svg/context-remaining-90.svg", + Icon::ContextRemaining100 => "bundled/svg/context-remaining-100.svg", Icon::LeftSidebarOpen => "bundled/svg/left-panel-open.svg", Icon::LeftSidebarClose => "bundled/svg/left-panel-close.svg", Icon::Diff => "bundled/svg/diff.svg", From 613edcf16ce1ef741fff0b0dc3187a70dd687f70 Mon Sep 17 00:00:00 2001 From: harryalbert Date: Fri, 26 Jun 2026 17:48:45 -0400 Subject: [PATCH 3/4] fix comments --- app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs | 3 --- .../ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs | 3 --- app/src/ai/blocklist/usage/mod.rs | 3 --- 3 files changed, 9 deletions(-) diff --git a/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs b/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs index 6584379aff..679dbb7b1b 100644 --- a/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs +++ b/app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs @@ -609,9 +609,6 @@ impl AgentInputFooter { let context_window_button = ctx.add_typed_action_view(|_ctx| { ActionButton::new("", AgentInputButtonTheme) - // Placeholder before live usage loads: a fresh conversation is - // at 100% context remaining, i.e. an all-white circle. The real - // level is set by `update_context_window_button`. .with_icon(Icon::ContextRemaining100) .with_tooltip("Context window usage") .with_size(button_size) diff --git a/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs b/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs index f065812784..601769ffda 100644 --- a/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs +++ b/app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs @@ -138,9 +138,6 @@ impl AgentToolbarItemKind { Self::NLDToggle => Some(Icon::NLD), Self::VoiceInput => Some(Icon::Microphone), Self::FileAttach => Some(Icon::Plus), - // Full-white circle as the representative/placeholder icon: under - // the remaining-context semantics a fresh conversation is at 100% - // remaining, and live usage replaces this via the render fn. Self::ContextWindowUsage => Some(Icon::ContextRemaining100), Self::FileExplorer => Some(Icon::FileCopy), Self::RichInput => Some(Icon::TextInput), diff --git a/app/src/ai/blocklist/usage/mod.rs b/app/src/ai/blocklist/usage/mod.rs index 9a31e35862..6e1ad33e0c 100644 --- a/app/src/ai/blocklist/usage/mod.rs +++ b/app/src/ai/blocklist/usage/mod.rs @@ -45,9 +45,6 @@ pub fn render_context_window_usage_icon( ) -> Box { let icon = icon_for_context_window_usage(context_window_usage); - // Independent of the white/grey fill level, tint the whole circle red once - // the context window is nearly full (>= 80% used) to warn that the - // conversation is running out of context. let fill = if context_window_usage >= 0.8 { Fill::Solid(theme.ansi_fg_red()) } else { From c51cb7b4ce72e0af013d713ce56eaa8d7dffdd00 Mon Sep 17 00:00:00 2001 From: Oz Date: Sun, 28 Jun 2026 20:44:15 +0000 Subject: [PATCH 4/4] Invert context window circle colors instead of reversing fill direction The previous approach flipped which icon was shown per state, which reversed the ring's sweep direction (it depleted the wrong way round). Per review feedback, keep the exact same icon / pattern / fill direction as the original and only invert the dark/light colors. Since the icon is rendered monochrome (per-segment luminance from the SVG's white fill-opacity acts as the mask), invert each segment's dark/light by swapping fill-opacity 0.4<->0.9 in the assets. Combined with the existing remaining-based selection, this renders the exact dark/light inverse of the original glyph at every state: empty conversation = full white ring, darkening in the same rotational direction the original filled, ending all-grey at 0% remaining. Verified by mapping bright segments to clock positions (each new asset is the precise color-inverse of the original at the same state) and on the running app via computer use. Co-Authored-By: Warp --- .../bundled/svg/context-remaining-0.svg | 96 ++++++++++++------- .../bundled/svg/context-remaining-10.svg | 54 ++++++++--- .../bundled/svg/context-remaining-100.svg | 96 +++++++------------ .../bundled/svg/context-remaining-20.svg | 54 +++++++---- .../bundled/svg/context-remaining-30.svg | 54 +++++++---- .../bundled/svg/context-remaining-40.svg | 52 +++++----- .../bundled/svg/context-remaining-50.svg | 48 +++++----- .../bundled/svg/context-remaining-60.svg | 52 +++++----- .../bundled/svg/context-remaining-70.svg | 54 ++++------- .../bundled/svg/context-remaining-80.svg | 54 ++++------- .../bundled/svg/context-remaining-90.svg | 54 +++-------- 11 files changed, 334 insertions(+), 334 deletions(-) diff --git a/app/assets/bundled/svg/context-remaining-0.svg b/app/assets/bundled/svg/context-remaining-0.svg index 7f941b1d5a..9511432b12 100644 --- a/app/assets/bundled/svg/context-remaining-0.svg +++ b/app/assets/bundled/svg/context-remaining-0.svg @@ -1,34 +1,66 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/bundled/svg/context-remaining-10.svg b/app/assets/bundled/svg/context-remaining-10.svg index 22a088599d..81d37c7daa 100644 --- a/app/assets/bundled/svg/context-remaining-10.svg +++ b/app/assets/bundled/svg/context-remaining-10.svg @@ -1,38 +1,62 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - - - - diff --git a/app/assets/bundled/svg/context-remaining-100.svg b/app/assets/bundled/svg/context-remaining-100.svg index 37d0ef1277..71e747d501 100644 --- a/app/assets/bundled/svg/context-remaining-100.svg +++ b/app/assets/bundled/svg/context-remaining-100.svg @@ -1,66 +1,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/bundled/svg/context-remaining-20.svg b/app/assets/bundled/svg/context-remaining-20.svg index fe16834842..2b17d71b10 100644 --- a/app/assets/bundled/svg/context-remaining-20.svg +++ b/app/assets/bundled/svg/context-remaining-20.svg @@ -1,40 +1,60 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - diff --git a/app/assets/bundled/svg/context-remaining-30.svg b/app/assets/bundled/svg/context-remaining-30.svg index 89fd8a7254..7d099372ad 100644 --- a/app/assets/bundled/svg/context-remaining-30.svg +++ b/app/assets/bundled/svg/context-remaining-30.svg @@ -1,44 +1,56 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + diff --git a/app/assets/bundled/svg/context-remaining-40.svg b/app/assets/bundled/svg/context-remaining-40.svg index eec0598c32..0a0b130a77 100644 --- a/app/assets/bundled/svg/context-remaining-40.svg +++ b/app/assets/bundled/svg/context-remaining-40.svg @@ -1,46 +1,54 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + - + - + - + - + - + - + diff --git a/app/assets/bundled/svg/context-remaining-50.svg b/app/assets/bundled/svg/context-remaining-50.svg index 7e730a66e2..6eccc18877 100644 --- a/app/assets/bundled/svg/context-remaining-50.svg +++ b/app/assets/bundled/svg/context-remaining-50.svg @@ -1,50 +1,50 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/app/assets/bundled/svg/context-remaining-60.svg b/app/assets/bundled/svg/context-remaining-60.svg index adbd499c3c..bce954852b 100644 --- a/app/assets/bundled/svg/context-remaining-60.svg +++ b/app/assets/bundled/svg/context-remaining-60.svg @@ -1,54 +1,46 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + - + - + - + - + - + diff --git a/app/assets/bundled/svg/context-remaining-70.svg b/app/assets/bundled/svg/context-remaining-70.svg index 513db5a6d8..4f3b1bde95 100644 --- a/app/assets/bundled/svg/context-remaining-70.svg +++ b/app/assets/bundled/svg/context-remaining-70.svg @@ -1,56 +1,44 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - + - + - + - + - + diff --git a/app/assets/bundled/svg/context-remaining-80.svg b/app/assets/bundled/svg/context-remaining-80.svg index 06260a6a37..6c2e644512 100644 --- a/app/assets/bundled/svg/context-remaining-80.svg +++ b/app/assets/bundled/svg/context-remaining-80.svg @@ -1,60 +1,40 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + diff --git a/app/assets/bundled/svg/context-remaining-90.svg b/app/assets/bundled/svg/context-remaining-90.svg index 747ffa68bb..5fa5d801e6 100644 --- a/app/assets/bundled/svg/context-remaining-90.svg +++ b/app/assets/bundled/svg/context-remaining-90.svg @@ -1,62 +1,38 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + + + + + + + + +