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>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
eaa2ddc75e
commit
6f54e2cb30
@@ -30,7 +30,7 @@ use galaxy_core::features::FeatureFlag;
|
||||
use galaxy_core::send_telemetry_from_ctx;
|
||||
use galaxy_core::ui::appearance::Appearance;
|
||||
use galaxy_core::ui::theme::color::internal_colors;
|
||||
use galaxy_core::ui::theme::WarpTheme;
|
||||
use galaxy_core::ui::theme::GalaxyTheme;
|
||||
use galaxyui::color::ColorU;
|
||||
use galaxyui::{EntityId, ModelContext, SingletonEntity};
|
||||
use uuid::Uuid;
|
||||
@@ -235,6 +235,19 @@ pub struct AIConversation {
|
||||
/// tool calls, and tool results sent to/received from Bedrock across all
|
||||
/// request cycles. This is the source of truth for what Bedrock sees.
|
||||
bedrock_message_history: Vec<crate::ai::bedrock::convert::ConversationMessage>,
|
||||
|
||||
/// Live context token count from the most recent Bedrock response.
|
||||
/// This is the actual input_tokens reported by Bedrock — represents the current
|
||||
/// context window size, NOT a cumulative total.
|
||||
current_context_tokens: u32,
|
||||
|
||||
/// Guards against repeated auto-compact triggers within the same high-usage window.
|
||||
/// Set to true when auto-compact fires; reset when summarization completes.
|
||||
has_pending_auto_compact: bool,
|
||||
|
||||
/// Number of times this child agent conversation has been automatically
|
||||
/// restarted after a transient error. Capped at MAX_SUBAGENT_RETRIES.
|
||||
subagent_retry_count: u8,
|
||||
}
|
||||
|
||||
pub(crate) fn artifact_from_fork_proto(
|
||||
@@ -287,6 +300,9 @@ impl AIConversation {
|
||||
is_remote_child: false,
|
||||
last_event_sequence: None,
|
||||
bedrock_message_history: Vec::new(),
|
||||
current_context_tokens: 0,
|
||||
has_pending_auto_compact: false,
|
||||
subagent_retry_count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +330,20 @@ impl AIConversation {
|
||||
.cmp(depths.get(a.as_str()).unwrap_or(&0))
|
||||
});
|
||||
|
||||
// Collect all task messages for rebuilding bedrock_message_history on restore.
|
||||
// We must do this before consuming the tasks into exchanges.
|
||||
let all_task_messages: Vec<&api::Message> = api_tasks_by_id
|
||||
.values()
|
||||
.flat_map(|task| task.messages.iter())
|
||||
.collect();
|
||||
let bedrock_message_history: Vec<crate::ai::bedrock::convert::ConversationMessage> =
|
||||
all_task_messages
|
||||
.iter()
|
||||
.filter_map(|msg| {
|
||||
crate::ai::bedrock::request_translator::convert_proto_message(msg)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut api_tasks_and_exchanges_by_id: HashMap<_, _> = api_tasks_by_id
|
||||
.into_iter()
|
||||
.map(|(id, task)| {
|
||||
@@ -469,7 +499,10 @@ impl AIConversation {
|
||||
parent_conversation_id,
|
||||
is_remote_child: false,
|
||||
last_event_sequence,
|
||||
bedrock_message_history: Vec::new(),
|
||||
bedrock_message_history,
|
||||
current_context_tokens: 0,
|
||||
has_pending_auto_compact: false,
|
||||
subagent_retry_count: 0,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -521,6 +554,26 @@ impl AIConversation {
|
||||
self.conversation_usage_metadata.context_window_usage
|
||||
}
|
||||
|
||||
pub fn set_context_window_usage(&mut self, value: f32) {
|
||||
self.conversation_usage_metadata.context_window_usage = value;
|
||||
}
|
||||
|
||||
pub fn current_context_tokens(&self) -> u32 {
|
||||
self.current_context_tokens
|
||||
}
|
||||
|
||||
pub fn set_current_context_tokens(&mut self, tokens: u32) {
|
||||
self.current_context_tokens = tokens;
|
||||
}
|
||||
|
||||
pub fn has_pending_auto_compact(&self) -> bool {
|
||||
self.has_pending_auto_compact
|
||||
}
|
||||
|
||||
pub fn set_has_pending_auto_compact(&mut self, value: bool) {
|
||||
self.has_pending_auto_compact = value;
|
||||
}
|
||||
|
||||
pub fn credits_spent(&self) -> f32 {
|
||||
(self.conversation_usage_metadata.credits_spent * 10.0).round() / 10.0
|
||||
}
|
||||
@@ -859,6 +912,14 @@ impl AIConversation {
|
||||
self.is_remote_child = true;
|
||||
}
|
||||
|
||||
pub fn subagent_retry_count(&self) -> u8 {
|
||||
self.subagent_retry_count
|
||||
}
|
||||
|
||||
pub fn increment_subagent_retry_count(&mut self) {
|
||||
self.subagent_retry_count = self.subagent_retry_count.saturating_add(1);
|
||||
}
|
||||
|
||||
/// Returns a flat list of linearized messages across all tasks, interpolating subtask messages
|
||||
/// in between subagent tool calls and results, effectively corresponding to the order in which
|
||||
/// the messages were created and added to the conversation.
|
||||
@@ -1566,6 +1627,17 @@ impl AIConversation {
|
||||
if was_user_initiated_request {
|
||||
self.last_block_token_usage_by_model.clear();
|
||||
}
|
||||
|
||||
// Update live context token count from this response's input tokens.
|
||||
// This represents the actual current context window size (not cumulative).
|
||||
let live_input: u32 = token_usage
|
||||
.iter()
|
||||
.map(|u| u.total_input + u.input_cache_read + u.input_cache_write)
|
||||
.sum();
|
||||
if live_input > 0 {
|
||||
self.current_context_tokens = live_input;
|
||||
}
|
||||
|
||||
for usage in token_usage.into_iter() {
|
||||
let entry = self
|
||||
.total_token_usage_by_model
|
||||
@@ -1666,6 +1738,7 @@ impl AIConversation {
|
||||
// so we only update the summarized flag if it's going from false to true.
|
||||
if usage_metadata.summarized && !self.conversation_usage_metadata.was_summarized {
|
||||
self.conversation_usage_metadata.was_summarized = usage_metadata.summarized;
|
||||
self.has_pending_auto_compact = false;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -3844,7 +3917,7 @@ impl ConversationStatus {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn status_icon_and_color(&self, theme: &WarpTheme) -> (Icon, ColorU) {
|
||||
pub fn status_icon_and_color(&self, theme: &GalaxyTheme) -> (Icon, ColorU) {
|
||||
match self {
|
||||
ConversationStatus::InProgress => (Icon::ClockLoader, theme.ansi_fg_magenta()),
|
||||
ConversationStatus::Success => (Icon::Check, theme.ansi_fg_green()),
|
||||
|
||||
Reference in New Issue
Block a user