use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ToolDefinition {
#[serde(rename = "type")]
pub kind: ToolKind,
pub function: FunctionDefinition,
}
impl ToolDefinition {
pub fn function(function: FunctionDefinition) -> Self {
Self { kind: ToolKind::Function, function }
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ToolKind {
Function,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FunctionDefinition {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub parameters: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub strict: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
pub enum ToolChoice {
String(ToolChoiceMode),
Object(ToolChoiceFunction),
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum ToolChoiceMode {
None,
Auto,
Required,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ToolChoiceFunction {
#[serde(rename = "type")]
pub kind: ToolKind,
pub function: FunctionName,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FunctionName {
pub name: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ResponseFormat {
Text,
JsonObject,
JsonSchema {
json_schema: JsonSchemaBody,
},
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct JsonSchemaBody {
pub name: String,
pub schema: serde_json::Value,
pub strict: bool,
}
impl From<crate::request::ToolChoice> for ToolChoice {
fn from(tc: crate::request::ToolChoice) -> Self {
match tc {
crate::request::ToolChoice::Auto => ToolChoice::String(ToolChoiceMode::Auto),
crate::request::ToolChoice::None => ToolChoice::String(ToolChoiceMode::None),
crate::request::ToolChoice::Required => ToolChoice::String(ToolChoiceMode::Required),
crate::request::ToolChoice::Tool(name) => ToolChoice::Object(ToolChoiceFunction {
kind: ToolKind::Function,
function: FunctionName { name },
}),
}
}
}
impl From<crate::request::ResponseFormat> for ResponseFormat {
fn from(f: crate::request::ResponseFormat) -> Self {
match f {
crate::request::ResponseFormat::Text => ResponseFormat::Text,
crate::request::ResponseFormat::JsonObject => ResponseFormat::JsonObject,
crate::request::ResponseFormat::JsonSchema { name, schema, strict } =>
ResponseFormat::JsonSchema { json_schema: JsonSchemaBody { name, schema, strict } },
}
}
}
#[derive(Debug)]
pub enum ContentWire<'a> {
Text(&'a str),
Parts(&'a [crate::request::Content]),
}
pub fn content_to_wire(parts: &[crate::request::Content]) -> ContentWire<'_> {
if let [crate::request::Content::Text { text }] = parts {
ContentWire::Text(text.as_str())
} else {
ContentWire::Parts(parts)
}
}