signalwire-agents 0.1.7__py3-none-any.whl → 0.1.9__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.
@@ -0,0 +1,88 @@
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 re
11
+ from typing import List, Dict, Any
12
+
13
+ from signalwire_agents.core.skill_base import SkillBase
14
+ from signalwire_agents.core.function_result import SwaigFunctionResult
15
+
16
+ class MathSkill(SkillBase):
17
+ """Provides basic mathematical calculation capabilities"""
18
+
19
+ SKILL_NAME = "math"
20
+ SKILL_DESCRIPTION = "Perform basic mathematical calculations"
21
+ SKILL_VERSION = "1.0.0"
22
+ REQUIRED_PACKAGES = []
23
+ REQUIRED_ENV_VARS = []
24
+
25
+ def setup(self) -> bool:
26
+ """Setup the math skill"""
27
+ return True
28
+
29
+ def register_tools(self) -> None:
30
+ """Register math tools with the agent"""
31
+
32
+ self.agent.define_tool(
33
+ name="calculate",
34
+ description="Perform a mathematical calculation with basic operations (+, -, *, /, %, **)",
35
+ parameters={
36
+ "expression": {
37
+ "type": "string",
38
+ "description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', '(10 + 5) / 3')"
39
+ }
40
+ },
41
+ handler=self._calculate_handler
42
+ )
43
+
44
+ def _calculate_handler(self, args, raw_data):
45
+ """Handler for calculate tool"""
46
+ expression = args.get("expression", "").strip()
47
+
48
+ if not expression:
49
+ return SwaigFunctionResult("Please provide a mathematical expression to calculate.")
50
+
51
+ # Security: only allow safe mathematical operations
52
+ safe_chars = re.compile(r'^[0-9+\-*/().\s%**]+$')
53
+ if not safe_chars.match(expression):
54
+ return SwaigFunctionResult(
55
+ "Invalid expression. Only numbers and basic math operators (+, -, *, /, %, **, parentheses) are allowed."
56
+ )
57
+
58
+ try:
59
+ # Evaluate the expression safely
60
+ result = eval(expression, {"__builtins__": {}}, {})
61
+
62
+ return SwaigFunctionResult(f"{expression} = {result}")
63
+
64
+ except ZeroDivisionError:
65
+ return SwaigFunctionResult("Error: Division by zero is not allowed.")
66
+ except Exception as e:
67
+ return SwaigFunctionResult(f"Error calculating '{expression}': Invalid expression")
68
+
69
+ def get_hints(self) -> List[str]:
70
+ """Return speech recognition hints"""
71
+ return [
72
+ "calculate", "math", "plus", "minus", "times", "multiply",
73
+ "divide", "equals", "percent", "power", "squared"
74
+ ]
75
+
76
+ def get_prompt_sections(self) -> List[Dict[str, Any]]:
77
+ """Return prompt sections to add to agent"""
78
+ return [
79
+ {
80
+ "title": "Mathematical Calculations",
81
+ "body": "You can perform mathematical calculations for users.",
82
+ "bullets": [
83
+ "Use the calculate tool for any math expressions",
84
+ "Supports basic operations: +, -, *, /, %, ** (power)",
85
+ "Can handle parentheses for complex expressions"
86
+ ]
87
+ }
88
+ ]
@@ -0,0 +1,98 @@
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 os
11
+ import importlib
12
+ import importlib.util
13
+ import inspect
14
+ from typing import Dict, List, Type, Optional
15
+ from pathlib import Path
16
+ import logging
17
+
18
+ from signalwire_agents.core.skill_base import SkillBase
19
+
20
+ class SkillRegistry:
21
+ """Global registry for discovering and managing skills"""
22
+
23
+ def __init__(self):
24
+ self._skills: Dict[str, Type[SkillBase]] = {}
25
+ self.logger = logging.getLogger("skill_registry")
26
+ self._discovered = False
27
+
28
+ def discover_skills(self) -> None:
29
+ """Discover skills from the skills directory"""
30
+ if self._discovered:
31
+ return
32
+
33
+ # Get the skills directory path
34
+ skills_dir = Path(__file__).parent
35
+
36
+ # Scan for skill directories
37
+ for item in skills_dir.iterdir():
38
+ if item.is_dir() and not item.name.startswith('__'):
39
+ self._load_skill_from_directory(item)
40
+
41
+ self._discovered = True
42
+ self.logger.info(f"Discovered {len(self._skills)} skills")
43
+
44
+ def _load_skill_from_directory(self, skill_dir: Path) -> None:
45
+ """Load a skill from a directory"""
46
+ skill_file = skill_dir / "skill.py"
47
+ if not skill_file.exists():
48
+ return
49
+
50
+ try:
51
+ # Import the skill module
52
+ module_name = f"signalwire_agents.skills.{skill_dir.name}.skill"
53
+ spec = importlib.util.spec_from_file_location(module_name, skill_file)
54
+ module = importlib.util.module_from_spec(spec)
55
+ spec.loader.exec_module(module)
56
+
57
+ # Find SkillBase subclasses in the module
58
+ for name, obj in inspect.getmembers(module):
59
+ if (inspect.isclass(obj) and
60
+ issubclass(obj, SkillBase) and
61
+ obj != SkillBase and
62
+ obj.SKILL_NAME is not None):
63
+
64
+ self.register_skill(obj)
65
+
66
+ except Exception as e:
67
+ self.logger.error(f"Failed to load skill from {skill_dir}: {e}")
68
+
69
+ def register_skill(self, skill_class: Type[SkillBase]) -> None:
70
+ """Register a skill class"""
71
+ if skill_class.SKILL_NAME in self._skills:
72
+ self.logger.warning(f"Skill '{skill_class.SKILL_NAME}' already registered")
73
+ return
74
+
75
+ self._skills[skill_class.SKILL_NAME] = skill_class
76
+ self.logger.debug(f"Registered skill '{skill_class.SKILL_NAME}'")
77
+
78
+ def get_skill_class(self, skill_name: str) -> Optional[Type[SkillBase]]:
79
+ """Get skill class by name"""
80
+ self.discover_skills() # Ensure skills are discovered
81
+ return self._skills.get(skill_name)
82
+
83
+ def list_skills(self) -> List[Dict[str, str]]:
84
+ """List all registered skills with metadata"""
85
+ self.discover_skills()
86
+ return [
87
+ {
88
+ "name": skill_class.SKILL_NAME,
89
+ "description": skill_class.SKILL_DESCRIPTION,
90
+ "version": skill_class.SKILL_VERSION,
91
+ "required_packages": skill_class.REQUIRED_PACKAGES,
92
+ "required_env_vars": skill_class.REQUIRED_ENV_VARS
93
+ }
94
+ for skill_class in self._skills.values()
95
+ ]
96
+
97
+ # Global registry instance
98
+ skill_registry = SkillRegistry()
@@ -0,0 +1 @@
1
+ """Web Search Skill for SignalWire Agents"""
@@ -0,0 +1,240 @@
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 os
11
+ import requests
12
+ import time
13
+ from urllib.parse import urljoin, urlparse
14
+ from bs4 import BeautifulSoup
15
+ import json
16
+ from typing import Optional, List, Dict, Any
17
+
18
+ from signalwire_agents.core.skill_base import SkillBase
19
+ from signalwire_agents.core.function_result import SwaigFunctionResult
20
+
21
+ class GoogleSearchScraper:
22
+ """Google Search and Web Scraping functionality"""
23
+
24
+ def __init__(self, api_key: str, search_engine_id: str):
25
+ self.api_key = api_key
26
+ self.search_engine_id = search_engine_id
27
+ self.session = requests.Session()
28
+ self.session.headers.update({
29
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
30
+ })
31
+
32
+ def search_google(self, query: str, num_results: int = 5) -> list:
33
+ """Search Google using Custom Search JSON API"""
34
+ url = "https://www.googleapis.com/customsearch/v1"
35
+
36
+ params = {
37
+ 'key': self.api_key,
38
+ 'cx': self.search_engine_id,
39
+ 'q': query,
40
+ 'num': min(num_results, 10)
41
+ }
42
+
43
+ try:
44
+ response = self.session.get(url, params=params)
45
+ response.raise_for_status()
46
+ data = response.json()
47
+
48
+ if 'items' not in data:
49
+ return []
50
+
51
+ results = []
52
+ for item in data['items'][:num_results]:
53
+ results.append({
54
+ 'title': item.get('title', ''),
55
+ 'url': item.get('link', ''),
56
+ 'snippet': item.get('snippet', '')
57
+ })
58
+
59
+ return results
60
+
61
+ except Exception as e:
62
+ return []
63
+
64
+ def extract_text_from_url(self, url: str, timeout: int = 10) -> str:
65
+ """Scrape a URL and extract readable text content"""
66
+ try:
67
+ response = self.session.get(url, timeout=timeout)
68
+ response.raise_for_status()
69
+
70
+ soup = BeautifulSoup(response.content, 'html.parser')
71
+
72
+ # Remove unwanted elements
73
+ for script in soup(["script", "style", "nav", "footer", "header", "aside"]):
74
+ script.decompose()
75
+
76
+ text = soup.get_text()
77
+
78
+ # Clean up the text
79
+ lines = (line.strip() for line in text.splitlines())
80
+ chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
81
+ text = ' '.join(chunk for chunk in chunks if chunk)
82
+
83
+ # Limit text length
84
+ if len(text) > 2000:
85
+ text = text[:2000] + "... [Content truncated]"
86
+
87
+ return text
88
+
89
+ except Exception as e:
90
+ return ""
91
+
92
+ def search_and_scrape(self, query: str, num_results: int = 3, delay: float = 0.5) -> str:
93
+ """Main function: search Google and scrape the resulting pages"""
94
+ search_results = self.search_google(query, num_results)
95
+
96
+ if not search_results:
97
+ return f"No search results found for query: {query}"
98
+
99
+ all_text = []
100
+
101
+ for i, result in enumerate(search_results, 1):
102
+ text_content = f"=== RESULT {i} ===\n"
103
+ text_content += f"Title: {result['title']}\n"
104
+ text_content += f"URL: {result['url']}\n"
105
+ text_content += f"Snippet: {result['snippet']}\n"
106
+ text_content += f"Content:\n"
107
+
108
+ page_text = self.extract_text_from_url(result['url'])
109
+
110
+ if page_text:
111
+ text_content += page_text
112
+ else:
113
+ text_content += "Failed to extract content from this page."
114
+
115
+ text_content += f"\n{'='*50}\n\n"
116
+ all_text.append(text_content)
117
+
118
+ if i < len(search_results):
119
+ time.sleep(delay)
120
+
121
+ return '\n'.join(all_text)
122
+
123
+
124
+ class WebSearchSkill(SkillBase):
125
+ """Web search capability using Google Custom Search API"""
126
+
127
+ SKILL_NAME = "web_search"
128
+ SKILL_DESCRIPTION = "Search the web for information using Google Custom Search API"
129
+ SKILL_VERSION = "1.0.0"
130
+ REQUIRED_PACKAGES = ["bs4", "requests"]
131
+ REQUIRED_ENV_VARS = ["GOOGLE_SEARCH_API_KEY", "GOOGLE_SEARCH_ENGINE_ID"]
132
+
133
+ def setup(self) -> bool:
134
+ """Setup the web search skill"""
135
+ if not self.validate_env_vars() or not self.validate_packages():
136
+ return False
137
+
138
+ # Set default parameters
139
+ self.default_num_results = self.params.get('num_results', 1)
140
+ self.default_delay = self.params.get('delay', 0)
141
+
142
+ # Initialize the search scraper
143
+ self.search_scraper = GoogleSearchScraper(
144
+ api_key=os.getenv('GOOGLE_SEARCH_API_KEY'),
145
+ search_engine_id=os.getenv('GOOGLE_SEARCH_ENGINE_ID')
146
+ )
147
+
148
+ return True
149
+
150
+ def register_tools(self) -> None:
151
+ """Register web search tool with the agent"""
152
+ self.agent.define_tool(
153
+ name="web_search",
154
+ description="Search the web for information on any topic and return detailed results with content from multiple sources",
155
+ parameters={
156
+ "query": {
157
+ "type": "string",
158
+ "description": "The search query - what you want to find information about"
159
+ },
160
+ "num_results": {
161
+ "type": "integer",
162
+ "description": f"Number of web pages to search and extract content from (1-10, default: {self.default_num_results})",
163
+ "minimum": 1,
164
+ "maximum": 10
165
+ }
166
+ },
167
+ handler=self._web_search_handler
168
+ )
169
+
170
+ def _web_search_handler(self, args, raw_data):
171
+ """Handler for web search tool"""
172
+ query = args.get("query", "").strip()
173
+ num_results = args.get("num_results", self.default_num_results)
174
+
175
+ if not query:
176
+ return SwaigFunctionResult(
177
+ "Please provide a search query. What would you like me to search for?"
178
+ )
179
+
180
+ # Validate num_results
181
+ try:
182
+ num_results = int(num_results)
183
+ num_results = max(1, min(num_results, 10))
184
+ except (ValueError, TypeError):
185
+ num_results = self.default_num_results
186
+
187
+ self.logger.info(f"Web search requested: '{query}' ({num_results} results)")
188
+
189
+ # Perform the search
190
+ try:
191
+ search_results = self.search_scraper.search_and_scrape(
192
+ query=query,
193
+ num_results=num_results,
194
+ delay=self.default_delay
195
+ )
196
+
197
+ if not search_results or "No search results found" in search_results:
198
+ return SwaigFunctionResult(
199
+ f"I couldn't find any results for '{query}'. "
200
+ "This might be due to a very specific query or temporary issues. "
201
+ "Try rephrasing your search or asking about a different topic."
202
+ )
203
+
204
+ response = f"I found {num_results} results for '{query}':\n\n{search_results}"
205
+ return SwaigFunctionResult(response)
206
+
207
+ except Exception as e:
208
+ self.logger.error(f"Error performing web search: {e}")
209
+ return SwaigFunctionResult(
210
+ "Sorry, I encountered an error while searching. Please try again later."
211
+ )
212
+
213
+ def get_hints(self) -> List[str]:
214
+ """Return speech recognition hints"""
215
+ return [
216
+ "Google", "search", "internet", "web", "information",
217
+ "find", "look up", "research", "query", "results"
218
+ ]
219
+
220
+ def get_global_data(self) -> Dict[str, Any]:
221
+ """Return global data for agent context"""
222
+ return {
223
+ "web_search_enabled": True,
224
+ "search_provider": "Google Custom Search"
225
+ }
226
+
227
+ def get_prompt_sections(self) -> List[Dict[str, Any]]:
228
+ """Return prompt sections to add to agent"""
229
+ return [
230
+ {
231
+ "title": "Web Search Capability",
232
+ "body": "You can search the internet for current, accurate information on any topic.",
233
+ "bullets": [
234
+ "Use the web_search tool when users ask for information you need to look up",
235
+ "Search for news, current events, product information, or any current data",
236
+ "Summarize search results in a clear, helpful way",
237
+ "Include relevant URLs so users can read more if interested"
238
+ ]
239
+ }
240
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalwire_agents
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: SignalWire AI Agents SDK
5
5
  Author-email: SignalWire Team <info@signalwire.com>
6
6
  Project-URL: Homepage, https://github.com/signalwire/signalwire-ai-agents
@@ -24,6 +24,8 @@ Requires-Dist: setuptools==66.1.1
24
24
  Requires-Dist: signalwire_pom==2.7.1
25
25
  Requires-Dist: structlog==25.3.0
26
26
  Requires-Dist: uvicorn==0.34.2
27
+ Requires-Dist: beautifulsoup4==4.12.3
28
+ Requires-Dist: pytz==2023.3
27
29
  Dynamic: license-file
28
30
 
29
31
  # SignalWire AI Agent SDK
@@ -35,12 +37,54 @@ A Python SDK for creating, hosting, and securing SignalWire AI agents as microse
35
37
  - **Self-Contained Agents**: Each agent is both a web app and an AI persona
36
38
  - **Prompt Object Model**: Structured prompt composition using POM
37
39
  - **SWAIG Integration**: Easily define and handle AI tools/functions
40
+ - **Dynamic Configuration**: Configure agents per-request for multi-tenant apps and personalization
38
41
  - **Custom Routing**: Dynamic request handling for different paths and content
39
42
  - **SIP Integration**: Route SIP calls to agents based on SIP usernames
40
43
  - **Security Built-In**: Session management, function-specific security tokens, and basic auth
41
44
  - **State Management**: Persistent conversation state with automatic tracking
42
45
  - **Prefab Archetypes**: Ready-to-use agent types for common scenarios
43
46
  - **Multi-Agent Support**: Host multiple agents on a single server
47
+ - **Modular Skills System**: Add capabilities to agents with simple one-liner calls
48
+
49
+ ## Skills System
50
+
51
+ The SignalWire Agents SDK includes a powerful modular skills system that allows you to add complex capabilities to your agents with simple one-liner calls:
52
+
53
+ ```python
54
+ from signalwire_agents import AgentBase
55
+
56
+ # Create an agent
57
+ agent = AgentBase("My Assistant", route="/assistant")
58
+
59
+ # Add skills with one-liners
60
+ agent.add_skill("web_search") # Web search capability
61
+ agent.add_skill("datetime") # Current date/time info
62
+ agent.add_skill("math") # Mathematical calculations
63
+
64
+ # Configure skills with parameters
65
+ agent.add_skill("web_search", {
66
+ "num_results": 3, # Get 3 search results
67
+ "delay": 0.5 # Small delay between requests
68
+ })
69
+
70
+ agent.serve()
71
+ ```
72
+
73
+ ### Available Built-in Skills
74
+
75
+ - **web_search**: Google Custom Search API integration with web scraping
76
+ - **datetime**: Current date and time with timezone support
77
+ - **math**: Safe mathematical expression evaluation
78
+
79
+ ### Benefits
80
+
81
+ - **One-liner integration**: `agent.add_skill("skill_name")`
82
+ - **Configurable parameters**: `agent.add_skill("skill_name", {"param": "value"})`
83
+ - **Automatic discovery**: Skills are automatically found from the skills directory
84
+ - **Dependency validation**: Clear error messages for missing requirements
85
+ - **Modular architecture**: Skills are self-contained and reusable
86
+
87
+ For detailed documentation, see [Skills System README](docs/SKILLS_SYSTEM_README.md).
44
88
 
45
89
  ## Installation
46
90
 
@@ -165,6 +209,73 @@ Available prefabs include:
165
209
  - `FAQBotAgent`: Answers questions based on a knowledge base
166
210
  - `ConciergeAgent`: Routes users to specialized agents
167
211
  - `SurveyAgent`: Conducts structured surveys with questions and rating scales
212
+ - `ReceptionistAgent`: Greets callers and transfers them to appropriate departments
213
+
214
+ ## Dynamic Agent Configuration
215
+
216
+ Configure agents dynamically based on request parameters for multi-tenant applications, A/B testing, and personalization.
217
+
218
+ ### Static vs Dynamic Configuration
219
+
220
+ - **Static**: Agent configured once at startup (traditional approach)
221
+ - **Dynamic**: Agent configured fresh for each request based on parameters
222
+
223
+ ### Basic Example
224
+
225
+ ```python
226
+ from signalwire_agents import AgentBase
227
+
228
+ class DynamicAgent(AgentBase):
229
+ def __init__(self):
230
+ super().__init__(name="dynamic-agent", route="/dynamic")
231
+
232
+ # Set up dynamic configuration callback
233
+ self.set_dynamic_config_callback(self.configure_per_request)
234
+
235
+ def configure_per_request(self, query_params, body_params, headers, agent):
236
+ """Configure agent based on request parameters"""
237
+
238
+ # Extract parameters from request
239
+ tier = query_params.get('tier', 'standard')
240
+ language = query_params.get('language', 'en')
241
+ customer_id = query_params.get('customer_id')
242
+
243
+ # Configure voice and language
244
+ if language == 'es':
245
+ agent.add_language("Spanish", "es-ES", "rime.spore:mistv2")
246
+ else:
247
+ agent.add_language("English", "en-US", "rime.spore:mistv2")
248
+
249
+ # Configure based on service tier
250
+ if tier == 'premium':
251
+ agent.set_params({"end_of_speech_timeout": 300}) # Faster response
252
+ agent.prompt_add_section("Service Level", "You provide premium support.")
253
+ else:
254
+ agent.set_params({"end_of_speech_timeout": 500}) # Standard response
255
+ agent.prompt_add_section("Service Level", "You provide standard support.")
256
+
257
+ # Personalize with customer data
258
+ global_data = {"tier": tier, "language": language}
259
+ if customer_id:
260
+ global_data["customer_id"] = customer_id
261
+ agent.set_global_data(global_data)
262
+
263
+ # Usage examples:
264
+ # curl "http://localhost:3000/dynamic?tier=premium&language=es&customer_id=123"
265
+ # curl "http://localhost:3000/dynamic?tier=standard&language=en"
266
+ ```
267
+
268
+ ### Use Cases
269
+
270
+ - **Multi-tenant SaaS**: Different configurations per customer/organization
271
+ - **A/B Testing**: Test different agent behaviors with different user groups
272
+ - **Personalization**: Customize voice, prompts, and behavior per user
273
+ - **Localization**: Language and cultural adaptation based on user location
274
+ - **Dynamic Pricing**: Adjust features and capabilities based on subscription tiers
275
+
276
+ The `EphemeralAgentConfig` object provides all the same familiar methods as `AgentBase` (like `add_language()`, `prompt_add_section()`, `set_global_data()`) but applies them per-request instead of at startup.
277
+
278
+ For detailed documentation and advanced examples, see the [Agent Guide](docs/agent_guide.md#dynamic-agent-configuration).
168
279
 
169
280
  ## Configuration
170
281
 
@@ -189,7 +300,7 @@ To enable HTTPS directly (without a reverse proxy), set `SWML_SSL_ENABLED` to "t
189
300
 
190
301
  The package includes comprehensive documentation in the `docs/` directory:
191
302
 
192
- - [Agent Guide](docs/agent_guide.md) - Detailed guide to creating and customizing agents
303
+ - [Agent Guide](docs/agent_guide.md) - Detailed guide to creating and customizing agents, including dynamic configuration
193
304
  - [Architecture](docs/architecture.md) - Overview of the SDK architecture and core concepts
194
305
  - [SWML Service Guide](docs/swml_service_guide.md) - Guide to the underlying SWML service
195
306
 
@@ -1,12 +1,14 @@
1
- signalwire_agents/__init__.py,sha256=WMXWZxEE3QuDgEKy6MBcL6hxdSDA3_gFd2XAQYmEwMg,800
1
+ signalwire_agents/__init__.py,sha256=aEEMPduIWEbHA41lbgxI6lOVAOmYI1C0nFc8_35bLj8,870
2
2
  signalwire_agents/agent_server.py,sha256=se_YzOQE5UUoRUKCbTnOg9qr4G3qN7iVuQLutwXEwFU,12850
3
3
  signalwire_agents/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
4
4
  signalwire_agents/core/__init__.py,sha256=mVDLbpq1pg_WwiqsQR28NNZwJ6-VUXFIfg-vN7pk0ew,806
5
- signalwire_agents/core/agent_base.py,sha256=D8ZiRRYDxF24cOjXoT253SWODEvmDZ-l8kwWMnr18Bw,103118
6
- signalwire_agents/core/function_result.py,sha256=vD8eBDJBQNNnss1jShadfogCZw_prODB6eBkTuVgZKA,3538
5
+ signalwire_agents/core/agent_base.py,sha256=sQHFKzOHtQrmMn9TGSda-BzfLsqNV9JgG9npUPUrovE,114016
6
+ signalwire_agents/core/function_result.py,sha256=OXzm4GOvA6TKbzZFsdz3iBU5vQs9LXxsmQue7zWVolE,43538
7
7
  signalwire_agents/core/pom_builder.py,sha256=ywuiIfP8BeLBPo_G4X1teZlG6zTCMkW71CZnmyoDTAQ,6636
8
+ signalwire_agents/core/skill_base.py,sha256=4IPSP422iKricMRcKWx0rIjy3XS5qaRUf5OSM_x_0QU,3015
9
+ signalwire_agents/core/skill_manager.py,sha256=kW17EOUR4u9mePo_90qKoCP6rusXDWzqZvJA0_FB-q4,5486
8
10
  signalwire_agents/core/swaig_function.py,sha256=WoHGQuCmU9L9k39pttRunmfRtIa_PnNRn9W0Xq3MfIk,6316
9
- signalwire_agents/core/swml_builder.py,sha256=Y_eHThVVso-_Hz4f73eEuu3HJstsM9PtBl-36GvAXhI,6594
11
+ signalwire_agents/core/swml_builder.py,sha256=Q1ikU9pedgjW888mjbqDFv-jMDvDZ-tZgfyMfu4qQN0,6719
10
12
  signalwire_agents/core/swml_handler.py,sha256=KvphI_YY47VWGVXaix_N3SuQSyygHEUr9We6xESQK44,7002
11
13
  signalwire_agents/core/swml_renderer.py,sha256=iobMWWoBR7dkHndI3Qlwf4C0fg2p7DmAU2Rb7ZmmLhA,13891
12
14
  signalwire_agents/core/swml_service.py,sha256=4zTtpIKDtL59MzKgkBdpPmBCT6s1wVIikWEzZ1hqnyc,49309
@@ -18,17 +20,25 @@ signalwire_agents/core/state/state_manager.py,sha256=76B4mDutMb826dK4c_IJhOXH09B
18
20
  signalwire_agents/prefabs/__init__.py,sha256=MW11J63XH7KxF2MWguRsMFM9iqMWexaEO9ynDPL_PDM,715
19
21
  signalwire_agents/prefabs/concierge.py,sha256=FQxSUBAVH2ECtNs4GGa3f0EPiOrAKaz14h7byNFy5K8,10106
20
22
  signalwire_agents/prefabs/faq_bot.py,sha256=NrUn5AGmtdzYTyxTHPt8BZ14ZN1sh4xKA2SVQUlfPPQ,10834
21
- signalwire_agents/prefabs/info_gatherer.py,sha256=NkRc6FSaslDMhvF3a2rAvTqD9V8t17OV6_awwtQPPRM,10219
22
- signalwire_agents/prefabs/receptionist.py,sha256=Bpb_okc5MnxEdrrO-PkXXo5Zp9awgyt4bvYJOahSbYE,10555
23
+ signalwire_agents/prefabs/info_gatherer.py,sha256=dr9UUgNGX7MIKdCMth3jDVLf6OrHov5G6_zIuNvnrOY,15468
24
+ signalwire_agents/prefabs/receptionist.py,sha256=8EyQ6M0Egs3g7KKWukHFiO9UPoVUxT4MLkvyT3V8o64,10585
23
25
  signalwire_agents/prefabs/survey.py,sha256=IIIQfgvMlfVNjEEEdWUn4lAJqVsCDlBsIAkOJ1ckyAE,14796
26
+ signalwire_agents/skills/__init__.py,sha256=xfxrQ0i-aTRomHiCsqelU4RlNlHPJFPgPu-UBDaBOqA,340
27
+ signalwire_agents/skills/registry.py,sha256=XffqhZQ4ZbAMRssMW8vnK5-Qk8oJBmiEoPwFCMcz1Gc,3515
28
+ signalwire_agents/skills/datetime/__init__.py,sha256=coPaY-k2EyZWuYckGunhSJ65Y1Jwz66h-iOo0QWb5WY,43
29
+ signalwire_agents/skills/datetime/skill.py,sha256=XtT-tvr-X07q15B96X1bmVCjFvWdXm3J0ZfJ1kxSJe4,3746
30
+ signalwire_agents/skills/math/__init__.py,sha256=lGAFWEmJH2fuwkuZUdDTY5dmucrIwtjfNT8bE2hOSP8,39
31
+ signalwire_agents/skills/math/skill.py,sha256=Li0oN_pSL3jlC36FGILeZO_P0txf1TVOMoKu1Hrnp_Q,3215
32
+ signalwire_agents/skills/web_search/__init__.py,sha256=wJlptYDExYw-nxZJVzlTLOgkKkDOLUUt1ZdoLt44ixs,45
33
+ signalwire_agents/skills/web_search/skill.py,sha256=whjY2v3k8hsHxn1KSyTibYl_rtkdVbi0kWAPZuegR5w,9018
24
34
  signalwire_agents/utils/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
25
35
  signalwire_agents/utils/pom_utils.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
26
36
  signalwire_agents/utils/schema_utils.py,sha256=LvFCFvJTQk_xYK0B-NXbkXKEF7Zmv-LqpV_vfpPnOb4,13473
27
37
  signalwire_agents/utils/token_generators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
28
38
  signalwire_agents/utils/validators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
29
- signalwire_agents-0.1.7.data/data/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
30
- signalwire_agents-0.1.7.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
31
- signalwire_agents-0.1.7.dist-info/METADATA,sha256=rlAExY7ealJ5HzZIx-IOHnH9MZn3zfXcuISBgnIRJbw,7486
32
- signalwire_agents-0.1.7.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
33
- signalwire_agents-0.1.7.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
34
- signalwire_agents-0.1.7.dist-info/RECORD,,
39
+ signalwire_agents-0.1.9.data/data/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
40
+ signalwire_agents-0.1.9.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
41
+ signalwire_agents-0.1.9.dist-info/METADATA,sha256=APX6OmsEYOL3iOdR6jwc5spU7pxy9lC8G1rSolR4SHU,12040
42
+ signalwire_agents-0.1.9.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
43
+ signalwire_agents-0.1.9.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
44
+ signalwire_agents-0.1.9.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.7.1)
2
+ Generator: setuptools (80.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5