signalwire-agents 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- signalwire_agents/__init__.py +10 -1
- signalwire_agents/agent_server.py +73 -44
- {signalwire_agents-0.1.0.dist-info → signalwire_agents-0.1.1.dist-info}/METADATA +75 -30
- signalwire_agents-0.1.1.dist-info/RECORD +9 -0
- {signalwire_agents-0.1.0.dist-info → signalwire_agents-0.1.1.dist-info}/WHEEL +1 -1
- signalwire_agents-0.1.1.dist-info/licenses/LICENSE +21 -0
- signalwire_agents/core/__init__.py +0 -20
- signalwire_agents/core/agent_base.py +0 -2449
- signalwire_agents/core/function_result.py +0 -104
- signalwire_agents/core/pom_builder.py +0 -195
- signalwire_agents/core/security/__init__.py +0 -0
- signalwire_agents/core/security/session_manager.py +0 -170
- signalwire_agents/core/state/__init__.py +0 -8
- signalwire_agents/core/state/file_state_manager.py +0 -210
- signalwire_agents/core/state/state_manager.py +0 -92
- signalwire_agents/core/swaig_function.py +0 -163
- signalwire_agents/core/swml_builder.py +0 -205
- signalwire_agents/core/swml_handler.py +0 -218
- signalwire_agents/core/swml_renderer.py +0 -359
- signalwire_agents/core/swml_service.py +0 -1009
- signalwire_agents/prefabs/__init__.py +0 -15
- signalwire_agents/prefabs/concierge.py +0 -276
- signalwire_agents/prefabs/faq_bot.py +0 -314
- signalwire_agents/prefabs/info_gatherer.py +0 -253
- signalwire_agents/prefabs/survey.py +0 -387
- signalwire_agents/utils/__init__.py +0 -0
- signalwire_agents/utils/pom_utils.py +0 -0
- signalwire_agents/utils/schema_utils.py +0 -348
- signalwire_agents/utils/token_generators.py +0 -0
- signalwire_agents/utils/validators.py +0 -0
- signalwire_agents-0.1.0.dist-info/RECORD +0 -32
- {signalwire_agents-0.1.0.data → signalwire_agents-0.1.1.data}/data/schema.json +0 -0
- {signalwire_agents-0.1.0.dist-info → signalwire_agents-0.1.1.dist-info}/top_level.txt +0 -0
@@ -1,348 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Utilities for working with the SWML JSON schema.
|
3
|
-
|
4
|
-
This module provides functions for loading, parsing, and validating SWML schemas.
|
5
|
-
It also provides utilities for working with SWML documents based on the schema.
|
6
|
-
"""
|
7
|
-
|
8
|
-
import json
|
9
|
-
import os
|
10
|
-
import re
|
11
|
-
from typing import Dict, List, Any, Optional, Set, Tuple, Callable
|
12
|
-
|
13
|
-
|
14
|
-
class SchemaUtils:
|
15
|
-
"""
|
16
|
-
Utilities for working with SWML JSON schema.
|
17
|
-
|
18
|
-
This class provides methods for:
|
19
|
-
- Loading and parsing schema files
|
20
|
-
- Extracting verb definitions
|
21
|
-
- Validating SWML objects against the schema
|
22
|
-
- Generating helpers for schema operations
|
23
|
-
"""
|
24
|
-
|
25
|
-
def __init__(self, schema_path: Optional[str] = None):
|
26
|
-
"""
|
27
|
-
Initialize the SchemaUtils with the provided schema
|
28
|
-
|
29
|
-
Args:
|
30
|
-
schema_path: Path to the schema file (optional)
|
31
|
-
"""
|
32
|
-
self.schema_path = schema_path
|
33
|
-
if not self.schema_path:
|
34
|
-
self.schema_path = self._get_default_schema_path()
|
35
|
-
print(f"No schema_path provided, using default: {self.schema_path}")
|
36
|
-
|
37
|
-
self.schema = self.load_schema()
|
38
|
-
self.verbs = self._extract_verb_definitions()
|
39
|
-
print(f"Extracted {len(self.verbs)} verbs from schema")
|
40
|
-
if self.verbs:
|
41
|
-
print(f"First few verbs: {list(self.verbs.keys())[:5]}")
|
42
|
-
|
43
|
-
def _get_default_schema_path(self) -> str:
|
44
|
-
"""
|
45
|
-
Get the default path to the schema file
|
46
|
-
|
47
|
-
Returns:
|
48
|
-
Path to the schema file
|
49
|
-
"""
|
50
|
-
# Default path is the schema.json in the root directory
|
51
|
-
package_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
52
|
-
default_path = os.path.join(package_dir, "schema.json")
|
53
|
-
print(f"Default schema path: {default_path}")
|
54
|
-
print(f"Path exists: {os.path.exists(default_path)}")
|
55
|
-
|
56
|
-
return default_path
|
57
|
-
|
58
|
-
def load_schema(self) -> Dict[str, Any]:
|
59
|
-
"""
|
60
|
-
Load the JSON schema from the specified path
|
61
|
-
|
62
|
-
Returns:
|
63
|
-
The schema as a dictionary
|
64
|
-
"""
|
65
|
-
if not self.schema_path:
|
66
|
-
print(f"Warning: No schema path provided. Using empty schema.")
|
67
|
-
return {}
|
68
|
-
|
69
|
-
try:
|
70
|
-
print(f"Attempting to load schema from: {self.schema_path}")
|
71
|
-
print(f"File exists: {os.path.exists(self.schema_path)}")
|
72
|
-
|
73
|
-
if os.path.exists(self.schema_path):
|
74
|
-
with open(self.schema_path, "r") as f:
|
75
|
-
schema = json.load(f)
|
76
|
-
print(f"Successfully loaded schema from {self.schema_path}")
|
77
|
-
print(f"Schema has {len(schema.keys()) if schema else 0} top-level keys")
|
78
|
-
if "$defs" in schema:
|
79
|
-
print(f"Schema has {len(schema['$defs'])} definitions")
|
80
|
-
return schema
|
81
|
-
else:
|
82
|
-
print(f"Schema file not found at {self.schema_path}")
|
83
|
-
return {}
|
84
|
-
except (FileNotFoundError, json.JSONDecodeError) as e:
|
85
|
-
print(f"Error loading schema: {e}")
|
86
|
-
print(f"Using empty schema as fallback")
|
87
|
-
return {}
|
88
|
-
|
89
|
-
def _extract_verb_definitions(self) -> Dict[str, Dict[str, Any]]:
|
90
|
-
"""
|
91
|
-
Extract verb definitions from the schema
|
92
|
-
|
93
|
-
Returns:
|
94
|
-
A dictionary mapping verb names to their definitions
|
95
|
-
"""
|
96
|
-
verbs = {}
|
97
|
-
|
98
|
-
# Extract from SWMLMethod anyOf
|
99
|
-
if "$defs" in self.schema and "SWMLMethod" in self.schema["$defs"]:
|
100
|
-
swml_method = self.schema["$defs"]["SWMLMethod"]
|
101
|
-
print(f"Found SWMLMethod in schema with keys: {swml_method.keys()}")
|
102
|
-
|
103
|
-
if "anyOf" in swml_method:
|
104
|
-
print(f"Found anyOf in SWMLMethod with {len(swml_method['anyOf'])} items")
|
105
|
-
|
106
|
-
for ref in swml_method["anyOf"]:
|
107
|
-
if "$ref" in ref:
|
108
|
-
# Extract the verb name from the reference
|
109
|
-
verb_ref = ref["$ref"]
|
110
|
-
verb_name = verb_ref.split("/")[-1]
|
111
|
-
print(f"Processing verb reference: {verb_ref} -> {verb_name}")
|
112
|
-
|
113
|
-
# Look up the verb definition
|
114
|
-
if verb_name in self.schema["$defs"]:
|
115
|
-
verb_def = self.schema["$defs"][verb_name]
|
116
|
-
|
117
|
-
# Extract the actual verb name (lowercase)
|
118
|
-
if "properties" in verb_def:
|
119
|
-
prop_names = list(verb_def["properties"].keys())
|
120
|
-
if prop_names:
|
121
|
-
actual_verb = prop_names[0]
|
122
|
-
verbs[actual_verb] = {
|
123
|
-
"name": actual_verb,
|
124
|
-
"schema_name": verb_name,
|
125
|
-
"definition": verb_def
|
126
|
-
}
|
127
|
-
print(f"Added verb: {actual_verb}")
|
128
|
-
else:
|
129
|
-
print(f"Missing $defs or SWMLMethod in schema")
|
130
|
-
if "$defs" in self.schema:
|
131
|
-
print(f"Available definitions: {list(self.schema['$defs'].keys())}")
|
132
|
-
|
133
|
-
return verbs
|
134
|
-
|
135
|
-
def get_verb_properties(self, verb_name: str) -> Dict[str, Any]:
|
136
|
-
"""
|
137
|
-
Get the properties for a specific verb
|
138
|
-
|
139
|
-
Args:
|
140
|
-
verb_name: The name of the verb (e.g., "ai", "answer", etc.)
|
141
|
-
|
142
|
-
Returns:
|
143
|
-
The properties for the verb or an empty dict if not found
|
144
|
-
"""
|
145
|
-
if verb_name in self.verbs:
|
146
|
-
verb_def = self.verbs[verb_name]["definition"]
|
147
|
-
if "properties" in verb_def and verb_name in verb_def["properties"]:
|
148
|
-
return verb_def["properties"][verb_name]
|
149
|
-
return {}
|
150
|
-
|
151
|
-
def get_verb_required_properties(self, verb_name: str) -> List[str]:
|
152
|
-
"""
|
153
|
-
Get the required properties for a specific verb
|
154
|
-
|
155
|
-
Args:
|
156
|
-
verb_name: The name of the verb (e.g., "ai", "answer", etc.)
|
157
|
-
|
158
|
-
Returns:
|
159
|
-
List of required property names for the verb or an empty list if not found
|
160
|
-
"""
|
161
|
-
if verb_name in self.verbs:
|
162
|
-
verb_def = self.verbs[verb_name]["definition"]
|
163
|
-
if "properties" in verb_def and verb_name in verb_def["properties"]:
|
164
|
-
verb_props = verb_def["properties"][verb_name]
|
165
|
-
return verb_props.get("required", [])
|
166
|
-
return []
|
167
|
-
|
168
|
-
def validate_verb(self, verb_name: str, verb_config: Dict[str, Any]) -> Tuple[bool, List[str]]:
|
169
|
-
"""
|
170
|
-
Validate a verb configuration against the schema
|
171
|
-
|
172
|
-
Args:
|
173
|
-
verb_name: The name of the verb (e.g., "ai", "answer", etc.)
|
174
|
-
verb_config: The configuration for the verb
|
175
|
-
|
176
|
-
Returns:
|
177
|
-
(is_valid, error_messages) tuple
|
178
|
-
"""
|
179
|
-
# Simple validation for now - can be enhanced with more complete JSON Schema validation
|
180
|
-
errors = []
|
181
|
-
|
182
|
-
# Check if the verb exists in the schema
|
183
|
-
if verb_name not in self.verbs:
|
184
|
-
errors.append(f"Unknown verb: {verb_name}")
|
185
|
-
return False, errors
|
186
|
-
|
187
|
-
# Get the required properties for this verb
|
188
|
-
required_props = self.get_verb_required_properties(verb_name)
|
189
|
-
|
190
|
-
# Check if all required properties are present
|
191
|
-
for prop in required_props:
|
192
|
-
if prop not in verb_config:
|
193
|
-
errors.append(f"Missing required property '{prop}' for verb '{verb_name}'")
|
194
|
-
|
195
|
-
# Return validation result
|
196
|
-
return len(errors) == 0, errors
|
197
|
-
|
198
|
-
def get_all_verb_names(self) -> List[str]:
|
199
|
-
"""
|
200
|
-
Get all verb names defined in the schema
|
201
|
-
|
202
|
-
Returns:
|
203
|
-
List of verb names
|
204
|
-
"""
|
205
|
-
return list(self.verbs.keys())
|
206
|
-
|
207
|
-
def get_verb_parameters(self, verb_name: str) -> Dict[str, Any]:
|
208
|
-
"""
|
209
|
-
Get the parameter definitions for a specific verb
|
210
|
-
|
211
|
-
Args:
|
212
|
-
verb_name: The name of the verb (e.g., "ai", "answer", etc.)
|
213
|
-
|
214
|
-
Returns:
|
215
|
-
Dictionary mapping parameter names to their definitions
|
216
|
-
"""
|
217
|
-
properties = self.get_verb_properties(verb_name)
|
218
|
-
if "properties" in properties:
|
219
|
-
return properties["properties"]
|
220
|
-
return {}
|
221
|
-
|
222
|
-
def generate_method_signature(self, verb_name: str) -> str:
|
223
|
-
"""
|
224
|
-
Generate a Python method signature for a verb
|
225
|
-
|
226
|
-
Args:
|
227
|
-
verb_name: The name of the verb
|
228
|
-
|
229
|
-
Returns:
|
230
|
-
A Python method signature string
|
231
|
-
"""
|
232
|
-
# Get the verb properties
|
233
|
-
verb_props = self.get_verb_properties(verb_name)
|
234
|
-
|
235
|
-
# Get verb parameters
|
236
|
-
verb_params = self.get_verb_parameters(verb_name)
|
237
|
-
|
238
|
-
# Get required parameters
|
239
|
-
required_params = self.get_verb_required_properties(verb_name)
|
240
|
-
|
241
|
-
# Initialize method parameters
|
242
|
-
param_list = ["self"]
|
243
|
-
|
244
|
-
# Add the parameters
|
245
|
-
for param_name, param_def in verb_params.items():
|
246
|
-
# Check if this is a required parameter
|
247
|
-
is_required = param_name in required_params
|
248
|
-
|
249
|
-
# Determine parameter type annotation
|
250
|
-
param_type = self._get_type_annotation(param_def)
|
251
|
-
|
252
|
-
# Add default value if not required
|
253
|
-
if is_required:
|
254
|
-
param_list.append(f"{param_name}: {param_type}")
|
255
|
-
else:
|
256
|
-
param_list.append(f"{param_name}: Optional[{param_type}] = None")
|
257
|
-
|
258
|
-
# Add **kwargs at the end
|
259
|
-
param_list.append("**kwargs")
|
260
|
-
|
261
|
-
# Generate method docstring
|
262
|
-
docstring = f'"""\n Add the {verb_name} verb to the current document\n \n'
|
263
|
-
|
264
|
-
# Add parameter documentation
|
265
|
-
for param_name, param_def in verb_params.items():
|
266
|
-
description = param_def.get("description", "")
|
267
|
-
# Clean up the description for docstring
|
268
|
-
description = description.replace('\n', ' ').strip()
|
269
|
-
docstring += f" Args:\n {param_name}: {description}\n"
|
270
|
-
|
271
|
-
# Add return documentation
|
272
|
-
docstring += f' \n Returns:\n True if the verb was added successfully, False otherwise\n """\n'
|
273
|
-
|
274
|
-
# Create the full method signature with docstring
|
275
|
-
method_signature = f"def {verb_name}({', '.join(param_list)}) -> bool:\n{docstring}"
|
276
|
-
|
277
|
-
return method_signature
|
278
|
-
|
279
|
-
def generate_method_body(self, verb_name: str) -> str:
|
280
|
-
"""
|
281
|
-
Generate the method body implementation for a verb
|
282
|
-
|
283
|
-
Args:
|
284
|
-
verb_name: The name of the verb
|
285
|
-
|
286
|
-
Returns:
|
287
|
-
The method body as a string
|
288
|
-
"""
|
289
|
-
# Get verb parameters
|
290
|
-
verb_params = self.get_verb_parameters(verb_name)
|
291
|
-
|
292
|
-
body = []
|
293
|
-
body.append(" # Prepare the configuration")
|
294
|
-
body.append(" config = {}")
|
295
|
-
|
296
|
-
# Add handling for each parameter
|
297
|
-
for param_name in verb_params.keys():
|
298
|
-
body.append(f" if {param_name} is not None:")
|
299
|
-
body.append(f" config['{param_name}'] = {param_name}")
|
300
|
-
|
301
|
-
# Add handling for kwargs
|
302
|
-
body.append(" # Add any additional parameters from kwargs")
|
303
|
-
body.append(" for key, value in kwargs.items():")
|
304
|
-
body.append(" if value is not None:")
|
305
|
-
body.append(" config[key] = value")
|
306
|
-
|
307
|
-
# Add the call to add_verb
|
308
|
-
body.append("")
|
309
|
-
body.append(f" # Add the {verb_name} verb")
|
310
|
-
body.append(f" return self.add_verb('{verb_name}', config)")
|
311
|
-
|
312
|
-
return "\n".join(body)
|
313
|
-
|
314
|
-
def _get_type_annotation(self, param_def: Dict[str, Any]) -> str:
|
315
|
-
"""
|
316
|
-
Get the Python type annotation for a parameter
|
317
|
-
|
318
|
-
Args:
|
319
|
-
param_def: Parameter definition from the schema
|
320
|
-
|
321
|
-
Returns:
|
322
|
-
Python type annotation as a string
|
323
|
-
"""
|
324
|
-
schema_type = param_def.get("type")
|
325
|
-
|
326
|
-
if schema_type == "string":
|
327
|
-
return "str"
|
328
|
-
elif schema_type == "integer":
|
329
|
-
return "int"
|
330
|
-
elif schema_type == "number":
|
331
|
-
return "float"
|
332
|
-
elif schema_type == "boolean":
|
333
|
-
return "bool"
|
334
|
-
elif schema_type == "array":
|
335
|
-
item_type = "Any"
|
336
|
-
if "items" in param_def:
|
337
|
-
item_def = param_def["items"]
|
338
|
-
item_type = self._get_type_annotation(item_def)
|
339
|
-
return f"List[{item_type}]"
|
340
|
-
elif schema_type == "object":
|
341
|
-
return "Dict[str, Any]"
|
342
|
-
else:
|
343
|
-
# Handle complex types or oneOf/anyOf
|
344
|
-
if "anyOf" in param_def or "oneOf" in param_def:
|
345
|
-
return "Any"
|
346
|
-
if "$ref" in param_def:
|
347
|
-
return "Any" # Could be enhanced to resolve references
|
348
|
-
return "Any"
|
File without changes
|
File without changes
|
@@ -1,32 +0,0 @@
|
|
1
|
-
signalwire_agents/__init__.py,sha256=CKOaLzrbPQWgPrMMdojp1fs7waFnxp_fxzhm79vDDt4,609
|
2
|
-
signalwire_agents/agent_server.py,sha256=FWRdNPqlrY6WXY5QqZD4ud4s0U57bDeKiKllo8cp40o,11837
|
3
|
-
signalwire_agents/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
|
4
|
-
signalwire_agents/core/__init__.py,sha256=KEfW2D3hTM13xB0zAH86zaFcMDw0OMKkuz2N3Eg1EuQ,615
|
5
|
-
signalwire_agents/core/agent_base.py,sha256=l8D-0Ufa5kXE3MD6waeITOiW4651xYe4PF4LS47LCnU,94067
|
6
|
-
signalwire_agents/core/function_result.py,sha256=myyoinywTcHrRDcBwl0Of5oJdH9g6fRVQK8Ke8G_22I,2963
|
7
|
-
signalwire_agents/core/pom_builder.py,sha256=f322xT3WTmc427YVbTPwi14qoZReCLKZ0YpjMKyM2x0,6445
|
8
|
-
signalwire_agents/core/swaig_function.py,sha256=MGKYhF9jJYLaBmSq2YtSKMDUtkrFeFwWbdP_0Hd3tts,6125
|
9
|
-
signalwire_agents/core/swml_builder.py,sha256=3MYTx_Wq6Bvy7hn5ubXBSKkX42n3VDF1o1YQe8_w8ss,6403
|
10
|
-
signalwire_agents/core/swml_handler.py,sha256=_O9JWufTvO219eEKUgcMGTuib0fY_6Qhs0yemgpBpLU,6811
|
11
|
-
signalwire_agents/core/swml_renderer.py,sha256=GKj1LYRw9paCaJbrwVDYiT4gPum7keMixHhZjxyYdAk,13700
|
12
|
-
signalwire_agents/core/swml_service.py,sha256=DkzIxe3Dc1BPDdL63dxN6qFqXqW8s6b00dLurDIag74,39470
|
13
|
-
signalwire_agents/core/security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
signalwire_agents/core/security/session_manager.py,sha256=2gcODBtk1Z_g0NVGr09V7GkCfuCmoEl4DVbW-1kAOos,5038
|
15
|
-
signalwire_agents/core/state/__init__.py,sha256=8Da6qFziYNmYuaIM8imEwAC3DGRJvX0u5hJIIPFmC7c,188
|
16
|
-
signalwire_agents/core/state/file_state_manager.py,sha256=rGD_rZy7rdIQm99kQVHLEUo_jiflaNCdQRJ2MllHnZ4,7116
|
17
|
-
signalwire_agents/core/state/state_manager.py,sha256=AFHhICiYlI1czOIKbNyi-vauI8RW8oTpp3ZZGUZnMeA,2320
|
18
|
-
signalwire_agents/prefabs/__init__.py,sha256=Zhhn0gRXrkDaS9ml54y5YItxJAqD1zhdDuN_-9C-jRo,430
|
19
|
-
signalwire_agents/prefabs/concierge.py,sha256=ELPYR1ZO_tH6_QF0xt3PaS0oFAKhQ3UPLvvbC7O_b0Q,10290
|
20
|
-
signalwire_agents/prefabs/faq_bot.py,sha256=k_Xd3CddIkPtXuw6X6DH0r-rDuT-5mB6CUM0ShKKkfk,11083
|
21
|
-
signalwire_agents/prefabs/info_gatherer.py,sha256=vfg55qlfx28Mcg3YW2o8SrYD7k0yrevg_VSGqZBAO70,9173
|
22
|
-
signalwire_agents/prefabs/survey.py,sha256=W3uKDlDtg34cuxuZg6Z0UqZrniQp2V2h3VxSB-Dj8K8,14857
|
23
|
-
signalwire_agents/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
-
signalwire_agents/utils/pom_utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
signalwire_agents/utils/schema_utils.py,sha256=ouvxLkulGIgacYj4ip18IlswxGYMBmBEug27Evz8dgs,13282
|
26
|
-
signalwire_agents/utils/token_generators.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
-
signalwire_agents/utils/validators.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
-
signalwire_agents-0.1.0.data/data/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
|
29
|
-
signalwire_agents-0.1.0.dist-info/METADATA,sha256=R4-f572VAowe2qTR6Ek_zIkeYEHmdMJzSpQK1TJrw6g,5366
|
30
|
-
signalwire_agents-0.1.0.dist-info/WHEEL,sha256=QZxptf4Y1BKFRCEDxD4h2V0mBFQOVFLFEpvxHmIs52A,91
|
31
|
-
signalwire_agents-0.1.0.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
|
32
|
-
signalwire_agents-0.1.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|