signalwire-agents 0.1.27__py3-none-any.whl → 0.1.29__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.
Files changed (30) hide show
  1. signalwire_agents/__init__.py +1 -4
  2. signalwire_agents/cli/config.py +11 -1
  3. signalwire_agents/cli/simulation/data_overrides.py +6 -2
  4. signalwire_agents/cli/test_swaig.py +6 -0
  5. signalwire_agents/core/agent_base.py +1 -12
  6. signalwire_agents/core/auth_handler.py +233 -0
  7. signalwire_agents/core/config_loader.py +259 -0
  8. signalwire_agents/core/contexts.py +75 -0
  9. signalwire_agents/core/mixins/state_mixin.py +1 -67
  10. signalwire_agents/core/mixins/tool_mixin.py +0 -65
  11. signalwire_agents/core/security_config.py +333 -0
  12. signalwire_agents/core/swml_service.py +19 -25
  13. signalwire_agents/prefabs/concierge.py +0 -3
  14. signalwire_agents/prefabs/faq_bot.py +0 -3
  15. signalwire_agents/prefabs/info_gatherer.py +0 -3
  16. signalwire_agents/prefabs/receptionist.py +0 -3
  17. signalwire_agents/prefabs/survey.py +0 -3
  18. signalwire_agents/search/search_service.py +200 -11
  19. signalwire_agents/skills/mcp_gateway/README.md +230 -0
  20. signalwire_agents/skills/mcp_gateway/__init__.py +1 -0
  21. signalwire_agents/skills/mcp_gateway/skill.py +339 -0
  22. {signalwire_agents-0.1.27.dist-info → signalwire_agents-0.1.29.dist-info}/METADATA +1 -59
  23. {signalwire_agents-0.1.27.dist-info → signalwire_agents-0.1.29.dist-info}/RECORD +27 -24
  24. signalwire_agents/core/state/__init__.py +0 -17
  25. signalwire_agents/core/state/file_state_manager.py +0 -219
  26. signalwire_agents/core/state/state_manager.py +0 -101
  27. {signalwire_agents-0.1.27.dist-info → signalwire_agents-0.1.29.dist-info}/WHEEL +0 -0
  28. {signalwire_agents-0.1.27.dist-info → signalwire_agents-0.1.29.dist-info}/entry_points.txt +0 -0
  29. {signalwire_agents-0.1.27.dist-info → signalwire_agents-0.1.29.dist-info}/licenses/LICENSE +0 -0
  30. {signalwire_agents-0.1.27.dist-info → signalwire_agents-0.1.29.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,339 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ import json
11
+ import requests
12
+ import logging
13
+ from typing import List, Dict, Any, Optional
14
+ from requests.auth import HTTPBasicAuth
15
+
16
+ from signalwire_agents.core.skill_base import SkillBase
17
+ from signalwire_agents.core.function_result import SwaigFunctionResult
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class MCPGatewaySkill(SkillBase):
23
+ """
24
+ MCP Gateway Skill - Bridge MCP servers with SWAIG functions
25
+
26
+ This skill connects SignalWire agents to MCP (Model Context Protocol) servers
27
+ through a gateway service, dynamically creating SWAIG functions for MCP tools.
28
+ """
29
+
30
+ SKILL_NAME = "mcp_gateway"
31
+ SKILL_DESCRIPTION = "Bridge MCP servers with SWAIG functions"
32
+ SKILL_VERSION = "1.0.0"
33
+ REQUIRED_PACKAGES = ["requests"]
34
+ REQUIRED_ENV_VARS = []
35
+
36
+ def setup(self) -> bool:
37
+ """Setup and validate skill configuration"""
38
+ # Check for auth method - either token or basic auth
39
+ self.auth_token = self.params.get('auth_token')
40
+ if not self.auth_token:
41
+ # Require basic auth if no token
42
+ required_params = ['gateway_url', 'auth_user', 'auth_password']
43
+ missing_params = [param for param in required_params if not self.params.get(param)]
44
+ if missing_params:
45
+ self.logger.error(f"Missing required parameters: {missing_params}")
46
+ return False
47
+ self.auth = HTTPBasicAuth(self.params['auth_user'], self.params['auth_password'])
48
+ else:
49
+ # Just need gateway URL with token auth
50
+ if not self.params.get('gateway_url'):
51
+ self.logger.error("Missing required parameter: gateway_url")
52
+ return False
53
+ self.auth = None
54
+
55
+ # Store configuration
56
+ self.gateway_url = self.params['gateway_url'].rstrip('/')
57
+ self.services = self.params.get('services', [])
58
+ self.session_timeout = self.params.get('session_timeout', 300)
59
+ self.tool_prefix = self.params.get('tool_prefix', 'mcp_')
60
+ self.retry_attempts = self.params.get('retry_attempts', 3)
61
+ self.request_timeout = self.params.get('request_timeout', 30)
62
+ self.verify_ssl = self.params.get('verify_ssl', True)
63
+
64
+ # Session ID will be set from call_id when first tool is used
65
+ self.session_id = None
66
+
67
+ # Validate gateway connection
68
+ try:
69
+ response = requests.get(
70
+ f"{self.gateway_url}/health",
71
+ timeout=self.request_timeout,
72
+ verify=self.verify_ssl
73
+ )
74
+ response.raise_for_status()
75
+ self.logger.info(f"Connected to MCP Gateway at {self.gateway_url}")
76
+ except Exception as e:
77
+ self.logger.error(f"Failed to connect to gateway: {e}")
78
+ return False
79
+
80
+ return True
81
+
82
+ def _make_request(self, method: str, url: str, **kwargs) -> requests.Response:
83
+ """Make HTTP request with appropriate authentication"""
84
+ headers = kwargs.get('headers', {})
85
+ if self.auth_token:
86
+ headers['Authorization'] = f'Bearer {self.auth_token}'
87
+ kwargs['headers'] = headers
88
+
89
+ if not self.auth_token:
90
+ kwargs['auth'] = self.auth
91
+
92
+ kwargs['timeout'] = kwargs.get('timeout', self.request_timeout)
93
+ kwargs['verify'] = kwargs.get('verify', self.verify_ssl)
94
+
95
+ return requests.request(method, url, **kwargs)
96
+
97
+ def register_tools(self) -> None:
98
+ """Register SWAIG tools from MCP services"""
99
+ # If no services specified, get all available
100
+ if not self.services:
101
+ try:
102
+ response = self._make_request('GET', f"{self.gateway_url}/services")
103
+ response.raise_for_status()
104
+ all_services = response.json()
105
+ self.services = [{"name": name} for name in all_services.keys()]
106
+ except Exception as e:
107
+ self.logger.error(f"Failed to list services: {e}")
108
+ return
109
+
110
+ # Process each service
111
+ for service_config in self.services:
112
+ service_name = service_config.get('name')
113
+ if not service_name:
114
+ continue
115
+
116
+ # Get tools for this service
117
+ try:
118
+ response = self._make_request('GET', f"{self.gateway_url}/services/{service_name}/tools")
119
+ response.raise_for_status()
120
+ tools_data = response.json()
121
+ tools = tools_data.get('tools', [])
122
+
123
+ # Filter tools if specified
124
+ tool_filter = service_config.get('tools', '*')
125
+ if tool_filter != '*' and isinstance(tool_filter, list):
126
+ tools = [t for t in tools if t['name'] in tool_filter]
127
+
128
+ # Register each tool as a SWAIG function
129
+ for tool in tools:
130
+ self._register_mcp_tool(service_name, tool)
131
+
132
+ except Exception as e:
133
+ self.logger.error(f"Failed to get tools for service '{service_name}': {e}")
134
+
135
+ # Register the hangup hook for session cleanup
136
+ self.agent.define_tool(
137
+ name="_mcp_gateway_hangup",
138
+ description="Internal cleanup function for MCP sessions",
139
+ parameters={},
140
+ handler=self._hangup_handler,
141
+ is_hangup_hook=True
142
+ )
143
+
144
+ def _register_mcp_tool(self, service_name: str, tool_def: Dict[str, Any]):
145
+ """Register a single MCP tool as a SWAIG function"""
146
+ tool_name = tool_def.get('name')
147
+ if not tool_name:
148
+ return
149
+
150
+ # Create SWAIG function name
151
+ swaig_name = f"{self.tool_prefix}{service_name}_{tool_name}"
152
+
153
+ # Build SWAIG parameters from MCP input schema
154
+ input_schema = tool_def.get('inputSchema', {})
155
+ properties = input_schema.get('properties', {})
156
+ required = input_schema.get('required', [])
157
+
158
+ # Convert MCP schema to SWAIG parameters
159
+ swaig_params = {}
160
+ for prop_name, prop_def in properties.items():
161
+ param_def = {
162
+ "type": prop_def.get('type', 'string'),
163
+ "description": prop_def.get('description', '')
164
+ }
165
+
166
+ # Add enum if present
167
+ if 'enum' in prop_def:
168
+ param_def['enum'] = prop_def['enum']
169
+
170
+ # Add default if present and not required
171
+ if 'default' in prop_def and prop_name not in required:
172
+ param_def['default'] = prop_def['default']
173
+
174
+ swaig_params[prop_name] = param_def
175
+
176
+ # Create handler function
177
+ def handler(args, raw_data):
178
+ return self._call_mcp_tool(service_name, tool_name, args, raw_data)
179
+
180
+ # Register the SWAIG function
181
+ self.agent.define_tool(
182
+ name=swaig_name,
183
+ description=f"[{service_name}] {tool_def.get('description', tool_name)}",
184
+ parameters=swaig_params,
185
+ handler=handler
186
+ )
187
+
188
+ self.logger.info(f"Registered SWAIG function: {swaig_name}")
189
+
190
+ def _call_mcp_tool(self, service_name: str, tool_name: str, args: Dict[str, Any],
191
+ raw_data: Dict[str, Any]) -> SwaigFunctionResult:
192
+ """Call an MCP tool through the gateway"""
193
+ # Check for mcp_call_id in global_data first, then fall back to top-level call_id
194
+ global_data = raw_data.get('global_data', {})
195
+ if 'mcp_call_id' in global_data:
196
+ self.session_id = global_data['mcp_call_id']
197
+ self.logger.info(f"Using session ID from global_data.mcp_call_id: {self.session_id}")
198
+ else:
199
+ self.session_id = raw_data.get('call_id', 'unknown')
200
+ self.logger.info(f"Using session ID from call_id: {self.session_id}")
201
+ self.logger.debug(f"Raw data keys: {list(raw_data.keys())}")
202
+ if 'global_data' in raw_data:
203
+ self.logger.debug(f"global_data keys: {list(global_data.keys())}")
204
+
205
+ # Prepare request
206
+ request_data = {
207
+ "tool": tool_name,
208
+ "arguments": args,
209
+ "session_id": self.session_id,
210
+ "timeout": self.session_timeout,
211
+ "metadata": {
212
+ "agent_id": self.agent.name,
213
+ "timestamp": raw_data.get('timestamp'),
214
+ "call_id": raw_data.get('call_id')
215
+ }
216
+ }
217
+
218
+ # Call the gateway with retries
219
+ last_error = None
220
+ for attempt in range(self.retry_attempts):
221
+ try:
222
+ response = self._make_request(
223
+ 'POST',
224
+ f"{self.gateway_url}/services/{service_name}/call",
225
+ json=request_data
226
+ )
227
+
228
+ if response.status_code == 200:
229
+ result_data = response.json()
230
+ result_text = result_data.get('result', 'No response')
231
+
232
+ # Create SWAIG result
233
+ return SwaigFunctionResult(result_text)
234
+
235
+ else:
236
+ error_data = response.json()
237
+ error_msg = error_data.get('error', f'HTTP {response.status_code}')
238
+ last_error = error_msg
239
+
240
+ if response.status_code >= 500:
241
+ # Server error, retry
242
+ self.logger.warning(f"Gateway error (attempt {attempt + 1}): {error_msg}")
243
+ continue
244
+ else:
245
+ # Client error, don't retry
246
+ break
247
+
248
+ except requests.exceptions.Timeout:
249
+ last_error = "Request timeout"
250
+ self.logger.warning(f"Timeout calling MCP tool (attempt {attempt + 1})")
251
+
252
+ except requests.exceptions.ConnectionError:
253
+ last_error = "Connection error"
254
+ self.logger.warning(f"Connection error (attempt {attempt + 1})")
255
+
256
+ except Exception as e:
257
+ last_error = str(e)
258
+ self.logger.error(f"Unexpected error: {e}")
259
+ break
260
+
261
+ # All attempts failed
262
+ error_msg = f"Failed to call {service_name}.{tool_name}: {last_error}"
263
+ self.logger.error(error_msg)
264
+ return SwaigFunctionResult(error_msg)
265
+
266
+ def _hangup_handler(self, args: Dict[str, Any], raw_data: Dict[str, Any]) -> SwaigFunctionResult:
267
+ """Handle call hangup - cleanup MCP session"""
268
+ # Check for mcp_call_id in global_data first, then fall back to top-level call_id
269
+ global_data = raw_data.get('global_data', {})
270
+ if 'mcp_call_id' in global_data:
271
+ session_id = global_data['mcp_call_id']
272
+ self.logger.info(f"Cleanup using session ID from global_data.mcp_call_id: {session_id}")
273
+ else:
274
+ session_id = raw_data.get('call_id', 'unknown')
275
+ self.logger.info(f"Cleanup using session ID from call_id: {session_id}")
276
+
277
+ try:
278
+ response = self._make_request('DELETE', f"{self.gateway_url}/sessions/{session_id}")
279
+
280
+ if response.status_code in [200, 404]:
281
+ self.logger.info(f"Cleaned up MCP session: {session_id}")
282
+ else:
283
+ self.logger.warning(f"Failed to cleanup session: HTTP {response.status_code}")
284
+
285
+ except Exception as e:
286
+ self.logger.error(f"Error cleaning up session: {e}")
287
+
288
+ return SwaigFunctionResult("Session cleanup complete")
289
+
290
+ def get_hints(self) -> List[str]:
291
+ """Return speech recognition hints"""
292
+ hints = ["MCP", "gateway"]
293
+
294
+ # Add service names as hints
295
+ for service in self.services:
296
+ if isinstance(service, dict) and 'name' in service:
297
+ hints.append(service['name'])
298
+
299
+ return hints
300
+
301
+ def get_global_data(self) -> Dict[str, Any]:
302
+ """Return global data for DataMap variables"""
303
+ return {
304
+ "mcp_gateway_url": self.gateway_url,
305
+ "mcp_session_id": self.session_id,
306
+ "mcp_services": [s.get('name') if isinstance(s, dict) else str(s)
307
+ for s in self.services]
308
+ }
309
+
310
+ def get_prompt_sections(self) -> List[Dict[str, Any]]:
311
+ """Return prompt sections to add to agent"""
312
+ sections = []
313
+
314
+ # Build service list for prompt
315
+ service_descriptions = []
316
+ for service in self.services:
317
+ if isinstance(service, dict):
318
+ name = service.get('name', 'Unknown')
319
+ tools = service.get('tools', '*')
320
+ if tools == '*':
321
+ service_descriptions.append(f"{name} (all tools)")
322
+ elif isinstance(tools, list):
323
+ service_descriptions.append(f"{name} ({len(tools)} tools)")
324
+ else:
325
+ service_descriptions.append(str(service))
326
+
327
+ if service_descriptions:
328
+ sections.append({
329
+ "title": "MCP Gateway Integration",
330
+ "body": "You have access to external MCP (Model Context Protocol) services through a gateway.",
331
+ "bullets": [
332
+ f"Connected to gateway at {self.gateway_url}",
333
+ f"Available services: {', '.join(service_descriptions)}",
334
+ f"Functions are prefixed with '{self.tool_prefix}' followed by service name",
335
+ "Each service maintains its own session state throughout the call"
336
+ ]
337
+ })
338
+
339
+ return sections
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalwire_agents
3
- Version: 0.1.27
3
+ Version: 0.1.29
4
4
  Summary: SignalWire AI Agents SDK
5
5
  Author-email: SignalWire Team <info@signalwire.com>
6
6
  License: MIT
@@ -593,64 +593,6 @@ if __name__ == "__main__":
593
593
  agent.serve(host="0.0.0.0", port=8000)
594
594
  ```
595
595
 
596
- ## Using State Management
597
-
598
- ```python
599
- from signalwire_agents import AgentBase
600
- from signalwire_agents.core.function_result import SwaigFunctionResult
601
- from signalwire_agents.core.state import FileStateManager
602
-
603
- class StatefulAgent(AgentBase):
604
- def __init__(self):
605
- # Configure state management
606
- state_manager = FileStateManager(storage_dir="./state_data")
607
-
608
- super().__init__(
609
- name="stateful",
610
- route="/stateful",
611
- enable_state_tracking=True, # Enable state tracking
612
- state_manager=state_manager # Use custom state manager
613
- )
614
-
615
- # When enable_state_tracking=True, startup_hook and hangup_hook
616
- # are automatically registered to track session lifecycle
617
-
618
- # Custom tool for accessing and updating state
619
- @AgentBase.tool(
620
- name="save_preference",
621
- description="Save a user preference",
622
- parameters={
623
- "preference_name": {
624
- "type": "string",
625
- "description": "Name of the preference to save"
626
- },
627
- "preference_value": {
628
- "type": "string",
629
- "description": "Value of the preference"
630
- }
631
- }
632
- )
633
- def save_preference(self, args, raw_data):
634
- # Get the call ID from the raw data
635
- call_id = raw_data.get("call_id")
636
-
637
- if call_id:
638
- # Get current state or empty dict if none exists
639
- state = self.get_state(call_id) or {}
640
-
641
- # Update the state
642
- preferences = state.get("preferences", {})
643
- preferences[args.get("preference_name")] = args.get("preference_value")
644
- state["preferences"] = preferences
645
-
646
- # Save the updated state
647
- self.update_state(call_id, state)
648
-
649
- return SwaigFunctionResult("Preference saved successfully")
650
- else:
651
- return SwaigFunctionResult("Could not save preference: No call ID")
652
- ```
653
-
654
596
  ## Using Prefab Agents
655
597
 
656
598
  ```python
@@ -1,10 +1,10 @@
1
- signalwire_agents/__init__.py,sha256=P611r1tfqaEgg2KJ1baYXlpR0AqLN2sg4PAfVNdaUlE,2707
1
+ signalwire_agents/__init__.py,sha256=HQbHkQ6xLuhMcksKcaD0i6UMCLjT1eCFvVgwhge8r-k,2608
2
2
  signalwire_agents/agent_server.py,sha256=x9HyWia8D3r6KMqY-Q4DtNVivfJWLTx8B-KzUI8okuA,26880
3
3
  signalwire_agents/schema.json,sha256=AWhh6MoMU95roA_6RSdVdvbHDWPYqMavRoSnsVeMiw8,240965
4
4
  signalwire_agents/cli/__init__.py,sha256=Iy2BfWDWBEZoA1cyHTDsooBSVMx4vH5Ddhr3sEuFe8c,197
5
5
  signalwire_agents/cli/build_search.py,sha256=KLQJBqVSADFyGcKAi0KLwU_UoUd5rtRoKAdfcH91u70,28652
6
- signalwire_agents/cli/config.py,sha256=SeUcI7bNr_eCdn3oPfdEwDrVIkl7kdmqPvPbQgREm7Q,1862
7
- signalwire_agents/cli/test_swaig.py,sha256=5cYX7V5U5uwvOebi0zGdOQzD5zzC8kLPt3QdgkihtmI,30255
6
+ signalwire_agents/cli/config.py,sha256=U5AhAzCaf7jkziaGTrnF_FYy8WVDDR_WXgbfyVGkST4,2350
7
+ signalwire_agents/cli/test_swaig.py,sha256=8Z7OGK0P3NUMAIMYuM-1pxcSsGG0airWDxut1lYLV_E,30571
8
8
  signalwire_agents/cli/types.py,sha256=fjj3LV6upZDzplxqOYHyi3lxIkKKTWNPUtKt9yPGYXs,1619
9
9
  signalwire_agents/cli/core/__init__.py,sha256=hfGAdbsh-TWkN8KvQGAlfHIs9D-KfG5W6peP47pjV08,38
10
10
  signalwire_agents/cli/core/agent_loader.py,sha256=55wXgJhIZX8gDP0d-EVqTrVYiZgXDGBJq9wErwL46e8,10394
@@ -18,22 +18,25 @@ signalwire_agents/cli/output/output_formatter.py,sha256=MidaaCrhOuLJ3L_nsbNFTh92
18
18
  signalwire_agents/cli/output/swml_dump.py,sha256=S0lPhm1-XiZk0TU2SfOPTMRa5iGubStHI6MbQsiAXaw,6449
19
19
  signalwire_agents/cli/simulation/__init__.py,sha256=D-9DVP3Xat3eTxgX-L63cSdtM5X8nGA54bcPGlEm600,45
20
20
  signalwire_agents/cli/simulation/data_generation.py,sha256=ueQ8Ga5mng8jd87dzxN5rzwbbzboMpd6vB7_yUwjGHE,11727
21
- signalwire_agents/cli/simulation/data_overrides.py,sha256=nXJp2x7QsCRvCjrhwkaEq-kXu0aKOywhVcx02S6S7Hk,5959
21
+ signalwire_agents/cli/simulation/data_overrides.py,sha256=EpWckF9-pc0AaZdh1C2msP3hcNxe0WoQO-n0VugE56k,6128
22
22
  signalwire_agents/cli/simulation/mock_env.py,sha256=S6uGDGEO-4dXAyCJEZO1hkwiyJmYXBZx5o8XT0as0fc,9950
23
23
  signalwire_agents/core/__init__.py,sha256=xjPq8DmUnWYUG28sd17n430VWPmMH9oZ9W14gYwG96g,806
24
- signalwire_agents/core/agent_base.py,sha256=5U_Wrcairdz42w6E9N_Sw5G3kPV8ad46v9qQDzbDoIg,44651
25
- signalwire_agents/core/contexts.py,sha256=NLMQ4ZxTbCXQgGHjTQ07tA-2hC-vdoYJHGl32kvDuqk,21314
24
+ signalwire_agents/core/agent_base.py,sha256=F0dL5bdWY_n3zIz9qVC8jWu3xxNXS6cO3dFW_RCyuro,43951
25
+ signalwire_agents/core/auth_handler.py,sha256=jXrof9WZ1W9qqlQT9WElcmSRafL2kG7207x5SqWN9MU,8481
26
+ signalwire_agents/core/config_loader.py,sha256=rStVRRUaeMGrMc44ocr0diMQQARZhbKqwMqQ6kqUNos,8722
27
+ signalwire_agents/core/contexts.py,sha256=jexhUSEzfpDekzjA8d01gOjy4o1QUn3ffcUsyosT698,24237
26
28
  signalwire_agents/core/data_map.py,sha256=0qp3VcrRS0RtZPApoAaGgM-udLBb1ysnyMJuWd6sSew,17134
27
29
  signalwire_agents/core/function_result.py,sha256=MZZUoAHN8AXry-OBNA6Od5l-bKvMM2ruvnqHLbNhSiQ,44959
28
30
  signalwire_agents/core/logging_config.py,sha256=x4d_RAjBjVpJOFA2vXnPP2dNr13BZHz091J5rGpC77Y,13142
29
31
  signalwire_agents/core/pom_builder.py,sha256=ywuiIfP8BeLBPo_G4X1teZlG6zTCMkW71CZnmyoDTAQ,6636
32
+ signalwire_agents/core/security_config.py,sha256=iAnAzKEJQiXL6mMpDaYm3Sjkxwm4x2N9HD6DeWSI8yI,12536
30
33
  signalwire_agents/core/skill_base.py,sha256=lOpVTLhD9NjStF7Lxh6bAQUGa3DpNYV4agXJRakRuX0,4258
31
34
  signalwire_agents/core/skill_manager.py,sha256=9E2mPcn8-97t4OAnHCSdUEOW0nyr_g4zkWe9OQrU48g,7938
32
35
  signalwire_agents/core/swaig_function.py,sha256=VFIYQWltvYMrUfN_lfda-YzuQ2PqF2vhb-PegAliwCc,7076
33
36
  signalwire_agents/core/swml_builder.py,sha256=tJBFDAVTENEfjGLp2h9_AKOYt5O9FrSYLI-nZZVwM1E,15604
34
37
  signalwire_agents/core/swml_handler.py,sha256=hFDq41dQWL3EdFbq6h0hizE1dIqdVeiTeCrujbZsPzo,8397
35
38
  signalwire_agents/core/swml_renderer.py,sha256=-WAB_5ss836a8nBo5zlb6SaQKFNF4XIo1odWIXM4eE8,6860
36
- signalwire_agents/core/swml_service.py,sha256=Tlyr2p1cPFoF3SPi8enFLiYkXepitH2LodOFawPpHos,50181
39
+ signalwire_agents/core/swml_service.py,sha256=vgK_OScBlXdsr3dMe7pLUnm_cQVWtmNl_lu5guAKDlg,49851
37
40
  signalwire_agents/core/agent/__init__.py,sha256=qccTmLD9b24tZDAoIPEY6vJ2p1R_ArZ_ZCKbBlKvPQ8,239
38
41
  signalwire_agents/core/agent/config/__init__.py,sha256=5XvTfnYeeGdoLr4tJjbe1OhF26nOcR5VTDIhtMGCu3I,244
39
42
  signalwire_agents/core/agent/deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -52,26 +55,23 @@ signalwire_agents/core/mixins/auth_mixin.py,sha256=Y9kR423-76U_pKL7KXzseeXX2a-4W
52
55
  signalwire_agents/core/mixins/prompt_mixin.py,sha256=2cAJpp3Ka-fmgpAg201xeTy-xps99k0vlP7YyqZiCnw,13374
53
56
  signalwire_agents/core/mixins/serverless_mixin.py,sha256=QIIbl_-16XFJi5aqrWpNzORbyCJQmhaplWXnW6U9i68,16137
54
57
  signalwire_agents/core/mixins/skill_mixin.py,sha256=Qz3RKPmq_iMY4NecyxOHk3dW3W-O4iEm2ahhMjAcqRs,1861
55
- signalwire_agents/core/mixins/state_mixin.py,sha256=GMYaPBCDqCj0O4Ol6owVnl7kK8OXe3l4BTd-ViOqDCg,9272
56
- signalwire_agents/core/mixins/tool_mixin.py,sha256=zVmBAfZpusdkZrYgSThTZt6O7YKi7UBQqZZEcWBDmvo,11333
58
+ signalwire_agents/core/mixins/state_mixin.py,sha256=q3achpyUYZKuJaqKf12O22FXpSsNNsMEonSvlpSHCkA,6594
59
+ signalwire_agents/core/mixins/tool_mixin.py,sha256=6CaNdaspHcfte0qSB_bSN8PTsqxRZzL_AXYk8QoWyXE,8660
57
60
  signalwire_agents/core/mixins/web_mixin.py,sha256=BUzmTkPIHGfitzbn1p94SDSqp-7x_IesjliypagB4oI,50324
58
61
  signalwire_agents/core/security/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
59
62
  signalwire_agents/core/security/session_manager.py,sha256=s5hXYcFnrsYFoyo-zcN7EJy-wInZQI_cWTBHX9MxHR4,9164
60
- signalwire_agents/core/state/__init__.py,sha256=qpYIfQBApet6VQsy6diS3yu0lMxCBC6REOUk5l1McUw,379
61
- signalwire_agents/core/state/file_state_manager.py,sha256=52I_KVlmhHCbKIaHj74Q-ksP_-AF6ewYmOXCf4n5DTQ,7307
62
- signalwire_agents/core/state/state_manager.py,sha256=76B4mDutMb826dK4c_IJhOXH09BW1bJu6EZa6Mh_LB4,2511
63
63
  signalwire_agents/prefabs/__init__.py,sha256=MW11J63XH7KxF2MWguRsMFM9iqMWexaEO9ynDPL_PDM,715
64
- signalwire_agents/prefabs/concierge.py,sha256=FQxSUBAVH2ECtNs4GGa3f0EPiOrAKaz14h7byNFy5K8,10106
65
- signalwire_agents/prefabs/faq_bot.py,sha256=NrUn5AGmtdzYTyxTHPt8BZ14ZN1sh4xKA2SVQUlfPPQ,10834
66
- signalwire_agents/prefabs/info_gatherer.py,sha256=dr9UUgNGX7MIKdCMth3jDVLf6OrHov5G6_zIuNvnrOY,15468
67
- signalwire_agents/prefabs/receptionist.py,sha256=8EyQ6M0Egs3g7KKWukHFiO9UPoVUxT4MLkvyT3V8o64,10585
68
- signalwire_agents/prefabs/survey.py,sha256=IIIQfgvMlfVNjEEEdWUn4lAJqVsCDlBsIAkOJ1ckyAE,14796
64
+ signalwire_agents/prefabs/concierge.py,sha256=XB-Ziy0tteYI5NHu7Sinx-N960nzkhq2m4v8Ei8UHas,9921
65
+ signalwire_agents/prefabs/faq_bot.py,sha256=cUuHhnDB8S4aVg-DiQe4jBmCAPrYQrND_Mff9iaeEa0,10572
66
+ signalwire_agents/prefabs/info_gatherer.py,sha256=0LpYTaU7C76Efp3yUIdNX6xzWH7mj5pBYewilpkCL5g,15189
67
+ signalwire_agents/prefabs/receptionist.py,sha256=em0uk_F0tmePvzE6Hi9HFlL3MHChH0RaHHqSvww9pK0,10323
68
+ signalwire_agents/prefabs/survey.py,sha256=a-0-xAnQYhdX4Lzgyna14lpNfaCV-rLUFkQF6QOCQAY,14534
69
69
  signalwire_agents/search/__init__.py,sha256=x7saU_MDbhoOIzcvCT1-gnqyH2rrMpzB4ZUqk-av-lI,3958
70
70
  signalwire_agents/search/document_processor.py,sha256=J4OG640qbqGslbVevvD4J2cbTmFCZiGJ1bLX2yDayaE,43699
71
71
  signalwire_agents/search/index_builder.py,sha256=MHqrLZfNjWAM7EtL1L4wqrS1ICXKI_GPrHtIFHn35kQ,25174
72
72
  signalwire_agents/search/query_processor.py,sha256=WMm_jjArQ6-Jpy0Cc0sUI4saidOtDRKx_XLv0qi3N3k,16739
73
73
  signalwire_agents/search/search_engine.py,sha256=KFF33aPsBdwb2N1aTJmAA0xo3KPANoXjwV53uSxih9o,14798
74
- signalwire_agents/search/search_service.py,sha256=Src_REgjkcddHBDCaLv2BMJnDSxcE4XV_1U8YStJOh8,8719
74
+ signalwire_agents/search/search_service.py,sha256=zidaQb2aRusAODU8C6Nw65ZlTy3DjJ2-bMJavhMl7vk,15608
75
75
  signalwire_agents/skills/README.md,sha256=sM1_08IsKdRDCzYHPLzppJbaK5MvRelsVL6Kd9A9Ubo,12193
76
76
  signalwire_agents/skills/__init__.py,sha256=j0HambEKTkrFNP2vsaSmfrMJNDabq4EuvYJqRKZXfxU,342
77
77
  signalwire_agents/skills/registry.py,sha256=lnr0XFOQ5YC_WgsAT6Id3RMAJ2-nf2ZCdqB7z_huLQI,4889
@@ -93,6 +93,9 @@ signalwire_agents/skills/joke/skill.py,sha256=AFaf6fMy0sxUPJHvcnf3CWMuPqpJP4ODsc
93
93
  signalwire_agents/skills/math/README.md,sha256=Nrv7PxkFPSxdnAN6856Fp1CfvsUwdncpRFFDERxmMe0,5335
94
94
  signalwire_agents/skills/math/__init__.py,sha256=lGAFWEmJH2fuwkuZUdDTY5dmucrIwtjfNT8bE2hOSP8,39
95
95
  signalwire_agents/skills/math/skill.py,sha256=5sErd5x1rFHJg2GlmdJB3LvrmvTNOrZsA2jRnG67Zw8,3342
96
+ signalwire_agents/skills/mcp_gateway/README.md,sha256=t-71TTWlEvjgWLTcT3v4kMw9zlrKXTAC_sCjb1haNew,5826
97
+ signalwire_agents/skills/mcp_gateway/__init__.py,sha256=w1XiSptNPQAoZe3ISvYzi7bUdNT_KrDrQYeKKGzy-4w,45
98
+ signalwire_agents/skills/mcp_gateway/skill.py,sha256=iS5ET9jYKnwuYsuFd-aqUJfLUhvX--RG2FfCq8BZ340,14050
96
99
  signalwire_agents/skills/native_vector_search/__init__.py,sha256=buvncVoH5u8MJA0SLlz1JQgIuyBTQW5aql-ydnc7Wh8,29
97
100
  signalwire_agents/skills/native_vector_search/skill.py,sha256=Ck74rnlZ1HtnmEWRhZW1bSF_-PzpV3q-sNOu_LmeDQ0,18934
98
101
  signalwire_agents/skills/play_background_file/README.md,sha256=omJ_jY5Co6Mk-gJt_hoSl40wemmTbzae3DBll6HL0B4,7026
@@ -118,9 +121,9 @@ signalwire_agents/utils/pom_utils.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_Pu
118
121
  signalwire_agents/utils/schema_utils.py,sha256=i4okv_O9bUApwT_jJf4Yoij3bLCrGrW3DC-vzSy2RuY,16392
119
122
  signalwire_agents/utils/token_generators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
120
123
  signalwire_agents/utils/validators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
121
- signalwire_agents-0.1.27.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
122
- signalwire_agents-0.1.27.dist-info/METADATA,sha256=7M8q5GHaeZzmsa2ieXymQRVbayHuyc-nkhJHdxpkzz8,37922
123
- signalwire_agents-0.1.27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
124
- signalwire_agents-0.1.27.dist-info/entry_points.txt,sha256=sfdeRaTSs9J56pqFdcZGRTxQcTuecb8IMx8gqleJ6s0,136
125
- signalwire_agents-0.1.27.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
126
- signalwire_agents-0.1.27.dist-info/RECORD,,
124
+ signalwire_agents-0.1.29.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
125
+ signalwire_agents-0.1.29.dist-info/METADATA,sha256=W52d5PaE5t2jU01BfgwECFPW--OeJeABeBgpsRDqebA,35907
126
+ signalwire_agents-0.1.29.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
127
+ signalwire_agents-0.1.29.dist-info/entry_points.txt,sha256=sfdeRaTSs9J56pqFdcZGRTxQcTuecb8IMx8gqleJ6s0,136
128
+ signalwire_agents-0.1.29.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
129
+ signalwire_agents-0.1.29.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- """
2
- Copyright (c) 2025 SignalWire
3
-
4
- This file is part of the SignalWire AI Agents SDK.
5
-
6
- Licensed under the MIT License.
7
- See LICENSE file in the project root for full license information.
8
- """
9
-
10
- """
11
- State management for SignalWire AI Agents
12
- """
13
-
14
- from .state_manager import StateManager
15
- from .file_state_manager import FileStateManager
16
-
17
- __all__ = ['StateManager', 'FileStateManager']