pub mod fetch;
pub mod search;
#[cfg(test)]
mod test;
pub mod types;
pub use fetch::{WebFetch, fetch};
pub use search::{WebSearch, search};
pub use types::{WebFetchInput, WebSearchInput};
use crate::ToolDescription;
pub struct Web {
num_results: u32,
pub description_fetch: ToolDescription,
pub description_search: ToolDescription,
}
impl Default for Web {
fn default() -> Self {
Self::new()
}
}
impl Web {
#[must_use]
pub fn new() -> Self {
Self {
num_results: 10,
description_fetch: serde_json::json!({
"name": "web_fetch",
"description": concat!(
"Fetch a URL and return its content as clean, readable markdown. ",
"Strips navigation, scripts, and boilerplate HTML to produce ",
"LLM-friendly text."
),
"inputSchema": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The full HTTP or HTTPS URL to fetch"
}
},
"required": ["url"]
}
}),
description_search: serde_json::json!({
"name": "web_search",
"description": concat!(
"Search the web using a text query and return results as clean ",
"markdown. Each result includes a title, snippet, and URL. ",
"Use this to find current information, documentation, or ",
"answers that are not available in the local codebase."
),
"inputSchema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query string"
}
},
"required": ["query"]
}
}),
}
}
#[must_use]
pub const fn num_results(mut self, n: u32) -> Self {
self.num_results = n;
self
}
pub async fn fetch(&self, fetch: WebFetch) -> Result<String, String> {
fetch::fetch(&fetch).await
}
pub async fn search(&self, query: &str) -> Result<String, String> {
search(&WebSearch {
num_results: self.num_results,
query: query.to_string(),
})
.await
}
}