signalwire-agents 1.0.5__tar.gz → 1.0.6__tar.gz
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.
- {signalwire_agents-1.0.5/signalwire_agents.egg-info → signalwire_agents-1.0.6}/PKG-INFO +1 -1
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/pyproject.toml +1 -1
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/__init__.py +1 -1
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent_base.py +4 -3
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6/signalwire_agents.egg-info}/PKG-INFO +1 -1
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/SOURCES.txt +2 -1
- signalwire_agents-1.0.6/tests/test_examples.py +510 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/LICENSE +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/setup.cfg +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/setup.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/agent_server.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/agents/bedrock.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/build_search.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/config.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/agent_loader.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/argparse_helpers.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/dynamic_config.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/service_loader.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/execution/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/execution/datamap_exec.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/execution/webhook_exec.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/output/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/output/output_formatter.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/output/swml_dump.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/simulation/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/simulation/data_generation.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/simulation/data_overrides.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/simulation/mock_env.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/swaig_test_wrapper.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/test_swaig.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/types.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/config/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/deployment/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/deployment/handlers/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/prompt/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/prompt/manager.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/routing/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/security/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/swml/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/tools/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/tools/decorator.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/tools/registry.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/auth_handler.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/config_loader.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/contexts.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/data_map.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/function_result.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/logging_config.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/ai_config_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/auth_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/prompt_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/serverless_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/skill_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/state_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/tool_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/web_mixin.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/pom_builder.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/security/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/security/session_manager.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/security_config.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/skill_base.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/skill_manager.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/swaig_function.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/swml_builder.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/swml_handler.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/swml_renderer.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/swml_service.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/concierge.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/faq_bot.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/info_gatherer.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/receptionist.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/survey.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/schema.json +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/document_processor.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/index_builder.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/migration.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/models.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/pgvector_backend.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/query_processor.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/search_engine.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/search_service.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/api_ninjas_trivia/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/api_ninjas_trivia/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/api_ninjas_trivia/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere_serverless/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere_serverless/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere_serverless/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datetime/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datetime/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datetime/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/joke/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/joke/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/joke/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/math/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/math/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/math/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/mcp_gateway/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/mcp_gateway/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/mcp_gateway/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/native_vector_search/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/native_vector_search/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/native_vector_search/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/play_background_file/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/play_background_file/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/play_background_file/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/registry.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/spider/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/spider/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/spider/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/swml_transfer/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/swml_transfer/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/swml_transfer/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/weather_api/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/weather_api/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/weather_api/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/web_search/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/web_search/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/web_search/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/wikipedia_search/README.md +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/wikipedia_search/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/wikipedia_search/skill.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/utils/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/utils/pom_utils.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/utils/schema_utils.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/utils/token_generators.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/utils/validators.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/web/__init__.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/web/web_service.py +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/dependency_links.txt +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/entry_points.txt +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/requires.txt +0 -0
- {signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/top_level.txt +0 -0
|
@@ -18,7 +18,7 @@ A package for building AI agents using SignalWire's AI and SWML capabilities.
|
|
|
18
18
|
from .core.logging_config import configure_logging
|
|
19
19
|
configure_logging()
|
|
20
20
|
|
|
21
|
-
__version__ = "1.0.
|
|
21
|
+
__version__ = "1.0.6"
|
|
22
22
|
|
|
23
23
|
# Import core classes for easier access
|
|
24
24
|
from .core.agent_base import AgentBase
|
|
@@ -1231,9 +1231,10 @@ class AgentBase(
|
|
|
1231
1231
|
if hasattr(self, '_internal_fillers'):
|
|
1232
1232
|
ephemeral_agent._internal_fillers = copy.deepcopy(self._internal_fillers)
|
|
1233
1233
|
|
|
1234
|
-
#
|
|
1235
|
-
|
|
1236
|
-
|
|
1234
|
+
# Don't deep copy _contexts_builder - it has a circular reference to the agent
|
|
1235
|
+
# The contexts are already copied via _prompt_manager._contexts (below)
|
|
1236
|
+
# Just copy the flag indicating contexts are defined
|
|
1237
|
+
if hasattr(self, '_contexts_defined'):
|
|
1237
1238
|
ephemeral_agent._contexts_defined = self._contexts_defined
|
|
1238
1239
|
|
|
1239
1240
|
# Deep copy the POM object if it exists to prevent sharing prompt sections
|
|
@@ -139,4 +139,5 @@ signalwire_agents/utils/schema_utils.py
|
|
|
139
139
|
signalwire_agents/utils/token_generators.py
|
|
140
140
|
signalwire_agents/utils/validators.py
|
|
141
141
|
signalwire_agents/web/__init__.py
|
|
142
|
-
signalwire_agents/web/web_service.py
|
|
142
|
+
signalwire_agents/web/web_service.py
|
|
143
|
+
tests/test_examples.py
|
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test suite for all examples in the examples/ directory.
|
|
4
|
+
|
|
5
|
+
This test suite verifies that all example files:
|
|
6
|
+
1. Can be loaded without import errors
|
|
7
|
+
2. Generate valid SWML output
|
|
8
|
+
3. Have properly defined tools/functions
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
pytest tests/test_examples.py -v
|
|
12
|
+
pytest tests/test_examples.py -v -k "test_agent"
|
|
13
|
+
pytest tests/test_examples.py -v --tb=short
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import subprocess
|
|
17
|
+
import json
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import pytest
|
|
22
|
+
|
|
23
|
+
# Get the examples directory
|
|
24
|
+
REPO_ROOT = Path(__file__).parent.parent
|
|
25
|
+
EXAMPLES_DIR = REPO_ROOT / "examples"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def run_swaig_test(agent_path: Path, *args, timeout: int = 30) -> tuple:
|
|
29
|
+
"""
|
|
30
|
+
Run swaig-test on an agent file and return (returncode, stdout, stderr).
|
|
31
|
+
"""
|
|
32
|
+
cmd = [sys.executable, "-m", "signalwire_agents.cli.swaig_test_wrapper", str(agent_path)] + list(args)
|
|
33
|
+
try:
|
|
34
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
|
35
|
+
return result.returncode, result.stdout, result.stderr
|
|
36
|
+
except subprocess.TimeoutExpired:
|
|
37
|
+
return -1, "", "Timeout expired"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_swml_json(agent_path: Path) -> dict:
|
|
41
|
+
"""
|
|
42
|
+
Get SWML JSON output from an agent file.
|
|
43
|
+
"""
|
|
44
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--dump-swml", "--raw")
|
|
45
|
+
if returncode != 0:
|
|
46
|
+
pytest.fail(f"swaig-test failed for {agent_path}:\nstderr: {stderr}\nstdout: {stdout}")
|
|
47
|
+
try:
|
|
48
|
+
return json.loads(stdout)
|
|
49
|
+
except json.JSONDecodeError as e:
|
|
50
|
+
pytest.fail(f"Invalid JSON from {agent_path}: {e}\nOutput: {stdout}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def list_tools(agent_path: Path) -> list:
|
|
54
|
+
"""
|
|
55
|
+
List tools available in an agent.
|
|
56
|
+
"""
|
|
57
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
58
|
+
if returncode != 0:
|
|
59
|
+
return []
|
|
60
|
+
tools = []
|
|
61
|
+
for line in stdout.split('\n'):
|
|
62
|
+
line = line.strip()
|
|
63
|
+
if ' - ' in line and not line.startswith('Parameters:'):
|
|
64
|
+
parts = line.split(' - ')
|
|
65
|
+
if parts:
|
|
66
|
+
tool_name = parts[0].strip()
|
|
67
|
+
if tool_name and not tool_name.startswith('('):
|
|
68
|
+
tools.append(tool_name)
|
|
69
|
+
return tools
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# Examples that require API keys or special environment variables
|
|
73
|
+
EXAMPLES_REQUIRING_CREDENTIALS = {
|
|
74
|
+
"joke_agent.py": "API_NINJAS_KEY",
|
|
75
|
+
"joke_skill_demo.py": "API_NINJAS_KEY",
|
|
76
|
+
"web_search_agent.py": "GOOGLE_SEARCH_API_KEY",
|
|
77
|
+
"datasphere_serverless_env_demo.py": "SIGNALWIRE_SPACE_NAME",
|
|
78
|
+
"datasphere_webhook_env_demo.py": "SIGNALWIRE_SPACE_NAME",
|
|
79
|
+
"env_auth_simple.py": "SWML_BASIC_AUTH_USER",
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Examples that are not standard agents (demos, tests, interactive)
|
|
83
|
+
NON_STANDARD_EXAMPLES = {
|
|
84
|
+
"swml_service_example.py", # Interactive menu
|
|
85
|
+
"basic_swml_service.py", # Has its own CLI
|
|
86
|
+
"dynamic_swml_service.py", # Has its own CLI
|
|
87
|
+
"auto_vivified_example.py", # Has its own CLI
|
|
88
|
+
"record_call_example.py", # Demo structure
|
|
89
|
+
"room_and_sip_example.py", # Demo structure
|
|
90
|
+
"tap_example.py", # Demo structure
|
|
91
|
+
"advanced_datamap_demo.py", # Demo structure
|
|
92
|
+
"search_server_standalone.py", # Not an agent
|
|
93
|
+
"test_lambda_handler.py", # Test file
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Examples requiring optional dependencies
|
|
97
|
+
EXAMPLES_REQUIRING_DEPS = {
|
|
98
|
+
"lambda_agent.py": "mangum",
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class TestBasicAgentExamples:
|
|
103
|
+
"""Test basic agent examples that should load cleanly."""
|
|
104
|
+
|
|
105
|
+
@pytest.mark.parametrize("agent_file", [
|
|
106
|
+
"simple_agent.py",
|
|
107
|
+
"simple_static_agent.py",
|
|
108
|
+
"simple_dynamic_agent.py",
|
|
109
|
+
"simple_dynamic_enhanced.py",
|
|
110
|
+
"declarative_agent.py",
|
|
111
|
+
"faq_bot_agent.py",
|
|
112
|
+
])
|
|
113
|
+
def test_basic_agents_load(self, agent_file):
|
|
114
|
+
"""Test basic agent examples can be loaded."""
|
|
115
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
116
|
+
if not agent_path.exists():
|
|
117
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
118
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
119
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
120
|
+
|
|
121
|
+
@pytest.mark.parametrize("agent_file", [
|
|
122
|
+
"simple_agent.py",
|
|
123
|
+
"simple_static_agent.py",
|
|
124
|
+
"declarative_agent.py",
|
|
125
|
+
])
|
|
126
|
+
def test_basic_agents_generate_valid_swml(self, agent_file):
|
|
127
|
+
"""Test basic agents generate valid SWML."""
|
|
128
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
129
|
+
if not agent_path.exists():
|
|
130
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
131
|
+
|
|
132
|
+
swml = get_swml_json(agent_path)
|
|
133
|
+
assert "version" in swml, "SWML missing 'version'"
|
|
134
|
+
assert "sections" in swml, "SWML missing 'sections'"
|
|
135
|
+
assert "main" in swml["sections"], "SWML missing 'sections.main'"
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class TestContextsExamples:
|
|
139
|
+
"""Test context and workflow examples."""
|
|
140
|
+
|
|
141
|
+
@pytest.mark.parametrize("agent_file", [
|
|
142
|
+
"contexts_demo.py",
|
|
143
|
+
"info_gatherer_example.py",
|
|
144
|
+
"dynamic_info_gatherer_example.py",
|
|
145
|
+
])
|
|
146
|
+
def test_contexts_agents_load(self, agent_file):
|
|
147
|
+
"""Test context-based agents can be loaded."""
|
|
148
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
149
|
+
if not agent_path.exists():
|
|
150
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
151
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
152
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
153
|
+
|
|
154
|
+
def test_survey_agent_multi_class(self):
|
|
155
|
+
"""Test survey_agent_example.py with explicit agent class."""
|
|
156
|
+
agent_path = EXAMPLES_DIR / "survey_agent_example.py"
|
|
157
|
+
if not agent_path.exists():
|
|
158
|
+
pytest.skip("survey_agent_example.py not found")
|
|
159
|
+
# This file has multiple agent classes - test with specific one
|
|
160
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--agent-class", "ProductSurveyAgent", "--list-tools")
|
|
161
|
+
assert returncode == 0, f"Failed to load ProductSurveyAgent:\nstderr: {stderr}\nstdout: {stdout}"
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class TestDataMapExamples:
|
|
165
|
+
"""Test DataMap examples."""
|
|
166
|
+
|
|
167
|
+
@pytest.mark.parametrize("agent_file", [
|
|
168
|
+
"data_map_demo.py",
|
|
169
|
+
])
|
|
170
|
+
def test_datamap_agents_load(self, agent_file):
|
|
171
|
+
"""Test DataMap agents can be loaded."""
|
|
172
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
173
|
+
if not agent_path.exists():
|
|
174
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
175
|
+
if agent_file in NON_STANDARD_EXAMPLES:
|
|
176
|
+
pytest.skip(f"Skipping {agent_file} - non-standard agent structure")
|
|
177
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
178
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class TestSkillsExamples:
|
|
182
|
+
"""Test skills-related examples."""
|
|
183
|
+
|
|
184
|
+
@pytest.mark.parametrize("agent_file", [
|
|
185
|
+
"skills_demo.py",
|
|
186
|
+
"wikipedia_demo.py",
|
|
187
|
+
])
|
|
188
|
+
def test_skills_agents_load(self, agent_file):
|
|
189
|
+
"""Test skills agents can be loaded."""
|
|
190
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
191
|
+
if not agent_path.exists():
|
|
192
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
193
|
+
if agent_file in EXAMPLES_REQUIRING_CREDENTIALS:
|
|
194
|
+
pytest.skip(f"Skipping {agent_file} - requires {EXAMPLES_REQUIRING_CREDENTIALS[agent_file]}")
|
|
195
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
196
|
+
# Skills may require env vars, so we accept load failure with specific error
|
|
197
|
+
if returncode != 0:
|
|
198
|
+
# Check if it's a missing env var error (expected for some skills)
|
|
199
|
+
if "GOOGLE_SEARCH" in stderr or "API_KEY" in stderr or "env" in stderr.lower():
|
|
200
|
+
pytest.skip(f"Skipping {agent_file} - requires API keys")
|
|
201
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class TestWebSearchExamples:
|
|
205
|
+
"""Test web search examples (may require API keys)."""
|
|
206
|
+
|
|
207
|
+
@pytest.mark.parametrize("agent_file", [
|
|
208
|
+
"web_search_multi_instance_demo.py",
|
|
209
|
+
])
|
|
210
|
+
def test_web_search_agents_load(self, agent_file):
|
|
211
|
+
"""Test web search agents can be loaded (may skip if no API keys)."""
|
|
212
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
213
|
+
if not agent_path.exists():
|
|
214
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
215
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
216
|
+
if returncode != 0:
|
|
217
|
+
if "GOOGLE_SEARCH" in stderr or "API_KEY" in stderr or "GOOGLE_SEARCH" in stdout:
|
|
218
|
+
pytest.skip(f"Skipping {agent_file} - requires Google API keys")
|
|
219
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class TestDatasphereExamples:
|
|
223
|
+
"""Test Datasphere examples (may require env vars)."""
|
|
224
|
+
|
|
225
|
+
@pytest.mark.parametrize("agent_file", [
|
|
226
|
+
"datasphere_serverless_demo.py",
|
|
227
|
+
"datasphere_multi_instance_demo.py",
|
|
228
|
+
])
|
|
229
|
+
def test_datasphere_agents_load(self, agent_file):
|
|
230
|
+
"""Test Datasphere agents can be loaded (may skip if no credentials)."""
|
|
231
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
232
|
+
if not agent_path.exists():
|
|
233
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
234
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
235
|
+
if returncode != 0:
|
|
236
|
+
if "SIGNALWIRE" in stderr or "credentials" in stderr.lower() or "SIGNALWIRE" in stdout:
|
|
237
|
+
pytest.skip(f"Skipping {agent_file} - requires SignalWire credentials")
|
|
238
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class TestSWAIGFeaturesExamples:
|
|
242
|
+
"""Test SWAIG feature examples."""
|
|
243
|
+
|
|
244
|
+
@pytest.mark.parametrize("agent_file", [
|
|
245
|
+
"swaig_features_agent.py",
|
|
246
|
+
])
|
|
247
|
+
def test_swaig_features_agents_load(self, agent_file):
|
|
248
|
+
"""Test SWAIG feature agents can be loaded."""
|
|
249
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
250
|
+
if not agent_path.exists():
|
|
251
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
252
|
+
if agent_file in NON_STANDARD_EXAMPLES:
|
|
253
|
+
pytest.skip(f"Skipping {agent_file} - non-standard agent structure")
|
|
254
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
255
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class TestSWMLServiceExamples:
|
|
259
|
+
"""Test SWML service examples."""
|
|
260
|
+
|
|
261
|
+
@pytest.mark.parametrize("agent_file", [
|
|
262
|
+
"swml_service_routing_example.py",
|
|
263
|
+
])
|
|
264
|
+
def test_swml_service_agents_load(self, agent_file):
|
|
265
|
+
"""Test SWML service examples can be loaded."""
|
|
266
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
267
|
+
if not agent_path.exists():
|
|
268
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
269
|
+
if agent_file in NON_STANDARD_EXAMPLES:
|
|
270
|
+
pytest.skip(f"Skipping {agent_file} - non-standard agent structure")
|
|
271
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
272
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class TestDeploymentExamples:
|
|
276
|
+
"""Test deployment-related examples."""
|
|
277
|
+
|
|
278
|
+
@pytest.mark.parametrize("agent_file", [
|
|
279
|
+
"kubernetes_ready_agent.py",
|
|
280
|
+
"custom_path_agent.py",
|
|
281
|
+
])
|
|
282
|
+
def test_deployment_agents_load(self, agent_file):
|
|
283
|
+
"""Test deployment examples can be loaded."""
|
|
284
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
285
|
+
if not agent_path.exists():
|
|
286
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
287
|
+
if agent_file in EXAMPLES_REQUIRING_DEPS:
|
|
288
|
+
pytest.skip(f"Skipping {agent_file} - requires {EXAMPLES_REQUIRING_DEPS[agent_file]}")
|
|
289
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
290
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class TestMultiAgentExamples:
|
|
294
|
+
"""Test multi-agent examples."""
|
|
295
|
+
|
|
296
|
+
def test_multi_agent_server_load(self):
|
|
297
|
+
"""Test multi-agent server can be loaded."""
|
|
298
|
+
agent_path = EXAMPLES_DIR / "multi_agent_server.py"
|
|
299
|
+
if not agent_path.exists():
|
|
300
|
+
pytest.skip("multi_agent_server.py not found")
|
|
301
|
+
# Multi-agent files may need --agent flag
|
|
302
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-agents")
|
|
303
|
+
# Should show agents or indicate multiple agents
|
|
304
|
+
assert returncode == 0 or "multiple" in stdout.lower() or "agent" in stdout.lower(), \
|
|
305
|
+
f"Failed to list agents:\nstderr: {stderr}\nstdout: {stdout}"
|
|
306
|
+
|
|
307
|
+
def test_multi_endpoint_agent_load(self):
|
|
308
|
+
"""Test multi-endpoint agent can be loaded."""
|
|
309
|
+
agent_path = EXAMPLES_DIR / "multi_endpoint_agent.py"
|
|
310
|
+
if not agent_path.exists():
|
|
311
|
+
pytest.skip("multi_endpoint_agent.py not found")
|
|
312
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
313
|
+
assert returncode == 0, f"Failed to load multi_endpoint_agent.py:\nstderr: {stderr}\nstdout: {stdout}"
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
class TestPrefabExamples:
|
|
317
|
+
"""Test prefab agent examples."""
|
|
318
|
+
|
|
319
|
+
@pytest.mark.parametrize("agent_file", [
|
|
320
|
+
"concierge_agent_example.py",
|
|
321
|
+
"receptionist_agent_example.py",
|
|
322
|
+
])
|
|
323
|
+
def test_prefab_agents_load(self, agent_file):
|
|
324
|
+
"""Test prefab examples can be loaded."""
|
|
325
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
326
|
+
if not agent_path.exists():
|
|
327
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
328
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
329
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class TestDynamicConfigExamples:
|
|
333
|
+
"""Test dynamic configuration examples."""
|
|
334
|
+
|
|
335
|
+
@pytest.mark.parametrize("agent_file", [
|
|
336
|
+
"comprehensive_dynamic_agent.py",
|
|
337
|
+
])
|
|
338
|
+
def test_dynamic_config_agents_load(self, agent_file):
|
|
339
|
+
"""Test dynamic config examples can be loaded."""
|
|
340
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
341
|
+
if not agent_path.exists():
|
|
342
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
343
|
+
if agent_file in NON_STANDARD_EXAMPLES:
|
|
344
|
+
pytest.skip(f"Skipping {agent_file} - non-standard agent structure")
|
|
345
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
346
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class TestAuthExamples:
|
|
350
|
+
"""Test authentication examples."""
|
|
351
|
+
|
|
352
|
+
@pytest.mark.parametrize("agent_file", [
|
|
353
|
+
"env_auth_test.py",
|
|
354
|
+
])
|
|
355
|
+
def test_auth_agents_load(self, agent_file):
|
|
356
|
+
"""Test auth examples can be loaded."""
|
|
357
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
358
|
+
if not agent_path.exists():
|
|
359
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
360
|
+
if agent_file in EXAMPLES_REQUIRING_CREDENTIALS:
|
|
361
|
+
pytest.skip(f"Skipping {agent_file} - requires {EXAMPLES_REQUIRING_CREDENTIALS[agent_file]}")
|
|
362
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
363
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
class TestSearchExamples:
|
|
367
|
+
"""Test search-related examples (may require index files)."""
|
|
368
|
+
|
|
369
|
+
@pytest.mark.parametrize("agent_file", [
|
|
370
|
+
"sigmond_simple.py",
|
|
371
|
+
"sigmond_native_search.py",
|
|
372
|
+
"sigmond_remote_search.py",
|
|
373
|
+
])
|
|
374
|
+
def test_search_agents_load(self, agent_file):
|
|
375
|
+
"""Test search agents can be loaded (may skip if no index)."""
|
|
376
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
377
|
+
if not agent_path.exists():
|
|
378
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
379
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
380
|
+
if returncode != 0:
|
|
381
|
+
if "index" in stderr.lower() or "swsearch" in stderr.lower():
|
|
382
|
+
pytest.skip(f"Skipping {agent_file} - requires search index")
|
|
383
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
class TestBedrockExamples:
|
|
387
|
+
"""Test AWS Bedrock examples (require AWS credentials)."""
|
|
388
|
+
|
|
389
|
+
@pytest.mark.parametrize("agent_file", [
|
|
390
|
+
"bedrock_agent_run.py",
|
|
391
|
+
"bedrock_agent_test.py",
|
|
392
|
+
"bedrock_server_test.py",
|
|
393
|
+
])
|
|
394
|
+
def test_bedrock_agents_load(self, agent_file):
|
|
395
|
+
"""Test Bedrock agents can be loaded (skip if no AWS credentials)."""
|
|
396
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
397
|
+
if not agent_path.exists():
|
|
398
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
399
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
400
|
+
if returncode != 0:
|
|
401
|
+
if "AWS" in stderr or "boto" in stderr or "credentials" in stderr.lower():
|
|
402
|
+
pytest.skip(f"Skipping {agent_file} - requires AWS credentials")
|
|
403
|
+
# bedrock_with_skills.py has a skill loading issue
|
|
404
|
+
if "Skill" in stdout and "not found" in stdout:
|
|
405
|
+
pytest.skip(f"Skipping {agent_file} - skill loading issue")
|
|
406
|
+
assert returncode == 0, f"Failed to load {agent_file}:\nstderr: {stderr}\nstdout: {stdout}"
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class TestSpecialExamples:
|
|
410
|
+
"""Test special/edge case examples."""
|
|
411
|
+
|
|
412
|
+
def test_search_server_standalone(self):
|
|
413
|
+
"""Test search server standalone (not an agent, may fail gracefully)."""
|
|
414
|
+
agent_path = EXAMPLES_DIR / "search_server_standalone.py"
|
|
415
|
+
if not agent_path.exists():
|
|
416
|
+
pytest.skip("search_server_standalone.py not found")
|
|
417
|
+
# This is a search server, not an agent - may not work with swaig-test
|
|
418
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
419
|
+
# Accept if it loads or fails with expected message
|
|
420
|
+
if returncode != 0:
|
|
421
|
+
if "not an agent" in stderr.lower() or "no agent" in stderr.lower():
|
|
422
|
+
pytest.skip("search_server_standalone.py is not an agent file")
|
|
423
|
+
|
|
424
|
+
def test_lambda_handler(self):
|
|
425
|
+
"""Test lambda handler example."""
|
|
426
|
+
agent_path = EXAMPLES_DIR / "test_lambda_handler.py"
|
|
427
|
+
if not agent_path.exists():
|
|
428
|
+
pytest.skip("test_lambda_handler.py not found")
|
|
429
|
+
# This is a test file, may not export an agent directly
|
|
430
|
+
returncode, stdout, stderr = run_swaig_test(agent_path, "--list-tools")
|
|
431
|
+
# Accept load or skip if it's not a standard agent
|
|
432
|
+
if returncode != 0:
|
|
433
|
+
if "no agent" in stderr.lower() or "not found" in stderr.lower():
|
|
434
|
+
pytest.skip("test_lambda_handler.py doesn't export a standard agent")
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class TestSWMLGeneration:
|
|
438
|
+
"""Test that key examples generate valid SWML."""
|
|
439
|
+
|
|
440
|
+
@pytest.mark.parametrize("agent_file", [
|
|
441
|
+
"simple_agent.py",
|
|
442
|
+
"contexts_demo.py",
|
|
443
|
+
"swaig_features_agent.py",
|
|
444
|
+
"declarative_agent.py",
|
|
445
|
+
])
|
|
446
|
+
def test_swml_has_ai_section(self, agent_file):
|
|
447
|
+
"""Test SWML has AI configuration."""
|
|
448
|
+
agent_path = EXAMPLES_DIR / agent_file
|
|
449
|
+
if not agent_path.exists():
|
|
450
|
+
pytest.skip(f"Agent file not found: {agent_file}")
|
|
451
|
+
|
|
452
|
+
swml = get_swml_json(agent_path)
|
|
453
|
+
main_section = swml.get("sections", {}).get("main", [])
|
|
454
|
+
|
|
455
|
+
# Find AI verb in main section
|
|
456
|
+
ai_found = False
|
|
457
|
+
for verb in main_section:
|
|
458
|
+
if "ai" in verb:
|
|
459
|
+
ai_found = True
|
|
460
|
+
break
|
|
461
|
+
|
|
462
|
+
assert ai_found, f"SWML for {agent_file} missing 'ai' verb"
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
class TestToolsPresence:
|
|
466
|
+
"""Test that specific agents have expected tools."""
|
|
467
|
+
|
|
468
|
+
def test_simple_agent_has_tools(self):
|
|
469
|
+
"""Test simple_agent has expected tools."""
|
|
470
|
+
agent_path = EXAMPLES_DIR / "simple_agent.py"
|
|
471
|
+
if not agent_path.exists():
|
|
472
|
+
pytest.skip("simple_agent.py not found")
|
|
473
|
+
|
|
474
|
+
tools = list_tools(agent_path)
|
|
475
|
+
# simple_agent.py defines get_time and get_weather
|
|
476
|
+
assert "get_time" in tools, f"Missing get_time tool. Found: {tools}"
|
|
477
|
+
assert "get_weather" in tools, f"Missing get_weather tool. Found: {tools}"
|
|
478
|
+
|
|
479
|
+
def test_swaig_features_agent_has_tools(self):
|
|
480
|
+
"""Test swaig_features_agent has expected tools."""
|
|
481
|
+
agent_path = EXAMPLES_DIR / "swaig_features_agent.py"
|
|
482
|
+
if not agent_path.exists():
|
|
483
|
+
pytest.skip("swaig_features_agent.py not found")
|
|
484
|
+
|
|
485
|
+
tools = list_tools(agent_path)
|
|
486
|
+
assert "get_time" in tools, f"Missing get_time tool. Found: {tools}"
|
|
487
|
+
assert "get_weather" in tools, f"Missing get_weather tool. Found: {tools}"
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
class TestServerlessSimulation:
|
|
491
|
+
"""Test serverless environment simulation."""
|
|
492
|
+
|
|
493
|
+
@pytest.mark.parametrize("platform", ["lambda", "cloud_function"])
|
|
494
|
+
def test_serverless_swml_generation(self, platform):
|
|
495
|
+
"""Test SWML generation in serverless simulation."""
|
|
496
|
+
agent_path = EXAMPLES_DIR / "simple_agent.py"
|
|
497
|
+
if not agent_path.exists():
|
|
498
|
+
pytest.skip("simple_agent.py not found")
|
|
499
|
+
|
|
500
|
+
returncode, stdout, stderr = run_swaig_test(
|
|
501
|
+
agent_path, "--simulate-serverless", platform, "--dump-swml", "--raw"
|
|
502
|
+
)
|
|
503
|
+
assert returncode == 0, f"Serverless simulation failed for {platform}:\nstderr: {stderr}"
|
|
504
|
+
|
|
505
|
+
swml = json.loads(stdout)
|
|
506
|
+
assert "version" in swml, f"Invalid SWML for {platform}"
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
if __name__ == "__main__":
|
|
510
|
+
pytest.main([__file__, "-v"])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/agent_loader.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/argparse_helpers.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/dynamic_config.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/core/service_loader.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/execution/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/execution/datamap_exec.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/execution/webhook_exec.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/output/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/output/output_formatter.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/output/swml_dump.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/simulation/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/simulation/mock_env.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/cli/swaig_test_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/config/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/prompt/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/prompt/manager.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/routing/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/swml/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/tools/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/tools/decorator.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/agent/tools/registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/function_result.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/logging_config.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/ai_config_mixin.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/auth_mixin.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/prompt_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/skill_mixin.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/state_mixin.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/tool_mixin.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/mixins/web_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/security/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/security_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/core/swaig_function.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/info_gatherer.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/prefabs/receptionist.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/document_processor.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/index_builder.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/pgvector_backend.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/query_processor.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/search_engine.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/search/search_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere/README.md
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datasphere/skill.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datetime/README.md
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datetime/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/datetime/skill.py
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/joke/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/math/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/mcp_gateway/README.md
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/mcp_gateway/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/mcp_gateway/skill.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/spider/README.md
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/spider/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/spider/skill.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/swml_transfer/README.md
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/swml_transfer/skill.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/weather_api/README.md
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/weather_api/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/weather_api/skill.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/web_search/README.md
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/web_search/__init__.py
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/skills/web_search/skill.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents/utils/token_generators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.5 → signalwire_agents-1.0.6}/signalwire_agents.egg-info/top_level.txt
RENAMED
|
File without changes
|