use serde::{Deserialize, Serialize};
use crate::client::Client;
use crate::error::Result;
#[derive(Debug, Clone, Serialize, Default)]
pub struct SearchOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub offset: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub freshness: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub safe_search: Option<String>,
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct ContextOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub freshness: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchMessage {
pub role: String,
pub content: String,
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct WebSearchRequest {
pub query: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub offset: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub freshness: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub safesearch: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WebResult {
pub title: String,
pub url: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub age: Option<String>,
#[serde(default)]
pub favicon: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NewsResult {
pub title: String,
pub url: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub age: Option<String>,
#[serde(default)]
pub source: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoResult {
pub title: String,
pub url: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub thumbnail: Option<String>,
#[serde(default)]
pub age: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Infobox {
pub title: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub url: Option<String>,
}
pub type InfoboxResult = Infobox;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Discussion {
pub title: String,
pub url: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub age: Option<String>,
#[serde(default)]
pub forum: Option<String>,
}
pub type DiscussionResult = Discussion;
#[derive(Debug, Clone, Deserialize)]
pub struct WebSearchResponse {
pub query: String,
#[serde(default)]
pub web: Vec<WebResult>,
#[serde(default)]
pub news: Vec<NewsResult>,
#[serde(default)]
pub videos: Vec<VideoResult>,
#[serde(default)]
pub infobox: Vec<Infobox>,
#[serde(default)]
pub discussions: Vec<Discussion>,
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct SearchContextRequest {
pub query: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub freshness: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchContextChunk {
pub content: String,
pub url: String,
#[serde(default)]
pub title: String,
#[serde(default)]
pub score: f64,
#[serde(default)]
pub content_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchContextSource {
pub url: String,
#[serde(default)]
pub title: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SearchContextResponse {
pub chunks: Vec<SearchContextChunk>,
#[serde(default)]
pub sources: Vec<SearchContextSource>,
pub query: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct LLMContextResponse {
pub query: String,
#[serde(default)]
pub chunks: Vec<ContextChunk>,
#[serde(default)]
pub sources: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContextChunk {
pub content: String,
pub url: String,
#[serde(default)]
pub title: String,
#[serde(default)]
pub score: f64,
#[serde(default)]
pub content_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchAnswerMessage {
pub role: String,
pub content: String,
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct SearchAnswerRequest {
pub messages: Vec<SearchAnswerMessage>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchAnswerCitation {
pub url: String,
#[serde(default)]
pub title: String,
#[serde(default)]
pub snippet: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SearchAnswerChoice {
pub index: i32,
pub message: SearchAnswerMessage,
#[serde(default)]
pub finish_reason: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SearchAnswerResponse {
pub choices: Vec<SearchAnswerChoice>,
#[serde(default)]
pub model: String,
#[serde(default)]
pub id: String,
#[serde(default)]
pub citations: Vec<SearchAnswerCitation>,
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct GoogleSearchRequest {
pub query: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoogleSearchCitation {
pub url: String,
#[serde(default)]
pub title: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoogleSearchSupport {
pub start_index: i32,
pub end_index: i32,
#[serde(default)]
pub text: String,
#[serde(default)]
pub grounding_chunk_indices: Vec<i32>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct GoogleSearchResponse {
#[serde(default)]
pub answer: String,
#[serde(default)]
pub citations: Vec<GoogleSearchCitation>,
#[serde(default)]
pub search_entry_point: String,
#[serde(default)]
pub web_search_queries: Vec<String>,
#[serde(default)]
pub supports: Vec<GoogleSearchSupport>,
}
impl Client {
pub async fn web_search(&self, req: &WebSearchRequest) -> Result<WebSearchResponse> {
let (resp, _meta) = self
.post_json::<WebSearchRequest, WebSearchResponse>("/qai/v1/search/web", req)
.await?;
Ok(resp)
}
pub async fn search_context(
&self,
req: &SearchContextRequest,
) -> Result<SearchContextResponse> {
let (resp, _meta) = self
.post_json::<SearchContextRequest, SearchContextResponse>(
"/qai/v1/search/context",
req,
)
.await?;
Ok(resp)
}
pub async fn search_answer(&self, req: &SearchAnswerRequest) -> Result<SearchAnswerResponse> {
let (resp, _meta) = self
.post_json::<SearchAnswerRequest, SearchAnswerResponse>(
"/qai/v1/search/answer",
req,
)
.await?;
Ok(resp)
}
pub async fn google_search(
&self,
req: &GoogleSearchRequest,
) -> Result<GoogleSearchResponse> {
let (resp, _meta) = self
.post_json::<GoogleSearchRequest, GoogleSearchResponse>(
"/qai/v1/search/google",
req,
)
.await?;
Ok(resp)
}
}