1use crate::common::Reasoning;
2use codex_protocol::models::ResponseItem;
3use schemars::JsonSchema;
4use serde::Deserialize;
5use serde::Serialize;
6use serde_json::Value as JsonValue;
7
8#[derive(Debug, Clone, Serialize, PartialEq)]
9pub struct SearchRequest {
10 pub id: String,
11 pub model: String,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 pub reasoning: Option<Reasoning>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub input: Option<SearchInput>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub commands: Option<SearchCommands>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub settings: Option<SearchSettings>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub max_output_tokens: Option<u64>,
22}
23
24#[derive(Debug, Clone, Serialize, PartialEq)]
25#[serde(untagged)]
26pub enum SearchInput {
27 Text(String),
28 Items(Vec<ResponseItem>),
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, JsonSchema)]
32pub struct SearchCommands {
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub search_query: Option<Vec<SearchQuery>>,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub image_query: Option<Vec<SearchQuery>>,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub open: Option<Vec<OpenOperation>>,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub click: Option<Vec<ClickOperation>>,
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub find: Option<Vec<FindOperation>>,
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub screenshot: Option<Vec<ScreenshotOperation>>,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub finance: Option<Vec<FinanceOperation>>,
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub weather: Option<Vec<WeatherOperation>>,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub sports: Option<Vec<SportsOperation>>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub time: Option<Vec<TimeOperation>>,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub response_length: Option<SearchResponseLength>,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
69pub struct SearchQuery {
70 pub q: String,
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub recency: Option<u64>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub domains: Option<Vec<String>>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
81pub struct OpenOperation {
82 pub ref_id: String,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub lineno: Option<u64>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
90pub struct ClickOperation {
91 pub ref_id: String,
93 pub id: u64,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
98pub struct FindOperation {
99 pub ref_id: String,
101 pub pattern: String,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
106pub struct ScreenshotOperation {
107 pub ref_id: String,
109 pub pageno: u64,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
114pub struct FinanceOperation {
115 pub ticker: String,
117 pub r#type: FinanceAssetType,
119 #[serde(skip_serializing_if = "Option::is_none")]
121 pub market: Option<String>,
122}
123
124#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
125#[serde(rename_all = "lowercase")]
126pub enum FinanceAssetType {
127 Equity,
128 Fund,
129 Crypto,
130 Index,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
134pub struct WeatherOperation {
135 pub location: String,
137 #[serde(skip_serializing_if = "Option::is_none")]
139 pub start: Option<String>,
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub duration: Option<u64>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
146pub struct SportsOperation {
147 #[serde(skip_serializing_if = "Option::is_none")]
149 pub tool: Option<SportsToolName>,
150 pub r#fn: SportsFunction,
152 pub league: SportsLeague,
154 #[serde(skip_serializing_if = "Option::is_none")]
156 pub team: Option<String>,
157 #[serde(skip_serializing_if = "Option::is_none")]
159 pub opponent: Option<String>,
160 #[serde(skip_serializing_if = "Option::is_none")]
162 pub date_from: Option<String>,
163 #[serde(skip_serializing_if = "Option::is_none")]
165 pub date_to: Option<String>,
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub num_games: Option<u64>,
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub locale: Option<String>,
172}
173
174#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
175#[serde(rename_all = "lowercase")]
176pub enum SportsToolName {
177 Sports,
178}
179
180#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
181#[serde(rename_all = "lowercase")]
182pub enum SportsFunction {
183 Schedule,
184 Standings,
185}
186
187#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
188#[serde(rename_all = "lowercase")]
189pub enum SportsLeague {
190 Nba,
191 Wnba,
192 Nfl,
193 Nhl,
194 Mlb,
195 Epl,
196 Ncaamb,
197 Ncaawb,
198 Ipl,
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
202pub struct TimeOperation {
203 pub utc_offset: String,
205}
206
207#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
208#[serde(rename_all = "lowercase")]
209pub enum SearchResponseLength {
210 Short,
211 Medium,
212 Long,
213}
214
215#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
216#[serde(rename_all = "snake_case")]
217pub enum ExternalWebAccessMode {
218 Cached,
219 Indexed,
220 Live,
221}
222
223#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
224#[serde(untagged)]
225pub enum ExternalWebAccess {
226 Boolean(bool),
227 Mode(ExternalWebAccessMode),
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
231pub struct SearchSettings {
232 #[serde(skip_serializing_if = "Option::is_none")]
233 pub user_location: Option<ApproximateLocation>,
234 #[serde(skip_serializing_if = "Option::is_none")]
235 pub search_context_size: Option<SearchContextSize>,
236 #[serde(skip_serializing_if = "Option::is_none")]
237 pub filters: Option<SearchFilters>,
238 #[serde(skip_serializing_if = "Option::is_none")]
239 pub image_settings: Option<SearchImageSettings>,
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub allowed_callers: Option<Vec<AllowedCaller>>,
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub external_web_access: Option<ExternalWebAccess>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
247pub struct ApproximateLocation {
248 pub r#type: LocationType,
249 #[serde(skip_serializing_if = "Option::is_none")]
250 pub country: Option<String>,
251 #[serde(skip_serializing_if = "Option::is_none")]
252 pub region: Option<String>,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 pub city: Option<String>,
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub timezone: Option<String>,
257}
258
259#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
260#[serde(rename_all = "lowercase")]
261pub enum LocationType {
262 Approximate,
263}
264
265#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
266#[serde(rename_all = "lowercase")]
267pub enum SearchContextSize {
268 Low,
269 Medium,
270 High,
271}
272
273#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
274pub struct SearchFilters {
275 #[serde(skip_serializing_if = "Option::is_none")]
276 pub allowed_domains: Option<Vec<String>>,
277 #[serde(skip_serializing_if = "Option::is_none")]
278 pub blocked_domains: Option<Vec<String>>,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
282pub struct SearchImageSettings {
283 #[serde(skip_serializing_if = "Option::is_none")]
284 pub max_results: Option<u64>,
285 #[serde(skip_serializing_if = "Option::is_none")]
286 pub caption: Option<bool>,
287}
288
289#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
290#[serde(rename_all = "snake_case")]
291pub enum AllowedCaller {
292 Direct,
293 Shell,
294 CodeInterpreter,
295}
296
297#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
298pub struct SearchResponse {
299 pub encrypted_output: Option<String>,
300 pub output: String,
301 #[serde(default)]
304 pub results: Option<Vec<JsonValue>>,
305}