@@ -8,7 +8,7 @@ use ::std::path::{Path, PathBuf};
88use duct:: cmd;
99use futures:: executor:: block_on;
1010use serde:: Deserialize ;
11- use serde_json:: { from_reader, json, to_string, Value } ;
11+ use serde_json:: { from_reader, json, to_string, Map , Value } ;
1212use tempfile:: Builder ;
1313
1414use crate :: pdl:: ast:: {
@@ -137,23 +137,46 @@ fn a_tool(tool: &BeeAiToolState) -> Value {
137137 "description" : tool. description,
138138 "parameters" : json!( {
139139 "type" : "object" ,
140- "properties" : tool. input_schema. properties,
140+ "properties" : strip_nulls ( & tool. input_schema. properties) ,
141141 } ) ,
142- "options" : tool. options
142+ // "options": tool.options
143143 } )
144144 } )
145145}
146146
147+ // Strip null values out of the given HashMap
148+ fn strip_nulls ( parameters : & HashMap < String , Value > ) -> HashMap < String , Value > {
149+ parameters
150+ . into_iter ( )
151+ . filter_map ( |( k, v) | match v {
152+ Value :: Null => None ,
153+ Value :: Object ( m) => Some ( ( k. clone ( ) , Value :: Object ( strip_nulls2 ( m) ) ) ) ,
154+ _ => Some ( ( k. clone ( ) , v. clone ( ) ) ) ,
155+ } )
156+ . collect ( )
157+ }
158+ // sigh, i need to figure out generics IntoIterator, FromIterator
159+ fn strip_nulls2 ( parameters : & Map < String , Value > ) -> Map < String , Value > {
160+ parameters
161+ . into_iter ( )
162+ . filter_map ( |( k, v) | match v {
163+ Value :: Null => None ,
164+ Value :: Object ( m) => Some ( ( k. clone ( ) , Value :: Object ( strip_nulls2 ( & m) ) ) ) ,
165+ _ => Some ( ( k. clone ( ) , v. clone ( ) ) ) ,
166+ } )
167+ . collect ( )
168+ }
169+
147170fn with_tools (
148171 tools : & Option < Vec < BeeAiTool > > ,
149172 parameters : & HashMap < String , Value > ,
150173) -> HashMap < String , Value > {
151174 match tools {
152175 Some ( tools) => {
153176 match tools. len ( ) {
154- 0 => parameters . clone ( ) , // litellm barfs on tools: []
177+ 0 => strip_nulls ( parameters ) , // Note: litellm barfs on tools: []
155178 _ => {
156- let mut copy = parameters . clone ( ) ;
179+ let mut copy = strip_nulls ( parameters ) ;
157180 copy. insert (
158181 "tools" . to_string ( ) ,
159182 tools. into_iter ( ) . map ( |tool| a_tool ( & tool. state ) ) . collect ( ) ,
@@ -162,7 +185,7 @@ fn with_tools(
162185 }
163186 }
164187 }
165- _ => parameters . clone ( ) ,
188+ _ => strip_nulls ( parameters ) ,
166189 }
167190}
168191
@@ -175,7 +198,7 @@ fn call_tools(model: &String, parameters: &HashMap<String, Value>) -> PdlBlock {
175198 description : Some ( "Calling tool ${ tool.function.name }" . to_string ( ) ) ,
176199 text : vec ! [ PdlBlock :: Model (
177200 PdlModelBlock :: new( model. as_str( ) )
178- . parameters( parameters)
201+ . parameters( & strip_nulls ( parameters) )
179202 . input( PdlBlock :: Array {
180203 array: vec![ PdlBlock :: Message ( PdlMessageBlock {
181204 role: Role :: Tool ,
@@ -239,7 +262,10 @@ fn json_schema_type_to_pdl_type(spec: &Value) -> PdlType {
239262 "boolean" => PdlBaseType :: Bool ,
240263 "integer" => PdlBaseType :: Int ,
241264 "null" => PdlBaseType :: Null ,
242- _ => PdlBaseType :: Null ,
265+ x => {
266+ eprintln ! ( "Warning: unhandled JSONSchema type mapping to PDL {:?}" , x) ;
267+ PdlBaseType :: Null
268+ }
243269 } ;
244270 match spec. get ( "default" ) {
245271 Some ( _) => PdlType :: Optional ( PdlOptionalType { optional : base } ) ,
@@ -258,10 +284,16 @@ fn json_schema_type_to_pdl_type(spec: &Value) -> PdlType {
258284 optional : t. clone ( ) ,
259285 } )
260286 }
261- _ => PdlType :: Base ( PdlBaseType :: Null ) ,
287+ x => {
288+ eprintln ! ( "Warning: unhandled JSONSchema type mapping to PDL {:?}" , x) ;
289+ PdlType :: Base ( PdlBaseType :: Null )
290+ }
262291 }
263292 }
264- _ => PdlType :: Base ( PdlBaseType :: Null ) ,
293+ x => {
294+ eprintln ! ( "Warning: unhandled JSONSchema type mapping to PDL {:?}" , x) ;
295+ PdlType :: Base ( PdlBaseType :: Null )
296+ }
265297 } ,
266298 }
267299}
0 commit comments