parent
0d4ca71e68
commit
2df06cd2e4
5 changed files with 219 additions and 166 deletions
3
assets/icons/light_bulb.svg
Normal file
3
assets/icons/light_bulb.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.1331 11.3776C10.2754 10.6665 10.1331 9.78593 11.1998 8.53327C11.82 7.80489 12.2664 6.96894 12.2664 6.04456C12.2664 4.91305 11.8169 3.82788 11.0168 3.02778C10.2167 2.22769 9.13152 1.7782 8.00001 1.7782C6.8685 1.7782 5.78334 2.22769 4.98324 3.02778C4.18314 3.82788 3.73364 4.91305 3.73364 6.04456C3.73364 6.75562 3.87586 7.6089 4.80024 8.53327C5.86683 9.80679 5.72462 10.6665 5.86683 11.3776M10.1331 11.3776V12.8821C10.1331 13.622 9.53341 14.2218 8.79353 14.2218H7.2065C6.46662 14.2218 5.86683 13.622 5.86683 12.8821V11.3776M10.1331 11.3776H5.86683" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 751 B |
|
@ -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(
|
||||
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({
|
||||
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(
|
||||
div()
|
||||
.id(("thinking-content", ix))
|
||||
.p_2()
|
||||
.h_20()
|
||||
.track_scroll(scroll_handle)
|
||||
.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,
|
||||
);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.overflow_hidden(),
|
||||
}),
|
||||
)
|
||||
.child(gradient_overlay),
|
||||
)
|
||||
})
|
||||
.when(is_open, |this| {
|
||||
this.child(
|
||||
div()
|
||||
.id(("thinking-content", ix))
|
||||
.h_full()
|
||||
.p_2()
|
||||
.rounded_b_lg()
|
||||
.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);
|
||||
}
|
||||
}),
|
||||
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()
|
||||
.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(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(
|
||||
h_flex()
|
||||
.gap_1p5()
|
||||
.child(
|
||||
Icon::new(IconName::LightBulb)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(Label::new("Thought Process").size(LabelSize::Small)),
|
||||
)
|
||||
.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(
|
||||
div()
|
||||
.id(("thinking-content", ix))
|
||||
.relative()
|
||||
.mt_1p5()
|
||||
.ml_1p5()
|
||||
.pl_2p5()
|
||||
.border_l_1()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
.text_ui_sm(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);
|
||||
}
|
||||
}),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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")
|
||||
|
|
|
@ -2793,7 +2793,7 @@ fn render_thought_process_fold_icon_button(
|
|||
let button = match status {
|
||||
ThoughtProcessStatus::Pending => button
|
||||
.child(
|
||||
Icon::new(IconName::Brain)
|
||||
Icon::new(IconName::LightBulb)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
|
@ -2808,7 +2808,7 @@ fn render_thought_process_fold_icon_button(
|
|||
),
|
||||
ThoughtProcessStatus::Completed => button
|
||||
.style(ButtonStyle::Filled)
|
||||
.child(Icon::new(IconName::Brain).size(IconSize::Small))
|
||||
.child(Icon::new(IconName::LightBulb).size(IconSize::Small))
|
||||
.child(Label::new("Thought Process").single_line()),
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ impl Tool for ThinkingTool {
|
|||
}
|
||||
|
||||
fn icon(&self) -> IconName {
|
||||
IconName::Brain
|
||||
IconName::LightBulb
|
||||
}
|
||||
|
||||
fn input_schema(&self, format: LanguageModelToolSchemaFormat) -> serde_json::Value {
|
||||
|
|
|
@ -141,6 +141,7 @@ pub enum IconName {
|
|||
InlayHint,
|
||||
Keyboard,
|
||||
Library,
|
||||
LightBulb,
|
||||
LineHeight,
|
||||
Link,
|
||||
ListTree,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue