use std::collections::BTreeMap;
use std::rc::Rc;
use super::components::ComponentRegistry;
use super::json_schema::json_schema_to_type_expr;
use super::type_expr::TypeExpr;
use crate::value::VmValue;
pub(super) fn extract_params_from_vm_dict(
td: &BTreeMap<String, VmValue>,
root_json: &serde_json::Value,
registry: &mut ComponentRegistry,
) -> Vec<ToolParamSchema> {
let mut params = Vec::new();
if let Some(VmValue::Dict(pd)) = td.get("parameters") {
for (pname, pval) in pd.iter() {
let (ty, desc, required, default, examples) = if let VmValue::Dict(pdef) = pval {
let desc = pdef
.get("description")
.map(|value| value.display())
.unwrap_or_default();
let required = match pdef.get("required") {
Some(VmValue::Bool(required)) => *required,
_ => true,
};
let json = vm_dict_to_json(pdef);
let ty = json_schema_to_type_expr(&json, root_json, registry);
let default = json.get("default").cloned();
let examples = extract_examples_vm(pdef);
(ty, desc, required, default, examples)
} else {
(
TypeExpr::Primitive("string".to_string()),
pval.display(),
true,
None,
Vec::new(),
)
};
params.push(ToolParamSchema {
name: pname.clone(),
ty,
description: desc,
required,
default,
examples,
});
}
}
params.sort_by_key(|param| !param.required);
params
}
fn vm_dict_to_json(dict: &BTreeMap<String, VmValue>) -> serde_json::Value {
super::super::vm_value_to_json(&VmValue::Dict(Rc::new(dict.clone())))
}
#[derive(Clone, Debug, serde::Serialize)]
pub(crate) struct ToolParamSchema {
pub(crate) name: String,
pub(crate) ty: TypeExpr,
pub(crate) description: String,
pub(crate) required: bool,
pub(crate) default: Option<serde_json::Value>,
pub(crate) examples: Vec<serde_json::Value>,
}
pub(super) fn extract_examples(
obj: &serde_json::Map<String, serde_json::Value>,
) -> Vec<serde_json::Value> {
if let Some(serde_json::Value::Array(arr)) = obj.get("examples") {
return arr.clone();
}
if let Some(single) = obj.get("example") {
return vec![single.clone()];
}
Vec::new()
}
pub(super) fn extract_examples_vm(pdef: &BTreeMap<String, VmValue>) -> Vec<serde_json::Value> {
if let Some(VmValue::List(items)) = pdef.get("examples") {
return items.iter().map(super::super::vm_value_to_json).collect();
}
if let Some(single) = pdef.get("example") {
return vec![super::super::vm_value_to_json(single)];
}
Vec::new()
}