signalwire-agents 1.0.18.dev8__py3-none-any.whl → 1.0.18.dev9__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.
@@ -18,7 +18,7 @@ A package for building AI agents using SignalWire's AI and SWML capabilities.
18
18
  from .core.logging_config import configure_logging
19
19
  configure_logging()
20
20
 
21
- __version__ = "1.0.18.dev8"
21
+ __version__ = "1.0.18.dev9"
22
22
 
23
23
  # Import core classes for easier access
24
24
  from .core.agent_base import AgentBase
@@ -61,7 +61,7 @@ class AgentServer:
61
61
  self.app = FastAPI(
62
62
  title="SignalWire AI Agents",
63
63
  description="Hosted SignalWire AI Agents",
64
- version="1.0.18.dev8",
64
+ version="1.0.18.dev9",
65
65
  redirect_slashes=False
66
66
  )
67
67
 
@@ -18,6 +18,10 @@ import json
18
18
  import logging
19
19
  from typing import Dict, Any, List, Optional, Tuple
20
20
 
21
+ # jsonschema is required for full JSON Schema Draft 2020-12 validation
22
+ from jsonschema import Draft202012Validator, ValidationError
23
+ from jsonschema.exceptions import best_match
24
+
21
25
  try:
22
26
  import structlog
23
27
  # Ensure structlog is configured
@@ -241,35 +245,84 @@ class SchemaUtils:
241
245
  return verb_props.get("required", [])
242
246
  return []
243
247
 
248
+ def _get_verb_schema(self, verb_name: str) -> Optional[Dict[str, Any]]:
249
+ """
250
+ Get the JSON Schema for validating a verb config.
251
+
252
+ This constructs a schema that can be used with jsonschema.validate() by:
253
+ 1. Getting the verb's property schema
254
+ 2. Including all $defs from the main schema so $ref references resolve
255
+
256
+ Args:
257
+ verb_name: The name of the verb
258
+
259
+ Returns:
260
+ A schema dict suitable for jsonschema validation, or None if not found
261
+ """
262
+ verb_props = self.get_verb_properties(verb_name)
263
+ if not verb_props:
264
+ return None
265
+
266
+ # Create a schema with the $defs from the main schema so refs work
267
+ schema = verb_props.copy()
268
+ if "$defs" in self.schema:
269
+ schema["$defs"] = self.schema["$defs"]
270
+
271
+ return schema
272
+
244
273
  def validate_verb(self, verb_name: str, verb_config: Dict[str, Any]) -> Tuple[bool, List[str]]:
245
274
  """
246
- Validate a verb configuration against the schema
247
-
275
+ Validate a verb configuration against the JSON Schema.
276
+
277
+ Uses the jsonschema library for full JSON Schema Draft 2020-12 validation,
278
+ which checks all constraints including:
279
+ - Required properties
280
+ - Type checking (string, number, boolean, array, object)
281
+ - Pattern matching (regex constraints)
282
+ - Enum values
283
+ - Minimum/maximum values
284
+ - MinLength/maxLength for strings
285
+ - MinItems/maxItems for arrays
286
+ - anyOf/oneOf/allOf composition
287
+ - And all other JSON Schema keywords
288
+
248
289
  Args:
249
290
  verb_name: The name of the verb (e.g., "ai", "answer", etc.)
250
291
  verb_config: The configuration for the verb
251
-
292
+
252
293
  Returns:
253
294
  (is_valid, error_messages) tuple
254
295
  """
255
- # Simple validation for now - can be enhanced with more complete JSON Schema validation
256
296
  errors = []
257
-
297
+
258
298
  # Check if the verb exists in the schema
259
299
  if verb_name not in self.verbs:
260
300
  errors.append(f"Unknown verb: {verb_name}")
261
301
  return False, errors
262
-
263
- # Get the required properties for this verb
264
- required_props = self.get_verb_required_properties(verb_name)
265
-
266
- # Check if all required properties are present
267
- for prop in required_props:
268
- if prop not in verb_config:
269
- errors.append(f"Missing required property '{prop}' for verb '{verb_name}'")
270
-
271
- # Return validation result
272
- return len(errors) == 0, errors
302
+
303
+ # Get the verb schema for validation
304
+ verb_schema = self._get_verb_schema(verb_name)
305
+ if not verb_schema:
306
+ self.log.debug("verb_schema_not_found", verb=verb_name,
307
+ message="Could not extract verb schema, allowing config")
308
+ return True, []
309
+
310
+ # Use jsonschema for full validation
311
+ validator = Draft202012Validator(verb_schema)
312
+ validation_errors = list(validator.iter_errors(verb_config))
313
+
314
+ if not validation_errors:
315
+ return True, []
316
+
317
+ # Collect all error messages with their paths
318
+ for error in validation_errors:
319
+ if error.path:
320
+ path_str = ".".join(str(p) for p in error.path)
321
+ errors.append(f"{path_str}: {error.message}")
322
+ else:
323
+ errors.append(error.message)
324
+
325
+ return False, errors
273
326
 
274
327
  def get_all_verb_names(self) -> List[str]:
275
328
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalwire_agents
3
- Version: 1.0.18.dev8
3
+ Version: 1.0.18.dev9
4
4
  Summary: SignalWire AI Agents SDK
5
5
  Author-email: SignalWire Team <info@signalwire.com>
6
6
  License: MIT
@@ -29,6 +29,7 @@ Requires-Dist: uvicorn>=0.34.2
29
29
  Requires-Dist: beautifulsoup4>=4.12.3
30
30
  Requires-Dist: pytz>=2023.3
31
31
  Requires-Dist: lxml>=4.9.0
32
+ Requires-Dist: jsonschema>=4.26.0
32
33
  Provides-Extra: search-queryonly
33
34
  Requires-Dist: numpy>=1.24.0; extra == "search-queryonly"
34
35
  Requires-Dist: scikit-learn>=1.3.0; extra == "search-queryonly"
@@ -1,5 +1,5 @@
1
- signalwire_agents/__init__.py,sha256=npeS4j80LTMW61xutzEwYole8zeZr7OLoIXHvWVwv6c,5036
2
- signalwire_agents/agent_server.py,sha256=5amS5HRy1L07pht8n0msLuYm9jw33sAe9Jt6OBnzeXY,32352
1
+ signalwire_agents/__init__.py,sha256=2sCw-ij5lO1AUuMDx4XvkyfUzY-N6D8qW9lcMH2grLg,5036
2
+ signalwire_agents/agent_server.py,sha256=w7hkGArZv7-AiMyTExrvQUIzsfhjuLBUrracvCYYa0I,32352
3
3
  signalwire_agents/schema.json,sha256=YQv4-KiegE00XvxoLMKAml6aCGitnt3kBq31ECxTHK8,385886
4
4
  signalwire_agents/agents/bedrock.py,sha256=J582gooNtxtep4xdVOfyDzRtHp_XrurPMS93xf2Xod0,10836
5
5
  signalwire_agents/cli/__init__.py,sha256=XbxAQFaCIdGXIXJiriVBWoFPOJsC401u21588nO4TG8,388
@@ -131,17 +131,17 @@ signalwire_agents/skills/wikipedia_search/__init__.py,sha256=yJ6iYTSyJC96mwwUsI_
131
131
  signalwire_agents/skills/wikipedia_search/skill.py,sha256=peNxT3GHMJY5OFQ-weneO83NpSstGjcmrTN_ENzUsEo,7910
132
132
  signalwire_agents/utils/__init__.py,sha256=1KVsHzwgfktSXHe3vqSRGImjtIE58szwD2FHHoFBtvY,601
133
133
  signalwire_agents/utils/pom_utils.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
134
- signalwire_agents/utils/schema_utils.py,sha256=i4okv_O9bUApwT_jJf4Yoij3bLCrGrW3DC-vzSy2RuY,16392
134
+ signalwire_agents/utils/schema_utils.py,sha256=fBbzRJx9GSJFfYbc_18CbjpFL2K83Nr7utNaH-ZnMqE,18224
135
135
  signalwire_agents/utils/token_generators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
136
136
  signalwire_agents/utils/validators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
137
137
  signalwire_agents/web/__init__.py,sha256=XE_pSTY9Aalzr7J7wqFth1Zr3cccQHPPcF5HWNrOpz8,383
138
138
  signalwire_agents/web/web_service.py,sha256=a2PSHJgX1tlZr0Iz1A1UouZjXEePJAZL632evvLVM38,21071
139
- signalwire_agents-1.0.18.dev8.data/data/share/man/man1/sw-agent-init.1,sha256=J4k5Oi74BnWCPCvsaw00vuyyqDPuIECjJIPu5OynvJc,8381
140
- signalwire_agents-1.0.18.dev8.data/data/share/man/man1/sw-search.1,sha256=9jJ6V6t6DgmXByz8Lw9exjf683Cw3sJGro8-eB0M9EY,10413
141
- signalwire_agents-1.0.18.dev8.data/data/share/man/man1/swaig-test.1,sha256=Ri0EITo8YMFowkcYltwPSwU4VJdRzo7XTWloi5WddCg,7815
142
- signalwire_agents-1.0.18.dev8.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
143
- signalwire_agents-1.0.18.dev8.dist-info/METADATA,sha256=38PNqIfDS1niAIzvHmPgP29UgLfufTJh1NDa-LxXd6s,41745
144
- signalwire_agents-1.0.18.dev8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
145
- signalwire_agents-1.0.18.dev8.dist-info/entry_points.txt,sha256=fMiBH-GLeXGaWWn58Mcj7KM_m3SdomQMUQu-1LTqscw,315
146
- signalwire_agents-1.0.18.dev8.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
147
- signalwire_agents-1.0.18.dev8.dist-info/RECORD,,
139
+ signalwire_agents-1.0.18.dev9.data/data/share/man/man1/sw-agent-init.1,sha256=J4k5Oi74BnWCPCvsaw00vuyyqDPuIECjJIPu5OynvJc,8381
140
+ signalwire_agents-1.0.18.dev9.data/data/share/man/man1/sw-search.1,sha256=9jJ6V6t6DgmXByz8Lw9exjf683Cw3sJGro8-eB0M9EY,10413
141
+ signalwire_agents-1.0.18.dev9.data/data/share/man/man1/swaig-test.1,sha256=Ri0EITo8YMFowkcYltwPSwU4VJdRzo7XTWloi5WddCg,7815
142
+ signalwire_agents-1.0.18.dev9.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
143
+ signalwire_agents-1.0.18.dev9.dist-info/METADATA,sha256=8RegFa1Xmud4xJAFo3SUEd3UMszJ982nZLH_7qjyAvc,41779
144
+ signalwire_agents-1.0.18.dev9.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
145
+ signalwire_agents-1.0.18.dev9.dist-info/entry_points.txt,sha256=fMiBH-GLeXGaWWn58Mcj7KM_m3SdomQMUQu-1LTqscw,315
146
+ signalwire_agents-1.0.18.dev9.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
147
+ signalwire_agents-1.0.18.dev9.dist-info/RECORD,,