@@ -1756,7 +1756,7 @@ impl ActiveThread {
None
};
- div()
+ v_flex()
.text_ui(cx)
.gap_2()
.children(
@@ -1841,177 +1841,225 @@ impl ActiveThread {
.copied()
.unwrap_or_default();
- let editor_bg = cx.theme().colors().editor_background;
+ let editor_bg = cx.theme().colors().panel_background;
- div().pt_0p5().pb_2().child(
- v_flex()
- .rounded_lg()
- .border_1()
- .border_color(self.tool_card_border_color(cx))
- .child(
- h_flex()
- .group("disclosure-header")
- .justify_between()
- .py_1()
- .px_2()
- .bg(self.tool_card_header_bg(cx))
- .map(|this| {
- if pending || is_open {
- this.rounded_t_md()
- .border_b_1()
- .border_color(self.tool_card_border_color(cx))
- } else {
- this.rounded_md()
- }
- })
- .child(
- h_flex()
- .gap_1p5()
- .child(
- Icon::new(IconName::Brain)
- .size(IconSize::XSmall)
- .color(Color::Muted),
- )
- .child({
- if pending {
- Label::new("Thinkingβ¦")
+ div().map(|this| {
+ if pending {
+ this.v_flex()
+ .mt_neg_2()
+ .mb_1p5()
+ .child(
+ h_flex()
+ .group("disclosure-header")
+ .justify_between()
+ .child(
+ h_flex()
+ .gap_1p5()
+ .child(
+ Icon::new(IconName::LightBulb)
+ .size(IconSize::XSmall)
+ .color(Color::Muted),
+ )
+ .child({
+ Label::new("Thinking")
+ .color(Color::Muted)
.size(LabelSize::Small)
- .buffer_font(cx)
+ .with_animation(
+ "generating-label",
+ Animation::new(Duration::from_secs(1)).repeat(),
+ |mut label, delta| {
+ let text = match delta {
+ d if d < 0.25 => "Thinking",
+ d if d < 0.5 => "Thinking.",
+ d if d < 0.75 => "Thinking..",
+ _ => "Thinking...",
+ };
+ label.set_text(text);
+ label
+ },
+ )
.with_animation(
"pulsating-label",
Animation::new(Duration::from_secs(2))
.repeat()
- .with_easing(pulsating_between(0.4, 0.8)),
- |label, delta| label.alpha(delta),
+ .with_easing(pulsating_between(0.6, 1.)),
+ |label, delta| {
+ label.map_element(|label| label.alpha(delta))
+ },
)
- .into_any_element()
- } else {
- Label::new("Thought Process")
- .size(LabelSize::Small)
- .buffer_font(cx)
- .into_any_element()
- }
- }),
- )
- .child(
- h_flex()
- .gap_1()
+ }),
+ )
+ .child(
+ h_flex()
+ .gap_1()
+ .child(
+ div().visible_on_hover("disclosure-header").child(
+ Disclosure::new("thinking-disclosure", is_open)
+ .opened_icon(IconName::ChevronUp)
+ .closed_icon(IconName::ChevronDown)
+ .on_click(cx.listener({
+ move |this, _event, _window, _cx| {
+ let is_open = this
+ .expanded_thinking_segments
+ .entry((message_id, ix))
+ .or_insert(false);
+
+ *is_open = !*is_open;
+ }
+ })),
+ ),
+ )
+ .child({
+ Icon::new(IconName::ArrowCircle)
+ .color(Color::Accent)
+ .size(IconSize::Small)
+ .with_animation(
+ "arrow-circle",
+ Animation::new(Duration::from_secs(2)).repeat(),
+ |icon, delta| {
+ icon.transform(Transformation::rotate(
+ percentage(delta),
+ ))
+ },
+ )
+ }),
+ ),
+ )
+ .when(!is_open, |this| {
+ let gradient_overlay = div()
+ .rounded_b_lg()
+ .h_full()
+ .absolute()
+ .w_full()
+ .bottom_0()
+ .left_0()
+ .bg(linear_gradient(
+ 180.,
+ linear_color_stop(editor_bg, 1.),
+ linear_color_stop(editor_bg.opacity(0.2), 0.),
+ ));
+
+ this.child(
+ div()
+ .relative()
+ .bg(editor_bg)
+ .rounded_b_lg()
+ .mt_2()
+ .pl_4()
.child(
- div().visible_on_hover("disclosure-header").child(
- Disclosure::new("thinking-disclosure", is_open)
- .opened_icon(IconName::ChevronUp)
- .closed_icon(IconName::ChevronDown)
- .on_click(cx.listener({
- move |this, _event, _window, _cx| {
- let is_open = this
- .expanded_thinking_segments
- .entry((message_id, ix))
- .or_insert(false);
-
- *is_open = !*is_open;
+ div()
+ .id(("thinking-content", ix))
+ .max_h_20()
+ .track_scroll(scroll_handle)
+ .text_ui_sm(cx)
+ .overflow_hidden()
+ .child(
+ MarkdownElement::new(
+ markdown.clone(),
+ default_markdown_style(window, cx),
+ )
+ .on_url_click({
+ let workspace = self.workspace.clone();
+ move |text, window, cx| {
+ open_markdown_link(
+ text,
+ workspace.clone(),
+ window,
+ cx,
+ );
}
- })),
- ),
+ }),
+ ),
)
- .child({
- let (icon_name, color, animated) = if pending {
- (IconName::ArrowCircle, Color::Accent, true)
- } else {
- (IconName::Check, Color::Success, false)
- };
-
- let icon =
- Icon::new(icon_name).color(color).size(IconSize::Small);
-
- if animated {
- icon.with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(
- delta,
- )))
- },
- )
- .into_any_element()
- } else {
- icon.into_any_element()
- }
- }),
- ),
- )
- .when(pending && !is_open, |this| {
- let gradient_overlay = div()
- .rounded_b_lg()
- .h_20()
- .absolute()
- .w_full()
- .bottom_0()
- .left_0()
- .bg(linear_gradient(
- 180.,
- linear_color_stop(editor_bg, 1.),
- linear_color_stop(editor_bg.opacity(0.2), 0.),
- ));
-
- this.child(
- div()
- .relative()
- .bg(editor_bg)
- .rounded_b_lg()
+ .child(gradient_overlay),
+ )
+ })
+ .when(is_open, |this| {
+ this.child(
+ div()
+ .id(("thinking-content", ix))
+ .h_full()
+ .bg(editor_bg)
+ .text_ui_sm(cx)
+ .child(
+ MarkdownElement::new(
+ markdown.clone(),
+ default_markdown_style(window, cx),
+ )
+ .on_url_click({
+ let workspace = self.workspace.clone();
+ move |text, window, cx| {
+ open_markdown_link(text, workspace.clone(), window, cx);
+ }
+ }),
+ ),
+ )
+ })
+ } else {
+ this.v_flex()
+ .mt_neg_2()
+ .child(
+ h_flex()
+ .group("disclosure-header")
+ .pr_1()
+ .justify_between()
+ .opacity(0.8)
+ .hover(|style| style.opacity(1.))
.child(
- div()
- .id(("thinking-content", ix))
- .p_2()
- .h_20()
- .track_scroll(scroll_handle)
- .text_ui_sm(cx)
+ h_flex()
+ .gap_1p5()
.child(
- MarkdownElement::new(
- markdown.clone(),
- default_markdown_style(window, cx),
- )
- .on_url_click({
- let workspace = self.workspace.clone();
- move |text, window, cx| {
- open_markdown_link(
- text,
- workspace.clone(),
- window,
- cx,
- );
- }
- }),
+ Icon::new(IconName::LightBulb)
+ .size(IconSize::XSmall)
+ .color(Color::Muted),
)
- .overflow_hidden(),
+ .child(Label::new("Thought Process").size(LabelSize::Small)),
)
- .child(gradient_overlay),
+ .child(
+ div().visible_on_hover("disclosure-header").child(
+ Disclosure::new("thinking-disclosure", is_open)
+ .opened_icon(IconName::ChevronUp)
+ .closed_icon(IconName::ChevronDown)
+ .on_click(cx.listener({
+ move |this, _event, _window, _cx| {
+ let is_open = this
+ .expanded_thinking_segments
+ .entry((message_id, ix))
+ .or_insert(false);
+
+ *is_open = !*is_open;
+ }
+ })),
+ ),
+ ),
)
- })
- .when(is_open, |this| {
- this.child(
+ .child(
div()
.id(("thinking-content", ix))
- .h_full()
- .p_2()
- .rounded_b_lg()
- .bg(editor_bg)
+ .relative()
+ .mt_1p5()
+ .ml_1p5()
+ .pl_2p5()
+ .border_l_1()
+ .border_color(cx.theme().colors().border_variant)
.text_ui_sm(cx)
- .child(
- MarkdownElement::new(
- markdown.clone(),
- default_markdown_style(window, cx),
+ .when(is_open, |this| {
+ this.child(
+ MarkdownElement::new(
+ markdown.clone(),
+ default_markdown_style(window, cx),
+ )
+ .on_url_click({
+ let workspace = self.workspace.clone();
+ move |text, window, cx| {
+ open_markdown_link(text, workspace.clone(), window, cx);
+ }
+ }),
)
- .on_url_click({
- let workspace = self.workspace.clone();
- move |text, window, cx| {
- open_markdown_link(text, workspace.clone(), window, cx);
- }
- }),
- ),
+ }),
)
- }),
- )
+ }
+ })
}
fn render_tool_use(
@@ -2033,6 +2081,7 @@ impl ActiveThread {
.upgrade()
.map(|workspace| workspace.read(cx).app_state().fs.clone());
let needs_confirmation = matches!(&tool_use.status, ToolUseStatus::NeedsConfirmation);
+ let edit_tools = tool_use.needs_confirmation;
let status_icons = div().child(match &tool_use.status {
ToolUseStatus::Pending | ToolUseStatus::NeedsConfirmation => {
@@ -2209,10 +2258,10 @@ impl ActiveThread {
};
div().map(|element| {
- if !tool_use.needs_confirmation {
+ if !edit_tools {
element.child(
v_flex()
- .my_1p5()
+ .my_2()
.child(
h_flex()
.group("disclosure-header")