agentic_core/tool/
function.rs1use std::collections::HashMap;
2
3use serde_json::Value;
4
5use crate::types::io::FunctionTool;
6use crate::types::tools::FunctionToolParam;
7use crate::utils::common::serialize_to_value_or_custom_default;
8
9use super::handler::{ToolError, ToolHandler};
10use super::registry::{ToolEntry, ToolType};
11
12impl From<&FunctionToolParam> for FunctionTool {
13 fn from(p: &FunctionToolParam) -> Self {
14 Self {
15 type_: "function".to_owned(),
16 name: p.name.as_str().to_owned(),
17 description: p.description.clone(),
18 parameters: p.parameters.clone(),
19 strict: p.strict,
20 }
21 }
22}
23
24#[derive(Debug)]
31pub struct FunctionHandler;
32
33impl ToolHandler for FunctionHandler {
34 fn tool_type(&self) -> ToolType {
35 ToolType::Function
36 }
37
38 fn validate(&self, param: &Value) -> Result<(), ToolError> {
39 match param.get("name").and_then(Value::as_str) {
40 Some(name) if !name.is_empty() => Ok(()),
41 _ => Err(ToolError::Config("function tool must have a non-empty name".into())),
42 }
43 }
44
45 fn normalize(&self, param: &Value) -> Vec<FunctionTool> {
46 match serde_json::from_value::<FunctionToolParam>(param.clone()) {
50 Ok(p) => vec![FunctionTool::from(&p)],
51 Err(e) => {
52 tracing::warn!("normalize() called with invalid param: {e} — validate() must be called first");
53 vec![]
54 }
55 }
56 }
57}
58
59pub(crate) fn insert_function_entry(entries: &mut HashMap<String, ToolEntry>, p: &FunctionToolParam) {
60 serialize_to_value_or_custom_default(
63 p,
64 "function tool config serialization failed",
65 |config| {
66 if entries
67 .insert(
68 p.name.as_str().to_owned(),
69 ToolEntry {
70 tool_type: ToolType::Function,
71 config,
72 server_label: None,
73 handler: None,
74 },
75 )
76 .is_some()
77 {
78 tracing::warn!(name = %p.name, "duplicate tool name — previous definition overwritten");
79 }
80 },
81 (),
82 );
83}