use ferrin_spec::JsonValue;
use ferrin_spec::ToolCallId;
use ferrin_spec::language_model::prompt::ToolResultOutput;
use crate::error::ToolError;
use crate::tool::ModelOutputArgs;
use crate::tool::Tool;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum ErrorMode {
#[default]
None,
Text,
Json,
}
#[must_use]
pub fn create_tool_model_output(
tool: Option<&Tool>,
tool_call_id: &ToolCallId,
input: &JsonValue,
output: &JsonValue,
error_mode: ErrorMode,
) -> ToolResultOutput {
match error_mode {
ErrorMode::Text => return ToolResultOutput::error_text(error_message(output)),
ErrorMode::Json => return ToolResultOutput::error_json(output.clone()),
ErrorMode::None => {}
}
if let Some(convert) = tool.and_then(Tool::to_model_output) {
return convert(ModelOutputArgs {
tool_call_id,
input,
output,
});
}
match output {
JsonValue::String(text) => ToolResultOutput::text(text.clone()),
other => ToolResultOutput::json(other.clone()),
}
}
#[must_use]
pub fn tool_error_output(error: &ToolError) -> ToolResultOutput {
match error {
ToolError::Json { value } => ToolResultOutput::error_json(value.clone()),
other => ToolResultOutput::error_text(other.to_string()),
}
}
#[must_use]
pub fn error_message(value: &JsonValue) -> String {
match value {
JsonValue::Null => "unknown error".to_owned(),
JsonValue::String(text) => text.clone(),
JsonValue::Object(map) => match map.get("message") {
Some(JsonValue::String(message)) => message.clone(),
_ => value.to_string(),
},
other => other.to_string(),
}
}