Add example agent tool preview (#28984)
This PR adds an example of rendering previews for tools using the new Agent ToolCard style.  Release Notes: - N/A --------- Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This commit is contained in:
parent
7a95c14625
commit
acc4a5ccb3
5 changed files with 121 additions and 3 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -703,6 +703,7 @@ dependencies = [
|
||||||
"assistant_tool",
|
"assistant_tool",
|
||||||
"chrono",
|
"chrono",
|
||||||
"collections",
|
"collections",
|
||||||
|
"component",
|
||||||
"feature_flags",
|
"feature_flags",
|
||||||
"futures 0.3.31",
|
"futures 0.3.31",
|
||||||
"gpui",
|
"gpui",
|
||||||
|
@ -711,6 +712,7 @@ dependencies = [
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"language",
|
"language",
|
||||||
"language_model",
|
"language_model",
|
||||||
|
"linkme",
|
||||||
"open",
|
"open",
|
||||||
"project",
|
"project",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
|
|
|
@ -16,6 +16,7 @@ anyhow.workspace = true
|
||||||
assistant_tool.workspace = true
|
assistant_tool.workspace = true
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
|
component.workspace = true
|
||||||
feature_flags.workspace = true
|
feature_flags.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
|
@ -24,6 +25,8 @@ http_client.workspace = true
|
||||||
itertools.workspace = true
|
itertools.workspace = true
|
||||||
language.workspace = true
|
language.workspace = true
|
||||||
language_model.workspace = true
|
language_model.workspace = true
|
||||||
|
linkme.workspace = true
|
||||||
|
open.workspace = true
|
||||||
project.workspace = true
|
project.workspace = true
|
||||||
regex.workspace = true
|
regex.workspace = true
|
||||||
schemars.workspace = true
|
schemars.workspace = true
|
||||||
|
@ -31,10 +34,9 @@ serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
ui.workspace = true
|
ui.workspace = true
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
worktree.workspace = true
|
|
||||||
open = { workspace = true }
|
|
||||||
web_search.workspace = true
|
web_search.workspace = true
|
||||||
workspace-hack.workspace = true
|
workspace-hack.workspace = true
|
||||||
|
worktree.workspace = true
|
||||||
zed_llm_client.workspace = true
|
zed_llm_client.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -14,7 +14,7 @@ use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ui::{IconName, Tooltip, prelude::*};
|
use ui::{IconName, Tooltip, prelude::*};
|
||||||
use web_search::WebSearchRegistry;
|
use web_search::WebSearchRegistry;
|
||||||
use zed_llm_client::WebSearchResponse;
|
use zed_llm_client::{WebSearchCitation, WebSearchResponse};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct WebSearchToolInput {
|
pub struct WebSearchToolInput {
|
||||||
|
@ -22,6 +22,7 @@ pub struct WebSearchToolInput {
|
||||||
query: String,
|
query: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(RegisterComponent)]
|
||||||
pub struct WebSearchTool;
|
pub struct WebSearchTool;
|
||||||
|
|
||||||
impl Tool for WebSearchTool {
|
impl Tool for WebSearchTool {
|
||||||
|
@ -211,3 +212,111 @@ impl ToolCard for WebSearchToolCard {
|
||||||
v_flex().my_2().gap_1().child(header).children(content)
|
v_flex().my_2().gap_1().child(header).children(content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Component for WebSearchTool {
|
||||||
|
fn scope() -> ComponentScope {
|
||||||
|
ComponentScope::Agent
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sort_name() -> &'static str {
|
||||||
|
"ToolWebSearch"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn preview(window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
||||||
|
let in_progress_search = cx.new(|cx| WebSearchToolCard {
|
||||||
|
response: None,
|
||||||
|
_task: cx.spawn(async move |_this, cx| {
|
||||||
|
loop {
|
||||||
|
cx.background_executor()
|
||||||
|
.timer(Duration::from_secs(60))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
let successful_search = cx.new(|_cx| WebSearchToolCard {
|
||||||
|
response: Some(Ok(example_search_response())),
|
||||||
|
_task: Task::ready(()),
|
||||||
|
});
|
||||||
|
|
||||||
|
let error_search = cx.new(|_cx| WebSearchToolCard {
|
||||||
|
response: Some(Err(anyhow!("Failed to resolve https://google.com"))),
|
||||||
|
_task: Task::ready(()),
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(
|
||||||
|
v_flex()
|
||||||
|
.gap_6()
|
||||||
|
.children(vec![example_group(vec![
|
||||||
|
single_example(
|
||||||
|
"In Progress",
|
||||||
|
div()
|
||||||
|
.size_full()
|
||||||
|
.child(in_progress_search.update(cx, |tool, cx| {
|
||||||
|
tool.render(&ToolUseStatus::Pending, window, cx)
|
||||||
|
.into_any_element()
|
||||||
|
}))
|
||||||
|
.into_any_element(),
|
||||||
|
),
|
||||||
|
single_example(
|
||||||
|
"Successful",
|
||||||
|
div()
|
||||||
|
.size_full()
|
||||||
|
.child(successful_search.update(cx, |tool, cx| {
|
||||||
|
tool.render(&ToolUseStatus::Finished("".into()), window, cx)
|
||||||
|
.into_any_element()
|
||||||
|
}))
|
||||||
|
.into_any_element(),
|
||||||
|
),
|
||||||
|
single_example(
|
||||||
|
"Error",
|
||||||
|
div()
|
||||||
|
.size_full()
|
||||||
|
.child(error_search.update(cx, |tool, cx| {
|
||||||
|
tool.render(&ToolUseStatus::Error("".into()), window, cx)
|
||||||
|
.into_any_element()
|
||||||
|
}))
|
||||||
|
.into_any_element(),
|
||||||
|
),
|
||||||
|
])])
|
||||||
|
.into_any_element(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn example_search_response() -> WebSearchResponse {
|
||||||
|
WebSearchResponse {
|
||||||
|
summary: r#"Toronto boasts a vibrant culinary scene with a diverse array of..."#
|
||||||
|
.to_string(),
|
||||||
|
citations: vec![
|
||||||
|
WebSearchCitation {
|
||||||
|
title: "Alo".to_string(),
|
||||||
|
url: "https://www.google.com/maps/search/Alo%2C+Toronto%2C+Canada".to_string(),
|
||||||
|
range: Some(147..213),
|
||||||
|
},
|
||||||
|
WebSearchCitation {
|
||||||
|
title: "Edulis".to_string(),
|
||||||
|
url: "https://www.google.com/maps/search/Edulis%2C+Toronto%2C+Canada".to_string(),
|
||||||
|
range: Some(447..519),
|
||||||
|
},
|
||||||
|
WebSearchCitation {
|
||||||
|
title: "Sushi Masaki Saito".to_string(),
|
||||||
|
url: "https://www.google.com/maps/search/Sushi+Masaki+Saito%2C+Toronto%2C+Canada"
|
||||||
|
.to_string(),
|
||||||
|
range: Some(776..872),
|
||||||
|
},
|
||||||
|
WebSearchCitation {
|
||||||
|
title: "Shoushin".to_string(),
|
||||||
|
url: "https://www.google.com/maps/search/Shoushin%2C+Toronto%2C+Canada".to_string(),
|
||||||
|
range: Some(1072..1148),
|
||||||
|
},
|
||||||
|
WebSearchCitation {
|
||||||
|
title: "Restaurant 20 Victoria".to_string(),
|
||||||
|
url:
|
||||||
|
"https://www.google.com/maps/search/Restaurant+20+Victoria%2C+Toronto%2C+Canada"
|
||||||
|
.to_string(),
|
||||||
|
range: Some(1291..1395),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -201,6 +201,7 @@ pub fn components() -> AllComponents {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum ComponentScope {
|
pub enum ComponentScope {
|
||||||
|
Agent,
|
||||||
Collaboration,
|
Collaboration,
|
||||||
DataDisplay,
|
DataDisplay,
|
||||||
Editor,
|
Editor,
|
||||||
|
@ -220,6 +221,7 @@ pub enum ComponentScope {
|
||||||
impl Display for ComponentScope {
|
impl Display for ComponentScope {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
ComponentScope::Agent => write!(f, "Agent"),
|
||||||
ComponentScope::Collaboration => write!(f, "Collaboration"),
|
ComponentScope::Collaboration => write!(f, "Collaboration"),
|
||||||
ComponentScope::DataDisplay => write!(f, "Data Display"),
|
ComponentScope::DataDisplay => write!(f, "Data Display"),
|
||||||
ComponentScope::Editor => write!(f, "Editor"),
|
ComponentScope::Editor => write!(f, "Editor"),
|
||||||
|
|
|
@ -19,6 +19,9 @@ extend-exclude = [
|
||||||
# Some crate names are flagged as typos.
|
# Some crate names are flagged as typos.
|
||||||
"crates/indexed_docs/src/providers/rustdoc/popular_crates.txt",
|
"crates/indexed_docs/src/providers/rustdoc/popular_crates.txt",
|
||||||
|
|
||||||
|
# Some mock data is flagged as typos.
|
||||||
|
"crates/assistant_tools/src/web_search_tool.rs",
|
||||||
|
|
||||||
# Stripe IDs are flagged as typos.
|
# Stripe IDs are flagged as typos.
|
||||||
"crates/collab/src/db/tests/processed_stripe_event_tests.rs",
|
"crates/collab/src/db/tests/processed_stripe_event_tests.rs",
|
||||||
# Not our typos.
|
# Not our typos.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue