xai_openapi/
responses.rs

1//! Responses API types for `/v1/responses` endpoint.
2
3use serde::{Deserialize, Serialize};
4
5use crate::prelude::*;
6
7use crate::common::{DebugOutput, IncompleteDetails};
8use crate::search::SearchParameters;
9use crate::tools::{
10    CodeInterpreterCall, CustomToolCall, FileSearchCall, FunctionToolCall, FunctionToolCallOutput,
11    McpCall, ModelTool, ModelToolChoice, OutputMessageContent, WebSearchCall,
12};
13use crate::usage::ModelUsage;
14
15/// The request body for `/v1/responses` endpoint.
16#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
17pub struct ModelRequest {
18    /// The input passed to the model. Can be text, image or file.
19    pub input: ModelInput,
20
21    /// Model name for the model to use.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub model: Option<String>,
24
25    /// An alternate way to specify the system prompt.
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub instructions: Option<String>,
28
29    /// What sampling temperature to use, between 0 and 2.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub temperature: Option<f32>,
32
33    /// An alternative to sampling with temperature, called nucleus sampling.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub top_p: Option<f32>,
36
37    /// Max number of tokens that can be generated in a response.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub max_output_tokens: Option<i32>,
40
41    /// If set, partial message deltas will be sent as server-sent events.
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub stream: Option<bool>,
44
45    /// Whether to return log probabilities of the output tokens.
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub logprobs: Option<bool>,
48
49    /// Whether to store the input message(s) and model response for later retrieval.
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub store: Option<bool>,
52
53    /// The ID of the previous response from the model.
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub previous_response_id: Option<String>,
56
57    /// A list of tools the model may call.
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub tools: Option<Vec<ModelTool>>,
60
61    /// Controls which (if any) tool is called by the model.
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub tool_choice: Option<ModelToolChoice>,
64
65    /// Whether to allow the model to run parallel tool calls.
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub parallel_tool_calls: Option<bool>,
68
69    /// Set the parameters to be used for searched data.
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub search_parameters: Option<SearchParameters>,
72
73    /// Reasoning configuration. Only for reasoning models.
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub reasoning: Option<ReasoningConfiguration>,
76
77    /// Settings for customizing a text response from the model.
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub text: Option<ModelResponseConfiguration>,
80
81    /// What additional output data to include in the response.
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub include: Option<Vec<String>>,
84
85    /// Not supported. Only maintained for compatibility reasons.
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub metadata: Option<serde_json::Value>,
88
89    /// Not supported. Only maintained for compatibility reasons.
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub service_tier: Option<String>,
92
93    /// (Unsupported) Whether to process the response asynchronously in the background.
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub background: Option<bool>,
96}
97
98/// Content of the input passed to a `/v1/responses` request.
99#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
100#[serde(untagged)]
101pub enum ModelInput {
102    /// Text input.
103    Text(String),
104    /// A list of input items to the model.
105    Parts(Vec<ModelInputPart>),
106}
107
108impl Default for ModelInput {
109    fn default() -> Self {
110        ModelInput::Text(String::new())
111    }
112}
113
114/// A part of model input.
115#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
116#[serde(untagged)]
117pub enum ModelInputPart {
118    /// Message input to the model.
119    Message {
120        /// The role of the message.
121        role: String,
122        /// Text, image or audio input.
123        content: ModelInputContent,
124        /// A unique identifier representing your end-user.
125        #[serde(skip_serializing_if = "Option::is_none")]
126        name: Option<String>,
127        /// The type of the message, which is always `message`.
128        #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
129        message_type: Option<String>,
130    },
131    /// Previous responses of the model and tool call outputs.
132    Item(ModelInputItem),
133}
134
135impl Default for ModelInputPart {
136    fn default() -> Self {
137        ModelInputPart::Message {
138            role: "user".to_string(),
139            content: ModelInputContent::default(),
140            name: None,
141            message_type: None,
142        }
143    }
144}
145
146/// Model input content.
147#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
148#[serde(untagged)]
149pub enum ModelInputContent {
150    /// Text input.
151    Text(String),
152    /// A list of input items to the model.
153    Parts(Vec<ModelInputContentItem>),
154}
155
156impl Default for ModelInputContent {
157    fn default() -> Self {
158        ModelInputContent::Text(String::new())
159    }
160}
161
162/// A model input content item.
163#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
164#[serde(tag = "type", rename_all = "snake_case")]
165pub enum ModelInputContentItem {
166    /// Text input.
167    InputText {
168        /// Text input.
169        text: String,
170    },
171    /// Image input.
172    InputImage {
173        /// A public URL of image prompt, only available for vision models.
174        image_url: String,
175        /// Specifies the detail level of the image.
176        #[serde(skip_serializing_if = "Option::is_none")]
177        detail: Option<String>,
178        /// Only included for compatibility.
179        #[serde(skip_serializing_if = "Option::is_none")]
180        file_id: Option<String>,
181    },
182    /// File input.
183    InputFile {
184        /// The file ID from the Files API.
185        file_id: String,
186    },
187}
188
189impl Default for ModelInputContentItem {
190    fn default() -> Self {
191        ModelInputContentItem::InputText {
192            text: String::new(),
193        }
194    }
195}
196
197/// Model input item (previous outputs or tool call outputs).
198#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
199#[serde(untagged)]
200pub enum ModelInputItem {
201    /// Previous model output.
202    Output(ModelOutput),
203    /// Function tool call output.
204    FunctionOutput(FunctionToolCallOutput),
205}
206
207impl Default for ModelInputItem {
208    fn default() -> Self {
209        ModelInputItem::FunctionOutput(FunctionToolCallOutput::default())
210    }
211}
212
213/// The response body for `/v1/responses` endpoint.
214#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
215pub struct ModelResponse {
216    /// Unique ID of the response.
217    pub id: String,
218
219    /// The object type of this resource. Always set to `response`.
220    pub object: String,
221
222    /// The Unix timestamp (in seconds) for the response creation time.
223    pub created_at: i64,
224
225    /// Model name used to generate the response.
226    pub model: String,
227
228    /// The response generated by the model.
229    pub output: Vec<ModelOutput>,
230
231    /// Whether to allow the model to run parallel tool calls.
232    pub parallel_tool_calls: bool,
233
234    /// Settings for customizing a text response from the model.
235    pub text: ModelResponseConfiguration,
236
237    /// Controls which (if any) tool is called by the model.
238    pub tool_choice: ModelToolChoice,
239
240    /// A list of tools the model may call.
241    pub tools: Vec<ModelTool>,
242
243    /// Status of the response. One of `completed`, `in_progress` or `incomplete`.
244    pub status: String,
245
246    /// Whether to store the input message(s) and model response for later retrieval.
247    pub store: bool,
248
249    /// Only included for compatibility.
250    pub metadata: serde_json::Value,
251
252    /// Token usage information.
253    #[serde(skip_serializing_if = "Option::is_none")]
254    pub usage: Option<ModelUsage>,
255
256    /// What sampling temperature to use, between 0 and 2.
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub temperature: Option<f32>,
259
260    /// An alternative to sampling with temperature, called nucleus sampling.
261    #[serde(skip_serializing_if = "Option::is_none")]
262    pub top_p: Option<f32>,
263
264    /// Max number of tokens that can be generated in a response.
265    #[serde(skip_serializing_if = "Option::is_none")]
266    pub max_output_tokens: Option<i32>,
267
268    /// The ID of the previous response from the model.
269    #[serde(skip_serializing_if = "Option::is_none")]
270    pub previous_response_id: Option<String>,
271
272    /// Reasoning configuration. Only for reasoning models.
273    #[serde(skip_serializing_if = "Option::is_none")]
274    pub reasoning: Option<ReasoningConfiguration>,
275
276    /// A unique identifier representing your end-user.
277    #[serde(skip_serializing_if = "Option::is_none")]
278    pub user: Option<String>,
279
280    /// Details about why the response is incomplete.
281    #[serde(skip_serializing_if = "Option::is_none")]
282    pub incomplete_details: Option<IncompleteDetails>,
283
284    /// Whether to process the response asynchronously in the background.
285    #[serde(skip_serializing_if = "Option::is_none")]
286    pub background: Option<bool>,
287
288    /// Debug output. Only available to trusted testers.
289    #[serde(skip_serializing_if = "Option::is_none")]
290    pub debug_output: Option<DebugOutput>,
291}
292
293/// Model output.
294#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
295#[serde(untagged)]
296pub enum ModelOutput {
297    /// An output message from the model.
298    Message(OutputMessage),
299    /// A function tool call.
300    FunctionCall(FunctionToolCall),
301    /// Reasoning done by the model.
302    Reasoning(Reasoning),
303    /// A web search tool call.
304    WebSearch(WebSearchCall),
305    /// A file search tool call.
306    FileSearch(FileSearchCall),
307    /// A code interpreter tool call.
308    CodeInterpreter(CodeInterpreterCall),
309    /// A MCP tool call.
310    Mcp(McpCall),
311    /// A custom tool call.
312    Custom(CustomToolCall),
313}
314
315impl Default for ModelOutput {
316    fn default() -> Self {
317        ModelOutput::Message(OutputMessage::default())
318    }
319}
320
321/// An output message from the model.
322#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
323pub struct OutputMessage {
324    /// The type of the output message, which is always `message`.
325    #[serde(rename = "type")]
326    pub message_type: String,
327
328    /// The role of the output message, which can be `assistant` or `tool`.
329    pub role: String,
330
331    /// Content of the output message.
332    pub content: Vec<OutputMessageContent>,
333
334    /// The unique ID of the output message.
335    #[serde(skip_serializing_if = "Option::is_none")]
336    pub id: Option<String>,
337
338    /// Status of the item. One of `completed`, `in_progress` or `incomplete`.
339    #[serde(skip_serializing_if = "Option::is_none")]
340    pub status: Option<String>,
341}
342
343/// Reasoning configuration.
344#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
345pub struct ReasoningConfiguration {
346    /// Constrains how hard a reasoning model thinks before responding.
347    #[serde(skip_serializing_if = "Option::is_none")]
348    pub effort: Option<String>,
349
350    /// A summary of the model's reasoning process.
351    #[serde(skip_serializing_if = "Option::is_none")]
352    pub summary: Option<String>,
353
354    /// Only included for compatibility.
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub generate_summary: Option<String>,
357}
358
359/// The reasoning done by the model.
360#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
361pub struct Reasoning {
362    /// The type of the object, which is always `reasoning`.
363    #[serde(rename = "type")]
364    pub reasoning_type: String,
365
366    /// The reasoning text contents.
367    pub summary: Vec<ReasoningText>,
368
369    /// The unique ID of the reasoning content.
370    #[serde(skip_serializing_if = "Option::is_none")]
371    pub id: Option<String>,
372
373    /// The encrypted reasoning.
374    #[serde(skip_serializing_if = "Option::is_none")]
375    pub encrypted_content: Option<String>,
376
377    /// Status of the item. One of `completed`, `in_progress` or `incomplete`.
378    #[serde(skip_serializing_if = "Option::is_none")]
379    pub status: Option<String>,
380}
381
382/// Reasoning text.
383#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
384pub struct ReasoningText {
385    /// The type of the object, which is always `summary_text`.
386    #[serde(rename = "type")]
387    pub text_type: String,
388
389    /// Reasoning done by the model.
390    pub text: String,
391}
392
393/// Settings for customizing a text response from the model.
394#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
395pub struct ModelResponseConfiguration {
396    /// An object specifying the format that the model must output.
397    #[serde(skip_serializing_if = "Option::is_none")]
398    pub format: Option<ModelResponseFormat>,
399}
400
401/// Response format parameter for structured outputs (Responses API).
402#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
403#[serde(tag = "type", rename_all = "snake_case")]
404pub enum ModelResponseFormat {
405    /// Specify text response format, always `"text"`.
406    #[default]
407    Text,
408    /// Specify `json_object` response format.
409    JsonObject,
410    /// Specify `json_schema` response format with a given schema.
411    JsonSchema {
412        /// A json schema representing the desired response schema.
413        schema: serde_json::Value,
414        /// Only included for compatibility.
415        #[serde(skip_serializing_if = "Option::is_none")]
416        name: Option<String>,
417        /// Only included for compatibility.
418        #[serde(skip_serializing_if = "Option::is_none")]
419        description: Option<String>,
420        /// Only included for compatibility.
421        #[serde(skip_serializing_if = "Option::is_none")]
422        strict: Option<bool>,
423    },
424}
425
426/// Response to delete a stored completion.
427#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
428pub struct DeleteStoredCompletionResponse {
429    /// The `response_id` to be deleted.
430    pub id: String,
431
432    /// The deleted object type, which is always `response`.
433    pub object: String,
434
435    /// Whether the response was successfully deleted.
436    pub deleted: bool,
437}