magi-openai 0.1.1

OpenAI compatible API SDK for Magi AI agents
Documentation
use std::sync::Arc;

use rmcp::model::Tool as RmcpTool;

use crate::responses::request::{FunctionTool, Tool};

impl From<RmcpTool> for Tool {
    fn from(rmcp_tool: RmcpTool) -> Self {
        Tool::Function(FunctionTool {
            name: rmcp_tool.name.to_string(),
            description: rmcp_tool.description,
            parameters: Some(serde_json::to_value(&*rmcp_tool.input_schema).unwrap_or_default()),
            strict: None,
        })
    }
}

impl From<Tool> for RmcpTool {
    fn from(tool: Tool) -> Self {
        match tool {
            Tool::Function(function) => {
                let input_schema: Arc<rmcp::model::JsonObject> = match function.parameters {
                    Some(params) => serde_json::from_value(params).unwrap_or_default(),
                    None => Default::default(),
                };
                RmcpTool::new_with_raw(
                    function.name.clone(),
                    function.description.clone(),
                    input_schema,
                )
            }
            // For non-function tools, create a placeholder tool
            _ => RmcpTool::new_with_raw(
                "unsupported_tool",
                None,
                Arc::<rmcp::model::JsonObject>::default(),
            ),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::responses::request::FunctionTool;
    use serde_json::json;
    use std::borrow::Cow;

    #[test]
    fn converts_rmcp_tool_to_openai_tool() {
        let rmcp_tool = RmcpTool::new(
            "get_weather",
            Cow::from("Get the current weather"),
            Arc::new(
                serde_json::from_value::<rmcp::model::JsonObject>(json!({
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city and state"
                        }
                    },
                    "required": ["location"]
                }))
                .unwrap(),
            ),
        );

        let openai_tool: Tool = rmcp_tool.into();
        match openai_tool {
            Tool::Function(function) => {
                assert_eq!(function.name, "get_weather");
                assert_eq!(
                    function.description,
                    Some(Cow::from("Get the current weather"))
                );
            }
            _ => panic!("Expected Function variant"),
        }
    }

    #[test]
    fn converts_openai_tool_to_rmcp_tool() {
        let openai_tool = Tool::Function(FunctionTool {
            name: "get_weather".into(),
            description: Some(Cow::from("Get the current weather")),
            parameters: Some(json!({
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state"
                    }
                },
                "required": ["location"]
            })),
            strict: None,
        });

        let rmcp_tool: RmcpTool = openai_tool.into();
        assert_eq!(rmcp_tool.name, "get_weather");
        assert_eq!(
            rmcp_tool.description,
            Some(Cow::from("Get the current weather"))
        );
    }
}