1use crate::models::{ResearchDepth, ResearchProvider};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ResearchConfig {
12 #[serde(default)]
14 pub provider: ResearchProvider,
15 #[serde(default)]
17 pub depth: ResearchDepth,
18 #[serde(default = "default_max_sources")]
20 pub max_sources: u32,
21 #[serde(default)]
23 pub include_images: bool,
24 #[serde(default)]
26 pub async_mode: bool,
27}
28
29fn default_max_sources() -> u32 {
30 10
31}
32
33impl Default for ResearchConfig {
34 fn default() -> Self {
35 Self {
36 provider: ResearchProvider::default(),
37 depth: ResearchDepth::default(),
38 max_sources: 10,
39 include_images: false,
40 async_mode: false,
41 }
42 }
43}
44
45impl ResearchConfig {
46 pub fn new() -> Self {
48 Self::default()
49 }
50
51 pub fn with_provider(mut self, provider: ResearchProvider) -> Self {
53 self.provider = provider;
54 self
55 }
56
57 pub fn with_depth(mut self, depth: ResearchDepth) -> Self {
59 self.depth = depth;
60 self
61 }
62
63 pub fn with_max_sources(mut self, max: u32) -> Self {
65 self.max_sources = max;
66 self
67 }
68
69 pub fn with_async(mut self, async_mode: bool) -> Self {
71 self.async_mode = async_mode;
72 self
73 }
74}
75
76#[derive(Debug, Clone, Serialize)]
78pub(crate) struct ResearchRequest {
79 pub topic: String,
80 pub provider: ResearchProvider,
81 pub depth: ResearchDepth,
82 #[serde(rename = "maxSources")]
83 pub max_sources: u32,
84 #[serde(rename = "async")]
85 pub async_mode: bool,
86}
87
88impl ResearchRequest {
89 pub fn new(topic: impl Into<String>, config: &ResearchConfig) -> Self {
90 Self {
91 topic: topic.into(),
92 provider: config.provider.clone(),
93 depth: config.depth.clone(),
94 max_sources: config.max_sources,
95 async_mode: config.async_mode,
96 }
97 }
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct ResearchResult {
103 pub topic: String,
105 pub content: String,
107 #[serde(default)]
109 pub sources: Vec<ResearchSource>,
110 pub provider: String,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct ResearchSource {
117 pub title: String,
118 pub url: String,
119 #[serde(default)]
120 pub snippet: Option<String>,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
125#[serde(untagged)]
126pub enum ResearchResponse {
127 Sync {
129 success: bool,
130 mode: String,
131 result: String, generated_at: String,
138 provider: String,
139 },
140 Async {
142 success: bool,
143 mode: String,
144 #[serde(rename = "taskId")]
145 task_id: String,
146 message: String,
147 },
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct DeepResearchResponse {
162 pub success: bool,
163 pub mode: String,
164 pub result: Option<String>, #[serde(rename = "taskId")]
166 pub task_id: Option<String>, #[serde(rename = "generatedAt")]
168 pub generated_at: Option<String>,
169 pub provider: Option<String>,
170 pub message: Option<String>,
171}
172
173pub use crate::search::DeepResearchResponse as ResearchApiResponse;