From a20c38463b5661ff060e44275902d3cd1296aad6 Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner Date: Tue, 6 May 2025 00:47:11 +0200 Subject: [PATCH] agent: Switch to new web search provider (#29951) Release Notes: - N/A --- Cargo.lock | 4 +- Cargo.toml | 2 +- crates/assistant_tools/src/web_search_tool.rs | 120 +++++++++--------- crates/web_search_providers/src/cloud.rs | 5 +- 4 files changed, 66 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97492da0f3..442545fbf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18873,9 +18873,9 @@ dependencies = [ [[package]] name = "zed_llm_client" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2adf9bc80def4ec93c190f06eb78111865edc2576019a9753eaef6fd7bc3b72c" +checksum = "6fe0d60001c02d0d21a4114a13bee3a905fbb9e146ada80a90435c05fda18852" dependencies = [ "anyhow", "serde", diff --git a/Cargo.toml b/Cargo.toml index 85d4babcfe..ea82544af9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -609,7 +609,7 @@ wasmtime-wasi = "29" which = "6.0.0" wit-component = "0.221" workspace-hack = "0.1.0" -zed_llm_client = "0.7.4" +zed_llm_client = "0.7.5" zstd = "0.11" [workspace.dependencies.async-stripe] diff --git a/crates/assistant_tools/src/web_search_tool.rs b/crates/assistant_tools/src/web_search_tool.rs index be236c7a6d..a2afde9f97 100644 --- a/crates/assistant_tools/src/web_search_tool.rs +++ b/crates/assistant_tools/src/web_search_tool.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; use ui::{IconName, Tooltip, prelude::*}; use web_search::WebSearchRegistry; use workspace::Workspace; -use zed_llm_client::{WebSearchCitation, WebSearchResponse}; +use zed_llm_client::{WebSearchResponse, WebSearchResult}; #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct WebSearchToolInput { @@ -120,10 +120,10 @@ impl ToolCard for WebSearchToolCard { ) -> impl IntoElement { let header = match self.response.as_ref() { Some(Ok(response)) => { - let text: SharedString = if response.citations.len() == 1 { + let text: SharedString = if response.results.len() == 1 { "1 result".into() } else { - format!("{} results", response.citations.len()).into() + format!("{} results", response.results.len()).into() }; ToolCallCardHeader::new(IconName::Globe, "Searched the Web") .with_secondary_text(text) @@ -134,52 +134,47 @@ impl ToolCard for WebSearchToolCard { None => ToolCallCardHeader::new(IconName::Globe, "Searching the Web").loading(), }; - let content = - self.response.as_ref().and_then(|response| match response { - Ok(response) => { - Some( - v_flex() - .overflow_hidden() - .ml_1p5() - .pl(px(5.)) - .border_l_1() - .border_color(cx.theme().colors().border_variant) - .gap_1() - .children(response.citations.iter().enumerate().map( - |(index, citation)| { - let title = citation.title.clone(); - let url = citation.url.clone(); + let content = self.response.as_ref().and_then(|response| match response { + Ok(response) => Some( + v_flex() + .overflow_hidden() + .ml_1p5() + .pl(px(5.)) + .border_l_1() + .border_color(cx.theme().colors().border_variant) + .gap_1() + .children(response.results.iter().enumerate().map(|(index, result)| { + let title = result.title.clone(); + let url = result.url.clone(); - Button::new(("citation", index), title) - .label_size(LabelSize::Small) - .color(Color::Muted) - .icon(IconName::ArrowUpRight) - .icon_size(IconSize::XSmall) - .icon_position(IconPosition::End) - .truncate(true) - .tooltip({ - let url = url.clone(); - move |window, cx| { - Tooltip::with_meta( - "Citation Link", - None, - url.clone(), - window, - cx, - ) - } - }) - .on_click({ - let url = url.clone(); - move |_, _, cx| cx.open_url(&url) - }) - }, - )) - .into_any(), - ) - } - Err(_) => None, - }); + Button::new(("result", index), title) + .label_size(LabelSize::Small) + .color(Color::Muted) + .icon(IconName::ArrowUpRight) + .icon_size(IconSize::XSmall) + .icon_position(IconPosition::End) + .truncate(true) + .tooltip({ + let url = url.clone(); + move |window, cx| { + Tooltip::with_meta( + "Web Search Result", + None, + url.clone(), + window, + cx, + ) + } + }) + .on_click({ + let url = url.clone(); + move |_, _, cx| cx.open_url(&url) + }) + })) + .into_any(), + ), + Err(_) => None, + }); v_flex().mb_3().gap_1().child(header).children(content) } @@ -269,36 +264,39 @@ impl Component for WebSearchToolCard { fn example_search_response() -> WebSearchResponse { WebSearchResponse { - summary: r#"Toronto boasts a vibrant culinary scene with a diverse array of..."# - .to_string(), - citations: vec![ - WebSearchCitation { + results: vec![ + WebSearchResult { title: "Alo".to_string(), url: "https://www.google.com/maps/search/Alo%2C+Toronto%2C+Canada".to_string(), - range: Some(147..213), + text: "Alo is a popular restaurant in Toronto.".to_string(), }, - WebSearchCitation { + WebSearchResult { + title: "Alo".to_string(), + url: "https://www.google.com/maps/search/Alo%2C+Toronto%2C+Canada".to_string(), + text: "Information about Alo restaurant in Toronto.".to_string(), + }, + WebSearchResult { title: "Edulis".to_string(), url: "https://www.google.com/maps/search/Edulis%2C+Toronto%2C+Canada".to_string(), - range: Some(447..519), + text: "Details about Edulis restaurant in Toronto.".to_string(), }, - WebSearchCitation { + WebSearchResult { 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), + text: "Information about Sushi Masaki Saito in Toronto.".to_string(), }, - WebSearchCitation { + WebSearchResult { title: "Shoushin".to_string(), url: "https://www.google.com/maps/search/Shoushin%2C+Toronto%2C+Canada".to_string(), - range: Some(1072..1148), + text: "Details about Shoushin restaurant in Toronto.".to_string(), }, - WebSearchCitation { + WebSearchResult { 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), + text: "Information about Restaurant 20 Victoria in Toronto.".to_string(), }, ], } diff --git a/crates/web_search_providers/src/cloud.rs b/crates/web_search_providers/src/cloud.rs index ec1469e0d2..40e03ea00a 100644 --- a/crates/web_search_providers/src/cloud.rs +++ b/crates/web_search_providers/src/cloud.rs @@ -7,7 +7,9 @@ use gpui::{App, AppContext, Context, Entity, Subscription, Task}; use http_client::{HttpClient, Method}; use language_model::{LlmApiToken, RefreshLlmTokenListener}; use web_search::{WebSearchProvider, WebSearchProviderId}; -use zed_llm_client::{WebSearchBody, WebSearchResponse}; +use zed_llm_client::{ + CLIENT_SUPPORTS_EXA_WEB_SEARCH_PROVIDER_HEADER_NAME, WebSearchBody, WebSearchResponse, +}; pub struct CloudWebSearchProvider { state: Entity, @@ -84,6 +86,7 @@ async fn perform_web_search( let request = request_builder .header("Content-Type", "application/json") .header("Authorization", format!("Bearer {token}")) + .header(CLIENT_SUPPORTS_EXA_WEB_SEARCH_PROVIDER_HEADER_NAME, "true") .body(serde_json::to_string(&body)?.into())?; let mut response = http_client .send(request)