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.
Files changed (211) hide show
  1. {signalwire_sdk-3.0.2.dev62/signalwire/signalwire_sdk.egg-info → signalwire_sdk-3.0.2.dev63}/PKG-INFO +1 -1
  2. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/pyproject.toml +15 -1
  3. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/__init__.py +1 -1
  4. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/agent_server.py +9 -7
  5. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/agents/bedrock.py +1 -1
  6. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/build_search.py +10 -5
  7. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/agent_loader.py +58 -34
  8. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/argparse_helpers.py +2 -2
  9. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/dynamic_config.py +2 -2
  10. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/service_loader.py +31 -16
  11. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/execution/datamap_exec.py +5 -5
  12. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/execution/webhook_exec.py +3 -1
  13. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/output/swml_dump.py +5 -2
  14. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/data_generation.py +1 -1
  15. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/mock_env.py +3 -3
  16. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/test_swaig.py +11 -4
  17. signalwire_sdk-3.0.2.dev63/signalwire/signalwire/core/_agent_host.py +24 -0
  18. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/prompt/manager.py +1 -1
  19. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/registry.py +1 -1
  20. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/type_inference.py +1 -1
  21. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent_base.py +61 -34
  22. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/auth_handler.py +27 -13
  23. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/config_loader.py +4 -2
  24. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/contexts.py +3 -3
  25. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/data_map.py +8 -8
  26. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/function_result.py +12 -8
  27. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/logging_config.py +2 -1
  28. signalwire_sdk-3.0.2.dev63/signalwire/signalwire/core/mixins/_mixin_host.py +42 -0
  29. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/ai_config_mixin.py +9 -6
  30. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/auth_mixin.py +4 -1
  31. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/mcp_server_mixin.py +2 -2
  32. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/prompt_mixin.py +9 -2
  33. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/serverless_mixin.py +2 -1
  34. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/skill_mixin.py +5 -2
  35. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/state_mixin.py +3 -1
  36. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/tool_mixin.py +6 -5
  37. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/web_mixin.py +19 -16
  38. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/webhook_middleware.py +2 -2
  39. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security_config.py +1 -1
  40. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/skill_base.py +4 -4
  41. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/skill_manager.py +2 -2
  42. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swaig_function.py +2 -2
  43. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_builder.py +8 -8
  44. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_handler.py +2 -2
  45. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_renderer.py +7 -4
  46. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/swml_service.py +15 -8
  47. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/livewire/__init__.py +15 -14
  48. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/gateway_service.py +3 -3
  49. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/mcp_manager.py +19 -14
  50. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/session_manager.py +3 -3
  51. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/pom/pom.py +7 -6
  52. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/faq_bot.py +3 -3
  53. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/info_gatherer.py +3 -1
  54. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/call.py +7 -3
  55. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/client.py +24 -11
  56. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/_base.py +3 -1
  57. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/compat.py +9 -9
  58. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/__init__.py +15 -12
  59. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/document_processor.py +83 -52
  60. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/index_builder.py +21 -10
  61. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/migration.py +10 -7
  62. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/pgvector_backend.py +17 -12
  63. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/query_processor.py +7 -7
  64. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/search_engine.py +29 -18
  65. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/search_service.py +45 -36
  66. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/api_ninjas_trivia/skill.py +2 -2
  67. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/claude_skills/skill.py +1 -1
  68. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/google_maps/skill.py +1 -1
  69. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/math/skill.py +3 -3
  70. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/mcp_gateway/skill.py +2 -2
  71. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/native_vector_search/skill.py +18 -5
  72. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/play_background_file/skill.py +2 -2
  73. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/registry.py +15 -11
  74. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/spider/skill.py +14 -12
  75. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/weather_api/skill.py +2 -2
  76. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/skill.py +10 -9
  77. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/skill_improved.py +5 -4
  78. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/skill_original.py +3 -3
  79. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/schema_utils.py +15 -10
  80. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/web/web_service.py +32 -28
  81. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63/signalwire/signalwire_sdk.egg-info}/PKG-INFO +1 -1
  82. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/SOURCES.txt +2 -0
  83. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/LICENSE +0 -0
  84. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/README.md +0 -0
  85. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/man/sw-agent-init.1 +0 -0
  86. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/man/sw-search.1 +0 -0
  87. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/man/swaig-test.1 +0 -0
  88. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/setup.cfg +0 -0
  89. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/setup.py +0 -0
  90. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/__init__.py +0 -0
  91. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/config.py +0 -0
  92. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/core/__init__.py +0 -0
  93. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/dokku.py +0 -0
  94. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/execution/__init__.py +0 -0
  95. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/init_project.py +0 -0
  96. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/output/__init__.py +0 -0
  97. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/output/output_formatter.py +0 -0
  98. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/__init__.py +0 -0
  99. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/simulation/data_overrides.py +0 -0
  100. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/swaig_test_wrapper.py +0 -0
  101. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/cli/types.py +0 -0
  102. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/__init__.py +0 -0
  103. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/__init__.py +0 -0
  104. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/config/__init__.py +0 -0
  105. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/deployment/__init__.py +0 -0
  106. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/deployment/handlers/__init__.py +0 -0
  107. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/prompt/__init__.py +0 -0
  108. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/routing/__init__.py +0 -0
  109. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/security/__init__.py +0 -0
  110. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/swml/__init__.py +0 -0
  111. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/__init__.py +0 -0
  112. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/agent/tools/decorator.py +0 -0
  113. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/mixins/__init__.py +0 -0
  114. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/pom_builder.py +0 -0
  115. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/__init__.py +0 -0
  116. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/security_utils.py +0 -0
  117. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/session_manager.py +0 -0
  118. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/core/security/webhook_validator.py +0 -0
  119. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/livewire/plugins.py +0 -0
  120. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/mcp_gateway/__init__.py +0 -0
  121. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/pom/__init__.py +0 -0
  122. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/pom/pom_tool.py +0 -0
  123. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/__init__.py +0 -0
  124. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/concierge.py +0 -0
  125. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/receptionist.py +0 -0
  126. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/prefabs/survey.py +0 -0
  127. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/__init__.py +0 -0
  128. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/constants.py +0 -0
  129. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/event.py +0 -0
  130. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/relay/message.py +0 -0
  131. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/__init__.py +0 -0
  132. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/_pagination.py +0 -0
  133. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/call_handler.py +0 -0
  134. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/client.py +0 -0
  135. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/__init__.py +0 -0
  136. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/addresses.py +0 -0
  137. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/calling.py +0 -0
  138. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/chat.py +0 -0
  139. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/datasphere.py +0 -0
  140. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/fabric.py +0 -0
  141. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/imported_numbers.py +0 -0
  142. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/logs.py +0 -0
  143. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/lookup.py +0 -0
  144. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/mfa.py +0 -0
  145. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/number_groups.py +0 -0
  146. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/phone_numbers.py +0 -0
  147. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/project.py +0 -0
  148. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/pubsub.py +0 -0
  149. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/queues.py +0 -0
  150. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/recordings.py +0 -0
  151. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/registry.py +0 -0
  152. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/short_codes.py +0 -0
  153. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/sip_profile.py +0 -0
  154. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/verified_callers.py +0 -0
  155. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/rest/namespaces/video.py +0 -0
  156. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/schema.json +0 -0
  157. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/search/models.py +0 -0
  158. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/README.md +0 -0
  159. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/__init__.py +0 -0
  160. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/api_ninjas_trivia/README.md +0 -0
  161. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/api_ninjas_trivia/__init__.py +0 -0
  162. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/claude_skills/README.md +0 -0
  163. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/claude_skills/__init__.py +0 -0
  164. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere/README.md +0 -0
  165. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere/__init__.py +0 -0
  166. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere/skill.py +0 -0
  167. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere_serverless/README.md +0 -0
  168. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere_serverless/__init__.py +0 -0
  169. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datasphere_serverless/skill.py +0 -0
  170. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datetime/README.md +0 -0
  171. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datetime/__init__.py +0 -0
  172. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/datetime/skill.py +0 -0
  173. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/google_maps/__init__.py +0 -0
  174. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/info_gatherer/README.md +0 -0
  175. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/info_gatherer/__init__.py +0 -0
  176. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/info_gatherer/skill.py +0 -0
  177. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/joke/README.md +0 -0
  178. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/joke/__init__.py +0 -0
  179. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/joke/skill.py +0 -0
  180. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/math/README.md +0 -0
  181. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/math/__init__.py +0 -0
  182. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/mcp_gateway/README.md +0 -0
  183. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/mcp_gateway/__init__.py +0 -0
  184. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/native_vector_search/README.md +0 -0
  185. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/native_vector_search/__init__.py +0 -0
  186. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/play_background_file/README.md +0 -0
  187. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/play_background_file/__init__.py +0 -0
  188. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/spider/README.md +0 -0
  189. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/spider/__init__.py +0 -0
  190. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/swml_transfer/README.md +0 -0
  191. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/swml_transfer/__init__.py +0 -0
  192. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/swml_transfer/skill.py +0 -0
  193. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/weather_api/README.md +0 -0
  194. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/weather_api/__init__.py +0 -0
  195. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/README.md +0 -0
  196. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/web_search/__init__.py +0 -0
  197. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/wikipedia_search/README.md +0 -0
  198. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/wikipedia_search/__init__.py +0 -0
  199. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/skills/wikipedia_search/skill.py +0 -0
  200. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/__init__.py +0 -0
  201. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/pom_utils.py +0 -0
  202. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/token_generators.py +0 -0
  203. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/url_validator.py +0 -0
  204. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/utils/validators.py +0 -0
  205. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire/web/__init__.py +0 -0
  206. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/dependency_links.txt +0 -0
  207. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/entry_points.txt +0 -0
  208. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/requires.txt +0 -0
  209. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/signalwire/signalwire_sdk.egg-info/top_level.txt +0 -0
  210. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/tests/test_examples.py +0 -0
  211. {signalwire_sdk-3.0.2.dev62 → signalwire_sdk-3.0.2.dev63}/tests/test_mcp_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalwire-sdk
3
- Version: 3.0.2.dev62
3
+ Version: 3.0.2.dev63
4
4
  Summary: SignalWire SDK
5
5
  Author-email: SignalWire Team <info@signalwire.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "signalwire-sdk"
7
- version = "3.0.2.dev62"
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.dev62"
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
@@ -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.dev62",
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
- if hasattr(self, "_sip_routing_callback") and self._sip_routing_callback:
149
- agent.register_routing_callback(
150
- self._sip_routing_callback, path=self._sip_route
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
- username, password = agent.get_basic_auth_credentials()
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}")
@@ -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
@@ -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 f in chunk_files_created:
579
- with open(f) as fh:
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=enhanced.get("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=enhanced.get("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
- try:
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
- except ImportError:
29
- AgentBase = None
30
- SWMLService = None
31
- ServiceCapture = None
32
- new_load_agent = None
33
- AGENT_BASE_AVAILABLE = False
34
- SWML_SERVICE_AVAILABLE = False
35
- NEW_LOADER_AVAILABLE = False
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
- service_path = Path(service_path).resolve()
96
+ resolved_path = Path(service_path).resolve()
81
97
 
82
- if not service_path.exists():
83
- raise FileNotFoundError(f"Service file not found: {service_path}")
98
+ if not resolved_path.exists():
99
+ raise FileNotFoundError(f"Service file not found: {resolved_path}")
84
100
 
85
- if not service_path.suffix == ".py":
86
- raise ValueError(f"Service file must be a Python file (.py): {service_path}")
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(service_path.parent)
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", service_path)
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
- service_path = Path(service_path).resolve()
280
+ resolved_path = Path(service_path).resolve()
263
281
 
264
- if not service_path.exists():
265
- raise FileNotFoundError(f"Service file not found: {service_path}")
282
+ if not resolved_path.exists():
283
+ raise FileNotFoundError(f"Service file not found: {resolved_path}")
266
284
 
267
- if not service_path.suffix == ".py":
268
- raise ValueError(f"Service file must be a Python file (.py): {service_path}")
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(service_path.parent)
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", service_path)
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
- temp_instance = obj()
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 = obj() # Create anyway if requested specifically
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: Dict[str, Any]
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
- try:
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
- except ImportError:
28
- AgentBase = None
29
- SWMLService = None
30
- Request = None
31
- Response = None
32
- DEPENDENCIES_AVAILABLE = False
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
- service_path = Path(service_path).resolve()
69
+ resolved_path = Path(service_path).resolve()
61
70
 
62
- if not service_path.exists():
63
- raise FileNotFoundError(f"Service file not found: {service_path}")
71
+ if not resolved_path.exists():
72
+ raise FileNotFoundError(f"Service file not found: {resolved_path}")
64
73
 
65
- if not service_path.suffix == ".py":
74
+ if not resolved_path.suffix == ".py":
66
75
  raise ValueError(
67
- f"Service file must be a Python file (.py): {service_path}"
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__", service_path)
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
- result = await service._handle_request(request, response)
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
- ) -> Dict[str, Any]:
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
- modifications = agent.on_swml_request(post_data, "/swml", mock_request)
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}")
@@ -165,7 +165,7 @@ def generate_comprehensive_post_data(
165
165
  current_time = datetime.now().isoformat()
166
166
 
167
167
  # Base structure with all keys
168
- post_data = {
168
+ post_data: Dict[str, Any] = {
169
169
  "call_id": call_id,
170
170
  "call": {
171
171
  "call_id": call_id,
@@ -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())
@@ -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(func, function_args, args.verbose)
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
- func, args.tool_name, function_args, post_data, args.verbose
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