ACP work
This commit is contained in:
@@ -22,7 +22,7 @@ use galaxy_core::ui::theme::color::internal_colors;
|
|||||||
use galaxy_util::local_or_remote_path::LocalOrRemotePath;
|
use galaxy_util::local_or_remote_path::LocalOrRemotePath;
|
||||||
use galaxyui::elements::new_scrollable::SingleAxisConfig;
|
use galaxyui::elements::new_scrollable::SingleAxisConfig;
|
||||||
use galaxyui::elements::{
|
use galaxyui::elements::{
|
||||||
Align, Border, ChildAnchor, ChildView, ConstrainedBox, Container, CornerRadius,
|
Align, Border, ChildAnchor, ChildView, Clipped, ConstrainedBox, Container, CornerRadius,
|
||||||
CrossAxisAlignment, Empty, Expanded, Fill, Flex, FormattedTextElement, Hoverable,
|
CrossAxisAlignment, Empty, Expanded, Fill, Flex, FormattedTextElement, Hoverable,
|
||||||
MainAxisAlignment, MainAxisSize, NewScrollable, OffsetPositioning, ParentAnchor, ParentElement,
|
MainAxisAlignment, MainAxisSize, NewScrollable, OffsetPositioning, ParentAnchor, ParentElement,
|
||||||
ParentOffsetBounds, Radius, Shrinkable, Stack, Text, Wrap,
|
ParentOffsetBounds, Radius, Shrinkable, Stack, Text, Wrap,
|
||||||
@@ -85,18 +85,22 @@ use crate::ai::blocklist::inline_action::ask_user_question_view::AskUserQuestion
|
|||||||
use crate::ai::blocklist::inline_action::aws_bedrock_credentials_error::AwsBedrockCredentialsErrorView;
|
use crate::ai::blocklist::inline_action::aws_bedrock_credentials_error::AwsBedrockCredentialsErrorView;
|
||||||
use crate::ai::blocklist::inline_action::create_or_edit_document::CreateOrEditDocumentAction;
|
use crate::ai::blocklist::inline_action::create_or_edit_document::CreateOrEditDocumentAction;
|
||||||
use crate::ai::blocklist::inline_action::inline_action_header::{
|
use crate::ai::blocklist::inline_action::inline_action_header::{
|
||||||
HeaderConfig, InteractionMode, INLINE_ACTION_HEADER_VERTICAL_PADDING,
|
ExpandedConfig, HeaderConfig, InteractionMode, INLINE_ACTION_HEADER_VERTICAL_PADDING,
|
||||||
INLINE_ACTION_HORIZONTAL_PADDING,
|
INLINE_ACTION_HORIZONTAL_PADDING,
|
||||||
};
|
};
|
||||||
use crate::ai::blocklist::inline_action::inline_action_icons::{self, icon_size};
|
use crate::ai::blocklist::inline_action::inline_action_icons::{self, icon_size};
|
||||||
use crate::ai::blocklist::inline_action::requested_action::{
|
use crate::ai::blocklist::inline_action::requested_action::{
|
||||||
render_requested_action_body_text, render_requested_action_row_for_text, RenderableAction,
|
render_requested_action_body_text, render_requested_action_row_for_text, RenderableAction,
|
||||||
};
|
};
|
||||||
use crate::ai::blocklist::inline_action::requested_command::RequestedCommand;
|
use crate::ai::blocklist::inline_action::requested_command::{
|
||||||
|
format_command_text, RequestedCommand, REQUESTED_COMMAND_BODY_VERTICAL_PADDING,
|
||||||
|
VIEWING_COMMAND_DETAIL_MESSAGE,
|
||||||
|
};
|
||||||
use crate::ai::blocklist::inline_action::run_agents_card_view::RunAgentsCardView;
|
use crate::ai::blocklist::inline_action::run_agents_card_view::RunAgentsCardView;
|
||||||
use crate::ai::blocklist::inline_action::search_codebase::SearchCodebaseView;
|
use crate::ai::blocklist::inline_action::search_codebase::SearchCodebaseView;
|
||||||
use crate::ai::blocklist::inline_action::suggested_unit_tests::SuggestedUnitTestsView;
|
use crate::ai::blocklist::inline_action::suggested_unit_tests::SuggestedUnitTestsView;
|
||||||
use crate::ai::blocklist::inline_action::summarization::SummarizationView;
|
use crate::ai::blocklist::inline_action::summarization::SummarizationView;
|
||||||
|
use crate::ai::blocklist::inline_action::tool_pane::render_tool_pane_shell;
|
||||||
use crate::ai::blocklist::inline_action::web_fetch::WebFetchView;
|
use crate::ai::blocklist::inline_action::web_fetch::WebFetchView;
|
||||||
use crate::ai::blocklist::inline_action::web_search::WebSearchView;
|
use crate::ai::blocklist::inline_action::web_search::WebSearchView;
|
||||||
use crate::ai::blocklist::keyboard_navigable_buttons::KeyboardNavigableButtons;
|
use crate::ai::blocklist::keyboard_navigable_buttons::KeyboardNavigableButtons;
|
||||||
@@ -1287,7 +1291,6 @@ fn render_runtime_activity(
|
|||||||
let state = props.collapsible_block_states.get(&output_message.id)?;
|
let state = props.collapsible_block_states.get(&output_message.id)?;
|
||||||
let appearance = Appearance::as_ref(app);
|
let appearance = Appearance::as_ref(app);
|
||||||
let theme = appearance.theme();
|
let theme = appearance.theme();
|
||||||
let text_color = blended_colors::text_main(theme, theme.background());
|
|
||||||
let output = activity
|
let output = activity
|
||||||
.output
|
.output
|
||||||
.as_deref()
|
.as_deref()
|
||||||
@@ -1296,56 +1299,51 @@ fn render_runtime_activity(
|
|||||||
state.expansion_state,
|
state.expansion_state,
|
||||||
CollapsibleExpansionState::Expanded { .. }
|
CollapsibleExpansionState::Expanded { .. }
|
||||||
);
|
);
|
||||||
let mut content = Flex::column().with_cross_axis_alignment(CrossAxisAlignment::Stretch);
|
let icon = match activity.status.as_ref() {
|
||||||
|
Some(RuntimeActivityStatus::Pending) => icons::pending_icon(appearance),
|
||||||
let title = Text::new(
|
Some(RuntimeActivityStatus::InProgress) => icons::yellow_running_icon(appearance),
|
||||||
activity.title.clone(),
|
Some(RuntimeActivityStatus::Completed) => inline_action_icons::green_check_icon(appearance),
|
||||||
appearance.monospace_font_family(),
|
Some(RuntimeActivityStatus::Failed) => inline_action_icons::red_x_icon(appearance),
|
||||||
appearance.monospace_font_size(),
|
Some(RuntimeActivityStatus::Other(_)) | None => icons::gray_circle_icon(appearance),
|
||||||
)
|
|
||||||
.with_color(text_color)
|
|
||||||
.with_selectable(false)
|
|
||||||
.finish();
|
|
||||||
if output.is_some() {
|
|
||||||
let chevron = if is_expanded {
|
|
||||||
Icon::ChevronDown
|
|
||||||
} else {
|
|
||||||
Icon::ChevronRight
|
|
||||||
};
|
};
|
||||||
let icon_sz = icon_size(app);
|
let title = if is_expanded {
|
||||||
|
VIEWING_COMMAND_DETAIL_MESSAGE.to_owned()
|
||||||
|
} else {
|
||||||
|
format_command_text(&activity.title)
|
||||||
|
};
|
||||||
|
let mut header = HeaderConfig::new(title, app)
|
||||||
|
.with_selectable_text()
|
||||||
|
.with_icon(icon)
|
||||||
|
.with_corner_radius_override(if is_expanded && output.is_some() {
|
||||||
|
CornerRadius::with_top(Radius::Pixels(8.))
|
||||||
|
} else {
|
||||||
|
CornerRadius::with_all(Radius::Pixels(8.))
|
||||||
|
});
|
||||||
|
if !is_expanded {
|
||||||
|
header = header.with_font_family(appearance.monospace_font_family());
|
||||||
|
}
|
||||||
|
if output.is_some() {
|
||||||
let message_id = output_message.id.clone();
|
let message_id = output_message.id.clone();
|
||||||
let mouse_state = state.expansion_toggle_mouse_state.clone();
|
let command = activity.title.clone();
|
||||||
let header = Hoverable::new(mouse_state, move |_| {
|
let expansion =
|
||||||
Flex::row()
|
ExpandedConfig::new(is_expanded, state.expansion_toggle_mouse_state.clone())
|
||||||
.with_cross_axis_alignment(CrossAxisAlignment::Center)
|
.with_toggle_callback(move |ctx| {
|
||||||
.with_child(Shrinkable::new(1., title).finish())
|
|
||||||
.with_child(
|
|
||||||
Container::new(
|
|
||||||
ConstrainedBox::new(chevron.to_galaxyui_icon(text_color.into()).finish())
|
|
||||||
.with_width(icon_sz)
|
|
||||||
.with_height(icon_sz)
|
|
||||||
.finish(),
|
|
||||||
)
|
|
||||||
.with_margin_left(6.)
|
|
||||||
.finish(),
|
|
||||||
)
|
|
||||||
.finish()
|
|
||||||
})
|
|
||||||
.with_cursor(Cursor::PointingHand)
|
|
||||||
.on_click(move |ctx, _, _| {
|
|
||||||
ctx.dispatch_typed_action(AIBlockAction::ToggleCollapsibleBlockExpanded(
|
ctx.dispatch_typed_action(AIBlockAction::ToggleCollapsibleBlockExpanded(
|
||||||
message_id.clone(),
|
message_id.clone(),
|
||||||
));
|
));
|
||||||
|
})
|
||||||
|
.with_right_click_callback(move |ctx| {
|
||||||
|
ctx.dispatch_typed_action(AIBlockAction::StoreRightClickedCommand {
|
||||||
|
command: command.clone(),
|
||||||
});
|
});
|
||||||
content.add_child(
|
});
|
||||||
Flex::row()
|
header = header.with_interaction_mode(InteractionMode::ManuallyExpandable(expansion));
|
||||||
.with_child(Shrinkable::new(1., header.finish()).finish())
|
|
||||||
.finish(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
content.add_child(title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut content = Flex::column()
|
||||||
|
.with_cross_axis_alignment(CrossAxisAlignment::Stretch)
|
||||||
|
.with_child(Clipped::new(header.render(app)).finish());
|
||||||
|
|
||||||
if let Some(output) = output {
|
if let Some(output) = output {
|
||||||
let body = render_requested_action_body_text(
|
let body = render_requested_action_body_text(
|
||||||
output.into(),
|
output.into(),
|
||||||
@@ -1364,31 +1362,18 @@ fn render_runtime_activity(
|
|||||||
is_streaming,
|
is_streaming,
|
||||||
320.,
|
320.,
|
||||||
) {
|
) {
|
||||||
content.add_child(Container::new(scrollable).with_margin_top(12.).finish());
|
content.add_child(
|
||||||
|
Container::new(scrollable)
|
||||||
|
.with_horizontal_padding(INLINE_ACTION_HORIZONTAL_PADDING)
|
||||||
|
.with_vertical_padding(REQUESTED_COMMAND_BODY_VERTICAL_PADDING)
|
||||||
|
.with_background(theme.background())
|
||||||
|
.with_corner_radius(CornerRadius::with_bottom(Radius::Pixels(8.)))
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let icon = match activity.status.as_ref() {
|
Some(render_tool_pane_shell(content.finish(), false, false, app))
|
||||||
Some(RuntimeActivityStatus::Completed) => {
|
|
||||||
inline_action_icons::green_check_icon(appearance).finish()
|
|
||||||
}
|
|
||||||
Some(RuntimeActivityStatus::Failed) => inline_action_icons::red_x_icon(appearance).finish(),
|
|
||||||
Some(RuntimeActivityStatus::Pending)
|
|
||||||
| Some(RuntimeActivityStatus::InProgress)
|
|
||||||
| Some(RuntimeActivityStatus::Other(_))
|
|
||||||
| None => galaxyui::elements::Icon::new(
|
|
||||||
Icon::ClockRefresh.into(),
|
|
||||||
internal_colors::neutral_5(appearance.theme()),
|
|
||||||
)
|
|
||||||
.finish(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(
|
|
||||||
RenderableAction::new_with_element(content.finish(), app)
|
|
||||||
.with_icon(icon)
|
|
||||||
.render(app)
|
|
||||||
.finish(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_render_stopped_output(props: Props, app: &AppContext) -> bool {
|
fn should_render_stopped_output(props: Props, app: &AppContext) -> bool {
|
||||||
|
|||||||
@@ -16,5 +16,6 @@ pub(super) mod search_codebase;
|
|||||||
pub(crate) mod search_results_common;
|
pub(crate) mod search_results_common;
|
||||||
pub(crate) mod suggested_unit_tests;
|
pub(crate) mod suggested_unit_tests;
|
||||||
pub(super) mod summarization;
|
pub(super) mod summarization;
|
||||||
|
pub(crate) mod tool_pane;
|
||||||
pub(super) mod web_fetch;
|
pub(super) mod web_fetch;
|
||||||
pub(super) mod web_search;
|
pub(super) mod web_search;
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ use crate::ai::blocklist::block::cli_controller::{
|
|||||||
use crate::ai::blocklist::block::view_impl::output::action_icon;
|
use crate::ai::blocklist::block::view_impl::output::action_icon;
|
||||||
use crate::ai::blocklist::block::view_impl::{
|
use crate::ai::blocklist::block::view_impl::{
|
||||||
render_autonomy_checkbox_setting_speedbump_footer, render_citation, render_citation_chips,
|
render_autonomy_checkbox_setting_speedbump_footer, render_citation, render_citation_chips,
|
||||||
CONTENT_HORIZONTAL_PADDING, CONTENT_ITEM_VERTICAL_MARGIN,
|
|
||||||
};
|
};
|
||||||
use crate::ai::blocklist::block::{AIBlockAction, AutonomySettingSpeedbump};
|
use crate::ai::blocklist::block::{AIBlockAction, AutonomySettingSpeedbump};
|
||||||
use crate::ai::blocklist::inline_action::inline_action_header::{
|
use crate::ai::blocklist::inline_action::inline_action_header::{
|
||||||
ExpandedConfig, HeaderConfig, InteractionMode, RightClickConfig,
|
ExpandedConfig, HeaderConfig, InteractionMode, RightClickConfig,
|
||||||
INLINE_ACTION_HORIZONTAL_PADDING,
|
INLINE_ACTION_HORIZONTAL_PADDING,
|
||||||
};
|
};
|
||||||
|
use crate::ai::blocklist::inline_action::tool_pane::render_tool_pane_shell;
|
||||||
use crate::ai::blocklist::model::{AIBlockModel, AIBlockModelHelper};
|
use crate::ai::blocklist::model::{AIBlockModel, AIBlockModelHelper};
|
||||||
use crate::ai::blocklist::{
|
use crate::ai::blocklist::{
|
||||||
AIBlock, BlocklistAIActionEvent, BlocklistAIActionModel, BlocklistAIHistoryModel,
|
AIBlock, BlocklistAIActionEvent, BlocklistAIActionModel, BlocklistAIHistoryModel,
|
||||||
@@ -1600,14 +1600,9 @@ impl View for RequestedCommandView {
|
|||||||
content.add_child(Clipped::new(footer).finish());
|
content.add_child(Clipped::new(footer).finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
let border_color = if action_status
|
let has_highlighted_border = action_status
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|status| status.is_blocked())
|
.is_some_and(|status| status.is_blocked());
|
||||||
{
|
|
||||||
theme.accent()
|
|
||||||
} else {
|
|
||||||
theme.surface_2()
|
|
||||||
};
|
|
||||||
|
|
||||||
// If the requested command is expanded above a terminal block or
|
// If the requested command is expanded above a terminal block or
|
||||||
// the next exchange flows directly after, remove bottom margin for
|
// the next exchange flows directly after, remove bottom margin for
|
||||||
@@ -1637,21 +1632,12 @@ impl View for RequestedCommandView {
|
|||||||
}))
|
}))
|
||||||
&& !is_input_pinned_to_top);
|
&& !is_input_pinned_to_top);
|
||||||
|
|
||||||
let container = Container::new(content.finish())
|
let container = render_tool_pane_shell(
|
||||||
.with_margin_left(if action_status.is_some_and(|status| status.is_blocked()) {
|
content.finish(),
|
||||||
CONTENT_HORIZONTAL_PADDING
|
has_highlighted_border,
|
||||||
} else {
|
should_remove_bottom_margin,
|
||||||
CONTENT_HORIZONTAL_PADDING + icon_size(app) + 16.
|
app,
|
||||||
})
|
);
|
||||||
.with_margin_right(CONTENT_HORIZONTAL_PADDING)
|
|
||||||
.with_margin_bottom(if should_remove_bottom_margin {
|
|
||||||
0.
|
|
||||||
} else {
|
|
||||||
CONTENT_ITEM_VERTICAL_MARGIN
|
|
||||||
})
|
|
||||||
.with_corner_radius(CornerRadius::with_all(Radius::Pixels(8.)))
|
|
||||||
.with_border(Border::all(1.).with_border_fill(border_color))
|
|
||||||
.finish();
|
|
||||||
|
|
||||||
let mut root_stack = Stack::new();
|
let mut root_stack = Stack::new();
|
||||||
root_stack.add_child(container);
|
root_stack.add_child(container);
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
use galaxy_core::ui::appearance::Appearance;
|
||||||
|
use warpui::elements::{Border, Container, CornerRadius, ParentElement, Radius};
|
||||||
|
use warpui::{AppContext, Element, SingletonEntity};
|
||||||
|
|
||||||
|
use super::inline_action_icons::icon_size;
|
||||||
|
use crate::ai::blocklist::block::view_impl::{
|
||||||
|
CONTENT_HORIZONTAL_PADDING, CONTENT_ITEM_VERTICAL_MARGIN,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Renders the shared outer shell used by native and runtime-owned tool panes.
|
||||||
|
///
|
||||||
|
/// Callers own execution and body content. This function owns the pane geometry
|
||||||
|
/// and theme treatment so display-only runtimes cannot drift from native tools.
|
||||||
|
pub(crate) fn render_tool_pane_shell(
|
||||||
|
content: Box<dyn Element>,
|
||||||
|
has_highlighted_border: bool,
|
||||||
|
should_remove_bottom_margin: bool,
|
||||||
|
app: &AppContext,
|
||||||
|
) -> Box<dyn Element> {
|
||||||
|
let theme = Appearance::as_ref(app).theme();
|
||||||
|
let border_color = if has_highlighted_border {
|
||||||
|
theme.accent()
|
||||||
|
} else {
|
||||||
|
theme.surface_2()
|
||||||
|
};
|
||||||
|
|
||||||
|
Container::new(content)
|
||||||
|
.with_margin_left(if has_highlighted_border {
|
||||||
|
CONTENT_HORIZONTAL_PADDING
|
||||||
|
} else {
|
||||||
|
CONTENT_HORIZONTAL_PADDING + icon_size(app) + 16.
|
||||||
|
})
|
||||||
|
.with_margin_right(CONTENT_HORIZONTAL_PADDING)
|
||||||
|
.with_margin_bottom(if should_remove_bottom_margin {
|
||||||
|
0.
|
||||||
|
} else {
|
||||||
|
CONTENT_ITEM_VERTICAL_MARGIN
|
||||||
|
})
|
||||||
|
.with_corner_radius(CornerRadius::with_all(Radius::Pixels(8.)))
|
||||||
|
.with_border(Border::all(1.).with_border_fill(border_color))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user