iridescentX/openui
0
1import inspect2from typing import get_type_hints, List, Dict, Any3 4 5def doc_to_dict(docstring):6 lines = docstring.split("\n")7 description = lines[1].strip()8 param_dict = {}9 10 for line in lines:11 if ":param" in line:12 line = line.replace(":param", "").strip()13 param, desc = line.split(":", 1)14 param_dict[param.strip()] = desc.strip()15 ret_dict = {"description": description, "params": param_dict}16 return ret_dict17 18 19def get_tools_specs(tools) -> List[dict]:20 function_list = [21 {"name": func, "function": getattr(tools, func)}22 for func in dir(tools)23 if callable(getattr(tools, func))24 and not func.startswith("__")25 and not inspect.isclass(getattr(tools, func))26 ]27 28 specs = []29 for function_item in function_list:30 function_name = function_item["name"]31 function = function_item["function"]32 33 function_doc = doc_to_dict(function.__doc__ or function_name)34 specs.append(35 {36 "name": function_name,37 # TODO: multi-line desc?38 "description": function_doc.get("description", function_name),39 "parameters": {40 "type": "object",41 "properties": {42 param_name: {43 "type": param_annotation.__name__.lower(),44 **(45 {46 "enum": (47 str(param_annotation.__args__)48 if hasattr(param_annotation, "__args__")49 else None50 )51 }52 if hasattr(param_annotation, "__args__")53 else {}54 ),55 "description": function_doc.get("params", {}).get(56 param_name, param_name57 ),58 }59 for param_name, param_annotation in get_type_hints(60 function61 ).items()62 if param_name != "return"63 and not (64 param_name.startswith("__") and param_name.endswith("__")65 )66 },67 "required": [68 name69 for name, param in inspect.signature(70 function71 ).parameters.items()72 if param.default is param.empty73 and not (name.startswith("__") and name.endswith("__"))74 ],75 },76 }77 )78 79 return specs80 