first pass of merging in warp (doesn't build)
This commit is contained in:
@@ -1,89 +1,75 @@
|
||||
use std::{collections::HashSet, sync::Arc, time::Duration};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::{
|
||||
cli_controller::{CLISubagentController, CLISubagentEvent, UserTakeOverReason},
|
||||
model::{AIBlockModel, AIBlockModelImpl, AIBlockOutputStatus},
|
||||
view_impl::common::{
|
||||
random_load_output_message, render_switch_control_to_user_button, render_warping_indicator,
|
||||
render_warping_indicator_base, ButtonProps, ForceRefreshButtonProps, MaybeShimmeringText,
|
||||
WarpingIndicatorProps, WarpingProps, WAITING_FOR_USER_INPUT_MESSAGE,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
ai::agent_tips::AITipModel,
|
||||
terminal::{
|
||||
input::buffer_model::InputBufferUpdateEvent,
|
||||
view::ambient_agent::is_cloud_agent_pre_first_exchange,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
ai::blocklist::agent_view::{
|
||||
agent_view_bg_fill, child_agent_status_card::ChildAgentStatusCard, AgentMessageBar,
|
||||
AgentViewController, EphemeralMessageModel,
|
||||
},
|
||||
terminal::input::{
|
||||
buffer_model::InputBufferModel,
|
||||
message_bar::common::render_standard_message_bar,
|
||||
message_bar::{Message, MessageItem},
|
||||
slash_command_model::SlashCommandModel,
|
||||
suggestions_mode_model::InputSuggestionsModeModel,
|
||||
},
|
||||
};
|
||||
use warp_multi_agent_api as api;
|
||||
|
||||
use crate::{
|
||||
ai::{
|
||||
agent::{
|
||||
conversation::AIConversationId, icons, AIAgentExchangeId, AIAgentOutput,
|
||||
AIAgentOutputMessageType, CancellationReason, SummarizationType,
|
||||
},
|
||||
blocklist::{
|
||||
agent_view::shortcuts::AgentShortcutViewModel,
|
||||
ai_brand_color,
|
||||
model::AIBlockModelHelper,
|
||||
summarization_cancel_dialog::{
|
||||
self, SummarizationCancelDialog, SummarizationCancelDialogEvent,
|
||||
},
|
||||
BlocklistAIActionEvent, BlocklistAIActionModel, BlocklistAIContextEvent,
|
||||
BlocklistAIContextModel, BlocklistAIController, BlocklistAIHistoryEvent,
|
||||
BlocklistAIInputEvent, BlocklistAIInputModel, ResponseStreamId,
|
||||
},
|
||||
llms::LLMPreferences,
|
||||
AgentTip,
|
||||
},
|
||||
send_telemetry_from_app_ctx,
|
||||
server::telemetry::TelemetryEvent,
|
||||
settings::{InputModeSettings, InputSettings},
|
||||
settings_view::keybindings::KeybindingChangedNotifier,
|
||||
terminal::{
|
||||
input::SET_INPUT_MODE_TERMINAL_ACTION_NAME,
|
||||
model::block::LONG_RUNNING_COMMAND_DURATION_MS,
|
||||
model_events::{ModelEvent, ModelEventDispatcher},
|
||||
view::ambient_agent::{AmbientAgentViewModel, AmbientAgentViewModelEvent},
|
||||
warpify::render::LEFT_STRIPE_WIDTH,
|
||||
TerminalModel, CANCEL_COMMAND_KEYBINDING, TOGGLE_AUTOEXECUTE_MODE_KEYBINDING,
|
||||
TOGGLE_HIDE_CLI_RESPONSES_KEYBINDING, TOGGLE_QUEUE_NEXT_PROMPT_KEYBINDING,
|
||||
},
|
||||
util::bindings::keybinding_name_to_keystroke,
|
||||
BlocklistAIHistoryModel,
|
||||
};
|
||||
use galaxy_core::{
|
||||
features::FeatureFlag,
|
||||
ui::{appearance::Appearance, theme::Fill, Icon as CoreIcon},
|
||||
};
|
||||
use galaxyui::elements::shimmering_text::ShimmeringTextStateHandle;
|
||||
use galaxyui::{
|
||||
elements::{Border, Container, Empty, Flex, MouseStateHandle, ParentElement, Text},
|
||||
keymap::Keystroke,
|
||||
presenter::ChildView,
|
||||
r#async::SpawnedFutureHandle,
|
||||
AppContext, Element, Entity, EntityId, ModelHandle, SingletonEntity, View, ViewContext,
|
||||
ViewHandle,
|
||||
};
|
||||
use galaxyui::{r#async::Timer, TypedActionView};
|
||||
use instant::Instant;
|
||||
use markdown_parser::FormattedTextFragment;
|
||||
use parking_lot::FairMutex;
|
||||
use pathfinder_color::ColorU;
|
||||
use galaxy_core::features::FeatureFlag;
|
||||
use galaxy_core::ui::appearance::Appearance;
|
||||
use galaxy_core::ui::theme::Fill;
|
||||
use galaxy_core::ui::Icon as CoreIcon;
|
||||
use warp_multi_agent_api as api;
|
||||
use galaxyui::elements::shimmering_text::ShimmeringTextStateHandle;
|
||||
use galaxyui::elements::{Border, Container, Empty, Flex, MouseStateHandle, ParentElement, Text};
|
||||
use galaxyui::keymap::Keystroke;
|
||||
use galaxyui::presenter::ChildView;
|
||||
use galaxyui::r#async::{SpawnedFutureHandle, Timer};
|
||||
use galaxyui::{
|
||||
AppContext, Element, Entity, EntityId, ModelHandle, SingletonEntity, TypedActionView, View,
|
||||
ViewContext, ViewHandle,
|
||||
};
|
||||
|
||||
use super::cli_controller::{CLISubagentController, CLISubagentEvent, UserTakeOverReason};
|
||||
use super::model::{AIBlockModel, AIBlockModelImpl, AIBlockOutputStatus};
|
||||
use super::view_impl::common::{
|
||||
render_switch_control_to_user_button, render_warping_indicator, render_warping_indicator_base,
|
||||
AutoExecuteButtonProps, ButtonProps, ForceRefreshButtonProps, MaybeShimmeringText,
|
||||
WarpingIndicatorProps, WarpingProps, LOAD_OUTPUT_MESSAGE, WAITING_FOR_USER_INPUT_MESSAGE,
|
||||
};
|
||||
use crate::ai::agent::conversation::AIConversationId;
|
||||
use crate::ai::agent::{
|
||||
icons, AIAgentExchangeId, AIAgentOutput, AIAgentOutputMessageType, CancellationReason,
|
||||
SummarizationType,
|
||||
};
|
||||
use crate::ai::agent_tips::AITipModel;
|
||||
use crate::ai::blocklist::agent_view::shortcuts::AgentShortcutViewModel;
|
||||
use crate::ai::blocklist::agent_view::{
|
||||
agent_view_bg_fill, is_in_cloud_context, AgentMessageBar, AgentViewController,
|
||||
EphemeralMessageModel,
|
||||
};
|
||||
use crate::ai::blocklist::model::AIBlockModelHelper;
|
||||
use crate::ai::blocklist::summarization_cancel_dialog::{
|
||||
self, SummarizationCancelDialog, SummarizationCancelDialogEvent,
|
||||
};
|
||||
use crate::ai::blocklist::{
|
||||
ai_brand_color, BlocklistAIActionEvent, BlocklistAIActionModel, BlocklistAIContextEvent,
|
||||
BlocklistAIContextModel, BlocklistAIController, BlocklistAIHistoryEvent, BlocklistAIInputEvent,
|
||||
BlocklistAIInputModel, QueuedQueryEvent, QueuedQueryModel, ResponseStreamId,
|
||||
};
|
||||
use crate::ai::llms::LLMPreferences;
|
||||
use crate::ai::AgentTip;
|
||||
use crate::server::telemetry::TelemetryEvent;
|
||||
use crate::settings::{InputModeSettings, InputSettings};
|
||||
use crate::settings_view::keybindings::KeybindingChangedNotifier;
|
||||
use crate::terminal::input::buffer_model::{InputBufferModel, InputBufferUpdateEvent};
|
||||
use crate::terminal::input::message_bar::common::render_wrapping_standard_message_bar;
|
||||
use crate::terminal::input::slash_command_model::SlashCommandModel;
|
||||
use crate::terminal::input::suggestions_mode_model::InputSuggestionsModeModel;
|
||||
use crate::terminal::input::{HandoffComposeState, SET_INPUT_MODE_TERMINAL_ACTION_NAME};
|
||||
use crate::terminal::model::block::LONG_RUNNING_COMMAND_DURATION_MS;
|
||||
use crate::terminal::model_events::{ModelEvent, ModelEventDispatcher};
|
||||
use crate::terminal::view::ambient_agent::{
|
||||
is_cloud_agent_pre_first_exchange, AmbientAgentViewModel, AmbientAgentViewModelEvent,
|
||||
};
|
||||
use crate::terminal::warpify::render::LEFT_STRIPE_WIDTH;
|
||||
use crate::terminal::{
|
||||
TerminalModel, CANCEL_COMMAND_KEYBINDING, TOGGLE_AUTOEXECUTE_MODE_KEYBINDING,
|
||||
TOGGLE_HIDE_CLI_RESPONSES_KEYBINDING, TOGGLE_QUEUE_NEXT_PROMPT_KEYBINDING,
|
||||
};
|
||||
use crate::util::bindings::keybinding_name_to_keystroke;
|
||||
use crate::{send_telemetry_from_app_ctx, BlocklistAIHistoryModel};
|
||||
|
||||
pub fn init(app: &mut AppContext) {
|
||||
summarization_cancel_dialog::init(app);
|
||||
@@ -96,7 +82,6 @@ struct StateHandles {
|
||||
stop_button: MouseStateHandle,
|
||||
take_over_button: MouseStateHandle,
|
||||
hide_cli_responses_button: MouseStateHandle,
|
||||
github_auth_link: MouseStateHandle,
|
||||
/// Tracks hover/press state for the inline `Check now` affordance rendered next to
|
||||
/// `Last seen by agent ...` while the agent is polling a long-running command.
|
||||
force_refresh_button: MouseStateHandle,
|
||||
@@ -113,7 +98,7 @@ pub struct BlocklistAIStatusBar {
|
||||
terminal_model: Arc<FairMutex<TerminalModel>>,
|
||||
shimmering_text_handle: ShimmeringTextStateHandle,
|
||||
state_handles: StateHandles,
|
||||
ambient_agent_view_model: ModelHandle<AmbientAgentViewModel>,
|
||||
ambient_agent_view_model: Option<ModelHandle<AmbientAgentViewModel>>,
|
||||
|
||||
autoexecute_keystroke: Option<Keystroke>,
|
||||
queue_next_prompt_keystroke: Option<Keystroke>,
|
||||
@@ -146,7 +131,6 @@ pub struct BlocklistAIStatusBar {
|
||||
|
||||
ephemeral_message_model: ModelHandle<EphemeralMessageModel>,
|
||||
agent_message_bar: ViewHandle<AgentMessageBar>,
|
||||
child_agent_status_card: ViewHandle<ChildAgentStatusCard>,
|
||||
}
|
||||
|
||||
impl BlocklistAIStatusBar {
|
||||
@@ -162,17 +146,18 @@ impl BlocklistAIStatusBar {
|
||||
model_event_dispatcher: &ModelHandle<ModelEventDispatcher>,
|
||||
terminal_model: Arc<FairMutex<TerminalModel>>,
|
||||
shortcut_view_model: ModelHandle<AgentShortcutViewModel>,
|
||||
ambient_agent_view_model: ModelHandle<AmbientAgentViewModel>,
|
||||
ambient_agent_view_model: Option<ModelHandle<AmbientAgentViewModel>>,
|
||||
input_suggestions_model: ModelHandle<InputSuggestionsModeModel>,
|
||||
slash_command_model: ModelHandle<SlashCommandModel>,
|
||||
ephemeral_message_model: ModelHandle<EphemeralMessageModel>,
|
||||
handoff_compose_state: ModelHandle<HandoffComposeState>,
|
||||
terminal_view_id: EntityId,
|
||||
ctx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let history_model = BlocklistAIHistoryModel::handle(ctx);
|
||||
ctx.subscribe_to_model(&history_model, move |me, _, event, ctx| {
|
||||
if event
|
||||
.terminal_view_id()
|
||||
.terminal_surface_id()
|
||||
.is_some_and(|id| id != terminal_view_id)
|
||||
{
|
||||
return;
|
||||
@@ -189,7 +174,7 @@ impl BlocklistAIStatusBar {
|
||||
}
|
||||
me.reset_model_for_exchange(*exchange_id, *conversation_id, ctx);
|
||||
}
|
||||
BlocklistAIHistoryEvent::ClearedConversationsInTerminalView { .. } => {
|
||||
BlocklistAIHistoryEvent::ClearedConversationsForTerminalSurface { .. } => {
|
||||
me.active_exchange_model = None;
|
||||
me.stop_warping_timer();
|
||||
ctx.notify();
|
||||
@@ -234,10 +219,15 @@ impl BlocklistAIStatusBar {
|
||||
}
|
||||
});
|
||||
ctx.subscribe_to_model(&context_model, |_, _, event, ctx| {
|
||||
if matches!(event, BlocklistAIContextEvent::PendingQueryStateUpdated) {
|
||||
ctx.notify();
|
||||
}
|
||||
});
|
||||
ctx.subscribe_to_model(&QueuedQueryModel::handle(ctx), |_, _, event, ctx| {
|
||||
if matches!(
|
||||
event,
|
||||
BlocklistAIContextEvent::PendingQueryStateUpdated
|
||||
| BlocklistAIContextEvent::QueueNextPromptToggled
|
||||
QueuedQueryEvent::QueueNextPromptToggled { .. }
|
||||
| QueuedQueryEvent::DefaultModeChanged
|
||||
) {
|
||||
ctx.notify();
|
||||
}
|
||||
@@ -303,6 +293,11 @@ impl BlocklistAIStatusBar {
|
||||
ctx.notify();
|
||||
});
|
||||
|
||||
ctx.observe(&AITipModel::handle(ctx), |me, tip_model, ctx| {
|
||||
me.current_tip = tip_model.as_ref(ctx).current_tip().cloned();
|
||||
ctx.notify();
|
||||
});
|
||||
|
||||
let summarization_cancel_dialog =
|
||||
ctx.add_typed_action_view(|_| SummarizationCancelDialog::default());
|
||||
ctx.subscribe_to_view(
|
||||
@@ -347,7 +342,7 @@ impl BlocklistAIStatusBar {
|
||||
ctx.notify();
|
||||
});
|
||||
|
||||
let agent_message_bar = ctx.add_view(|ctx| {
|
||||
let agent_message_bar = ctx.add_typed_action_view(|ctx| {
|
||||
AgentMessageBar::new(
|
||||
agent_view_controller.clone(),
|
||||
ephemeral_message_model.clone(),
|
||||
@@ -357,28 +352,28 @@ impl BlocklistAIStatusBar {
|
||||
input_suggestions_model,
|
||||
slash_command_model,
|
||||
context_model.clone(),
|
||||
handoff_compose_state,
|
||||
terminal_model.clone(),
|
||||
ctx,
|
||||
)
|
||||
});
|
||||
|
||||
let child_agent_status_card = ctx.add_typed_action_view(|ctx| {
|
||||
ChildAgentStatusCard::new(agent_view_controller.clone(), ctx)
|
||||
});
|
||||
ctx.subscribe_to_model(&ambient_agent_view_model, |me, _, event, ctx| match event {
|
||||
AmbientAgentViewModelEvent::DispatchedAgent
|
||||
| AmbientAgentViewModelEvent::ProgressUpdated => {
|
||||
me.update_agent_tip(ctx);
|
||||
ctx.notify();
|
||||
}
|
||||
AmbientAgentViewModelEvent::SessionReady { .. }
|
||||
| AmbientAgentViewModelEvent::Failed { .. }
|
||||
| AmbientAgentViewModelEvent::NeedsGithubAuth
|
||||
| AmbientAgentViewModelEvent::Cancelled => {
|
||||
ctx.notify();
|
||||
}
|
||||
_ => (),
|
||||
});
|
||||
if let Some(ambient_agent_view_model) = ambient_agent_view_model.as_ref() {
|
||||
ctx.subscribe_to_model(ambient_agent_view_model, |me, _, event, ctx| match event {
|
||||
AmbientAgentViewModelEvent::DispatchedAgent
|
||||
| AmbientAgentViewModelEvent::ProgressUpdated => {
|
||||
me.update_agent_tip(ctx);
|
||||
ctx.notify();
|
||||
}
|
||||
AmbientAgentViewModelEvent::SessionReady { .. }
|
||||
| AmbientAgentViewModelEvent::Failed { .. }
|
||||
| AmbientAgentViewModelEvent::NeedsGithubAuth
|
||||
| AmbientAgentViewModelEvent::Cancelled => {
|
||||
ctx.notify();
|
||||
}
|
||||
_ => (),
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
active_exchange_model: None,
|
||||
@@ -409,7 +404,6 @@ impl BlocklistAIStatusBar {
|
||||
current_tip: None,
|
||||
ephemeral_message_model,
|
||||
agent_message_bar,
|
||||
child_agent_status_card,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,23 +903,28 @@ impl BlocklistAIStatusBar {
|
||||
shimmering_text_handle: &self.shimmering_text_handle,
|
||||
summarization_start_time: self.summarization_start_time,
|
||||
auto_execute_button: (!model.request_type(app).is_passive_code_diff()).then_some(
|
||||
ButtonProps {
|
||||
AutoExecuteButtonProps {
|
||||
button_handle: &self.state_handles.autoexecute_button,
|
||||
keystroke: self.autoexecute_keystroke.as_ref(),
|
||||
is_active: model
|
||||
.conversation(app)
|
||||
.map(|c| c.autoexecute_any_action())
|
||||
.unwrap_or(false),
|
||||
is_locked: is_in_cloud_context(
|
||||
terminal_model.block_list().agent_view_state(),
|
||||
&terminal_model,
|
||||
),
|
||||
},
|
||||
),
|
||||
queue_next_prompt_button: FeatureFlag::QueueSlashCommand.is_enabled().then_some(
|
||||
ButtonProps {
|
||||
button_handle: &self.state_handles.queue_next_prompt_button,
|
||||
keystroke: self.queue_next_prompt_keystroke.as_ref(),
|
||||
is_active: self
|
||||
.context_model
|
||||
.as_ref(app)
|
||||
.is_queue_next_prompt_enabled(),
|
||||
is_active: QueuedQueryModel::as_ref(app).is_queue_next_prompt_enabled(
|
||||
conversation.id(),
|
||||
active_block,
|
||||
app,
|
||||
),
|
||||
},
|
||||
),
|
||||
stop_button: Some(ButtonProps {
|
||||
@@ -961,16 +960,21 @@ impl BlocklistAIStatusBar {
|
||||
return None;
|
||||
}
|
||||
|
||||
let ambient_agent_model = self.ambient_agent_view_model.as_ref(app);
|
||||
let ambient_agent_model = self
|
||||
.ambient_agent_view_model
|
||||
.as_ref()
|
||||
.map(|ambient_agent_view_model| ambient_agent_view_model.as_ref(app))?;
|
||||
|
||||
// The step indicator is only meaningful while a spawn is in flight. Terminal states
|
||||
// (`Failed`, `NeedsGithubAuth`, `Cancelled`) still carry an `AgentProgress` for
|
||||
// telemetry purposes, so guard on `is_waiting_for_session()` rather than relying on
|
||||
// `agent_progress()` being `None`.
|
||||
if !ambient_agent_model.is_waiting_for_session() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let progress = ambient_agent_model.agent_progress()?;
|
||||
let progress_text = if progress.harness_started_at.is_some() {
|
||||
"Starting Environment (Step 3/3)"
|
||||
} else if progress.claimed_at.is_some() {
|
||||
"Creating Environment (Step 2/3)"
|
||||
} else {
|
||||
"Connecting to Host (Step 1/3)"
|
||||
};
|
||||
let progress_text = progress.setup_status_text();
|
||||
Some(render_warping_indicator_base(
|
||||
WarpingIndicatorProps {
|
||||
icon: None,
|
||||
@@ -988,58 +992,58 @@ impl BlocklistAIStatusBar {
|
||||
))
|
||||
}
|
||||
|
||||
fn render_cloud_mode_setup_terminal_message(&self, app: &AppContext) -> Option<Message> {
|
||||
fn render_cloud_mode_setup_terminal_message(
|
||||
&self,
|
||||
app: &AppContext,
|
||||
) -> Option<Box<dyn Element>> {
|
||||
if !FeatureFlag::CloudModeSetupV2.is_enabled() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let ambient_agent_model = self.ambient_agent_view_model.as_ref(app);
|
||||
let ambient_agent_model = self
|
||||
.ambient_agent_view_model
|
||||
.as_ref()
|
||||
.map(|ambient_agent_view_model| ambient_agent_view_model.as_ref(app))?;
|
||||
let theme = Appearance::as_ref(app).theme();
|
||||
let error_color = theme.ansi_fg_red();
|
||||
|
||||
if let Some(auth_url) = ambient_agent_model.github_auth_url() {
|
||||
return Some(Message::new(vec![
|
||||
MessageItem::Icon {
|
||||
icon: CoreIcon::Triangle,
|
||||
color: Some(error_color),
|
||||
},
|
||||
MessageItem::Text {
|
||||
content: "Missing GitHub authentication. ".into(),
|
||||
color: Some(error_color),
|
||||
},
|
||||
MessageItem::hyperlink(
|
||||
"Authenticate GitHub",
|
||||
auth_url.to_owned(),
|
||||
self.state_handles.github_auth_link.clone(),
|
||||
),
|
||||
]));
|
||||
}
|
||||
|
||||
if let Some(error_message) = ambient_agent_model.error_message() {
|
||||
return Some(Message::new(vec![
|
||||
MessageItem::Icon {
|
||||
icon: CoreIcon::Triangle,
|
||||
color: Some(error_color),
|
||||
},
|
||||
MessageItem::Text {
|
||||
content: error_message.to_owned().into(),
|
||||
color: Some(error_color),
|
||||
},
|
||||
]));
|
||||
let error_message = ambient_agent_model
|
||||
.github_auth_error_message()
|
||||
.unwrap_or("Missing GitHub authentication.");
|
||||
return Some(render_wrapping_standard_message_bar(
|
||||
CoreIcon::Triangle,
|
||||
error_color,
|
||||
error_color,
|
||||
vec![
|
||||
FormattedTextFragment::plain_text(format!("{error_message} ")),
|
||||
FormattedTextFragment::hyperlink("Authenticate GitHub", auth_url.to_owned()),
|
||||
],
|
||||
app,
|
||||
));
|
||||
}
|
||||
|
||||
if ambient_agent_model.is_cancelled() {
|
||||
let color = theme.disabled_text_color(theme.background()).into_solid();
|
||||
return Some(Message::new(vec![
|
||||
MessageItem::Icon {
|
||||
icon: CoreIcon::StopFilled,
|
||||
color: Some(color),
|
||||
},
|
||||
MessageItem::Text {
|
||||
content: "Cloud agent run cancelled".into(),
|
||||
color: Some(color),
|
||||
},
|
||||
]));
|
||||
return Some(render_wrapping_standard_message_bar(
|
||||
CoreIcon::StopFilled,
|
||||
color,
|
||||
color,
|
||||
vec![FormattedTextFragment::plain_text(
|
||||
"Cloud agent run cancelled",
|
||||
)],
|
||||
app,
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(error_message) = ambient_agent_model.error_message() {
|
||||
return Some(render_wrapping_standard_message_bar(
|
||||
CoreIcon::Triangle,
|
||||
error_color,
|
||||
error_color,
|
||||
vec![FormattedTextFragment::plain_text(error_message.to_owned())],
|
||||
app,
|
||||
));
|
||||
}
|
||||
|
||||
None
|
||||
@@ -1065,15 +1069,16 @@ fn latest_model_used_before_exchange<V: View>(
|
||||
model_id: model_info.model_id.to_string(),
|
||||
model_display_name: model_info.display_name.clone(),
|
||||
is_fallback: model_info.is_fallback,
|
||||
prompt_cache_expires_at: None,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn render_agent_tip(tip: &AgentTip, app: &AppContext) -> Box<dyn Element> {
|
||||
use crate::ai::agent_tips::AITip;
|
||||
use galaxyui::text_layout::ClipConfig;
|
||||
use markdown_parser::{FormattedTextFragment, FormattedTextLine};
|
||||
|
||||
use crate::ai::agent_tips::AITip;
|
||||
|
||||
let appearance = Appearance::as_ref(app);
|
||||
let theme = appearance.theme();
|
||||
|
||||
@@ -1218,17 +1223,24 @@ impl View for BlocklistAIStatusBar {
|
||||
if let Some(cloud_mode_setup_terminal_message) =
|
||||
self.render_cloud_mode_setup_terminal_message(app)
|
||||
{
|
||||
return render_standard_message_bar(cloud_mode_setup_terminal_message, None, app);
|
||||
return cloud_mode_setup_terminal_message;
|
||||
}
|
||||
let status_element =
|
||||
if let Some(cloud_mode_setup_status) = self.render_cloud_mode_setup_status(app) {
|
||||
cloud_mode_setup_status
|
||||
} else if FeatureFlag::CloudModeSetupV2.is_enabled()
|
||||
&& is_cloud_agent_pre_first_exchange(
|
||||
&self.ambient_agent_view_model,
|
||||
&self.agent_view_controller,
|
||||
app,
|
||||
)
|
||||
&& self
|
||||
.ambient_agent_view_model
|
||||
.as_ref()
|
||||
.is_some_and(|ambient_agent_view_model| {
|
||||
let terminal_model = self.terminal_model.lock();
|
||||
is_cloud_agent_pre_first_exchange(
|
||||
Some(ambient_agent_view_model),
|
||||
&self.agent_view_controller,
|
||||
&terminal_model,
|
||||
app,
|
||||
)
|
||||
})
|
||||
{
|
||||
render_warping_indicator_base(
|
||||
WarpingIndicatorProps {
|
||||
@@ -1288,16 +1300,20 @@ impl View for BlocklistAIStatusBar {
|
||||
.is_none(),
|
||||
) {
|
||||
warping_indicator
|
||||
} else if self
|
||||
.ambient_agent_view_model
|
||||
.as_ref(app)
|
||||
.is_waiting_for_session()
|
||||
{
|
||||
} else if self.ambient_agent_view_model.as_ref().is_some_and(
|
||||
|ambient_agent_view_model| {
|
||||
ambient_agent_view_model
|
||||
.as_ref(app)
|
||||
.is_waiting_for_session()
|
||||
},
|
||||
) {
|
||||
// Don't render warping indicator - the loading screen is shown in the main view
|
||||
return Empty::new().finish();
|
||||
} else if agent_view_controller.is_active() {
|
||||
// The orchestration pill bar in the agent view header
|
||||
// replaces the legacy child-agent status card rows;
|
||||
// render only the message bar here.
|
||||
return Flex::column()
|
||||
.with_child(ChildView::new(&self.child_agent_status_card).finish())
|
||||
.with_child(ChildView::new(&self.agent_message_bar).finish())
|
||||
.finish();
|
||||
} else {
|
||||
@@ -1363,16 +1379,6 @@ impl View for BlocklistAIStatusBar {
|
||||
container = container.with_vertical_padding(8.);
|
||||
}
|
||||
|
||||
// When the agent view is active, keep the child agent status card
|
||||
// visible above the warping/status indicator so it doesn't disappear
|
||||
// while the agent is working.
|
||||
if agent_view_controller.is_active() {
|
||||
return Flex::column()
|
||||
.with_child(ChildView::new(&self.child_agent_status_card).finish())
|
||||
.with_child(container.finish())
|
||||
.finish();
|
||||
}
|
||||
|
||||
container.finish()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user