Files
galaxy/app/src/terminal/blockgrid_renderer.rs
T
Ryan WardandClaude Opus 4.6 6f54e2cb30 v1.4.0: Auto-compact streaming, Bedrock summarization support, subagent orchestration, and Galaxy rebrand continuation
Major features:
- Auto-compact: triggers conversation summarization when context window >= 85%,
  compacts Bedrock message history to a summary pair, and tracks live context tokens
- Bedrock summarization: plumbs `is_summarization` flag through translator/client/response
  pipeline, handles SummarizeConversation input type, and marks `summarized` in metadata
- Session restore: rebuilds bedrock_message_history from persisted task messages via
  newly-public `convert_proto_message`, preventing empty history on reconnect
- Subagent orchestration: adds SubagentQuestion/Answer/CompletionSummary event types,
  parent-child question routing with depth limits, retry counting, and drain methods
- Summarization UI: inline SummarizationView in AI blocks with progress/finished states

Refactors:
- Rename WarpTheme → GalaxyTheme across ~100 files (rebrand continuation)
- Rename warp_home_config_dir → galaxy_home_config_dir and related path functions
- Predefined rules: replace "System Defined Rule #N" with descriptive names
  (e.g. "Correctness Over Speed", "Never Guess") and add lookup helpers
- Usage view: replace cumulative input/output token display with live context tokens,
  cache hit rate calculation, and separate cache read/write stats
- Telemetry: remove verbose doc comments, simplify trait definitions
- Facts view: simplify delete permission check (always allow local deletion)
- Remove warp_managed_paths_watcher.rs (dead code)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-21 11:59:37 -05:00

232 lines
7.6 KiB
Rust

use crate::settings::EnforceMinimumContrast;
use crate::terminal::color;
use crate::terminal::grid_renderer::{render_cursor, render_grid, CellGlyphCache};
use crate::terminal::model::blockgrid::{BlockGrid, CursorDisplayPoint};
use crate::terminal::model::grid::grid_handler::Link;
use crate::terminal::model::index::Point;
use crate::terminal::model::ObfuscateSecrets;
use crate::terminal::SizeInfo;
use crate::themes::theme::GalaxyTheme;
use galaxyui::fonts::{FamilyId, Properties, Weight};
use galaxyui::geometry::rect::RectF;
use galaxyui::geometry::vector::{vec2f, Vector2F};
use galaxyui::{AppContext, Element, EntityId, PaintContext};
use pathfinder_color::ColorU;
use std::collections::HashMap;
use std::ops::Neg;
use std::ops::RangeInclusive;
use super::model::ansi::{CursorShape, CursorStyle};
use super::model::grid::RespectDisplayedOutput;
use super::model::image_map::StoredImageMetadata;
use super::model::SecretHandle;
pub struct GridRenderParams {
pub warp_theme: GalaxyTheme,
pub font_family: FamilyId,
pub font_size: f32,
pub font_weight: Weight,
pub line_height_ratio: f32,
pub enforce_minimum_contrast: EnforceMinimumContrast,
pub obfuscate_secrets: ObfuscateSecrets,
pub size_info: SizeInfo,
pub cell_size: Vector2F,
pub use_ligature_rendering: bool,
/// When true, suppresses cursor rendering for CLI agents when rich input is open. For agents that draw their own cursor (SHOW_CURSOR off),
/// the cursor cell is skipped. For agents that let Warp draw the cursor
/// (SHOW_CURSOR on), the `draw_cursor` call and cursor contrast colouring
/// are suppressed instead.
pub hide_cursor_cell: bool,
}
pub struct BlockGridParams {
pub grid_render_params: GridRenderParams,
pub colors: color::List,
pub override_colors: color::OverrideList,
pub bounds: RectF,
}
impl BlockGrid {
#[allow(clippy::too_many_arguments)]
pub fn draw<'a>(
&self,
grid_origin: Vector2F,
origin: Vector2F,
glyphs: &mut CellGlyphCache,
alpha: u8,
highlighted_url: Option<&Link>,
link_tool_tip: Option<&Link>,
hovered_secret: Option<SecretHandle>,
ordered_matches: Option<impl Iterator<Item = &'a RangeInclusive<Point>>>,
focused_match_range: Option<&RangeInclusive<Point>>,
properties: Properties,
block_grid_params: &BlockGridParams,
visible_cursor_shape: Option<CursorShape>,
image_metadata: &HashMap<u32, StoredImageMetadata>,
ctx: &mut PaintContext,
app: &AppContext,
) {
let start_row = hidden_rows_above(
grid_origin,
origin,
block_grid_params.grid_render_params.cell_size,
);
let hidden_rows_below = hidden_rows_below(
grid_origin,
origin,
block_grid_params.grid_render_params.cell_size,
block_grid_params.bounds,
self.len_displayed(),
);
let end_row = self.len_displayed().saturating_sub(hidden_rows_below);
let grid = self.grid_handler();
let obfuscate_secrets = block_grid_params
.grid_render_params
.obfuscate_secrets
.and(&grid.get_secret_obfuscation());
render_grid(
grid,
start_row,
end_row,
&block_grid_params.colors,
&block_grid_params.override_colors,
&block_grid_params.grid_render_params.warp_theme,
properties,
block_grid_params.grid_render_params.font_family,
block_grid_params.grid_render_params.font_size,
block_grid_params.grid_render_params.line_height_ratio,
block_grid_params.grid_render_params.cell_size,
block_grid_params
.grid_render_params
.size_info
.padding_x_px(),
grid_origin,
glyphs,
alpha,
highlighted_url,
link_tool_tip,
ordered_matches,
focused_match_range,
block_grid_params
.grid_render_params
.enforce_minimum_contrast,
obfuscate_secrets,
hovered_secret,
block_grid_params.grid_render_params.use_ligature_rendering,
visible_cursor_shape,
RespectDisplayedOutput::Yes,
image_metadata,
None,
block_grid_params.grid_render_params.hide_cursor_cell,
ctx,
app,
);
}
pub fn draw_with_default_params(
&self,
grid_origin: Vector2F,
origin: Vector2F,
block_grid_params: &BlockGridParams,
ctx: &mut PaintContext,
app: &AppContext,
) {
let mut glyphs = CellGlyphCache::default();
self.draw(
grid_origin,
origin,
&mut glyphs,
255,
None,
None,
None,
None::<std::iter::Empty<&RangeInclusive<Point>>>,
None,
Properties::default(),
block_grid_params,
None,
&HashMap::new(),
ctx,
app,
)
}
#[allow(clippy::too_many_arguments)]
pub fn draw_cursor(
&self,
grid_origin: Vector2F,
grid_render_params: &GridRenderParams,
ctx: &mut PaintContext,
terminal_view_id: EntityId,
cursor_hint_text: Option<&mut Box<dyn Element>>,
color: ColorU,
app: &AppContext,
) {
let cursor_style = self.cursor_style();
let (cursor_display_point, is_cursor_on_wide_char, cursor_style, cursor_hint_text) =
match self.cursor_display_point() {
Some(CursorDisplayPoint::Visible(cursor_display_point)) => (
cursor_display_point,
self.grid_handler().is_cursor_on_wide_char(),
cursor_style,
cursor_hint_text,
),
Some(CursorDisplayPoint::HiddenCache(cursor_display_point)) => (
cursor_display_point,
false,
CursorStyle {
shape: CursorShape::Hidden,
..cursor_style
},
None,
),
None => return,
};
render_cursor(
grid_render_params,
cursor_display_point,
is_cursor_on_wide_char,
cursor_style,
grid_render_params.size_info.padding_x_px(),
grid_origin,
color,
ctx,
terminal_view_id,
cursor_hint_text,
app,
)
}
}
fn lines_to_pixels(line: usize, cell_size: Vector2F) -> Vector2F {
vec2f(0., line as f32 * cell_size.y())
}
fn pixels_to_lines(coord: Vector2F, cell_size: Vector2F) -> usize {
(coord.y() / cell_size.y()) as usize
}
/// Computes the number of rows that are not visible in the current grid above the viewport.
fn hidden_rows_above(grid_origin: Vector2F, origin: Vector2F, cell_size: Vector2F) -> usize {
((grid_origin.y() - origin.y()) / cell_size.y())
.neg()
.max(0.)
.floor() as usize
}
/// Computes the number of rows that are not visible in the grid below the viewport.
fn hidden_rows_below(
grid_origin: Vector2F,
origin: Vector2F,
cell_size: Vector2F,
bounds: RectF,
grid_len: usize,
) -> usize {
let grid_end = grid_origin + lines_to_pixels(grid_len, cell_size);
let lower_left = origin.y() + bounds.height();
pixels_to_lines(grid_end - lower_left, cell_size)
}