signalwire-sdk 3.0.2.dev62__tar.gz → 3.0.2.dev63__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_sdk-3.0.2.dev62/signalwire/signalwire_sdk.egg-info → signalwire_sdk-3.0.2.dev63}/PKG-INFO +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/pyproject.toml +15 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/__init__.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/agent_server.py +9 -7
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/agents/bedrock.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/build_search.py +10 -5
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/agent_loader.py +58 -34
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/argparse_helpers.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/dynamic_config.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/service_loader.py +31 -16
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/execution/datamap_exec.py +5 -5
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/execution/webhook_exec.py +3 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/output/swml_dump.py +5 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/data_generation.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/mock_env.py +3 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/test_swaig.py +11 -4
- signalwire_sdk-3.0.2.dev63/signalwire/signalwire/core/_agent_host.py +24 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/prompt/manager.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/registry.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/type_inference.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent_base.py +61 -34
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/auth_handler.py +27 -13
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/config_loader.py +4 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/contexts.py +3 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/data_map.py +8 -8
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/function_result.py +12 -8
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/logging_config.py +2 -1
- signalwire_sdk-3.0.2.dev63/signalwire/signalwire/core/mixins/_mixin_host.py +42 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/ai_config_mixin.py +9 -6
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/auth_mixin.py +4 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/mcp_server_mixin.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/prompt_mixin.py +9 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/serverless_mixin.py +2 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/skill_mixin.py +5 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/state_mixin.py +3 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/tool_mixin.py +6 -5
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/web_mixin.py +19 -16
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/webhook_middleware.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security_config.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/skill_base.py +4 -4
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/skill_manager.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swaig_function.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_builder.py +8 -8
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_handler.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_renderer.py +7 -4
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_service.py +15 -8
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/livewire/__init__.py +15 -14
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/gateway_service.py +3 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/mcp_manager.py +19 -14
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/session_manager.py +3 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/pom/pom.py +7 -6
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/faq_bot.py +3 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/info_gatherer.py +3 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/call.py +7 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/client.py +24 -11
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/_base.py +3 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/compat.py +9 -9
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/__init__.py +15 -12
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/document_processor.py +83 -52
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/index_builder.py +21 -10
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/migration.py +10 -7
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/pgvector_backend.py +17 -12
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/query_processor.py +7 -7
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/search_engine.py +29 -18
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/search_service.py +45 -36
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/api_ninjas_trivia/skill.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/claude_skills/skill.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/google_maps/skill.py +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/math/skill.py +3 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/mcp_gateway/skill.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/native_vector_search/skill.py +18 -5
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/play_background_file/skill.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/registry.py +15 -11
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/spider/skill.py +14 -12
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/weather_api/skill.py +2 -2
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/skill.py +10 -9
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/skill_improved.py +5 -4
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/skill_original.py +3 -3
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/schema_utils.py +15 -10
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/web/web_service.py +32 -28
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63/signalwire/signalwire_sdk.egg-info}/PKG-INFO +1 -1
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/SOURCES.txt +2 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/LICENSE +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/man/sw-agent-init.1 +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/man/sw-search.1 +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/man/swaig-test.1 +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/setup.cfg +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/setup.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/config.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/dokku.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/execution/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/init_project.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/output/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/output/output_formatter.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/data_overrides.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/swaig_test_wrapper.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/types.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/config/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/deployment/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/deployment/handlers/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/prompt/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/routing/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/security/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/swml/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/decorator.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/pom_builder.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/security_utils.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/session_manager.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/webhook_validator.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/livewire/plugins.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/pom/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/pom/pom_tool.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/concierge.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/receptionist.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/survey.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/constants.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/event.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/message.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/_pagination.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/call_handler.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/client.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/addresses.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/calling.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/chat.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/datasphere.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/fabric.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/imported_numbers.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/logs.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/lookup.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/mfa.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/number_groups.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/phone_numbers.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/project.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/pubsub.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/queues.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/recordings.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/registry.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/short_codes.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/sip_profile.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/verified_callers.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/video.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/schema.json +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/models.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/api_ninjas_trivia/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/api_ninjas_trivia/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/claude_skills/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/claude_skills/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere/skill.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere_serverless/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere_serverless/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere_serverless/skill.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datetime/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datetime/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datetime/skill.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/google_maps/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/info_gatherer/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/info_gatherer/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/info_gatherer/skill.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/joke/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/joke/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/joke/skill.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/math/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/math/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/mcp_gateway/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/mcp_gateway/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/native_vector_search/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/native_vector_search/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/play_background_file/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/play_background_file/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/spider/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/spider/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/swml_transfer/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/swml_transfer/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/swml_transfer/skill.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/weather_api/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/weather_api/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/wikipedia_search/README.md +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/wikipedia_search/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/wikipedia_search/skill.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/pom_utils.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/token_generators.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/url_validator.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/validators.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/web/__init__.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/dependency_links.txt +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/entry_points.txt +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/requires.txt +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/top_level.txt +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/tests/test_examples.py +0 -0
- {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/tests/test_mcp_integration.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "signalwire-sdk"
|
|
7
|
-
version = "3.0.2.
|
|
7
|
+
version = "3.0.2.dev63"
|
|
8
8
|
description = "SignalWire SDK"
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "SignalWire Team", email = "info@signalwire.com"}
|
|
@@ -165,3 +165,17 @@ signalwire = [
|
|
|
165
165
|
[tool.ruff]
|
|
166
166
|
target-version = "py310"
|
|
167
167
|
line-length = 88
|
|
168
|
+
|
|
169
|
+
[tool.mypy]
|
|
170
|
+
python_version = "3.10"
|
|
171
|
+
files = ["signalwire/signalwire"]
|
|
172
|
+
# Third-party packages without type stubs (nltk, sentence_transformers, the
|
|
173
|
+
# search/relay stacks) are out of scope — we type our own code, not theirs.
|
|
174
|
+
ignore_missing_imports = true
|
|
175
|
+
# The bar: our own code is clean. Bodies of untyped defs are checked so real
|
|
176
|
+
# type errors inside them surface (this is what found the mixin cluster).
|
|
177
|
+
check_untyped_defs = true
|
|
178
|
+
warn_unused_ignores = true
|
|
179
|
+
# `# type: ignore` is reserved for genuinely-unfixable third-party-stub gaps and
|
|
180
|
+
# must carry an error code + reason. warn_unused_ignores keeps them honest.
|
|
181
|
+
show_error_codes = true
|
|
@@ -17,7 +17,7 @@ from .core.logging_config import configure_logging
|
|
|
17
17
|
|
|
18
18
|
configure_logging()
|
|
19
19
|
|
|
20
|
-
__version__ = "3.0.2.
|
|
20
|
+
__version__ = "3.0.2.dev63"
|
|
21
21
|
|
|
22
22
|
# Import core classes for easier access.
|
|
23
23
|
# These imports are intentionally placed after configure_logging() so the SDK's
|
{signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/agent_server.py
RENAMED
|
@@ -61,7 +61,7 @@ class AgentServer:
|
|
|
61
61
|
self.app = FastAPI(
|
|
62
62
|
title="SignalWire AI Agents",
|
|
63
63
|
description="Hosted SignalWire AI Agents",
|
|
64
|
-
version="3.0.2.
|
|
64
|
+
version="3.0.2.dev63",
|
|
65
65
|
redirect_slashes=False,
|
|
66
66
|
docs_url=None,
|
|
67
67
|
redoc_url=None,
|
|
@@ -87,7 +87,7 @@ class AgentServer:
|
|
|
87
87
|
|
|
88
88
|
# Keep track of SIP routing configuration
|
|
89
89
|
self._sip_routing_enabled = False
|
|
90
|
-
self._sip_route = None
|
|
90
|
+
self._sip_route: Optional[str] = None
|
|
91
91
|
self._sip_username_mapping: Dict[str, str] = {} # Maps SIP usernames to routes
|
|
92
92
|
|
|
93
93
|
# Register health endpoints immediately so they're available
|
|
@@ -145,10 +145,9 @@ class AgentServer:
|
|
|
145
145
|
self._auto_map_agent_sip_usernames(agent, route)
|
|
146
146
|
|
|
147
147
|
# Register the SIP routing callback with this agent if we have one
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
)
|
|
148
|
+
sip_cb = getattr(self, "_sip_routing_callback", None)
|
|
149
|
+
if sip_cb is not None and self._sip_route is not None:
|
|
150
|
+
agent.register_routing_callback(sip_cb, path=self._sip_route)
|
|
152
151
|
|
|
153
152
|
def setup_sip_routing(self, route: str = "/sip", auto_map: bool = True) -> None:
|
|
154
153
|
"""
|
|
@@ -689,7 +688,10 @@ class AgentServer:
|
|
|
689
688
|
|
|
690
689
|
self.logger.info(f"Starting server on {protocol}://{display_host}")
|
|
691
690
|
for route, agent in self.agents.items():
|
|
692
|
-
|
|
691
|
+
# include_source defaults False -> 2-tuple at runtime; index to
|
|
692
|
+
# avoid the union-tuple unpack ambiguity mypy sees.
|
|
693
|
+
creds = agent.get_basic_auth_credentials()
|
|
694
|
+
username = creds[0]
|
|
693
695
|
agent_url = agent.get_full_url(include_auth=False)
|
|
694
696
|
self.logger.info(f"Agent '{agent.get_name()}' available at:")
|
|
695
697
|
self.logger.info(f"URL: {agent_url}")
|
{signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/agents/bedrock.py
RENAMED
|
@@ -77,7 +77,7 @@ class BedrockAgent(AgentBase):
|
|
|
77
77
|
logger.info(f"BedrockAgent initialized: {name} on route {route}")
|
|
78
78
|
|
|
79
79
|
def _render_swml(
|
|
80
|
-
self, call_id: str = None, modifications: Optional[dict] = None
|
|
80
|
+
self, call_id: Optional[str] = None, modifications: Optional[dict] = None
|
|
81
81
|
) -> str:
|
|
82
82
|
"""
|
|
83
83
|
Render SWML document with amazon_bedrock verb
|
{signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/build_search.py
RENAMED
|
@@ -11,6 +11,7 @@ import argparse
|
|
|
11
11
|
import sys
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from datetime import datetime
|
|
14
|
+
from typing import List, cast
|
|
14
15
|
from urllib.parse import urlparse, urlunparse
|
|
15
16
|
|
|
16
17
|
from signalwire.search.models import MODEL_ALIASES, DEFAULT_MODEL, resolve_model_alias
|
|
@@ -518,7 +519,7 @@ Examples:
|
|
|
518
519
|
relative_path = (
|
|
519
520
|
file_path.relative_to(base_dir)
|
|
520
521
|
if base_dir
|
|
521
|
-
else file_path.name
|
|
522
|
+
else Path(file_path.name)
|
|
522
523
|
)
|
|
523
524
|
json_filename = relative_path.with_suffix(".json")
|
|
524
525
|
json_path = Path(args.output_dir) / json_filename
|
|
@@ -575,8 +576,8 @@ Examples:
|
|
|
575
576
|
f"✓ Created {len(chunk_files_created)} JSON files in {args.output_dir}"
|
|
576
577
|
)
|
|
577
578
|
total_chunks = 0
|
|
578
|
-
for
|
|
579
|
-
with open(
|
|
579
|
+
for chunk_file in chunk_files_created:
|
|
580
|
+
with open(chunk_file) as fh:
|
|
580
581
|
total_chunks += len(json.load(fh)["chunks"])
|
|
581
582
|
print(f" Total chunks: {total_chunks}")
|
|
582
583
|
|
|
@@ -920,7 +921,9 @@ def search_command():
|
|
|
920
921
|
|
|
921
922
|
# Perform search
|
|
922
923
|
results = engine.search(
|
|
923
|
-
query_vector=
|
|
924
|
+
query_vector=cast(
|
|
925
|
+
List[float], enhanced.get("vector")
|
|
926
|
+
), # vector is None for keyword-only search; search() tolerates it at runtime
|
|
924
927
|
enhanced_text=enhanced.get("enhanced_text", query),
|
|
925
928
|
count=args.count,
|
|
926
929
|
similarity_threshold=args.distance_threshold,
|
|
@@ -1003,7 +1006,9 @@ def search_command():
|
|
|
1003
1006
|
|
|
1004
1007
|
# Perform search
|
|
1005
1008
|
results = engine.search(
|
|
1006
|
-
query_vector=
|
|
1009
|
+
query_vector=cast(
|
|
1010
|
+
List[float], enhanced.get("vector")
|
|
1011
|
+
), # vector is None for keyword-only search; search() tolerates it at runtime
|
|
1007
1012
|
enhanced_text=enhanced.get("enhanced_text", args.query),
|
|
1008
1013
|
count=args.count,
|
|
1009
1014
|
similarity_threshold=args.distance_threshold,
|
|
@@ -12,10 +12,10 @@ Agent discovery and loading functionality
|
|
|
12
12
|
|
|
13
13
|
import importlib.util
|
|
14
14
|
from pathlib import Path
|
|
15
|
-
from typing import List, Dict, Any, Optional
|
|
15
|
+
from typing import List, Dict, Any, Optional, cast, Type, TYPE_CHECKING
|
|
16
16
|
|
|
17
17
|
# Import after checking if available
|
|
18
|
-
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
19
|
from signalwire.core.agent_base import AgentBase
|
|
20
20
|
from signalwire.core.swml_service import SWMLService
|
|
21
21
|
|
|
@@ -25,14 +25,30 @@ try:
|
|
|
25
25
|
AGENT_BASE_AVAILABLE = True
|
|
26
26
|
SWML_SERVICE_AVAILABLE = True
|
|
27
27
|
NEW_LOADER_AVAILABLE = True
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
else:
|
|
29
|
+
# Optional-dependency shims: these names are real types/callables when the
|
|
30
|
+
# signalwire-agents package is importable, None otherwise.
|
|
31
|
+
try:
|
|
32
|
+
from signalwire.core.agent_base import AgentBase
|
|
33
|
+
from signalwire.core.swml_service import SWMLService
|
|
34
|
+
|
|
35
|
+
# Import the new service loader
|
|
36
|
+
from .service_loader import (
|
|
37
|
+
ServiceCapture,
|
|
38
|
+
load_agent_from_file as new_load_agent,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
AGENT_BASE_AVAILABLE = True
|
|
42
|
+
SWML_SERVICE_AVAILABLE = True
|
|
43
|
+
NEW_LOADER_AVAILABLE = True
|
|
44
|
+
except ImportError:
|
|
45
|
+
AgentBase = None
|
|
46
|
+
SWMLService = None
|
|
47
|
+
ServiceCapture = None
|
|
48
|
+
new_load_agent = None
|
|
49
|
+
AGENT_BASE_AVAILABLE = False
|
|
50
|
+
SWML_SERVICE_AVAILABLE = False
|
|
51
|
+
NEW_LOADER_AVAILABLE = False
|
|
36
52
|
|
|
37
53
|
|
|
38
54
|
def discover_services_in_file(service_path: str) -> List[Dict[str, Any]]:
|
|
@@ -77,25 +93,27 @@ def _discover_services_impl(service_path: str) -> List[Dict[str, Any]]:
|
|
|
77
93
|
"""
|
|
78
94
|
Internal implementation for discovering services
|
|
79
95
|
"""
|
|
80
|
-
|
|
96
|
+
resolved_path = Path(service_path).resolve()
|
|
81
97
|
|
|
82
|
-
if not
|
|
83
|
-
raise FileNotFoundError(f"Service file not found: {
|
|
98
|
+
if not resolved_path.exists():
|
|
99
|
+
raise FileNotFoundError(f"Service file not found: {resolved_path}")
|
|
84
100
|
|
|
85
|
-
if not
|
|
86
|
-
raise ValueError(f"Service file must be a Python file (.py): {
|
|
101
|
+
if not resolved_path.suffix == ".py":
|
|
102
|
+
raise ValueError(f"Service file must be a Python file (.py): {resolved_path}")
|
|
87
103
|
|
|
88
104
|
# Add the module's directory to sys.path temporarily to allow local imports
|
|
89
105
|
import sys
|
|
90
106
|
|
|
91
|
-
module_dir = str(
|
|
107
|
+
module_dir = str(resolved_path.parent)
|
|
92
108
|
sys_path_added = False
|
|
93
109
|
if module_dir not in sys.path:
|
|
94
110
|
sys.path.insert(0, module_dir)
|
|
95
111
|
sys_path_added = True
|
|
96
112
|
|
|
97
113
|
# Load the module, but prevent main() execution by setting __name__ to something other than "__main__"
|
|
98
|
-
spec = importlib.util.spec_from_file_location("service_module",
|
|
114
|
+
spec = importlib.util.spec_from_file_location("service_module", resolved_path)
|
|
115
|
+
if spec is None or spec.loader is None:
|
|
116
|
+
raise ImportError(f"Failed to create module spec for: {resolved_path}")
|
|
99
117
|
module = importlib.util.module_from_spec(spec)
|
|
100
118
|
|
|
101
119
|
try:
|
|
@@ -112,12 +130,12 @@ def _discover_services_impl(service_path: str) -> List[Dict[str, Any]]:
|
|
|
112
130
|
if sys_path_added and module_dir in sys.path:
|
|
113
131
|
sys.path.remove(module_dir)
|
|
114
132
|
|
|
115
|
-
services_found = []
|
|
133
|
+
services_found: List[Dict[str, Any]] = []
|
|
116
134
|
|
|
117
135
|
# Look for SWMLService instances (including AgentBase which inherits from it)
|
|
118
136
|
for name, obj in vars(module).items():
|
|
119
137
|
if isinstance(obj, SWMLService):
|
|
120
|
-
is_agent = isinstance(obj, AgentBase) if AgentBase else False
|
|
138
|
+
is_agent = isinstance(obj, AgentBase) if AgentBase is not None else False
|
|
121
139
|
services_found.append(
|
|
122
140
|
{
|
|
123
141
|
"name": name,
|
|
@@ -144,7 +162,7 @@ def _discover_services_impl(service_path: str) -> List[Dict[str, Any]]:
|
|
|
144
162
|
service["class_name"] == name for service in services_found
|
|
145
163
|
)
|
|
146
164
|
if not instance_found:
|
|
147
|
-
is_agent = AgentBase and issubclass(obj, AgentBase)
|
|
165
|
+
is_agent = AgentBase is not None and issubclass(obj, AgentBase)
|
|
148
166
|
try:
|
|
149
167
|
# Try to get class information without instantiating
|
|
150
168
|
service_info = {
|
|
@@ -259,25 +277,27 @@ def _load_service_impl(
|
|
|
259
277
|
"""
|
|
260
278
|
Internal implementation for loading services with smart detection
|
|
261
279
|
"""
|
|
262
|
-
|
|
280
|
+
resolved_path = Path(service_path).resolve()
|
|
263
281
|
|
|
264
|
-
if not
|
|
265
|
-
raise FileNotFoundError(f"Service file not found: {
|
|
282
|
+
if not resolved_path.exists():
|
|
283
|
+
raise FileNotFoundError(f"Service file not found: {resolved_path}")
|
|
266
284
|
|
|
267
|
-
if not
|
|
268
|
-
raise ValueError(f"Service file must be a Python file (.py): {
|
|
285
|
+
if not resolved_path.suffix == ".py":
|
|
286
|
+
raise ValueError(f"Service file must be a Python file (.py): {resolved_path}")
|
|
269
287
|
|
|
270
288
|
# Add the module's directory to sys.path temporarily to allow local imports
|
|
271
289
|
import sys
|
|
272
290
|
|
|
273
|
-
module_dir = str(
|
|
291
|
+
module_dir = str(resolved_path.parent)
|
|
274
292
|
sys_path_added = False
|
|
275
293
|
if module_dir not in sys.path:
|
|
276
294
|
sys.path.insert(0, module_dir)
|
|
277
295
|
sys_path_added = True
|
|
278
296
|
|
|
279
297
|
# Load the module, but prevent main() execution by setting __name__ to something other than "__main__"
|
|
280
|
-
spec = importlib.util.spec_from_file_location("service_module",
|
|
298
|
+
spec = importlib.util.spec_from_file_location("service_module", resolved_path)
|
|
299
|
+
if spec is None or spec.loader is None:
|
|
300
|
+
raise ImportError(f"Failed to create module spec for: {resolved_path}")
|
|
281
301
|
module = importlib.util.module_from_spec(spec)
|
|
282
302
|
|
|
283
303
|
try:
|
|
@@ -315,7 +335,9 @@ def _load_service_impl(
|
|
|
315
335
|
and obj not in (SWMLService, AgentBase)
|
|
316
336
|
):
|
|
317
337
|
try:
|
|
318
|
-
|
|
338
|
+
# Discovered subclasses define their own (often no-arg)
|
|
339
|
+
# constructors; cast away the abstract base signature.
|
|
340
|
+
temp_instance = cast(Type[Any], obj)()
|
|
319
341
|
if (
|
|
320
342
|
hasattr(temp_instance, "route")
|
|
321
343
|
and temp_instance.route == service_identifier
|
|
@@ -331,7 +353,7 @@ def _load_service_impl(
|
|
|
331
353
|
obj = getattr(module, service_identifier)
|
|
332
354
|
if isinstance(obj, type) and issubclass(obj, SWMLService):
|
|
333
355
|
try:
|
|
334
|
-
service = obj()
|
|
356
|
+
service = cast(Type[Any], obj)()
|
|
335
357
|
except Exception as e:
|
|
336
358
|
raise ValueError(
|
|
337
359
|
f"No service found with route '{service_identifier}' and failed to instantiate class '{service_identifier}': {e}"
|
|
@@ -348,13 +370,15 @@ def _load_service_impl(
|
|
|
348
370
|
obj = getattr(module, service_identifier)
|
|
349
371
|
if isinstance(obj, type) and issubclass(obj, SWMLService):
|
|
350
372
|
try:
|
|
351
|
-
service = obj()
|
|
373
|
+
service = cast(Type[Any], obj)()
|
|
352
374
|
if service and not service.route.endswith(
|
|
353
375
|
"dummy"
|
|
354
376
|
): # Avoid test services with dummy routes
|
|
355
377
|
pass # Successfully created specific service
|
|
356
378
|
else:
|
|
357
|
-
service =
|
|
379
|
+
service = cast(
|
|
380
|
+
Type[Any], obj
|
|
381
|
+
)() # Create anyway if requested specifically
|
|
358
382
|
except Exception as e:
|
|
359
383
|
raise ValueError(
|
|
360
384
|
f"Failed to instantiate service class '{service_identifier}': {e}"
|
|
@@ -416,7 +440,7 @@ def _load_service_impl(
|
|
|
416
440
|
|
|
417
441
|
if len(service_classes_found) == 1:
|
|
418
442
|
try:
|
|
419
|
-
service = service_classes_found[0][1]()
|
|
443
|
+
service = cast(Type[Any], service_classes_found[0][1])()
|
|
420
444
|
except Exception as e:
|
|
421
445
|
print(
|
|
422
446
|
f"Warning: Failed to instantiate {service_classes_found[0][0]}: {e}"
|
|
@@ -427,7 +451,7 @@ def _load_service_impl(
|
|
|
427
451
|
for name, cls in service_classes_found:
|
|
428
452
|
try:
|
|
429
453
|
# Try to instantiate temporarily to get route
|
|
430
|
-
temp_instance = cls()
|
|
454
|
+
temp_instance = cast(Type[Any], cls)()
|
|
431
455
|
route = getattr(temp_instance, "route", "Unknown")
|
|
432
456
|
service_name = getattr(temp_instance, "name", "Unknown")
|
|
433
457
|
service_info.append(
|
|
@@ -469,7 +493,7 @@ def _load_service_impl(
|
|
|
469
493
|
and obj not in (SWMLService, AgentBase)
|
|
470
494
|
):
|
|
471
495
|
try:
|
|
472
|
-
service = obj()
|
|
496
|
+
service = cast(Type[Any], obj)()
|
|
473
497
|
break
|
|
474
498
|
except Exception as e:
|
|
475
499
|
print(f"Warning: Failed to instantiate {name}: {e}")
|
|
@@ -82,7 +82,7 @@ class CustomArgumentParser(argparse.ArgumentParser):
|
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
def parse_function_arguments(
|
|
85
|
-
function_args_list: List[str], func_schema:
|
|
85
|
+
function_args_list: List[str], func_schema: Any
|
|
86
86
|
) -> Dict[str, Any]:
|
|
87
87
|
"""
|
|
88
88
|
Parse function arguments from command line with type coercion based on schema
|
|
@@ -94,7 +94,7 @@ def parse_function_arguments(
|
|
|
94
94
|
Returns:
|
|
95
95
|
Dictionary of parsed function arguments
|
|
96
96
|
"""
|
|
97
|
-
parsed_args = {}
|
|
97
|
+
parsed_args: Dict[str, Any] = {}
|
|
98
98
|
i = 0
|
|
99
99
|
|
|
100
100
|
# Get parameter schema
|
|
@@ -10,7 +10,7 @@ See LICENSE file in the project root for full license information.
|
|
|
10
10
|
Apply dynamic configuration to agents
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
-
from typing import Optional, TYPE_CHECKING
|
|
13
|
+
from typing import Optional, Dict, Any, TYPE_CHECKING
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
16
|
from signalwire.core.agent_base import AgentBase
|
|
@@ -47,7 +47,7 @@ def apply_dynamic_config(
|
|
|
47
47
|
|
|
48
48
|
# Extract request data
|
|
49
49
|
query_params = dict(mock_request.query_params)
|
|
50
|
-
body_params = {} # Empty for GET requests
|
|
50
|
+
body_params: Dict[str, Any] = {} # Empty for GET requests
|
|
51
51
|
headers = dict(mock_request.headers)
|
|
52
52
|
|
|
53
53
|
if verbose:
|
|
@@ -12,24 +12,33 @@ Service discovery and loading functionality - new simplified approach
|
|
|
12
12
|
|
|
13
13
|
import importlib.util
|
|
14
14
|
from pathlib import Path
|
|
15
|
-
from typing import List, Dict, Any, Optional
|
|
15
|
+
from typing import List, Dict, Any, Optional, cast, TYPE_CHECKING
|
|
16
16
|
import asyncio
|
|
17
17
|
import io
|
|
18
18
|
import contextlib
|
|
19
19
|
|
|
20
20
|
# Import after checking if available
|
|
21
|
-
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
22
|
from signalwire.core.agent_base import AgentBase
|
|
23
23
|
from signalwire.core.swml_service import SWMLService
|
|
24
24
|
from fastapi import Request, Response
|
|
25
25
|
|
|
26
26
|
DEPENDENCIES_AVAILABLE = True
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
else:
|
|
28
|
+
# Optional-dependency shims: real types when signalwire-agents/fastapi are
|
|
29
|
+
# importable, None otherwise.
|
|
30
|
+
try:
|
|
31
|
+
from signalwire.core.agent_base import AgentBase
|
|
32
|
+
from signalwire.core.swml_service import SWMLService
|
|
33
|
+
from fastapi import Request, Response
|
|
34
|
+
|
|
35
|
+
DEPENDENCIES_AVAILABLE = True
|
|
36
|
+
except ImportError:
|
|
37
|
+
AgentBase = None
|
|
38
|
+
SWMLService = None
|
|
39
|
+
Request = None
|
|
40
|
+
Response = None
|
|
41
|
+
DEPENDENCIES_AVAILABLE = False
|
|
33
42
|
|
|
34
43
|
|
|
35
44
|
class ServiceCapture:
|
|
@@ -57,14 +66,14 @@ class ServiceCapture:
|
|
|
57
66
|
"Required dependencies not available. Please install signalwire-agents package."
|
|
58
67
|
)
|
|
59
68
|
|
|
60
|
-
|
|
69
|
+
resolved_path = Path(service_path).resolve()
|
|
61
70
|
|
|
62
|
-
if not
|
|
63
|
-
raise FileNotFoundError(f"Service file not found: {
|
|
71
|
+
if not resolved_path.exists():
|
|
72
|
+
raise FileNotFoundError(f"Service file not found: {resolved_path}")
|
|
64
73
|
|
|
65
|
-
if not
|
|
74
|
+
if not resolved_path.suffix == ".py":
|
|
66
75
|
raise ValueError(
|
|
67
|
-
f"Service file must be a Python file (.py): {
|
|
76
|
+
f"Service file must be a Python file (.py): {resolved_path}"
|
|
68
77
|
)
|
|
69
78
|
|
|
70
79
|
# Reset captured services
|
|
@@ -83,7 +92,11 @@ class ServiceCapture:
|
|
|
83
92
|
else contextlib.nullcontext()
|
|
84
93
|
):
|
|
85
94
|
# Load and execute the module
|
|
86
|
-
spec = importlib.util.spec_from_file_location("__main__",
|
|
95
|
+
spec = importlib.util.spec_from_file_location("__main__", resolved_path)
|
|
96
|
+
if spec is None or spec.loader is None:
|
|
97
|
+
raise ImportError(
|
|
98
|
+
f"Failed to create module spec for: {resolved_path}"
|
|
99
|
+
)
|
|
87
100
|
module = importlib.util.module_from_spec(spec)
|
|
88
101
|
|
|
89
102
|
# Set __name__ to "__main__" to trigger if __name__ == "__main__": blocks
|
|
@@ -173,8 +186,9 @@ async def simulate_request_to_service(
|
|
|
173
186
|
# Create a mock response
|
|
174
187
|
response = Response()
|
|
175
188
|
|
|
176
|
-
# Call the service's request handler
|
|
177
|
-
|
|
189
|
+
# Call the service's request handler. `request` is a duck-typed MockRequest
|
|
190
|
+
# that stands in for a FastAPI Request at runtime; cast for the type checker.
|
|
191
|
+
result = await service._handle_request(cast(Any, request), response)
|
|
178
192
|
|
|
179
193
|
# If result is a Response object, extract the content
|
|
180
194
|
if hasattr(result, "body"):
|
|
@@ -249,6 +263,7 @@ def load_and_simulate_service(
|
|
|
249
263
|
)
|
|
250
264
|
|
|
251
265
|
# Simulate the request
|
|
266
|
+
assert service is not None # guaranteed by the selection logic above
|
|
252
267
|
return asyncio.run(
|
|
253
268
|
simulate_request_to_service(
|
|
254
269
|
service,
|
|
@@ -81,7 +81,7 @@ def simple_template_expand(template: str, data: Dict[str, Any]) -> str:
|
|
|
81
81
|
parts.append(current_part)
|
|
82
82
|
|
|
83
83
|
# Navigate through the data structure
|
|
84
|
-
value = data
|
|
84
|
+
value: Any = data
|
|
85
85
|
try:
|
|
86
86
|
for part in parts:
|
|
87
87
|
if part.startswith("[") and part.endswith("]"):
|
|
@@ -121,7 +121,7 @@ def simple_template_expand(template: str, data: Dict[str, Any]) -> str:
|
|
|
121
121
|
|
|
122
122
|
def execute_datamap_function(
|
|
123
123
|
datamap_config: Dict[str, Any], args: Dict[str, Any], verbose: bool = False
|
|
124
|
-
) ->
|
|
124
|
+
) -> Any:
|
|
125
125
|
"""
|
|
126
126
|
Execute a DataMap function following the actual DataMap processing pipeline:
|
|
127
127
|
1. Expressions (pattern matching)
|
|
@@ -151,7 +151,7 @@ def execute_datamap_function(
|
|
|
151
151
|
print(f"Extracted data_map: {json.dumps(actual_datamap, indent=2)}")
|
|
152
152
|
|
|
153
153
|
# Initialize context with function arguments
|
|
154
|
-
context = {"args": args}
|
|
154
|
+
context: Dict[str, Any] = {"args": args}
|
|
155
155
|
context.update(
|
|
156
156
|
args
|
|
157
157
|
) # Also make args available at top level for backward compatibility
|
|
@@ -171,7 +171,7 @@ def execute_datamap_function(
|
|
|
171
171
|
if pattern in str(args):
|
|
172
172
|
if verbose:
|
|
173
173
|
print(f"Expression matched: {pattern}")
|
|
174
|
-
result = simple_template_expand(str(expr["output"]), context)
|
|
174
|
+
result: Any = simple_template_expand(str(expr["output"]), context)
|
|
175
175
|
if verbose:
|
|
176
176
|
print(f"Expression result: {result}")
|
|
177
177
|
return result
|
|
@@ -428,7 +428,7 @@ def execute_datamap_function(
|
|
|
428
428
|
|
|
429
429
|
if isinstance(webhook_output, dict):
|
|
430
430
|
# Process each key-value pair in the output
|
|
431
|
-
final_result = {}
|
|
431
|
+
final_result: Any = {}
|
|
432
432
|
for key, template in webhook_output.items():
|
|
433
433
|
expanded_value = simple_template_expand(
|
|
434
434
|
str(template), webhook_context
|
|
@@ -41,6 +41,8 @@ def execute_external_webhook_function(
|
|
|
41
41
|
Response from the external webhook service
|
|
42
42
|
"""
|
|
43
43
|
webhook_url = func.webhook_url
|
|
44
|
+
if not webhook_url:
|
|
45
|
+
raise ValueError(f"Function '{function_name}' has no webhook_url configured")
|
|
44
46
|
|
|
45
47
|
if verbose:
|
|
46
48
|
print(f"\nCalling EXTERNAL webhook: {function_name}")
|
|
@@ -49,7 +51,7 @@ def execute_external_webhook_function(
|
|
|
49
51
|
print("-" * 60)
|
|
50
52
|
|
|
51
53
|
# Prepare the SWAIG function call payload that SignalWire would send
|
|
52
|
-
swaig_payload = {
|
|
54
|
+
swaig_payload: Dict[str, Any] = {
|
|
53
55
|
"function": function_name,
|
|
54
56
|
"argument": {
|
|
55
57
|
"parsed": [function_args] if function_args else [{}],
|
|
@@ -14,7 +14,7 @@ import sys
|
|
|
14
14
|
import json
|
|
15
15
|
import warnings
|
|
16
16
|
import argparse
|
|
17
|
-
from typing import TYPE_CHECKING
|
|
17
|
+
from typing import Any, cast, TYPE_CHECKING
|
|
18
18
|
from ..simulation.data_generation import generate_fake_swml_post_data
|
|
19
19
|
from ..simulation.data_overrides import apply_convenience_mappings, apply_overrides
|
|
20
20
|
from ..simulation.mock_env import create_mock_request
|
|
@@ -146,7 +146,10 @@ def handle_dump_swml(agent: "AgentBase", args: argparse.Namespace) -> int:
|
|
|
146
146
|
try:
|
|
147
147
|
# Dynamic agents expect (request_data, callback_path, request)
|
|
148
148
|
call_id = post_data.get("call", {}).get("call_id", "test-call-id")
|
|
149
|
-
|
|
149
|
+
# mock_request is a duck-typed stand-in for a FastAPI Request
|
|
150
|
+
modifications = agent.on_swml_request(
|
|
151
|
+
post_data, "/swml", cast(Any, mock_request)
|
|
152
|
+
)
|
|
150
153
|
|
|
151
154
|
if args.verbose and not args.raw:
|
|
152
155
|
print(f"Dynamic agent modifications: {modifications}")
|
|
@@ -12,7 +12,7 @@ Mock environment and serverless simulation functionality
|
|
|
12
12
|
|
|
13
13
|
import os
|
|
14
14
|
import json
|
|
15
|
-
from typing import Optional, Dict, Any
|
|
15
|
+
from typing import Optional, Dict, Any, List
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class MockQueryParams:
|
|
@@ -186,7 +186,7 @@ class ServerlessSimulator:
|
|
|
186
186
|
self.preset_env = self.PLATFORM_PRESETS.get(platform, {}).copy()
|
|
187
187
|
self.overrides = overrides or {}
|
|
188
188
|
self.active = False
|
|
189
|
-
self._cleared_vars = {}
|
|
189
|
+
self._cleared_vars: Dict[str, str] = {}
|
|
190
190
|
|
|
191
191
|
def activate(self, verbose: bool = False):
|
|
192
192
|
"""Apply serverless environment simulation"""
|
|
@@ -260,7 +260,7 @@ class ServerlessSimulator:
|
|
|
260
260
|
def _clear_conflicting_env(self):
|
|
261
261
|
"""Clear environment variables that might conflict with simulation"""
|
|
262
262
|
# Remove variables from other platforms
|
|
263
|
-
conflicting_vars = []
|
|
263
|
+
conflicting_vars: List[str] = []
|
|
264
264
|
for platform, preset in self.PLATFORM_PRESETS.items():
|
|
265
265
|
if platform != self.platform:
|
|
266
266
|
conflicting_vars.extend(preset.keys())
|
{signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/test_swaig.py
RENAMED
|
@@ -23,6 +23,7 @@ if "--raw" in sys.argv or "--dump-swml" in sys.argv:
|
|
|
23
23
|
import json
|
|
24
24
|
import argparse
|
|
25
25
|
from pathlib import Path
|
|
26
|
+
from typing import Any, Dict, cast
|
|
26
27
|
|
|
27
28
|
# Import submodules
|
|
28
29
|
from .config import (
|
|
@@ -738,8 +739,10 @@ def main():
|
|
|
738
739
|
print("Function type: DataMap (serverless)")
|
|
739
740
|
print("-" * 60)
|
|
740
741
|
|
|
741
|
-
# Execute DataMap function
|
|
742
|
-
result = execute_datamap_function(
|
|
742
|
+
# Execute DataMap function (is_datamap implies func is a dict)
|
|
743
|
+
result = execute_datamap_function(
|
|
744
|
+
cast(Dict[str, Any], func), function_args, args.verbose
|
|
745
|
+
)
|
|
743
746
|
print("RESULT:")
|
|
744
747
|
print(format_result(result))
|
|
745
748
|
else:
|
|
@@ -749,7 +752,7 @@ def main():
|
|
|
749
752
|
print(f"Arguments: {json.dumps(function_args, indent=2)}")
|
|
750
753
|
if is_external_webhook:
|
|
751
754
|
print("Function type: EXTERNAL webhook")
|
|
752
|
-
print(f"External URL: {func.webhook_url}")
|
|
755
|
+
print(f"External URL: {cast(Any, func).webhook_url}")
|
|
753
756
|
else:
|
|
754
757
|
print("Function type: LOCAL webhook")
|
|
755
758
|
|
|
@@ -791,7 +794,11 @@ def main():
|
|
|
791
794
|
if is_external_webhook:
|
|
792
795
|
# For external webhook functions, make HTTP request to external service
|
|
793
796
|
result = execute_external_webhook_function(
|
|
794
|
-
|
|
797
|
+
cast(Any, func),
|
|
798
|
+
args.tool_name,
|
|
799
|
+
function_args,
|
|
800
|
+
post_data,
|
|
801
|
+
args.verbose,
|
|
795
802
|
)
|
|
796
803
|
else:
|
|
797
804
|
# For local webhook functions, call the agent's handler
|