signalwire-agents 0.1.44__py3-none-any.whl → 0.1.46__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__ = "0.1.44"
21
+ __version__ = "0.1.46"
22
22
 
23
23
  # Import core classes for easier access
24
24
  from .core.agent_base import AgentBase
@@ -40,6 +40,8 @@ class ToolRegistry:
40
40
  handler: Callable,
41
41
  secure: bool = True,
42
42
  fillers: Optional[Dict[str, List[str]]] = None,
43
+ wait_file: Optional[str] = None,
44
+ wait_file_loops: Optional[int] = None,
43
45
  webhook_url: Optional[str] = None,
44
46
  required: Optional[List[str]] = None,
45
47
  **swaig_fields
@@ -53,7 +55,9 @@ class ToolRegistry:
53
55
  parameters: JSON Schema of parameters
54
56
  handler: Function to call when invoked
55
57
  secure: Whether to require token validation
56
- fillers: Optional dict mapping language codes to arrays of filler phrases
58
+ fillers: Optional dict mapping language codes to arrays of filler phrases (deprecated)
59
+ wait_file: Optional URL to audio file to play while function executes
60
+ wait_file_loops: Optional number of times to loop the wait_file
57
61
  webhook_url: Optional external webhook URL to use instead of local handling
58
62
  required: Optional list of required parameter names
59
63
  **swaig_fields: Additional SWAIG fields to include in function definition
@@ -71,6 +75,8 @@ class ToolRegistry:
71
75
  handler=handler,
72
76
  secure=secure,
73
77
  fillers=fillers,
78
+ wait_file=wait_file,
79
+ wait_file_loops=wait_file_loops,
74
80
  webhook_url=webhook_url,
75
81
  required=required,
76
82
  **swaig_fields
@@ -132,6 +138,8 @@ class ToolRegistry:
132
138
  parameters = tool_params_copy.pop("parameters", {})
133
139
  secure = tool_params_copy.pop("secure", True)
134
140
  fillers = tool_params_copy.pop("fillers", None)
141
+ wait_file = tool_params_copy.pop("wait_file", None)
142
+ wait_file_loops = tool_params_copy.pop("wait_file_loops", None)
135
143
  webhook_url = tool_params_copy.pop("webhook_url", None)
136
144
  required = tool_params_copy.pop("required", None)
137
145
 
@@ -143,6 +151,8 @@ class ToolRegistry:
143
151
  handler=attr.__get__(self.agent, cls), # Bind the method to this instance
144
152
  secure=secure,
145
153
  fillers=fillers,
154
+ wait_file=wait_file,
155
+ wait_file_loops=wait_file_loops,
146
156
  webhook_url=webhook_url,
147
157
  required=required,
148
158
  **tool_params_copy # Pass through any additional swaig_fields
@@ -562,6 +562,7 @@ class AgentBase(
562
562
  SWML document as a string
563
563
  """
564
564
  self.log.debug("_render_swml_called",
565
+ call_id=call_id,
565
566
  has_modifications=bool(modifications),
566
567
  use_ephemeral=bool(modifications and modifications.get("__use_ephemeral_agent")),
567
568
  has_dynamic_callback=bool(self._dynamic_config_callback))
@@ -618,6 +619,9 @@ class AgentBase(
618
619
  # Generate a call ID if needed
619
620
  if call_id is None:
620
621
  call_id = agent_to_use._session_manager.create_session()
622
+ self.log.debug("generated_call_id", call_id=call_id)
623
+ else:
624
+ self.log.debug("using_provided_call_id", call_id=call_id)
621
625
 
622
626
  # Start with any SWAIG query params that were set
623
627
  query_params = agent_to_use._swaig_query_params.copy() if agent_to_use._swaig_query_params else {}
@@ -679,6 +683,7 @@ class AgentBase(
679
683
  token = None
680
684
  if func.secure and call_id:
681
685
  token = agent_to_use._create_tool_token(tool_name=name, call_id=call_id)
686
+ self.log.debug("created_token_for_function", function=name, call_id=call_id, token_prefix=token[:20] if token else None)
682
687
 
683
688
  # Prepare function entry
684
689
  function_entry = {
@@ -687,9 +692,25 @@ class AgentBase(
687
692
  "parameters": func._ensure_parameter_structure()
688
693
  }
689
694
 
690
- # Add fillers if present
691
- if func.fillers:
692
- function_entry["fillers"] = func.fillers
695
+ # Add wait_file if present (SignalWire SWML expects wait_file, not fillers)
696
+ if hasattr(func, 'wait_file') and func.wait_file:
697
+ wait_file_url = func.wait_file
698
+ # If wait_file is a relative URL, convert it to absolute using agent's base URL
699
+ if wait_file_url and not wait_file_url.startswith(('http://', 'https://', '//')):
700
+ # Build full URL using the agent's base URL
701
+ base_url = agent_to_use._get_base_url(include_auth=False)
702
+ # Handle relative paths appropriately
703
+ if not wait_file_url.startswith('/'):
704
+ wait_file_url = '/' + wait_file_url
705
+ wait_file_url = f"{base_url}{wait_file_url}"
706
+ function_entry["wait_file"] = wait_file_url
707
+ elif func.fillers:
708
+ # Backward compatibility: use fillers as wait_file if wait_file not specified
709
+ function_entry["wait_file"] = func.fillers
710
+
711
+ # Add wait_file_loops if present
712
+ if hasattr(func, 'wait_file_loops') and func.wait_file_loops is not None:
713
+ function_entry["wait_file_loops"] = func.wait_file_loops
693
714
 
694
715
  # Handle webhook URL
695
716
  if hasattr(func, 'webhook_url') and func.webhook_url:
@@ -7,7 +7,13 @@ Licensed under the MIT License.
7
7
  See LICENSE file in the project root for full license information.
8
8
  """
9
9
 
10
- from typing import Optional, Union, List, Dict, Any
10
+ from typing import Optional, Union, List, Dict, Any, TYPE_CHECKING
11
+
12
+ if TYPE_CHECKING:
13
+ from signalwire_agents.core.agent_base import AgentBase
14
+ from signalwire_agents.core.contexts import ContextBuilder
15
+ else:
16
+ from signalwire_agents.core.contexts import ContextBuilder
11
17
 
12
18
 
13
19
  class PromptMixin:
@@ -112,7 +118,7 @@ class PromptMixin:
112
118
  bullets=sub_bullets if sub_bullets else None
113
119
  )
114
120
 
115
- def define_contexts(self, contexts=None) -> Optional['ContextBuilder']:
121
+ def define_contexts(self, contexts=None) -> Union['AgentBase', 'ContextBuilder']:
116
122
  """
117
123
  Define contexts and steps for this agent (alternative to POM/prompt)
118
124
 
@@ -132,15 +138,22 @@ class PromptMixin:
132
138
  return self
133
139
  else:
134
140
  # Legacy behavior - return ContextBuilder
135
- # Import here to avoid circular imports
136
- from signalwire_agents.core.contexts import ContextBuilder
137
-
138
141
  if self._contexts_builder is None:
139
142
  self._contexts_builder = ContextBuilder(self)
140
143
  self._contexts_defined = True
141
144
 
142
145
  return self._contexts_builder
143
146
 
147
+ @property
148
+ def contexts(self) -> 'ContextBuilder':
149
+ """
150
+ Get the ContextBuilder for this agent
151
+
152
+ Returns:
153
+ ContextBuilder instance for defining contexts
154
+ """
155
+ return self.define_contexts()
156
+
144
157
  def _validate_prompt_mode_exclusivity(self):
145
158
  """
146
159
  Validate that POM sections and raw text are not mixed in the main prompt
@@ -494,6 +494,10 @@ class WebMixin:
494
494
 
495
495
  # Get call_id from body if present
496
496
  call_id = body.get("call_id")
497
+ if not call_id and "call" in body:
498
+ # Sometimes it might be nested under 'call'
499
+ call_id = body.get("call", {}).get("call_id")
500
+ req_log.debug("extracted_call_id_from_body", call_id=call_id, body_keys=list(body.keys()))
497
501
  else:
498
502
  # Get call_id from query params for GET
499
503
  call_id = request.query_params.get("call_id")
@@ -30,6 +30,8 @@ class SWAIGFunction:
30
30
  parameters: Dict[str, Dict] = None,
31
31
  secure: bool = False,
32
32
  fillers: Optional[Dict[str, List[str]]] = None,
33
+ wait_file: Optional[str] = None,
34
+ wait_file_loops: Optional[int] = None,
33
35
  webhook_url: Optional[str] = None,
34
36
  required: Optional[List[str]] = None,
35
37
  **extra_swaig_fields
@@ -43,7 +45,9 @@ class SWAIGFunction:
43
45
  description: Human-readable description of the function
44
46
  parameters: Dictionary of parameters, keys are parameter names, values are param definitions
45
47
  secure: Whether this function requires token validation
46
- fillers: Optional dictionary of filler phrases by language code
48
+ fillers: Optional dictionary of filler phrases by language code (deprecated, use wait_file)
49
+ wait_file: Optional URL to audio file to play while function executes
50
+ wait_file_loops: Optional number of times to loop the wait_file
47
51
  webhook_url: Optional external webhook URL to use instead of local handling
48
52
  required: Optional list of required parameter names
49
53
  **extra_swaig_fields: Additional SWAIG fields to include in function definition
@@ -53,7 +57,9 @@ class SWAIGFunction:
53
57
  self.description = description
54
58
  self.parameters = parameters or {}
55
59
  self.secure = secure
56
- self.fillers = fillers
60
+ self.fillers = fillers # Keep for backward compatibility
61
+ self.wait_file = wait_file or fillers # Use wait_file if provided, else fall back to fillers
62
+ self.wait_file_loops = wait_file_loops
57
63
  self.webhook_url = webhook_url
58
64
  self.required = required or []
59
65
  self.extra_swaig_fields = extra_swaig_fields
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalwire_agents
3
- Version: 0.1.44
3
+ Version: 0.1.46
4
4
  Summary: SignalWire AI Agents SDK
5
5
  Author-email: SignalWire Team <info@signalwire.com>
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- signalwire_agents/__init__.py,sha256=CnXHre_0n--VeQ3Wt6aRA6nRhIXhpEYObD6l-wBDSHA,5031
1
+ signalwire_agents/__init__.py,sha256=Hv5VQbfoIDYAidp17GYz_wbKRqSGKGQ87ZlHhhZ0DSM,5031
2
2
  signalwire_agents/agent_server.py,sha256=x9HyWia8D3r6KMqY-Q4DtNVivfJWLTx8B-KzUI8okuA,26880
3
3
  signalwire_agents/schema.json,sha256=6-7ccbt39iM1CO36dOfvupRPfd0gnQ0XoAdyo-EFyjo,238042
4
4
  signalwire_agents/agents/bedrock.py,sha256=J582gooNtxtep4xdVOfyDzRtHp_XrurPMS93xf2Xod0,10836
@@ -24,7 +24,7 @@ signalwire_agents/cli/simulation/data_generation.py,sha256=pxa9aJ6XkI0O8yAIGvBTU
24
24
  signalwire_agents/cli/simulation/data_overrides.py,sha256=3_3pT6j-q2gRufPX2bZ1BrmY7u1IdloLooKAJil33vI,6319
25
25
  signalwire_agents/cli/simulation/mock_env.py,sha256=fvaR_xdLMm8AbpNUbTJOFG9THcti3Zds-0QNDbKMaYk,10249
26
26
  signalwire_agents/core/__init__.py,sha256=xjPq8DmUnWYUG28sd17n430VWPmMH9oZ9W14gYwG96g,806
27
- signalwire_agents/core/agent_base.py,sha256=Wy1xAyJgquI4Cabss1lddoNonJzOYeo3VtY9suEFDFA,48634
27
+ signalwire_agents/core/agent_base.py,sha256=vAx9sQ985juMi0lnfP7bw1fl_1iYRzXVIpPyE-xEFBE,50139
28
28
  signalwire_agents/core/auth_handler.py,sha256=jXrof9WZ1W9qqlQT9WElcmSRafL2kG7207x5SqWN9MU,8481
29
29
  signalwire_agents/core/config_loader.py,sha256=rStVRRUaeMGrMc44ocr0diMQQARZhbKqwMqQ6kqUNos,8722
30
30
  signalwire_agents/core/contexts.py,sha256=g9FgOGMfGCUWlm57YZcv7CvOf-Ub9FdKZIOMu14ADfE,24428
@@ -35,7 +35,7 @@ signalwire_agents/core/pom_builder.py,sha256=ywuiIfP8BeLBPo_G4X1teZlG6zTCMkW71CZ
35
35
  signalwire_agents/core/security_config.py,sha256=iAnAzKEJQiXL6mMpDaYm3Sjkxwm4x2N9HD6DeWSI8yI,12536
36
36
  signalwire_agents/core/skill_base.py,sha256=1b_4ht_T1BVnfzHYqoILb3idrrPYMs5-G-adHo2IVss,6903
37
37
  signalwire_agents/core/skill_manager.py,sha256=D4erpz0tmSYLqyfeteNNIY0VRWDtX0rDw3n7Z_f0W5U,10493
38
- signalwire_agents/core/swaig_function.py,sha256=VFIYQWltvYMrUfN_lfda-YzuQ2PqF2vhb-PegAliwCc,7076
38
+ signalwire_agents/core/swaig_function.py,sha256=Zf1RQOadBgV4oxXJY7n4IfueYu0dKinfjB5RkBoHbrI,7534
39
39
  signalwire_agents/core/swml_builder.py,sha256=tJBFDAVTENEfjGLp2h9_AKOYt5O9FrSYLI-nZZVwM1E,15604
40
40
  signalwire_agents/core/swml_handler.py,sha256=hFDq41dQWL3EdFbq6h0hizE1dIqdVeiTeCrujbZsPzo,8397
41
41
  signalwire_agents/core/swml_renderer.py,sha256=-WAB_5ss836a8nBo5zlb6SaQKFNF4XIo1odWIXM4eE8,6860
@@ -51,16 +51,16 @@ signalwire_agents/core/agent/security/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_
51
51
  signalwire_agents/core/agent/swml/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
52
52
  signalwire_agents/core/agent/tools/__init__.py,sha256=eOcmyeGm6qogT3wsBx7QvdjmTbc1p5hnPR6uIlvTLxI,339
53
53
  signalwire_agents/core/agent/tools/decorator.py,sha256=pC6j1114GwVBd2U3h23I9gKLtu8AgeiuWV0lUzz682U,2961
54
- signalwire_agents/core/agent/tools/registry.py,sha256=CgsCUMWBV4Use1baNl2KLYS2ewKjjOwm28kC_T7R6mU,7459
54
+ signalwire_agents/core/agent/tools/registry.py,sha256=HScbKKwpJqFZ_odmeFklSQ0p0EMasEyKSxNwX568OPo,8054
55
55
  signalwire_agents/core/mixins/__init__.py,sha256=NsFpfF7TDP_lNR0Riw4Nbvt4fDbv_A3OoVbBqRrtXQM,652
56
56
  signalwire_agents/core/mixins/ai_config_mixin.py,sha256=kT-xVVWMIE6RQe6qQFCRYxli345bxOs5uS1dCtMTeTc,18232
57
57
  signalwire_agents/core/mixins/auth_mixin.py,sha256=Y9kR423-76U_pKL7KXzseeXX2a-4WxNWyo3odS7TDQM,9879
58
- signalwire_agents/core/mixins/prompt_mixin.py,sha256=2cAJpp3Ka-fmgpAg201xeTy-xps99k0vlP7YyqZiCnw,13374
58
+ signalwire_agents/core/mixins/prompt_mixin.py,sha256=bEsuw9J2F_upFYI02KyC7o2eGZjwOKQ352rmJBZirAM,13729
59
59
  signalwire_agents/core/mixins/serverless_mixin.py,sha256=QIIbl_-16XFJi5aqrWpNzORbyCJQmhaplWXnW6U9i68,16137
60
60
  signalwire_agents/core/mixins/skill_mixin.py,sha256=Qz3RKPmq_iMY4NecyxOHk3dW3W-O4iEm2ahhMjAcqRs,1861
61
61
  signalwire_agents/core/mixins/state_mixin.py,sha256=q3achpyUYZKuJaqKf12O22FXpSsNNsMEonSvlpSHCkA,6594
62
62
  signalwire_agents/core/mixins/tool_mixin.py,sha256=6CaNdaspHcfte0qSB_bSN8PTsqxRZzL_AXYk8QoWyXE,8660
63
- signalwire_agents/core/mixins/web_mixin.py,sha256=BUzmTkPIHGfitzbn1p94SDSqp-7x_IesjliypagB4oI,50324
63
+ signalwire_agents/core/mixins/web_mixin.py,sha256=2Tj0mulcjiUBuqHnJ76UHc5C2L5xV91HKyxfG3lNj4k,50612
64
64
  signalwire_agents/core/security/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
65
65
  signalwire_agents/core/security/session_manager.py,sha256=s5hXYcFnrsYFoyo-zcN7EJy-wInZQI_cWTBHX9MxHR4,9164
66
66
  signalwire_agents/prefabs/__init__.py,sha256=MW11J63XH7KxF2MWguRsMFM9iqMWexaEO9ynDPL_PDM,715
@@ -128,9 +128,9 @@ signalwire_agents/utils/token_generators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663
128
128
  signalwire_agents/utils/validators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
129
129
  signalwire_agents/web/__init__.py,sha256=XE_pSTY9Aalzr7J7wqFth1Zr3cccQHPPcF5HWNrOpz8,383
130
130
  signalwire_agents/web/web_service.py,sha256=a2PSHJgX1tlZr0Iz1A1UouZjXEePJAZL632evvLVM38,21071
131
- signalwire_agents-0.1.44.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
132
- signalwire_agents-0.1.44.dist-info/METADATA,sha256=UTsROVybKE1fRykQxtCcPh7cWJLuS5ADqrjFU-SxDEo,41281
133
- signalwire_agents-0.1.44.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
134
- signalwire_agents-0.1.44.dist-info/entry_points.txt,sha256=ZDT65zfTO_YyDzi_hwQbCxIhrUfu_t8RpNXMMXlUPWI,144
135
- signalwire_agents-0.1.44.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
136
- signalwire_agents-0.1.44.dist-info/RECORD,,
131
+ signalwire_agents-0.1.46.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
132
+ signalwire_agents-0.1.46.dist-info/METADATA,sha256=8Ek6hbt3XtY4I_7nZj4LKk8qJL0KZogp6tOzmd-ioro,41281
133
+ signalwire_agents-0.1.46.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
134
+ signalwire_agents-0.1.46.dist-info/entry_points.txt,sha256=ZDT65zfTO_YyDzi_hwQbCxIhrUfu_t8RpNXMMXlUPWI,144
135
+ signalwire_agents-0.1.46.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
136
+ signalwire_agents-0.1.46.dist-info/RECORD,,