use serde::{Deserialize, Serialize};
use crate::prelude::*;
use crate::common::{DebugOutput, IncompleteDetails};
use crate::search::SearchParameters;
use crate::tools::{
CodeInterpreterCall, CustomToolCall, FileSearchCall, FunctionToolCall, FunctionToolCallOutput,
McpCall, ModelTool, ModelToolChoice, OutputMessageContent, WebSearchCall,
};
use crate::usage::ModelUsage;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ModelRequest {
pub input: ModelInput,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_output_tokens: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stream: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub logprobs: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub store: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub previous_response_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<ModelTool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_choice: Option<ModelToolChoice>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parallel_tool_calls: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub search_parameters: Option<SearchParameters>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning: Option<ReasoningConfiguration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<ModelResponseConfiguration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub include: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub service_tier: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub background: Option<bool>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ModelInput {
Text(String),
Parts(Vec<ModelInputPart>),
}
impl Default for ModelInput {
fn default() -> Self {
ModelInput::Text(String::new())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ModelInputPart {
Message {
role: String,
content: ModelInputContent,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
message_type: Option<String>,
},
Item(ModelInputItem),
}
impl Default for ModelInputPart {
fn default() -> Self {
ModelInputPart::Message {
role: "user".to_string(),
content: ModelInputContent::default(),
name: None,
message_type: None,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ModelInputContent {
Text(String),
Parts(Vec<ModelInputContentItem>),
}
impl Default for ModelInputContent {
fn default() -> Self {
ModelInputContent::Text(String::new())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ModelInputContentItem {
InputText {
text: String,
},
InputImage {
image_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
detail: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
file_id: Option<String>,
},
InputFile {
file_id: String,
},
}
impl Default for ModelInputContentItem {
fn default() -> Self {
ModelInputContentItem::InputText {
text: String::new(),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ModelInputItem {
Output(ModelOutput),
FunctionOutput(FunctionToolCallOutput),
}
impl Default for ModelInputItem {
fn default() -> Self {
ModelInputItem::FunctionOutput(FunctionToolCallOutput::default())
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ModelResponse {
pub id: String,
pub object: String,
pub created_at: i64,
pub model: String,
pub output: Vec<ModelOutput>,
pub parallel_tool_calls: bool,
pub text: ModelResponseConfiguration,
pub tool_choice: ModelToolChoice,
pub tools: Vec<ModelTool>,
pub status: String,
pub store: bool,
pub metadata: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub usage: Option<ModelUsage>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_output_tokens: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub previous_response_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning: Option<ReasoningConfiguration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub incomplete_details: Option<IncompleteDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
pub background: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub debug_output: Option<DebugOutput>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ModelOutput {
Message(OutputMessage),
FunctionCall(FunctionToolCall),
Reasoning(Reasoning),
WebSearch(WebSearchCall),
FileSearch(FileSearchCall),
CodeInterpreter(CodeInterpreterCall),
Mcp(McpCall),
Custom(CustomToolCall),
}
impl Default for ModelOutput {
fn default() -> Self {
ModelOutput::Message(OutputMessage::default())
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct OutputMessage {
#[serde(rename = "type")]
pub message_type: String,
pub role: String,
pub content: Vec<OutputMessageContent>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ReasoningConfiguration {
#[serde(skip_serializing_if = "Option::is_none")]
pub effort: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_summary: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Reasoning {
#[serde(rename = "type")]
pub reasoning_type: String,
pub summary: Vec<ReasoningText>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub encrypted_content: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ReasoningText {
#[serde(rename = "type")]
pub text_type: String,
pub text: String,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ModelResponseConfiguration {
#[serde(skip_serializing_if = "Option::is_none")]
pub format: Option<ModelResponseFormat>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ModelResponseFormat {
#[default]
Text,
JsonObject,
JsonSchema {
schema: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
strict: Option<bool>,
},
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct DeleteStoredCompletionResponse {
pub id: String,
pub object: String,
pub deleted: bool,
}