web-search 0.3.1

A multi-provider web search aggregator with reranking support
Documentation
//! Base provider trait and common types

use async_trait::async_trait;
use serde::{Deserialize, Serialize};

use crate::error::SearchError;

/// A single search result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResult {
    /// The title of the search result
    pub title: String,
    /// The URL of the search result
    pub url: String,
    /// The description/snippet of the search result
    pub snippet: String,
    /// The search provider that returned this result
    pub source: String,
    /// The rank position in the original results (1-based)
    pub rank: usize,
    /// Computed score after merging (optional)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub score: Option<f64>,
    /// Sources that returned this result (after deduplication)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sources: Option<Vec<String>>,
}

/// Options for search queries
#[derive(Debug, Clone, Default)]
pub struct SearchOptions {
    /// Maximum number of results to return
    pub limit: Option<usize>,
    /// Language code (e.g., "en", "de")
    pub language: Option<String>,
    /// Region code (e.g., "us", "de")
    pub region: Option<String>,
    /// Enable safe search filtering
    pub safe_search: Option<bool>,
}

/// Trait that all search providers must implement
#[async_trait]
pub trait SearchProvider: Send + Sync {
    /// Get the provider name
    fn name(&self) -> &str;

    /// Check if the provider is available/enabled
    fn is_available(&self) -> bool;

    /// Get the provider weight for reranking
    fn weight(&self) -> f64;

    /// Set the provider weight for reranking
    fn set_weight(&mut self, weight: f64);

    /// Enable or disable the provider
    fn set_enabled(&mut self, enabled: bool);

    /// Perform a search
    async fn search(
        &self,
        query: &str,
        options: &SearchOptions,
    ) -> Result<Vec<SearchResult>, SearchError>;
}