signalwire-agents 0.1.6__py3-none-any.whl → 1.0.7__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 (140) hide show
  1. signalwire_agents/__init__.py +130 -4
  2. signalwire_agents/agent_server.py +438 -32
  3. signalwire_agents/agents/bedrock.py +296 -0
  4. signalwire_agents/cli/__init__.py +18 -0
  5. signalwire_agents/cli/build_search.py +1367 -0
  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/execution/__init__.py +10 -0
  13. signalwire_agents/cli/execution/datamap_exec.py +446 -0
  14. signalwire_agents/cli/execution/webhook_exec.py +134 -0
  15. signalwire_agents/cli/init_project.py +1225 -0
  16. signalwire_agents/cli/output/__init__.py +10 -0
  17. signalwire_agents/cli/output/output_formatter.py +255 -0
  18. signalwire_agents/cli/output/swml_dump.py +186 -0
  19. signalwire_agents/cli/simulation/__init__.py +10 -0
  20. signalwire_agents/cli/simulation/data_generation.py +374 -0
  21. signalwire_agents/cli/simulation/data_overrides.py +200 -0
  22. signalwire_agents/cli/simulation/mock_env.py +282 -0
  23. signalwire_agents/cli/swaig_test_wrapper.py +52 -0
  24. signalwire_agents/cli/test_swaig.py +809 -0
  25. signalwire_agents/cli/types.py +81 -0
  26. signalwire_agents/core/__init__.py +2 -2
  27. signalwire_agents/core/agent/__init__.py +12 -0
  28. signalwire_agents/core/agent/config/__init__.py +12 -0
  29. signalwire_agents/core/agent/deployment/__init__.py +9 -0
  30. signalwire_agents/core/agent/deployment/handlers/__init__.py +9 -0
  31. signalwire_agents/core/agent/prompt/__init__.py +14 -0
  32. signalwire_agents/core/agent/prompt/manager.py +306 -0
  33. signalwire_agents/core/agent/routing/__init__.py +9 -0
  34. signalwire_agents/core/agent/security/__init__.py +9 -0
  35. signalwire_agents/core/agent/swml/__init__.py +9 -0
  36. signalwire_agents/core/agent/tools/__init__.py +15 -0
  37. signalwire_agents/core/agent/tools/decorator.py +97 -0
  38. signalwire_agents/core/agent/tools/registry.py +210 -0
  39. signalwire_agents/core/agent_base.py +959 -2166
  40. signalwire_agents/core/auth_handler.py +233 -0
  41. signalwire_agents/core/config_loader.py +259 -0
  42. signalwire_agents/core/contexts.py +707 -0
  43. signalwire_agents/core/data_map.py +487 -0
  44. signalwire_agents/core/function_result.py +1150 -1
  45. signalwire_agents/core/logging_config.py +376 -0
  46. signalwire_agents/core/mixins/__init__.py +28 -0
  47. signalwire_agents/core/mixins/ai_config_mixin.py +442 -0
  48. signalwire_agents/core/mixins/auth_mixin.py +287 -0
  49. signalwire_agents/core/mixins/prompt_mixin.py +358 -0
  50. signalwire_agents/core/mixins/serverless_mixin.py +368 -0
  51. signalwire_agents/core/mixins/skill_mixin.py +55 -0
  52. signalwire_agents/core/mixins/state_mixin.py +153 -0
  53. signalwire_agents/core/mixins/tool_mixin.py +230 -0
  54. signalwire_agents/core/mixins/web_mixin.py +1134 -0
  55. signalwire_agents/core/security/session_manager.py +174 -86
  56. signalwire_agents/core/security_config.py +333 -0
  57. signalwire_agents/core/skill_base.py +200 -0
  58. signalwire_agents/core/skill_manager.py +244 -0
  59. signalwire_agents/core/swaig_function.py +33 -9
  60. signalwire_agents/core/swml_builder.py +212 -12
  61. signalwire_agents/core/swml_handler.py +43 -13
  62. signalwire_agents/core/swml_renderer.py +123 -297
  63. signalwire_agents/core/swml_service.py +277 -260
  64. signalwire_agents/prefabs/concierge.py +6 -2
  65. signalwire_agents/prefabs/info_gatherer.py +149 -33
  66. signalwire_agents/prefabs/receptionist.py +14 -22
  67. signalwire_agents/prefabs/survey.py +6 -2
  68. signalwire_agents/schema.json +9218 -5489
  69. signalwire_agents/search/__init__.py +137 -0
  70. signalwire_agents/search/document_processor.py +1223 -0
  71. signalwire_agents/search/index_builder.py +804 -0
  72. signalwire_agents/search/migration.py +418 -0
  73. signalwire_agents/search/models.py +30 -0
  74. signalwire_agents/search/pgvector_backend.py +752 -0
  75. signalwire_agents/search/query_processor.py +502 -0
  76. signalwire_agents/search/search_engine.py +1264 -0
  77. signalwire_agents/search/search_service.py +574 -0
  78. signalwire_agents/skills/README.md +452 -0
  79. signalwire_agents/skills/__init__.py +23 -0
  80. signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
  81. signalwire_agents/skills/api_ninjas_trivia/__init__.py +12 -0
  82. signalwire_agents/skills/api_ninjas_trivia/skill.py +237 -0
  83. signalwire_agents/skills/datasphere/README.md +210 -0
  84. signalwire_agents/skills/datasphere/__init__.py +12 -0
  85. signalwire_agents/skills/datasphere/skill.py +310 -0
  86. signalwire_agents/skills/datasphere_serverless/README.md +258 -0
  87. signalwire_agents/skills/datasphere_serverless/__init__.py +10 -0
  88. signalwire_agents/skills/datasphere_serverless/skill.py +237 -0
  89. signalwire_agents/skills/datetime/README.md +132 -0
  90. signalwire_agents/skills/datetime/__init__.py +10 -0
  91. signalwire_agents/skills/datetime/skill.py +126 -0
  92. signalwire_agents/skills/joke/README.md +149 -0
  93. signalwire_agents/skills/joke/__init__.py +10 -0
  94. signalwire_agents/skills/joke/skill.py +109 -0
  95. signalwire_agents/skills/math/README.md +161 -0
  96. signalwire_agents/skills/math/__init__.py +10 -0
  97. signalwire_agents/skills/math/skill.py +105 -0
  98. signalwire_agents/skills/mcp_gateway/README.md +230 -0
  99. signalwire_agents/skills/mcp_gateway/__init__.py +10 -0
  100. signalwire_agents/skills/mcp_gateway/skill.py +421 -0
  101. signalwire_agents/skills/native_vector_search/README.md +210 -0
  102. signalwire_agents/skills/native_vector_search/__init__.py +10 -0
  103. signalwire_agents/skills/native_vector_search/skill.py +820 -0
  104. signalwire_agents/skills/play_background_file/README.md +218 -0
  105. signalwire_agents/skills/play_background_file/__init__.py +12 -0
  106. signalwire_agents/skills/play_background_file/skill.py +242 -0
  107. signalwire_agents/skills/registry.py +459 -0
  108. signalwire_agents/skills/spider/README.md +236 -0
  109. signalwire_agents/skills/spider/__init__.py +13 -0
  110. signalwire_agents/skills/spider/skill.py +598 -0
  111. signalwire_agents/skills/swml_transfer/README.md +395 -0
  112. signalwire_agents/skills/swml_transfer/__init__.py +10 -0
  113. signalwire_agents/skills/swml_transfer/skill.py +359 -0
  114. signalwire_agents/skills/weather_api/README.md +178 -0
  115. signalwire_agents/skills/weather_api/__init__.py +12 -0
  116. signalwire_agents/skills/weather_api/skill.py +191 -0
  117. signalwire_agents/skills/web_search/README.md +163 -0
  118. signalwire_agents/skills/web_search/__init__.py +10 -0
  119. signalwire_agents/skills/web_search/skill.py +739 -0
  120. signalwire_agents/skills/wikipedia_search/README.md +228 -0
  121. signalwire_agents/{core/state → skills/wikipedia_search}/__init__.py +5 -4
  122. signalwire_agents/skills/wikipedia_search/skill.py +210 -0
  123. signalwire_agents/utils/__init__.py +14 -0
  124. signalwire_agents/utils/schema_utils.py +111 -44
  125. signalwire_agents/web/__init__.py +17 -0
  126. signalwire_agents/web/web_service.py +559 -0
  127. signalwire_agents-1.0.7.data/data/share/man/man1/sw-agent-init.1 +307 -0
  128. signalwire_agents-1.0.7.data/data/share/man/man1/sw-search.1 +483 -0
  129. signalwire_agents-1.0.7.data/data/share/man/man1/swaig-test.1 +308 -0
  130. signalwire_agents-1.0.7.dist-info/METADATA +992 -0
  131. signalwire_agents-1.0.7.dist-info/RECORD +142 -0
  132. {signalwire_agents-0.1.6.dist-info → signalwire_agents-1.0.7.dist-info}/WHEEL +1 -1
  133. signalwire_agents-1.0.7.dist-info/entry_points.txt +4 -0
  134. signalwire_agents/core/state/file_state_manager.py +0 -219
  135. signalwire_agents/core/state/state_manager.py +0 -101
  136. signalwire_agents-0.1.6.data/data/schema.json +0 -5611
  137. signalwire_agents-0.1.6.dist-info/METADATA +0 -199
  138. signalwire_agents-0.1.6.dist-info/RECORD +0 -34
  139. {signalwire_agents-0.1.6.dist-info → signalwire_agents-1.0.7.dist-info}/licenses/LICENSE +0 -0
  140. {signalwire_agents-0.1.6.dist-info → signalwire_agents-1.0.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,376 @@
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
+ Central logging configuration for SignalWire Agents SDK
12
+
13
+ This module provides a single point of control for all logging across the SDK
14
+ and applications built with it. All components should use get_logger() instead
15
+ of direct logging module usage or print() statements.
16
+
17
+ The StructuredLoggerWrapper provides backward compatibility with existing
18
+ structured logging calls (e.g., log.info("message", key=value)) while using
19
+ standard Python logging underneath. This allows the entire codebase to work
20
+ without changes while providing centralized logging control.
21
+ """
22
+
23
+ import logging
24
+ import os
25
+ import sys
26
+ from typing import Optional, Any, Dict
27
+
28
+ # Global flag to ensure configuration only happens once
29
+ _logging_configured = False
30
+
31
+
32
+ class StructuredLoggerWrapper:
33
+ """
34
+ A wrapper that provides structured logging interface while using standard Python logging
35
+
36
+ This allows existing structured logging calls to work without changes while
37
+ giving us centralized control over logging behavior.
38
+ """
39
+
40
+ def __init__(self, logger: logging.Logger):
41
+ self._logger = logger
42
+
43
+ def _format_structured_message(self, message: str, **kwargs) -> str:
44
+ """Format a message with structured keyword arguments"""
45
+ if not kwargs:
46
+ return message
47
+
48
+ # Convert kwargs to readable string format
49
+ parts = []
50
+ for key, value in kwargs.items():
51
+ # Handle different value types appropriately
52
+ if isinstance(value, str):
53
+ parts.append(f"{key}={value}")
54
+ elif isinstance(value, (list, dict)):
55
+ parts.append(f"{key}={str(value)}")
56
+ else:
57
+ parts.append(f"{key}={value}")
58
+
59
+ if parts:
60
+ return f"{message} ({', '.join(parts)})"
61
+ else:
62
+ return message
63
+
64
+ def debug(self, message: str, **kwargs) -> None:
65
+ """Log debug message with optional structured data"""
66
+ formatted = self._format_structured_message(message, **kwargs)
67
+ self._logger.debug(formatted)
68
+
69
+ def info(self, message: str, **kwargs) -> None:
70
+ """Log info message with optional structured data"""
71
+ formatted = self._format_structured_message(message, **kwargs)
72
+ self._logger.info(formatted)
73
+
74
+ def warning(self, message: str, **kwargs) -> None:
75
+ """Log warning message with optional structured data"""
76
+ formatted = self._format_structured_message(message, **kwargs)
77
+ self._logger.warning(formatted)
78
+
79
+ def error(self, message: str, **kwargs) -> None:
80
+ """Log error message with optional structured data"""
81
+ formatted = self._format_structured_message(message, **kwargs)
82
+ self._logger.error(formatted)
83
+
84
+ def critical(self, message: str, **kwargs) -> None:
85
+ """Log critical message with optional structured data"""
86
+ formatted = self._format_structured_message(message, **kwargs)
87
+ self._logger.critical(formatted)
88
+
89
+ # Also support the 'warn' alias
90
+ warn = warning
91
+
92
+ def bind(self, **kwargs) -> 'StructuredLoggerWrapper':
93
+ """
94
+ Create a new logger instance with bound context data
95
+
96
+ This maintains compatibility with structlog's bind() method.
97
+ The bound data will be included in all subsequent log messages.
98
+ """
99
+ # Create a new wrapper that includes the bound context
100
+ return BoundStructuredLoggerWrapper(self._logger, kwargs)
101
+
102
+ # Support direct access to underlying logger attributes if needed
103
+ def __getattr__(self, name: str) -> Any:
104
+ """Delegate any unknown attributes to the underlying logger"""
105
+ return getattr(self._logger, name)
106
+
107
+
108
+ class BoundStructuredLoggerWrapper(StructuredLoggerWrapper):
109
+ """
110
+ A structured logger wrapper that includes bound context data in all messages
111
+ """
112
+
113
+ def __init__(self, logger: logging.Logger, bound_data: Dict[str, Any]):
114
+ super().__init__(logger)
115
+ self._bound_data = bound_data
116
+
117
+ def _format_structured_message(self, message: str, **kwargs) -> str:
118
+ """Format a message with both bound data and additional keyword arguments"""
119
+ # Combine bound data with additional kwargs
120
+ all_kwargs = {**self._bound_data, **kwargs}
121
+ return super()._format_structured_message(message, **all_kwargs)
122
+
123
+ def bind(self, **kwargs) -> 'BoundStructuredLoggerWrapper':
124
+ """Create a new logger with additional bound context"""
125
+ # Combine existing bound data with new data
126
+ new_bound_data = {**self._bound_data, **kwargs}
127
+ return BoundStructuredLoggerWrapper(self._logger, new_bound_data)
128
+
129
+
130
+ def get_execution_mode():
131
+ """
132
+ Determine the execution mode based on environment variables
133
+
134
+ Returns:
135
+ str: 'server', 'cgi', 'lambda', 'google_cloud_function', 'azure_function', or 'unknown'
136
+ """
137
+ # Check for CGI environment
138
+ if os.getenv('GATEWAY_INTERFACE'):
139
+ return 'cgi'
140
+
141
+ # Check for AWS Lambda environment
142
+ if os.getenv('AWS_LAMBDA_FUNCTION_NAME') or os.getenv('LAMBDA_TASK_ROOT'):
143
+ return 'lambda'
144
+
145
+ # Check for Google Cloud Functions environment
146
+ if (os.getenv('FUNCTION_TARGET') or
147
+ os.getenv('K_SERVICE') or
148
+ os.getenv('GOOGLE_CLOUD_PROJECT')):
149
+ return 'google_cloud_function'
150
+
151
+ # Check for Azure Functions environment
152
+ if (os.getenv('AZURE_FUNCTIONS_ENVIRONMENT') or
153
+ os.getenv('FUNCTIONS_WORKER_RUNTIME') or
154
+ os.getenv('AzureWebJobsStorage')):
155
+ return 'azure_function'
156
+
157
+ # Default to server mode
158
+ return 'server'
159
+
160
+
161
+ def reset_logging_configuration():
162
+ """
163
+ Reset the logging configuration flag to allow reconfiguration
164
+
165
+ This is useful when environment variables change after initial configuration.
166
+ """
167
+ global _logging_configured
168
+ _logging_configured = False
169
+
170
+
171
+ def configure_logging():
172
+ """
173
+ Configure logging system once, globally, based on environment variables
174
+
175
+ Environment Variables:
176
+ SIGNALWIRE_LOG_MODE: off, stderr, default, auto
177
+ SIGNALWIRE_LOG_LEVEL: debug, info, warning, error, critical
178
+ """
179
+ global _logging_configured
180
+
181
+ if _logging_configured:
182
+ return
183
+
184
+ # Get configuration from environment
185
+ log_mode = os.getenv('SIGNALWIRE_LOG_MODE', '').lower()
186
+ log_level = os.getenv('SIGNALWIRE_LOG_LEVEL', 'info').lower()
187
+
188
+ # Determine log mode if auto or not specified
189
+ if not log_mode or log_mode == 'auto':
190
+ execution_mode = get_execution_mode()
191
+ if execution_mode == 'cgi':
192
+ log_mode = 'off'
193
+ else:
194
+ log_mode = 'default'
195
+
196
+ # Configure based on mode
197
+ if log_mode == 'off':
198
+ _configure_off_mode()
199
+ elif log_mode == 'stderr':
200
+ _configure_stderr_mode(log_level)
201
+ else: # default mode
202
+ _configure_default_mode(log_level)
203
+
204
+ _logging_configured = True
205
+
206
+
207
+ def _configure_off_mode():
208
+ """Suppress all logging output"""
209
+ # Redirect to devnull
210
+ null_file = open(os.devnull, 'w')
211
+
212
+ # Clear existing handlers and configure to devnull
213
+ logging.getLogger().handlers.clear()
214
+ logging.basicConfig(
215
+ stream=null_file,
216
+ level=logging.CRITICAL,
217
+ format=''
218
+ )
219
+
220
+ # Set all known loggers to CRITICAL to prevent any output
221
+ logger_names = [
222
+ '', 'signalwire_agents', 'skill_registry', 'swml_service',
223
+ 'agent_base', 'AgentServer', 'uvicorn', 'fastapi'
224
+ ]
225
+ for name in logger_names:
226
+ logging.getLogger(name).setLevel(logging.CRITICAL)
227
+
228
+ # Configure structlog if available
229
+ try:
230
+ import structlog
231
+ structlog.configure(
232
+ processors=[],
233
+ wrapper_class=structlog.make_filtering_bound_logger(logging.CRITICAL),
234
+ logger_factory=structlog.PrintLoggerFactory(file=null_file),
235
+ cache_logger_on_first_use=True,
236
+ )
237
+ except ImportError:
238
+ pass
239
+
240
+
241
+ def _configure_stderr_mode(log_level: str):
242
+ """Configure logging to stderr with colored formatting"""
243
+ # Clear existing handlers
244
+ logging.getLogger().handlers.clear()
245
+
246
+ # Convert log level
247
+ numeric_level = getattr(logging, log_level.upper(), logging.INFO)
248
+
249
+ # Create handler with colored formatter
250
+ handler = logging.StreamHandler(sys.stderr)
251
+ handler.setFormatter(ColoredFormatter())
252
+
253
+ # Configure root logger
254
+ root_logger = logging.getLogger()
255
+ root_logger.setLevel(numeric_level)
256
+ root_logger.addHandler(handler)
257
+
258
+
259
+ def _configure_default_mode(log_level: str):
260
+ """Configure standard logging behavior with colored formatting"""
261
+ # Clear existing handlers
262
+ logging.getLogger().handlers.clear()
263
+
264
+ # Convert log level
265
+ numeric_level = getattr(logging, log_level.upper(), logging.INFO)
266
+
267
+ # Create handler with colored formatter
268
+ handler = logging.StreamHandler()
269
+ handler.setFormatter(ColoredFormatter())
270
+
271
+ # Configure root logger
272
+ root_logger = logging.getLogger()
273
+ root_logger.setLevel(numeric_level)
274
+ root_logger.addHandler(handler)
275
+
276
+
277
+ def get_logger(name: str) -> StructuredLoggerWrapper:
278
+ """
279
+ Get a logger instance for the specified name with structured logging support
280
+
281
+ This is the single entry point for all logging in the SDK.
282
+ All modules should use this instead of direct logging module usage.
283
+
284
+ Args:
285
+ name: Logger name, typically __name__
286
+
287
+ Returns:
288
+ StructuredLoggerWrapper that supports both regular and structured logging
289
+ """
290
+ # Ensure logging is configured
291
+ configure_logging()
292
+
293
+ # Get the standard Python logger
294
+ python_logger = logging.getLogger(name)
295
+
296
+ # Wrap it with our structured logging interface
297
+ return StructuredLoggerWrapper(python_logger)
298
+
299
+
300
+ class ColoredFormatter(logging.Formatter):
301
+ """
302
+ A beautiful colored logging formatter that makes logs easy to read and visually appealing
303
+ """
304
+
305
+ # ANSI color codes
306
+ COLORS = {
307
+ 'DEBUG': '\033[36m', # Cyan
308
+ 'INFO': '\033[32m', # Green
309
+ 'WARNING': '\033[33m', # Yellow
310
+ 'ERROR': '\033[31m', # Red
311
+ 'CRITICAL': '\033[35m', # Magenta
312
+ 'RESET': '\033[0m', # Reset
313
+ 'BOLD': '\033[1m', # Bold
314
+ 'DIM': '\033[2m', # Dim
315
+ 'WHITE': '\033[37m', # White
316
+ 'BLUE': '\033[34m', # Blue
317
+ 'BLACK': '\033[30m', # Black (for brackets)
318
+ }
319
+
320
+ def __init__(self):
321
+ super().__init__()
322
+
323
+ def format(self, record):
324
+ # Check if we should use colors (not in raw mode, and stdout is a tty)
325
+ use_colors = (
326
+ hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() and
327
+ os.getenv('SIGNALWIRE_LOG_MODE') != 'off' and
328
+ '--raw' not in sys.argv and '--dump-swml' not in sys.argv
329
+ )
330
+
331
+ if use_colors:
332
+ # Get colors
333
+ level_color = self.COLORS.get(record.levelname, self.COLORS['WHITE'])
334
+ reset = self.COLORS['RESET']
335
+ dim = self.COLORS['DIM']
336
+ bold = self.COLORS['BOLD']
337
+ blue = self.COLORS['BLUE']
338
+ black = self.COLORS['BLACK']
339
+
340
+ # Format timestamp in a compact, readable way
341
+ timestamp = self.formatTime(record, '%H:%M:%S')
342
+
343
+ # Format level with appropriate color and consistent width
344
+ level_name = f"{level_color}{record.levelname:<8}{reset}"
345
+
346
+ # Format logger name - keep it short and readable
347
+ logger_name = record.name
348
+ if len(logger_name) > 15:
349
+ # Truncate long logger names but keep the end (most specific part)
350
+ logger_name = "..." + logger_name[-12:]
351
+
352
+ # Get function and line info if available
353
+ func_info = ""
354
+ if hasattr(record, 'funcName') and hasattr(record, 'lineno'):
355
+ func_name = getattr(record, 'funcName', '')
356
+ line_no = getattr(record, 'lineno', 0)
357
+ if func_name and func_name != '<module>':
358
+ func_info = f" {dim}({func_name}:{line_no}){reset}"
359
+
360
+ # Format the message
361
+ message = record.getMessage()
362
+
363
+ # Create the final formatted message with a clean, readable layout
364
+ formatted = (
365
+ f"{black}[{reset}{dim}{timestamp}{reset}{black}]{reset} "
366
+ f"{level_name} "
367
+ f"{blue}{logger_name:<15}{reset}"
368
+ f"{func_info} "
369
+ f"{message}"
370
+ )
371
+
372
+ return formatted
373
+ else:
374
+ # Non-colored format (fallback for files, pipes, etc.)
375
+ timestamp = self.formatTime(record, '%Y-%m-%d %H:%M:%S')
376
+ return f"{timestamp} {record.levelname:<8} {record.name} {record.getMessage()}"
@@ -0,0 +1,28 @@
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
+ from .prompt_mixin import PromptMixin
11
+ from .tool_mixin import ToolMixin
12
+ from .web_mixin import WebMixin
13
+ from .auth_mixin import AuthMixin
14
+ from .skill_mixin import SkillMixin
15
+ from .ai_config_mixin import AIConfigMixin
16
+ from .serverless_mixin import ServerlessMixin
17
+ from .state_mixin import StateMixin
18
+
19
+ __all__ = [
20
+ 'PromptMixin',
21
+ 'ToolMixin',
22
+ 'WebMixin',
23
+ 'AuthMixin',
24
+ 'SkillMixin',
25
+ 'AIConfigMixin',
26
+ 'ServerlessMixin',
27
+ 'StateMixin'
28
+ ]