| 42 | |
| 43 | @dataclass |
| 44 | class Function: |
| 45 | fn_name: str |
| 46 | fn_description: str |
| 47 | args: List[FunctionArgument] |
| 48 | config: FunctionConfig |
| 49 | hint: str = "" |
| 50 | id: str = None |
| 51 | |
| 52 | def __post_init__(self): |
| 53 | self.id = self.id or str(uuid.uuid4()) |
| 54 | |
| 55 | def toJson(self): |
| 56 | return { |
| 57 | "id": self.id, |
| 58 | "fn_name": self.fn_name, |
| 59 | "fn_description": self.fn_description, |
| 60 | "args": [asdict(arg) for arg in self.args], |
| 61 | "hint": self.hint, |
| 62 | "config": asdict(self.config) |
| 63 | } |
| 64 | |
| 65 | def _validate_args(self, *args) -> Dict[str, Any]: |
| 66 | """Validate and convert positional arguments to named arguments""" |
| 67 | if len(args) != len(self.args): |
| 68 | raise ValueError(f"Expected {len(self.args)} arguments, got {len(args)}") |
| 69 | |
| 70 | # Create dictionary of argument name to value |
| 71 | arg_dict = {} |
| 72 | for provided_value, arg_def in zip(args, self.args): |
| 73 | arg_dict[arg_def.name] = provided_value |
| 74 | |
| 75 | # Type validation (basic) |
| 76 | if arg_def.type == "string" and not isinstance(provided_value, str): |
| 77 | raise TypeError(f"Argument {arg_def.name} must be a string") |
| 78 | elif arg_def.type == "array" and not isinstance(provided_value, (list, tuple)): |
| 79 | raise TypeError(f"Argument {arg_def.name} must be an array") |
| 80 | # elif arg_def.type == "boolean" and not isinstance(provided_value, bool): |
| 81 | # raise TypeError(f"Argument {arg_def.name} must be a boolean") |
| 82 | |
| 83 | return arg_dict |
| 84 | |
| 85 | def _interpolate_template(self, template_str: str, values: Dict[str, Any]) -> str: |
| 86 | """Interpolate a template string with given values""" |
| 87 | # Convert Template-style placeholders ({{var}}) to Python style ($var) |
| 88 | python_style = template_str.replace('{{', '$').replace('}}', '') |
| 89 | return Template(python_style).safe_substitute(values) |
| 90 | |
| 91 | def _prepare_request(self, arg_dict: Dict[str, Any]) -> Dict[str, Any]: |
| 92 | """Prepare the request configuration with interpolated values""" |
| 93 | config = self.config |
| 94 | |
| 95 | # Interpolate URL |
| 96 | url = self._interpolate_template(config.url, arg_dict) |
| 97 | |
| 98 | # Interpolate payload |
| 99 | payload = {} |
| 100 | for key, value in config.payload.items(): |
| 101 | if isinstance(value, str): |
nothing calls this directly
no outgoing calls
no test coverage detected