signalwire-agents 0.1.13__py3-none-any.whl → 1.0.17.dev4__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 (143) hide show
  1. signalwire_agents/__init__.py +99 -15
  2. signalwire_agents/agent_server.py +248 -60
  3. signalwire_agents/agents/bedrock.py +296 -0
  4. signalwire_agents/cli/__init__.py +9 -0
  5. signalwire_agents/cli/build_search.py +951 -41
  6. signalwire_agents/cli/config.py +80 -0
  7. signalwire_agents/cli/core/__init__.py +10 -0
  8. signalwire_agents/cli/core/agent_loader.py +470 -0
  9. signalwire_agents/cli/core/argparse_helpers.py +179 -0
  10. signalwire_agents/cli/core/dynamic_config.py +71 -0
  11. signalwire_agents/cli/core/service_loader.py +303 -0
  12. signalwire_agents/cli/dokku.py +2320 -0
  13. signalwire_agents/cli/execution/__init__.py +10 -0
  14. signalwire_agents/cli/execution/datamap_exec.py +446 -0
  15. signalwire_agents/cli/execution/webhook_exec.py +134 -0
  16. signalwire_agents/cli/init_project.py +2636 -0
  17. signalwire_agents/cli/output/__init__.py +10 -0
  18. signalwire_agents/cli/output/output_formatter.py +255 -0
  19. signalwire_agents/cli/output/swml_dump.py +186 -0
  20. signalwire_agents/cli/simulation/__init__.py +10 -0
  21. signalwire_agents/cli/simulation/data_generation.py +374 -0
  22. signalwire_agents/cli/simulation/data_overrides.py +200 -0
  23. signalwire_agents/cli/simulation/mock_env.py +282 -0
  24. signalwire_agents/cli/swaig_test_wrapper.py +52 -0
  25. signalwire_agents/cli/test_swaig.py +566 -2366
  26. signalwire_agents/cli/types.py +81 -0
  27. signalwire_agents/core/__init__.py +2 -2
  28. signalwire_agents/core/agent/__init__.py +12 -0
  29. signalwire_agents/core/agent/config/__init__.py +12 -0
  30. signalwire_agents/core/agent/deployment/__init__.py +9 -0
  31. signalwire_agents/core/agent/deployment/handlers/__init__.py +9 -0
  32. signalwire_agents/core/agent/prompt/__init__.py +14 -0
  33. signalwire_agents/core/agent/prompt/manager.py +306 -0
  34. signalwire_agents/core/agent/routing/__init__.py +9 -0
  35. signalwire_agents/core/agent/security/__init__.py +9 -0
  36. signalwire_agents/core/agent/swml/__init__.py +9 -0
  37. signalwire_agents/core/agent/tools/__init__.py +15 -0
  38. signalwire_agents/core/agent/tools/decorator.py +97 -0
  39. signalwire_agents/core/agent/tools/registry.py +210 -0
  40. signalwire_agents/core/agent_base.py +845 -2916
  41. signalwire_agents/core/auth_handler.py +233 -0
  42. signalwire_agents/core/config_loader.py +259 -0
  43. signalwire_agents/core/contexts.py +418 -0
  44. signalwire_agents/core/data_map.py +3 -15
  45. signalwire_agents/core/function_result.py +116 -44
  46. signalwire_agents/core/logging_config.py +162 -18
  47. signalwire_agents/core/mixins/__init__.py +28 -0
  48. signalwire_agents/core/mixins/ai_config_mixin.py +442 -0
  49. signalwire_agents/core/mixins/auth_mixin.py +280 -0
  50. signalwire_agents/core/mixins/prompt_mixin.py +358 -0
  51. signalwire_agents/core/mixins/serverless_mixin.py +460 -0
  52. signalwire_agents/core/mixins/skill_mixin.py +55 -0
  53. signalwire_agents/core/mixins/state_mixin.py +153 -0
  54. signalwire_agents/core/mixins/tool_mixin.py +230 -0
  55. signalwire_agents/core/mixins/web_mixin.py +1142 -0
  56. signalwire_agents/core/security_config.py +333 -0
  57. signalwire_agents/core/skill_base.py +84 -1
  58. signalwire_agents/core/skill_manager.py +62 -20
  59. signalwire_agents/core/swaig_function.py +18 -5
  60. signalwire_agents/core/swml_builder.py +207 -11
  61. signalwire_agents/core/swml_handler.py +27 -21
  62. signalwire_agents/core/swml_renderer.py +123 -312
  63. signalwire_agents/core/swml_service.py +171 -203
  64. signalwire_agents/mcp_gateway/__init__.py +29 -0
  65. signalwire_agents/mcp_gateway/gateway_service.py +564 -0
  66. signalwire_agents/mcp_gateway/mcp_manager.py +513 -0
  67. signalwire_agents/mcp_gateway/session_manager.py +218 -0
  68. signalwire_agents/prefabs/concierge.py +0 -3
  69. signalwire_agents/prefabs/faq_bot.py +0 -3
  70. signalwire_agents/prefabs/info_gatherer.py +0 -3
  71. signalwire_agents/prefabs/receptionist.py +0 -3
  72. signalwire_agents/prefabs/survey.py +0 -3
  73. signalwire_agents/schema.json +9218 -5489
  74. signalwire_agents/search/__init__.py +7 -1
  75. signalwire_agents/search/document_processor.py +490 -31
  76. signalwire_agents/search/index_builder.py +307 -37
  77. signalwire_agents/search/migration.py +418 -0
  78. signalwire_agents/search/models.py +30 -0
  79. signalwire_agents/search/pgvector_backend.py +748 -0
  80. signalwire_agents/search/query_processor.py +162 -31
  81. signalwire_agents/search/search_engine.py +916 -35
  82. signalwire_agents/search/search_service.py +376 -53
  83. signalwire_agents/skills/README.md +452 -0
  84. signalwire_agents/skills/__init__.py +14 -2
  85. signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
  86. signalwire_agents/skills/api_ninjas_trivia/__init__.py +12 -0
  87. signalwire_agents/skills/api_ninjas_trivia/skill.py +237 -0
  88. signalwire_agents/skills/datasphere/README.md +210 -0
  89. signalwire_agents/skills/datasphere/skill.py +84 -3
  90. signalwire_agents/skills/datasphere_serverless/README.md +258 -0
  91. signalwire_agents/skills/datasphere_serverless/__init__.py +9 -0
  92. signalwire_agents/skills/datasphere_serverless/skill.py +82 -1
  93. signalwire_agents/skills/datetime/README.md +132 -0
  94. signalwire_agents/skills/datetime/__init__.py +9 -0
  95. signalwire_agents/skills/datetime/skill.py +20 -7
  96. signalwire_agents/skills/joke/README.md +149 -0
  97. signalwire_agents/skills/joke/__init__.py +9 -0
  98. signalwire_agents/skills/joke/skill.py +21 -0
  99. signalwire_agents/skills/math/README.md +161 -0
  100. signalwire_agents/skills/math/__init__.py +9 -0
  101. signalwire_agents/skills/math/skill.py +18 -4
  102. signalwire_agents/skills/mcp_gateway/README.md +230 -0
  103. signalwire_agents/skills/mcp_gateway/__init__.py +10 -0
  104. signalwire_agents/skills/mcp_gateway/skill.py +421 -0
  105. signalwire_agents/skills/native_vector_search/README.md +210 -0
  106. signalwire_agents/skills/native_vector_search/__init__.py +9 -0
  107. signalwire_agents/skills/native_vector_search/skill.py +569 -101
  108. signalwire_agents/skills/play_background_file/README.md +218 -0
  109. signalwire_agents/skills/play_background_file/__init__.py +12 -0
  110. signalwire_agents/skills/play_background_file/skill.py +242 -0
  111. signalwire_agents/skills/registry.py +395 -40
  112. signalwire_agents/skills/spider/README.md +236 -0
  113. signalwire_agents/skills/spider/__init__.py +13 -0
  114. signalwire_agents/skills/spider/skill.py +598 -0
  115. signalwire_agents/skills/swml_transfer/README.md +395 -0
  116. signalwire_agents/skills/swml_transfer/__init__.py +10 -0
  117. signalwire_agents/skills/swml_transfer/skill.py +359 -0
  118. signalwire_agents/skills/weather_api/README.md +178 -0
  119. signalwire_agents/skills/weather_api/__init__.py +12 -0
  120. signalwire_agents/skills/weather_api/skill.py +191 -0
  121. signalwire_agents/skills/web_search/README.md +163 -0
  122. signalwire_agents/skills/web_search/__init__.py +9 -0
  123. signalwire_agents/skills/web_search/skill.py +586 -112
  124. signalwire_agents/skills/wikipedia_search/README.md +228 -0
  125. signalwire_agents/{core/state → skills/wikipedia_search}/__init__.py +5 -4
  126. signalwire_agents/skills/{wikipedia → wikipedia_search}/skill.py +33 -3
  127. signalwire_agents/web/__init__.py +17 -0
  128. signalwire_agents/web/web_service.py +559 -0
  129. signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-agent-init.1 +400 -0
  130. signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-search.1 +483 -0
  131. signalwire_agents-1.0.17.dev4.data/data/share/man/man1/swaig-test.1 +308 -0
  132. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/METADATA +347 -215
  133. signalwire_agents-1.0.17.dev4.dist-info/RECORD +147 -0
  134. signalwire_agents-1.0.17.dev4.dist-info/entry_points.txt +6 -0
  135. signalwire_agents/core/state/file_state_manager.py +0 -219
  136. signalwire_agents/core/state/state_manager.py +0 -101
  137. signalwire_agents/skills/wikipedia/__init__.py +0 -9
  138. signalwire_agents-0.1.13.data/data/schema.json +0 -5611
  139. signalwire_agents-0.1.13.dist-info/RECORD +0 -67
  140. signalwire_agents-0.1.13.dist-info/entry_points.txt +0 -3
  141. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/WHEEL +0 -0
  142. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/licenses/LICENSE +0 -0
  143. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,210 @@
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
+ """Tool registration and management."""
11
+
12
+ from typing import Dict, Any, Optional, List, Callable, Union
13
+ import inspect
14
+ import logging
15
+
16
+ from signalwire_agents.core.swaig_function import SWAIGFunction
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class ToolRegistry:
22
+ """Manages SWAIG function registration."""
23
+
24
+ def __init__(self, agent):
25
+ """
26
+ Initialize ToolRegistry with reference to parent agent.
27
+
28
+ Args:
29
+ agent: Parent AgentBase instance
30
+ """
31
+ self.agent = agent
32
+ self._swaig_functions = {}
33
+ self._class_decorated_tools = []
34
+
35
+ def define_tool(
36
+ self,
37
+ name: str,
38
+ description: str,
39
+ parameters: Dict[str, Any],
40
+ handler: Callable,
41
+ secure: bool = True,
42
+ fillers: Optional[Dict[str, List[str]]] = None,
43
+ wait_file: Optional[str] = None,
44
+ wait_file_loops: Optional[int] = None,
45
+ webhook_url: Optional[str] = None,
46
+ required: Optional[List[str]] = None,
47
+ **swaig_fields
48
+ ) -> None:
49
+ """
50
+ Define a SWAIG function that the AI can call.
51
+
52
+ Args:
53
+ name: Function name (must be unique)
54
+ description: Function description for the AI
55
+ parameters: JSON Schema of parameters
56
+ handler: Function to call when invoked
57
+ secure: Whether to require token validation
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
61
+ webhook_url: Optional external webhook URL to use instead of local handling
62
+ required: Optional list of required parameter names
63
+ **swaig_fields: Additional SWAIG fields to include in function definition
64
+
65
+ Raises:
66
+ ValueError: If tool name already exists
67
+ """
68
+ if name in self._swaig_functions:
69
+ raise ValueError(f"Tool with name '{name}' already exists")
70
+
71
+ self._swaig_functions[name] = SWAIGFunction(
72
+ name=name,
73
+ description=description,
74
+ parameters=parameters,
75
+ handler=handler,
76
+ secure=secure,
77
+ fillers=fillers,
78
+ wait_file=wait_file,
79
+ wait_file_loops=wait_file_loops,
80
+ webhook_url=webhook_url,
81
+ required=required,
82
+ **swaig_fields
83
+ )
84
+
85
+ logger.debug(f"Defined tool: {name}")
86
+
87
+ def register_swaig_function(self, function_dict: Dict[str, Any]) -> None:
88
+ """
89
+ Register a raw SWAIG function dictionary (e.g., from DataMap.to_swaig_function()).
90
+
91
+ Args:
92
+ function_dict: Complete SWAIG function definition dictionary
93
+
94
+ Raises:
95
+ ValueError: If function name missing or already exists
96
+ """
97
+ function_name = function_dict.get('function')
98
+ if not function_name:
99
+ raise ValueError("Function dictionary must contain 'function' field with the function name")
100
+
101
+ if function_name in self._swaig_functions:
102
+ raise ValueError(f"Tool with name '{function_name}' already exists")
103
+
104
+ # Store the raw function dictionary for data_map tools
105
+ # These don't have handlers since they execute on SignalWire's server
106
+ self._swaig_functions[function_name] = function_dict
107
+
108
+ # Debug logging using the module logger with proper format
109
+ logger.debug(f"Registered SWAIG function in registry: {function_name} (registry_id={id(self)}, agent_id={id(self.agent) if hasattr(self, 'agent') else None}, total_functions={len(self._swaig_functions)})")
110
+
111
+ logger.debug(f"Registered SWAIG function: {function_name}")
112
+
113
+ def register_class_decorated_tools(self) -> None:
114
+ """
115
+ Register tools defined with @AgentBase.tool class decorator.
116
+
117
+ This method scans the class for methods decorated with @AgentBase.tool
118
+ and registers them automatically.
119
+ """
120
+ # Get the class of this instance
121
+ cls = self.agent.__class__
122
+
123
+ # Loop through all attributes in the class
124
+ for name in dir(cls):
125
+ # Get the attribute
126
+ attr = getattr(cls, name)
127
+
128
+ # Check if it's a method decorated with @AgentBase.tool
129
+ if inspect.ismethod(attr) or inspect.isfunction(attr):
130
+ if hasattr(attr, "_is_tool") and getattr(attr, "_is_tool", False):
131
+ # Extract tool information
132
+ tool_name = getattr(attr, "_tool_name", name)
133
+ tool_params = getattr(attr, "_tool_params", {})
134
+
135
+ # Extract known parameters and pass through the rest as swaig_fields
136
+ tool_params_copy = tool_params.copy()
137
+ description = tool_params_copy.pop("description", attr.__doc__ or f"Function {tool_name}")
138
+ parameters = tool_params_copy.pop("parameters", {})
139
+ secure = tool_params_copy.pop("secure", True)
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)
143
+ webhook_url = tool_params_copy.pop("webhook_url", None)
144
+ required = tool_params_copy.pop("required", None)
145
+
146
+ # Register the tool with any remaining params as swaig_fields
147
+ self.define_tool(
148
+ name=tool_name,
149
+ description=description,
150
+ parameters=parameters,
151
+ handler=attr.__get__(self.agent, cls), # Bind the method to this instance
152
+ secure=secure,
153
+ fillers=fillers,
154
+ wait_file=wait_file,
155
+ wait_file_loops=wait_file_loops,
156
+ webhook_url=webhook_url,
157
+ required=required,
158
+ **tool_params_copy # Pass through any additional swaig_fields
159
+ )
160
+
161
+ logger.debug(f"Registered class-decorated tool: {tool_name}")
162
+
163
+ def get_function(self, name: str) -> Optional[Union[SWAIGFunction, Dict[str, Any]]]:
164
+ """
165
+ Get a registered function by name.
166
+
167
+ Args:
168
+ name: Function name
169
+
170
+ Returns:
171
+ SWAIGFunction instance or raw function dict, or None if not found
172
+ """
173
+ return self._swaig_functions.get(name)
174
+
175
+ def get_all_functions(self) -> Dict[str, Union[SWAIGFunction, Dict[str, Any]]]:
176
+ """
177
+ Get all registered functions.
178
+
179
+ Returns:
180
+ Dictionary of function name to function object/dict
181
+ """
182
+ return self._swaig_functions.copy()
183
+
184
+ def has_function(self, name: str) -> bool:
185
+ """
186
+ Check if a function is registered.
187
+
188
+ Args:
189
+ name: Function name
190
+
191
+ Returns:
192
+ True if function exists, False otherwise
193
+ """
194
+ return name in self._swaig_functions
195
+
196
+ def remove_function(self, name: str) -> bool:
197
+ """
198
+ Remove a registered function.
199
+
200
+ Args:
201
+ name: Function name
202
+
203
+ Returns:
204
+ True if removed, False if not found
205
+ """
206
+ if name in self._swaig_functions:
207
+ del self._swaig_functions[name]
208
+ logger.debug(f"Removed function: {name}")
209
+ return True
210
+ return False