use crate::types::io::FunctionTool;
use crate::types::io::input::FunctionToolResultMessage;
use crate::types::tools::ResponsesTool;
use crate::utils::common::serialize_to_value_or_custom_default;
use super::codex::CodexNamespaceHandler;
use super::custom::CustomHandler;
use super::function::FunctionHandler;
use super::handler::{ToolError, ToolHandler, ToolOutput};
use super::mcp::McpHandler;
use super::registry::ToolType;
use super::web_search::web_search_function_tool;
impl ResponsesTool {
pub fn validate(&self) -> Result<(), ToolError> {
match self {
Self::Function(param) => serialize_to_value_or_custom_default(
param,
"function tool config serialization failed",
|param| FunctionHandler.validate(¶m),
Err(ToolError::Config(
"function tool config serialization failed".to_owned(),
)),
),
Self::Mcp(param) => serialize_to_value_or_custom_default(
param,
"MCP tool config serialization failed",
|param| McpHandler::spec_from_param(¶m).validate(¶m),
Err(ToolError::Config("MCP tool config serialization failed".to_owned())),
),
Self::WebSearch(_) | Self::FileSearch(_) | Self::CodeInterpreter(_) | Self::Unknown => Ok(()),
Self::Namespace(param) => serialize_to_value_or_custom_default(
param,
"namespace tool config serialization failed",
|param| CodexNamespaceHandler.validate(¶m),
Err(ToolError::Config(
"namespace tool config serialization failed".to_owned(),
)),
),
Self::Custom(param) => serialize_to_value_or_custom_default(
param,
"custom tool config serialization failed",
|param| CustomHandler.validate(¶m),
Err(ToolError::Config("custom tool config serialization failed".to_owned())),
),
}
}
#[must_use]
pub fn tool_type(&self) -> Option<ToolType> {
match self {
Self::Function(_) => Some(ToolType::Function),
Self::Mcp(_) => Some(ToolType::Mcp),
Self::WebSearch(_) => Some(ToolType::WebSearch),
Self::FileSearch(_) => Some(ToolType::FileSearch),
Self::CodeInterpreter(_) => Some(ToolType::CodeInterpreter),
Self::Namespace(_) => Some(ToolType::CodexNamespace),
Self::Custom(_) => Some(ToolType::Custom),
Self::Unknown => None,
}
}
#[must_use]
pub fn is_gateway_owned(&self) -> bool {
self.tool_type().is_some_and(ToolType::is_gateway_owned)
}
#[must_use]
pub fn to_function_tools(&self) -> Vec<FunctionTool> {
match self {
Self::Function(p) => serialize_to_value_or_custom_default(
p,
"function tool config serialization failed",
|param| FunctionHandler.normalize(¶m).into_iter().take(1).collect(),
vec![],
),
Self::Mcp(p) => serialize_to_value_or_custom_default(
p,
"MCP tool config serialization failed",
|param| McpHandler::spec_from_param(¶m).normalize(¶m),
vec![],
),
Self::WebSearch(_) => vec![web_search_function_tool()],
Self::FileSearch(_) => {
tracing::debug!("file_search tool skipped in normalize - handler not yet registered");
vec![]
}
Self::CodeInterpreter(_) => {
tracing::debug!("code_interpreter tool skipped in normalize - handler not yet registered");
vec![]
}
Self::Namespace(p) => serialize_to_value_or_custom_default(
p,
"function tool config serialization failed",
|param| CodexNamespaceHandler.normalize(¶m),
vec![],
),
Self::Custom(p) => serialize_to_value_or_custom_default(
p,
"custom tool config serialization failed",
|param| CustomHandler.normalize(¶m),
vec![],
),
Self::Unknown => {
tracing::debug!("unknown tool skipped in normalize");
vec![]
}
}
}
}
impl From<ToolOutput> for FunctionToolResultMessage {
fn from(o: ToolOutput) -> Self {
Self {
call_id: o.call_id,
output: o.output.into(),
}
}
}