Skip to main content

web_search/providers/
base.rs

1//! Base provider trait and common types
2
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5
6use crate::error::SearchError;
7use crate::transport::SearchTransport;
8
9/// A single search result
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct SearchResult {
12    /// The title of the search result
13    pub title: String,
14    /// The URL of the search result
15    pub url: String,
16    /// The description/snippet of the search result
17    pub snippet: String,
18    /// The search provider that returned this result
19    pub source: String,
20    /// The rank position in the original results (1-based)
21    pub rank: usize,
22    /// Computed score after merging (optional)
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub score: Option<f64>,
25    /// Sources that returned this result (after deduplication)
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub sources: Option<Vec<String>>,
28}
29
30/// Options for search queries
31#[derive(Debug, Clone, Default)]
32pub struct SearchOptions {
33    /// Maximum number of results to return
34    pub limit: Option<usize>,
35    /// Language code (e.g., "en", "de")
36    pub language: Option<String>,
37    /// Region code (e.g., "us", "de")
38    pub region: Option<String>,
39    /// Enable safe search filtering
40    pub safe_search: Option<bool>,
41}
42
43/// Trait that all search providers must implement
44#[async_trait]
45pub trait SearchProvider: Send + Sync {
46    /// Get the provider name
47    fn name(&self) -> &str;
48
49    /// Check if the provider is available/enabled
50    fn is_available(&self) -> bool;
51
52    /// Get the provider weight for reranking
53    fn weight(&self) -> f64;
54
55    /// Set the provider weight for reranking
56    fn set_weight(&mut self, weight: f64);
57
58    /// Enable or disable the provider
59    fn set_enabled(&mut self, enabled: bool);
60
61    /// Perform a search with the provider's default transport.
62    async fn search(
63        &self,
64        query: &str,
65        options: &SearchOptions,
66    ) -> Result<Vec<SearchResult>, SearchError>;
67
68    /// Perform a search with a caller-owned transport.
69    ///
70    /// The default preserves compatibility for third-party providers; built-in
71    /// providers override this method so every network request is routed through
72    /// the supplied transport.
73    async fn search_with_transport(
74        &self,
75        query: &str,
76        options: &SearchOptions,
77        transport: &dyn SearchTransport,
78    ) -> Result<Vec<SearchResult>, SearchError> {
79        let _ = transport;
80        self.search(query, options).await
81    }
82}