Files
galaxy/crates/galaxyui_core/src/notification.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

130 lines
4.0 KiB
Rust

/// At the UI framework level, we have structs for interacting with
/// platform-level notification data (mostly in the form of strings).
/// Similar structs are available at the app level, which are more
/// specific to the data we make use of.
use chrono::NaiveDateTime;
use serde::Serialize;
/// Content to be sent as a notification to the user. Includes `data` that is sent back to
/// application when the notification is clicked--see `NotificationResponse` for more details.
#[derive(Clone, Debug)]
pub struct UserNotification {
title: String,
body: String,
// Arbitrary data associated with the notification.
data: Option<String>,
// Whether to play sound with the notification.
play_sound: bool,
}
impl UserNotification {
/// These limits were discovered experimentally, by testing with example
/// commands/outputs and ensuring the text was not truncated in most cases.
/// The official MacOS docs do not mention specific byte/char constraints.
/// In reality, the strings are limited by the sum of width of the chars,
/// which is dependent on the string itself (e.g. 'W' is much wider than ' ').
pub const MAX_TITLE_LENGTH: usize = 40;
pub const MAX_BODY_LENGTH: usize = 120;
pub fn new(title: String, body: String, data: Option<String>) -> Self {
Self {
title,
body,
data,
play_sound: true,
}
}
pub fn new_with_sound(
title: String,
body: String,
data: Option<String>,
play_sound: bool,
) -> Self {
Self {
title,
body,
data,
play_sound,
}
}
pub fn with_data(mut self, data: impl Into<String>) -> Self {
self.data = Some(data.into());
self
}
pub fn title(&self) -> &str {
self.title.as_str()
}
pub fn body(&self) -> &str {
self.body.as_str()
}
pub fn data(&self) -> Option<&str> {
self.data.as_deref()
}
pub fn play_sound(&self) -> bool {
self.play_sound
}
}
/// A response sent when a notification sent by the app was clicked.
#[derive(Debug)]
pub struct NotificationResponse {
// Time the notification was sent.
sent_date: NaiveDateTime,
/// The data associated with the notification, if any. This matches the data included in the
/// `NotificationContent` when the notification was sent.
data: Option<String>,
}
impl NotificationResponse {
pub fn new(sent_date: NaiveDateTime, data: Option<String>) -> Self {
NotificationResponse { sent_date, data }
}
pub fn sent_date(&self) -> NaiveDateTime {
self.sent_date
}
pub fn data(&self) -> Option<&str> {
self.data.as_deref()
}
}
#[derive(Clone, Debug, Serialize)]
pub enum NotificationSendError {
/// App does not have permissions to send notifications.
PermissionsDenied,
/// On web, there's a difference between permissions being default and being denied. While they are still default,
/// we should prompt the user to accept or block notifications, since they haven't chosen yet.
PermissionsNotYetGranted,
/// Some unknown error occurred when sending the a notification.
Other { error_message: String },
}
impl NotificationSendError {
pub fn notifications_error_banner_title(&self) -> &str {
match self {
NotificationSendError::PermissionsDenied | NotificationSendError::PermissionsNotYetGranted => "Galaxy tried to send you a notification for the last block but does not have permission.",
NotificationSendError::Other { .. } => "Galaxy tried to send you a notification for the last block, but something went wrong.",
}
}
}
#[derive(Clone, Debug, Serialize)]
pub enum RequestPermissionsOutcome {
/// User accepted the request for permissions.
Accepted,
/// User explicitly denied permissions.
PermissionsDenied,
/// Some unknown error occurred when requesting permissions.
OtherError { error_message: String },
}