use serde::{Deserialize, Serialize};
use crate::prelude::*;
use crate::common::Annotation;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Tool {
Function {
function: FunctionDefinition,
},
LiveSearch {
sources: Vec<crate::search::SearchSource>,
},
}
impl Default for Tool {
fn default() -> Self {
Tool::Function {
function: FunctionDefinition::default(),
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct FunctionDefinition {
pub name: String,
pub parameters: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub strict: Option<bool>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ToolCall {
pub id: String,
pub function: Function,
#[serde(skip_serializing_if = "Option::is_none")]
pub index: Option<i32>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub tool_type: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Function {
pub name: String,
pub arguments: String,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct FunctionChoice {
pub name: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ToolChoice {
Mode(String),
Specific {
#[serde(rename = "type")]
tool_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
function: Option<FunctionChoice>,
},
}
impl Default for ToolChoice {
fn default() -> Self {
ToolChoice::Mode("auto".to_string())
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct FunctionToolCall {
#[serde(rename = "type")]
pub call_type: String,
pub call_id: String,
pub name: String,
pub arguments: String,
#[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 FunctionToolCallOutput {
#[serde(rename = "type")]
pub output_type: String,
pub call_id: String,
pub output: String,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct WebSearchCall {
#[serde(rename = "type")]
pub call_type: String,
pub action: WebSearchAction,
#[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, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum WebSearchAction {
Search {
query: String,
#[serde(skip_serializing_if = "Option::is_none")]
sources: Option<Vec<WebSearchSource>>,
},
OpenPage {
url: String,
},
Find {
source: WebSearchSource,
pattern: String,
},
}
impl Default for WebSearchAction {
fn default() -> Self {
WebSearchAction::Search {
query: String::new(),
sources: None,
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct WebSearchSource {
#[serde(rename = "type")]
pub source_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct WebSearchOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub search_context_size: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub filters: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_location: Option<serde_json::Value>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct WebSearchFilters {
#[serde(skip_serializing_if = "Option::is_none")]
pub allowed_domains: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub excluded_domains: Option<Vec<String>>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct FileSearchCall {
#[serde(rename = "type")]
pub call_type: String,
pub queries: Vec<String>,
pub results: Vec<FileSearchResult>,
#[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 FileSearchResult {
pub file_id: String,
pub filename: String,
pub score: f64,
pub text: String,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct CodeInterpreterCall {
#[serde(rename = "type")]
pub call_type: String,
pub outputs: Vec<CodeInterpreterOutput>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[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, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CodeInterpreterOutput {
Logs {
logs: String,
},
Image {
url: String,
},
}
impl Default for CodeInterpreterOutput {
fn default() -> Self {
CodeInterpreterOutput::Logs {
logs: String::new(),
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct McpCall {
#[serde(rename = "type")]
pub call_type: String,
pub name: String,
pub server_label: String,
pub arguments: String,
pub output: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct CustomToolCall {
#[serde(rename = "type")]
pub call_type: String,
pub call_id: String,
pub name: String,
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub input: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ModelTool {
Function {
name: String,
parameters: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
strict: Option<bool>,
},
WebSearch {
#[serde(skip_serializing_if = "Option::is_none")]
allowed_domains: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
excluded_domains: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
enable_image_understanding: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
external_web_access: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
filters: Option<WebSearchFilters>,
#[serde(skip_serializing_if = "Option::is_none")]
search_context_size: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
user_location: Option<serde_json::Value>,
},
XSearch {
#[serde(skip_serializing_if = "Option::is_none")]
allowed_x_handles: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
excluded_x_handles: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
enable_image_understanding: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
enable_video_understanding: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
from_date: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
to_date: Option<String>,
},
FileSearch {
vector_store_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
max_num_results: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
filters: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
ranking_options: Option<serde_json::Value>,
},
CodeInterpreter {
#[serde(skip_serializing_if = "Option::is_none")]
container: Option<serde_json::Value>,
},
Mcp {
server_label: String,
server_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
allowed_tools: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
authorization: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
connector_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
headers: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
require_approval: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
server_description: Option<String>,
},
}
impl Default for ModelTool {
fn default() -> Self {
ModelTool::Function {
name: String::new(),
parameters: serde_json::Value::Null,
description: None,
strict: None,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ModelToolChoice {
Mode(String),
Specific {
#[serde(rename = "type")]
tool_type: String,
name: String,
},
}
impl Default for ModelToolChoice {
fn default() -> Self {
ModelToolChoice::Mode("auto".to_string())
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct OutputText {
#[serde(rename = "type")]
pub output_type: String,
pub text: String,
pub annotations: Vec<Annotation>,
#[serde(skip_serializing_if = "Option::is_none")]
pub logprobs: Option<Vec<crate::chat::TokenLogProb>>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct OutputRefusal {
#[serde(rename = "type")]
pub output_type: String,
pub refusal: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum OutputMessageContent {
OutputText {
text: String,
annotations: Vec<Annotation>,
#[serde(skip_serializing_if = "Option::is_none")]
logprobs: Option<Vec<crate::chat::TokenLogProb>>,
},
Refusal {
refusal: String,
},
}
impl Default for OutputMessageContent {
fn default() -> Self {
OutputMessageContent::OutputText {
text: String::new(),
annotations: Vec::new(),
logprobs: None,
}
}
}