1
1
from abc import ABC
2
2
from enum import Enum
3
- from typing import Any , Dict , List , Callable , Optional , Union , ClassVar , Type
3
+ from typing import Any , Dict , List , Callable , Optional , Union , ClassVar
4
4
from pydantic import BaseModel , Field , model_validator
5
5
6
6
@@ -17,22 +17,23 @@ class ParameterType(str, Enum):
17
17
18
18
class ToolParameter (BaseModel ):
19
19
"""Base class for all tool parameters using Pydantic."""
20
+
20
21
description : str
21
22
required : bool = False
22
23
type : ClassVar [ParameterType ]
23
-
24
+
24
25
def model_dump_tool (self ) -> Dict [str , Any ]:
25
26
"""Convert the parameter to a dictionary format for tool usage."""
26
27
result = {"type" : self .type , "description" : self .description }
27
28
return result
28
-
29
+
29
30
@classmethod
30
31
def from_dict (cls , data : Dict [str , Any ]) -> "ToolParameter" :
31
32
"""Create a parameter from a dictionary."""
32
33
param_type = data .get ("type" )
33
34
if not param_type :
34
35
raise ValueError ("Parameter type is required" )
35
-
36
+
36
37
# Find the appropriate class based on the type
37
38
param_classes = {
38
39
ParameterType .STRING : StringParameter ,
@@ -42,19 +43,20 @@ def from_dict(cls, data: Dict[str, Any]) -> "ToolParameter":
42
43
ParameterType .OBJECT : ObjectParameter ,
43
44
ParameterType .ARRAY : ArrayParameter ,
44
45
}
45
-
46
+
46
47
param_class = param_classes .get (param_type )
47
48
if not param_class :
48
49
raise ValueError (f"Unknown parameter type: { param_type } " )
49
-
50
+
50
51
return param_class .model_validate (data )
51
52
52
53
53
54
class StringParameter (ToolParameter ):
54
55
"""String parameter for tools."""
56
+
55
57
type : ClassVar [ParameterType ] = ParameterType .STRING
56
58
enum : Optional [List [str ]] = None
57
-
59
+
58
60
def model_dump_tool (self ) -> Dict [str , Any ]:
59
61
result = super ().model_dump_tool ()
60
62
if self .enum :
@@ -64,10 +66,11 @@ def model_dump_tool(self) -> Dict[str, Any]:
64
66
65
67
class IntegerParameter (ToolParameter ):
66
68
"""Integer parameter for tools."""
69
+
67
70
type : ClassVar [ParameterType ] = ParameterType .INTEGER
68
71
minimum : Optional [int ] = None
69
72
maximum : Optional [int ] = None
70
-
73
+
71
74
def model_dump_tool (self ) -> Dict [str , Any ]:
72
75
result = super ().model_dump_tool ()
73
76
if self .minimum is not None :
@@ -79,10 +82,11 @@ def model_dump_tool(self) -> Dict[str, Any]:
79
82
80
83
class NumberParameter (ToolParameter ):
81
84
"""Number parameter for tools."""
85
+
82
86
type : ClassVar [ParameterType ] = ParameterType .NUMBER
83
87
minimum : Optional [float ] = None
84
88
maximum : Optional [float ] = None
85
-
89
+
86
90
def model_dump_tool (self ) -> Dict [str , Any ]:
87
91
result = super ().model_dump_tool ()
88
92
if self .minimum is not None :
@@ -94,16 +98,18 @@ def model_dump_tool(self) -> Dict[str, Any]:
94
98
95
99
class BooleanParameter (ToolParameter ):
96
100
"""Boolean parameter for tools."""
101
+
97
102
type : ClassVar [ParameterType ] = ParameterType .BOOLEAN
98
103
99
104
100
105
class ArrayParameter (ToolParameter ):
101
106
"""Array parameter for tools."""
107
+
102
108
type : ClassVar [ParameterType ] = ParameterType .ARRAY
103
109
items : "ToolParameter"
104
110
min_items : Optional [int ] = None
105
111
max_items : Optional [int ] = None
106
-
112
+
107
113
def model_dump_tool (self ) -> Dict [str , Any ]:
108
114
result = super ().model_dump_tool ()
109
115
result ["items" ] = self .items .model_dump_tool ()
@@ -112,40 +118,43 @@ def model_dump_tool(self) -> Dict[str, Any]:
112
118
if self .max_items is not None :
113
119
result ["maxItems" ] = self .max_items
114
120
return result
115
-
121
+
116
122
@model_validator (mode = "after" )
117
123
def validate_items (self ) -> "ArrayParameter" :
118
124
if not isinstance (self .items , ToolParameter ):
119
125
if isinstance (self .items , dict ):
120
126
self .items = ToolParameter .from_dict (self .items )
121
127
else :
122
- raise ValueError (f"Items must be a ToolParameter or dict, got { type (self .items )} " )
128
+ raise ValueError (
129
+ f"Items must be a ToolParameter or dict, got { type (self .items )} "
130
+ )
123
131
return self
124
132
125
133
126
134
class ObjectParameter (ToolParameter ):
127
135
"""Object parameter for tools."""
136
+
128
137
type : ClassVar [ParameterType ] = ParameterType .OBJECT
129
138
properties : Dict [str , ToolParameter ]
130
139
required_properties : List [str ] = Field (default_factory = list )
131
140
additional_properties : bool = True
132
-
141
+
133
142
def model_dump_tool (self ) -> Dict [str , Any ]:
134
143
properties_dict : Dict [str , Any ] = {}
135
144
for name , param in self .properties .items ():
136
145
properties_dict [name ] = param .model_dump_tool ()
137
146
138
147
result = super ().model_dump_tool ()
139
148
result ["properties" ] = properties_dict
140
-
149
+
141
150
if self .required_properties :
142
151
result ["required" ] = self .required_properties
143
-
152
+
144
153
if not self .additional_properties :
145
154
result ["additionalProperties" ] = False
146
-
155
+
147
156
return result
148
-
157
+
149
158
@model_validator (mode = "after" )
150
159
def validate_properties (self ) -> "ObjectParameter" :
151
160
validated_properties = {}
@@ -154,7 +163,9 @@ def validate_properties(self) -> "ObjectParameter":
154
163
if isinstance (param , dict ):
155
164
validated_properties [name ] = ToolParameter .from_dict (param )
156
165
else :
157
- raise ValueError (f"Property { name } must be a ToolParameter or dict, got { type (param )} " )
166
+ raise ValueError (
167
+ f"Property { name } must be a ToolParameter or dict, got { type (param )} "
168
+ )
158
169
else :
159
170
validated_properties [name ] = param
160
171
self .properties = validated_properties
@@ -173,13 +184,13 @@ def __init__(
173
184
):
174
185
self ._name = name
175
186
self ._description = description
176
-
187
+
177
188
# Allow parameters to be provided as a dictionary
178
189
if isinstance (parameters , dict ):
179
190
self ._parameters = ObjectParameter .model_validate (parameters )
180
191
else :
181
192
self ._parameters = parameters
182
-
193
+
183
194
self ._execute_func = execute_func
184
195
185
196
def get_name (self ) -> str :
0 commit comments