rasa-pro 3.14.0.dev20250922__py3-none-any.whl → 3.14.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rasa-pro might be problematic. Click here for more details.

Files changed (304) hide show
  1. rasa/__main__.py +15 -3
  2. rasa/agents/__init__.py +0 -0
  3. rasa/agents/agent_factory.py +122 -0
  4. rasa/agents/agent_manager.py +211 -0
  5. rasa/agents/constants.py +43 -0
  6. rasa/agents/core/__init__.py +0 -0
  7. rasa/agents/core/agent_protocol.py +107 -0
  8. rasa/agents/core/types.py +81 -0
  9. rasa/agents/exceptions.py +38 -0
  10. rasa/agents/protocol/__init__.py +5 -0
  11. rasa/agents/protocol/a2a/__init__.py +0 -0
  12. rasa/agents/protocol/a2a/a2a_agent.py +879 -0
  13. rasa/agents/protocol/mcp/__init__.py +0 -0
  14. rasa/agents/protocol/mcp/mcp_base_agent.py +726 -0
  15. rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
  16. rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
  17. rasa/agents/schemas/__init__.py +13 -0
  18. rasa/agents/schemas/agent_input.py +38 -0
  19. rasa/agents/schemas/agent_output.py +26 -0
  20. rasa/agents/schemas/agent_tool_result.py +65 -0
  21. rasa/agents/schemas/agent_tool_schema.py +186 -0
  22. rasa/agents/templates/__init__.py +0 -0
  23. rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
  24. rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
  25. rasa/agents/utils.py +206 -0
  26. rasa/agents/validation.py +485 -0
  27. rasa/api.py +24 -9
  28. rasa/builder/config.py +6 -2
  29. rasa/builder/copilot/constants.py +4 -1
  30. rasa/builder/copilot/copilot.py +155 -79
  31. rasa/builder/copilot/models.py +304 -108
  32. rasa/builder/copilot/prompts/copilot_training_error_handler_prompt.jinja2 +53 -0
  33. rasa/builder/guardrails/{lakera.py → clients.py} +55 -5
  34. rasa/builder/guardrails/constants.py +3 -0
  35. rasa/builder/guardrails/models.py +45 -10
  36. rasa/builder/guardrails/policy_checker.py +324 -0
  37. rasa/builder/guardrails/utils.py +42 -276
  38. rasa/builder/jobs.py +182 -12
  39. rasa/builder/llm_service.py +32 -5
  40. rasa/builder/models.py +13 -3
  41. rasa/builder/project_generator.py +6 -1
  42. rasa/builder/service.py +31 -15
  43. rasa/builder/training_service.py +18 -24
  44. rasa/builder/validation_service.py +1 -1
  45. rasa/cli/arguments/default_arguments.py +12 -0
  46. rasa/cli/arguments/run.py +2 -0
  47. rasa/cli/arguments/train.py +2 -0
  48. rasa/cli/data.py +10 -8
  49. rasa/cli/dialogue_understanding_test.py +10 -7
  50. rasa/cli/e2e_test.py +9 -6
  51. rasa/cli/evaluate.py +4 -2
  52. rasa/cli/export.py +5 -2
  53. rasa/cli/inspect.py +8 -4
  54. rasa/cli/interactive.py +5 -4
  55. rasa/cli/llm_fine_tuning.py +11 -6
  56. rasa/cli/project_templates/finance/domain/general/help.yml +0 -0
  57. rasa/cli/project_templates/tutorial/credentials.yml +10 -0
  58. rasa/cli/run.py +12 -10
  59. rasa/cli/scaffold.py +4 -4
  60. rasa/cli/shell.py +9 -5
  61. rasa/cli/studio/studio.py +1 -1
  62. rasa/cli/test.py +34 -14
  63. rasa/cli/train.py +41 -28
  64. rasa/cli/utils.py +1 -393
  65. rasa/cli/validation/__init__.py +0 -0
  66. rasa/cli/validation/bot_config.py +223 -0
  67. rasa/cli/validation/config_path_validation.py +257 -0
  68. rasa/cli/x.py +8 -4
  69. rasa/constants.py +7 -1
  70. rasa/core/actions/action.py +51 -10
  71. rasa/core/actions/grpc_custom_action_executor.py +1 -1
  72. rasa/core/agent.py +19 -2
  73. rasa/core/available_agents.py +229 -0
  74. rasa/core/brokers/kafka.py +5 -1
  75. rasa/core/channels/__init__.py +82 -35
  76. rasa/core/channels/development_inspector.py +3 -3
  77. rasa/core/channels/inspector/README.md +25 -13
  78. rasa/core/channels/inspector/dist/assets/{arc-35222594.js → arc-6177260a.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-a0efbfd3.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0584c0f2.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
  82. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-39f40dbe.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-1ad755f3.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
  85. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-b0f4f0fe.js → createText-2e5e7dd3-088372e2.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-9039bff9.js → edges-e0da2a9e-58676240.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-65c9b127.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4f08b38e.js → flowDb-956e92f1-ea63f85c.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-e95c362a.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
  91. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-703c3015.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
  92. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-699328ea.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
  93. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-04cf4b05.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
  94. rasa/core/channels/inspector/dist/assets/{graph-ee94449e.js → graph-0a6f8466.js} +1 -1
  95. rasa/core/channels/inspector/dist/assets/{index-3862675e-940162b4.js → index-3862675e-7610671a.js} +1 -1
  96. rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
  97. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-c79c2866.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
  98. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-84489d30.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
  99. rasa/core/channels/inspector/dist/assets/{layout-a9aa9858.js → layout-e7fbc2bf.js} +1 -1
  100. rasa/core/channels/inspector/dist/assets/{line-eb73cf26.js → line-a8aa457c.js} +1 -1
  101. rasa/core/channels/inspector/dist/assets/{linear-b3399f9a.js → linear-3351e0d2.js} +1 -1
  102. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-b095bf1a.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
  103. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-07644b66.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
  104. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-573a3f9c.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
  105. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d457e1e1.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
  106. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-9d26e1a2.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
  107. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3a9cde10.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
  108. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-4f3e8cec.js → stateDiagram-587899a1-0e770395.js} +1 -1
  109. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e617e5bf.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
  110. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-eab30d2f.js → styles-6aaf32cf-36a9e70d.js} +1 -1
  111. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-09994be2.js → styles-9a916d00-884a8b5b.js} +1 -1
  112. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-b7110364.js → styles-c10674c1-dc097813.js} +1 -1
  113. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-3ebc92ad.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
  114. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-7d13d2f2.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
  115. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-488385e1.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
  116. rasa/core/channels/inspector/dist/index.html +1 -1
  117. rasa/core/channels/inspector/package.json +18 -18
  118. rasa/core/channels/inspector/src/App.tsx +29 -4
  119. rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
  120. rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
  121. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +7 -4
  122. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
  123. rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
  124. rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
  125. rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
  126. rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
  127. rasa/core/channels/inspector/src/types.ts +21 -0
  128. rasa/core/channels/inspector/yarn.lock +336 -189
  129. rasa/core/channels/studio_chat.py +6 -6
  130. rasa/core/channels/telegram.py +4 -9
  131. rasa/core/channels/voice_stream/genesys.py +1 -1
  132. rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
  133. rasa/core/channels/voice_stream/twilio_media_streams.py +5 -1
  134. rasa/core/channels/voice_stream/voice_channel.py +3 -0
  135. rasa/core/concurrent_lock_store.py +38 -21
  136. rasa/core/config/__init__.py +0 -0
  137. rasa/core/{available_endpoints.py → config/available_endpoints.py} +51 -16
  138. rasa/core/config/configuration.py +260 -0
  139. rasa/core/config/credentials.py +19 -0
  140. rasa/core/config/message_procesing_config.py +34 -0
  141. rasa/core/constants.py +10 -0
  142. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +69 -4
  143. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +2 -1
  144. rasa/core/lock_store.py +4 -0
  145. rasa/core/policies/enterprise_search_policy.py +5 -3
  146. rasa/core/policies/flow_policy.py +4 -4
  147. rasa/core/policies/flows/agent_executor.py +632 -0
  148. rasa/core/policies/flows/flow_executor.py +136 -75
  149. rasa/core/policies/flows/mcp_tool_executor.py +298 -0
  150. rasa/core/policies/intentless_policy.py +1 -1
  151. rasa/core/policies/ted_policy.py +20 -12
  152. rasa/core/policies/unexpected_intent_policy.py +6 -0
  153. rasa/core/processor.py +68 -44
  154. rasa/core/redis_connection_factory.py +7 -2
  155. rasa/core/run.py +37 -8
  156. rasa/core/test.py +4 -0
  157. rasa/core/tracker_stores/redis_tracker_store.py +4 -0
  158. rasa/core/tracker_stores/sql_tracker_store.py +3 -1
  159. rasa/core/tracker_stores/tracker_store.py +3 -7
  160. rasa/core/train.py +1 -1
  161. rasa/core/training/interactive.py +20 -18
  162. rasa/core/training/story_conflict.py +5 -5
  163. rasa/core/utils.py +22 -23
  164. rasa/dialogue_understanding/commands/__init__.py +8 -0
  165. rasa/dialogue_understanding/commands/cancel_flow_command.py +19 -5
  166. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
  167. rasa/dialogue_understanding/commands/clarify_command.py +20 -2
  168. rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
  169. rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
  170. rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
  171. rasa/dialogue_understanding/commands/start_flow_command.py +68 -7
  172. rasa/dialogue_understanding/commands/utils.py +124 -2
  173. rasa/dialogue_understanding/generator/command_parser.py +4 -0
  174. rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
  175. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  176. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
  177. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
  178. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
  179. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
  180. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
  181. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
  182. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
  183. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
  184. rasa/dialogue_understanding/patterns/cancel.py +27 -6
  185. rasa/dialogue_understanding/patterns/clarify.py +3 -14
  186. rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
  187. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +46 -8
  188. rasa/dialogue_understanding/processor/command_processor.py +136 -15
  189. rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
  190. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
  191. rasa/dialogue_understanding/stack/utils.py +57 -3
  192. rasa/dialogue_understanding/utils.py +24 -4
  193. rasa/dialogue_understanding_test/du_test_runner.py +8 -3
  194. rasa/e2e_test/e2e_test_runner.py +13 -3
  195. rasa/engine/caching.py +2 -2
  196. rasa/engine/constants.py +1 -1
  197. rasa/engine/recipes/default_components.py +138 -49
  198. rasa/engine/recipes/default_recipe.py +108 -11
  199. rasa/engine/runner/dask.py +8 -5
  200. rasa/engine/validation.py +19 -6
  201. rasa/graph_components/validators/default_recipe_validator.py +86 -28
  202. rasa/hooks.py +5 -5
  203. rasa/llm_fine_tuning/utils.py +2 -2
  204. rasa/model_training.py +60 -47
  205. rasa/nlu/classifiers/diet_classifier.py +198 -98
  206. rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
  207. rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
  208. rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
  209. rasa/nlu/extractors/crf_entity_extractor.py +9 -10
  210. rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
  211. rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
  212. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
  213. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
  214. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
  215. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
  216. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
  217. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
  218. rasa/nlu/selectors/response_selector.py +10 -2
  219. rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
  220. rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
  221. rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
  222. rasa/nlu/utils/mitie_utils.py +3 -0
  223. rasa/nlu/utils/spacy_utils.py +3 -2
  224. rasa/plugin.py +8 -8
  225. rasa/privacy/privacy_manager.py +12 -3
  226. rasa/server.py +15 -3
  227. rasa/shared/agents/__init__.py +0 -0
  228. rasa/shared/agents/auth/__init__.py +0 -0
  229. rasa/shared/agents/auth/agent_auth_factory.py +105 -0
  230. rasa/shared/agents/auth/agent_auth_manager.py +92 -0
  231. rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
  232. rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
  233. rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
  234. rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
  235. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +167 -0
  236. rasa/shared/agents/auth/constants.py +12 -0
  237. rasa/shared/agents/auth/types.py +12 -0
  238. rasa/shared/agents/utils.py +35 -0
  239. rasa/shared/constants.py +8 -0
  240. rasa/shared/core/constants.py +16 -1
  241. rasa/shared/core/domain.py +0 -7
  242. rasa/shared/core/events.py +327 -0
  243. rasa/shared/core/flows/constants.py +5 -0
  244. rasa/shared/core/flows/flows_list.py +21 -5
  245. rasa/shared/core/flows/flows_yaml_schema.json +119 -184
  246. rasa/shared/core/flows/steps/call.py +49 -5
  247. rasa/shared/core/flows/steps/collect.py +98 -13
  248. rasa/shared/core/flows/validation.py +372 -8
  249. rasa/shared/core/flows/yaml_flows_io.py +3 -2
  250. rasa/shared/core/slots.py +2 -2
  251. rasa/shared/core/trackers.py +5 -2
  252. rasa/shared/exceptions.py +16 -0
  253. rasa/shared/importers/rasa.py +1 -1
  254. rasa/shared/importers/utils.py +9 -3
  255. rasa/shared/providers/llm/_base_litellm_client.py +41 -9
  256. rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
  257. rasa/shared/providers/llm/llm_client.py +7 -3
  258. rasa/shared/providers/llm/llm_response.py +66 -0
  259. rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
  260. rasa/shared/utils/common.py +24 -0
  261. rasa/shared/utils/health_check/health_check.py +7 -3
  262. rasa/shared/utils/llm.py +39 -16
  263. rasa/shared/utils/mcp/__init__.py +0 -0
  264. rasa/shared/utils/mcp/server_connection.py +247 -0
  265. rasa/shared/utils/mcp/utils.py +20 -0
  266. rasa/shared/utils/schemas/events.py +42 -0
  267. rasa/shared/utils/yaml.py +3 -1
  268. rasa/studio/pull/pull.py +3 -2
  269. rasa/studio/train.py +8 -7
  270. rasa/studio/upload.py +3 -6
  271. rasa/telemetry.py +69 -5
  272. rasa/tracing/config.py +45 -12
  273. rasa/tracing/constants.py +14 -0
  274. rasa/tracing/instrumentation/attribute_extractors.py +142 -9
  275. rasa/tracing/instrumentation/instrumentation.py +626 -21
  276. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
  277. rasa/tracing/instrumentation/metrics.py +32 -0
  278. rasa/tracing/metric_instrument_provider.py +68 -0
  279. rasa/utils/common.py +92 -1
  280. rasa/utils/endpoints.py +11 -2
  281. rasa/utils/log_utils.py +96 -5
  282. rasa/utils/ml_utils.py +1 -1
  283. rasa/utils/tensorflow/__init__.py +7 -0
  284. rasa/utils/tensorflow/callback.py +136 -101
  285. rasa/utils/tensorflow/crf.py +1 -1
  286. rasa/utils/tensorflow/data_generator.py +21 -8
  287. rasa/utils/tensorflow/layers.py +21 -11
  288. rasa/utils/tensorflow/metrics.py +7 -3
  289. rasa/utils/tensorflow/models.py +56 -8
  290. rasa/utils/tensorflow/rasa_layers.py +8 -6
  291. rasa/utils/tensorflow/transformer.py +2 -3
  292. rasa/utils/train_utils.py +54 -24
  293. rasa/validator.py +5 -5
  294. rasa/version.py +1 -1
  295. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/METADATA +47 -41
  296. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/RECORD +299 -238
  297. rasa/builder/scrape_rasa_docs.py +0 -97
  298. rasa/core/channels/inspector/dist/assets/channel-8e08bed9.js +0 -1
  299. rasa/core/channels/inspector/dist/assets/clone-78c82dea.js +0 -1
  300. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b08f601.js +0 -1
  301. rasa/core/channels/inspector/dist/assets/index-c941dcb3.js +0 -1336
  302. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/NOTICE +0 -0
  303. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/WHEEL +0 -0
  304. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/entry_points.txt +0 -0
@@ -93,12 +93,12 @@ class StudioTrackerUpdatePlugin:
93
93
  """Remove tasks that have already completed."""
94
94
  self.tasks = [task for task in self.tasks if not task.done()]
95
95
 
96
- @hookimpl # type: ignore[misc]
96
+ @hookimpl
97
97
  def after_new_user_message(self, tracker: "DialogueStateTracker") -> None:
98
98
  """Triggers a tracker update notification after a new user message."""
99
99
  self.handle_tracker_update(tracker)
100
100
 
101
- @hookimpl # type: ignore[misc]
101
+ @hookimpl
102
102
  def after_action_executed(self, tracker: "DialogueStateTracker") -> None:
103
103
  """Triggers a tracker update notification after an action is executed."""
104
104
  self.handle_tracker_update(tracker)
@@ -118,7 +118,7 @@ class StudioTrackerUpdatePlugin:
118
118
  self.tasks.append(task)
119
119
  self._cleanup_tasks()
120
120
 
121
- @hookimpl # type: ignore[misc]
121
+ @hookimpl
122
122
  def after_server_stop(self) -> None:
123
123
  """Cancels all remaining tasks when the server stops."""
124
124
  self._cancel_tasks()
@@ -438,7 +438,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
438
438
  if sid in self.active_connections:
439
439
  del self.active_connections[sid]
440
440
 
441
- @hookimpl # type: ignore[misc]
441
+ @hookimpl
442
442
  def after_server_stop(self) -> None:
443
443
  """Cleanup background tasks and active connections when the server stops."""
444
444
  structlogger.info("studio_chat.after_server_stop.cleanup")
@@ -533,7 +533,7 @@ class StudioVoiceOutputChannel(VoiceOutputChannel):
533
533
 
534
534
  def create_marker_message(self, recipient_id: str) -> Tuple[str, str]:
535
535
  message_id = uuid.uuid4().hex
536
- marker_data = {"marker": message_id}
536
+ marker_data: Dict[str, Any] = {"marker": message_id}
537
537
 
538
538
  # Include comprehensive latency information if available
539
539
  latency_data = {
@@ -548,7 +548,7 @@ class StudioVoiceOutputChannel(VoiceOutputChannel):
548
548
 
549
549
  # Add latency data to marker if any metrics are available
550
550
  if latency_data:
551
- marker_data["latency"] = latency_data # type: ignore[assignment]
551
+ marker_data["latency"] = latency_data
552
552
 
553
553
  return json.dumps(marker_data), message_id
554
554
 
@@ -4,6 +4,9 @@ import typing
4
4
  from copy import deepcopy
5
5
  from typing import Any, Awaitable, Callable, Dict, List, Optional, Text
6
6
 
7
+ # Import aiogram at module level to raise error if not installed
8
+ from aiogram import Bot
9
+ from aiogram.types import Message, Update
7
10
  from sanic import Blueprint, response
8
11
  from sanic.request import Request
9
12
  from sanic.response import HTTPResponse
@@ -28,15 +31,7 @@ class TelegramOutput(OutputChannel):
28
31
  return "telegram"
29
32
 
30
33
  def __init__(self, access_token: Optional[Text]) -> None:
31
- try:
32
- from aiogram import Bot
33
-
34
- self.bot = Bot(access_token)
35
- except ImportError:
36
- raise ImportError(
37
- "To use the Telegram channel, please install the aiogram package "
38
- "with 'pip install aiogram'"
39
- )
34
+ self.bot = Bot(access_token)
40
35
 
41
36
  async def send_text_message(
42
37
  self, recipient_id: Text, text: Text, **kwargs: Any
@@ -275,7 +275,7 @@ class GenesysInputChannel(VoiceInputChannel):
275
275
 
276
276
  def handle_ping(self, ws: Websocket, message: dict) -> None:
277
277
  """Handle ping message from Genesys."""
278
- response = {
278
+ response: Dict[str, Any] = {
279
279
  "version": "2",
280
280
  "type": "pong",
281
281
  "seq": self._get_next_sequence(),
@@ -0,0 +1,140 @@
1
+ import os
2
+ from dataclasses import dataclass
3
+ from typing import AsyncIterator, Dict, Optional
4
+ from urllib.parse import urlencode
5
+
6
+ import aiohttp
7
+ import orjson
8
+ import structlog
9
+ from aiohttp import ClientConnectorError, ClientTimeout, WSMsgType
10
+
11
+ from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
12
+ from rasa.core.channels.voice_stream.tts.tts_engine import (
13
+ TTSEngine,
14
+ TTSEngineConfig,
15
+ TTSError,
16
+ )
17
+ from rasa.shared.constants import DEEPGRAM_API_KEY_ENV_VAR
18
+ from rasa.shared.exceptions import ConnectionException
19
+
20
+ structlogger = structlog.get_logger()
21
+
22
+
23
+ @dataclass
24
+ class DeepgramTTSConfig(TTSEngineConfig):
25
+ model_id: Optional[str] = None
26
+ endpoint: Optional[str] = None
27
+
28
+
29
+ class DeepgramTTS(TTSEngine[DeepgramTTSConfig]):
30
+ session: Optional[aiohttp.ClientSession] = None
31
+ required_env_vars = (DEEPGRAM_API_KEY_ENV_VAR,)
32
+ ws: Optional[aiohttp.ClientWebSocketResponse] = None
33
+
34
+ def __init__(self, config: Optional[DeepgramTTSConfig] = None):
35
+ super().__init__(config)
36
+ timeout = ClientTimeout(total=self.config.timeout)
37
+ # Have to create this class-shared session lazily at run time otherwise
38
+ # the async event loop doesn't work
39
+ if self.__class__.session is None or self.__class__.session.closed:
40
+ self.__class__.session = aiohttp.ClientSession(timeout=timeout)
41
+
42
+ @staticmethod
43
+ def get_request_headers(config: DeepgramTTSConfig) -> dict[str, str]:
44
+ deepgram_api_key = os.environ[DEEPGRAM_API_KEY_ENV_VAR]
45
+ return {
46
+ "Authorization": f"Token {deepgram_api_key!s}",
47
+ }
48
+
49
+ async def close_connection(self) -> None:
50
+ """Close WebSocket connection if it exists."""
51
+ if self.ws and not self.ws.closed:
52
+ await self.ws.close()
53
+ self.ws = None
54
+
55
+ def get_websocket_url(self, config: DeepgramTTSConfig) -> str:
56
+ """Build WebSocket URL with query parameters."""
57
+ base_url = config.endpoint
58
+ query_params = {
59
+ "model": config.model_id,
60
+ "encoding": "mulaw",
61
+ "sample_rate": "8000",
62
+ }
63
+ return f"{base_url}?{urlencode(query_params)}"
64
+
65
+ async def synthesize(
66
+ self, text: str, config: Optional[DeepgramTTSConfig] = None
67
+ ) -> AsyncIterator[RasaAudioBytes]:
68
+ """Generate speech from text using Deepgram WebSocket TTS API."""
69
+ config = self.config.merge(config)
70
+ headers = self.get_request_headers(config)
71
+ ws_url = self.get_websocket_url(config)
72
+
73
+ if self.session is None:
74
+ raise ConnectionException("Client session is not initialized")
75
+
76
+ try:
77
+ self.ws = await self.session.ws_connect(
78
+ ws_url,
79
+ headers=headers,
80
+ timeout=float(self.config.timeout),
81
+ )
82
+ await self.ws.send_json(
83
+ {
84
+ "type": "Speak",
85
+ "text": text,
86
+ }
87
+ )
88
+ await self.ws.send_json({"type": "Flush"})
89
+ async for msg in self.ws:
90
+ if msg.type == WSMsgType.BINARY:
91
+ # Binary data is the raw audio
92
+ yield self.engine_bytes_to_rasa_audio_bytes(msg.data)
93
+ elif msg.type == WSMsgType.TEXT:
94
+ # Handle control messages if needed
95
+ data = orjson.loads(msg.data)
96
+ if data.get("type") == "Close":
97
+ break
98
+ elif data.get("type") == "Flushed":
99
+ break # End of stream
100
+ elif msg.type == WSMsgType.CLOSED:
101
+ break
102
+ elif msg.type == WSMsgType.ERROR:
103
+ structlogger.error(
104
+ "deepgram.synthesize.ws.error", error=str(msg.data)
105
+ )
106
+ raise TTSError(f"WebSocket error: {msg.data}")
107
+
108
+ # Send a close message
109
+ if self.ws and not self.ws.closed:
110
+ await self.ws.send_json({"type": "Close"})
111
+
112
+ except ClientConnectorError as e:
113
+ structlogger.error("deepgram.synthesize.ws.connection_error", error=str(e))
114
+ raise TTSError(f"Failed to connect to Deepgram TTS service: {e}")
115
+ except TimeoutError as e:
116
+ structlogger.error("deepgram.synthesize.ws.timeout", error=str(e))
117
+ raise TTSError(f"Connection to Deepgram TTS service timed out: {e}")
118
+ except Exception as e:
119
+ structlogger.error("deepgram.synthesize.ws.error", error=str(e))
120
+ raise TTSError(f"Error during TTS synthesis: {e}")
121
+ finally:
122
+ # Ensure connection is closed
123
+ await self.close_connection()
124
+
125
+ def engine_bytes_to_rasa_audio_bytes(self, chunk: bytes) -> RasaAudioBytes:
126
+ """Convert the generated tts audio bytes into rasa audio bytes."""
127
+ # WebSocket returns raw audio bytes directly
128
+ return RasaAudioBytes(chunk)
129
+
130
+ @staticmethod
131
+ def get_default_config() -> DeepgramTTSConfig:
132
+ return DeepgramTTSConfig(
133
+ model_id="aura-2-andromeda-en",
134
+ endpoint="wss://api.deepgram.com/v1/speak",
135
+ timeout=30,
136
+ )
137
+
138
+ @classmethod
139
+ def from_config_dict(cls, config: Dict) -> "DeepgramTTS":
140
+ return cls(DeepgramTTSConfig.from_dict(config))
@@ -14,6 +14,9 @@ from sanic import ( # type: ignore[attr-defined]
14
14
  response,
15
15
  )
16
16
 
17
+ # Import twilio at module level to raise error if not installed
18
+ from twilio.twiml.voice_response import VoiceResponse
19
+
17
20
  from rasa.core.channels import UserMessage
18
21
  from rasa.core.channels.channel import (
19
22
  create_auth_requested_response_provider,
@@ -145,7 +148,8 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
145
148
  """Get the sender ID for the channel.
146
149
 
147
150
  Twilio Media Streams uses the Stream ID as Sender ID because
148
- it is required in OutputChannel.send_text_message to send messages."""
151
+ it is required in OutputChannel.send_text_message to send messages.
152
+ """
149
153
  return call_parameters.stream_id # type: ignore[return-value]
150
154
 
151
155
  def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
@@ -38,6 +38,7 @@ from rasa.core.channels.voice_stream.call_state import (
38
38
  )
39
39
  from rasa.core.channels.voice_stream.tts.azure import AzureTTS
40
40
  from rasa.core.channels.voice_stream.tts.cartesia import CartesiaTTS
41
+ from rasa.core.channels.voice_stream.tts.deepgram import DeepgramTTS
41
42
  from rasa.core.channels.voice_stream.tts.tts_cache import TTSCache
42
43
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine, TTSError
43
44
  from rasa.core.channels.voice_stream.util import (
@@ -133,6 +134,8 @@ def tts_engine_from_config(tts_config: Dict) -> TTSEngine:
133
134
  return AzureTTS.from_config_dict(tts_config)
134
135
  elif name.lower() == "cartesia":
135
136
  return CartesiaTTS.from_config_dict(tts_config)
137
+ elif name.lower() == "deepgram":
138
+ return DeepgramTTS.from_config_dict(tts_config)
136
139
  else:
137
140
  mark_as_beta_feature("Custom TTS Engine")
138
141
  try:
@@ -6,6 +6,9 @@ from typing import Deque, Optional, Text
6
6
  import structlog
7
7
  from pydantic import ValidationError
8
8
 
9
+ from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
10
+ SupportedServiceType,
11
+ )
9
12
  from rasa.core.lock import Ticket, TicketLock
10
13
  from rasa.core.lock_store import (
11
14
  DEFAULT_SOCKET_TIMEOUT_IN_SECONDS,
@@ -108,6 +111,7 @@ class ConcurrentRedisLockStore(LockStore):
108
111
  redis_config = RedisConfig(
109
112
  host=host,
110
113
  port=port,
114
+ service_type=SupportedServiceType.LOCK_STORE,
111
115
  db=db,
112
116
  username=username,
113
117
  password=password,
@@ -150,32 +154,45 @@ class ConcurrentRedisLockStore(LockStore):
150
154
  ),
151
155
  )
152
156
 
153
- def _get_keys_by_pattern(self, pattern: Text) -> list:
154
- """Get keys by pattern, using SCAN for cluster mode and KEYS for others."""
155
- if self.deployment_mode == DeploymentMode.CLUSTER.value:
156
- # In cluster mode, use SCAN to get keys more reliably
157
- keys = []
158
- cursor = 0
159
-
160
- while True:
161
- try:
162
- cursor, batch_keys = self.red.scan(cursor, match=pattern, count=100)
163
- keys.extend(batch_keys)
157
+ def _scan_cluster_keys(self, pattern: Text) -> list:
158
+ """Scan keys in cluster mode with proper cursor handling."""
159
+ keys = []
160
+ cursor = 0
161
+
162
+ while True:
163
+ try:
164
+ cursor, batch_keys = self.red.scan(cursor, match=pattern, count=100)
165
+ keys.extend(batch_keys)
166
+
167
+ if isinstance(cursor, dict):
168
+ # cursor is a dict mapping each node to its scan position. e.g
169
+ # {'127.0.0.1:7000': 0, '127.0.0.1:7001': 5, '127.0.0.1:7002': 0}
170
+ # A cursor value of 0 means that node has finished scanning
171
+ # When all nodes show 0, the entire cluster scan is complete
172
+ if all(v == 0 for v in cursor.values()):
173
+ break
174
+ else:
175
+ # if scan is complete
164
176
  if cursor == 0:
165
177
  break
166
- except Exception as e:
167
- structlogger.warning(
168
- "concurrent_redis_lock_store._get_keys_by_pattern.scan_interrupted",
169
- event_info=f"SCAN interrupted in cluster mode: {e}. "
170
- f"Returning {len(keys)} keys found so far.",
171
- )
172
- break
173
- else:
174
- # Standard and sentinel modes use KEYS
175
- keys = self.red.keys(pattern)
178
+
179
+ except Exception as e:
180
+ structlogger.warning(
181
+ "concurrent_redis_lock_store._get_keys_by_pattern.scan_interrupted",
182
+ event_info=f"SCAN interrupted in cluster mode: {e}. "
183
+ f"Returning {len(keys)} keys found so far.",
184
+ )
185
+ break
176
186
 
177
187
  return keys
178
188
 
189
+ def _get_keys_by_pattern(self, pattern: Text) -> list:
190
+ """Get keys by pattern, using SCAN for cluster mode and KEYS for others."""
191
+ if self.deployment_mode == DeploymentMode.CLUSTER.value:
192
+ return self._scan_cluster_keys(pattern)
193
+ else:
194
+ return self.red.keys(pattern)
195
+
179
196
  def issue_ticket(
180
197
  self, conversation_id: Text, lock_lifetime: float = LOCK_LIFETIME
181
198
  ) -> int:
File without changes
@@ -1,9 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import dataclasses
4
+ from pathlib import Path
4
5
  from typing import Any, Dict, List, Optional, Union
5
6
 
6
- from rasa.shared.constants import DEFAULT_ENDPOINTS_PATH
7
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
8
+
9
+ from rasa.core.constants import MCP_SERVERS_KEY
7
10
  from rasa.shared.core.constants import (
8
11
  GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE,
9
12
  GLOBAL_SILENCE_TIMEOUT_KEY,
@@ -57,14 +60,46 @@ class InteractionHandlingConfig:
57
60
  )
58
61
 
59
62
 
63
+ class MCPServerConfig(BaseModel):
64
+ model_config = ConfigDict(extra="allow")
65
+ name: str = Field(..., description="The name of the MCP server.")
66
+ url: str = Field(..., description="The URL of the MCP server.")
67
+ type: str = Field(..., description="The type of the MCP server.")
68
+ additional_params: Optional[Dict[str, Any]] = Field(
69
+ default_factory=dict, description="Additional parameters for the MCP server."
70
+ )
71
+
72
+ @model_validator(mode="after")
73
+ def validate_type(self) -> MCPServerConfig:
74
+ # validate that type is "http"
75
+ if self.type not in ["http", "https"]:
76
+ raise ValueError(f"Invalid MCP server type: {self.type}")
77
+ # validate that name and url are not empty
78
+ if not self.name or not self.url:
79
+ raise ValueError("Name and URL cannot be empty")
80
+ return self
81
+
82
+ @model_validator(mode="before")
83
+ def collect_additional_params(cls, values: Dict[str, Any]) -> Dict[str, Any]:
84
+ base_fields = {"name", "url", "type"}
85
+ extras = {k: v for k, v in values.items() if k not in base_fields}
86
+ if extras:
87
+ values["additional_params"] = extras
88
+ # remove them from top level so Pydantic doesn’t complain
89
+ for k in extras:
90
+ values.pop(k)
91
+ return values
92
+
93
+
60
94
  class AvailableEndpoints:
61
95
  """Collection of configured endpoints."""
62
96
 
63
97
  _instance = None
64
98
 
65
99
  @classmethod
66
- def read_endpoints(cls, endpoint_file: str) -> AvailableEndpoints:
100
+ def read_endpoints(cls, endpoint_file: Path) -> AvailableEndpoints:
67
101
  """Read the different endpoints from a yaml file."""
102
+
68
103
  nlg = read_endpoint_config(endpoint_file, endpoint_type="nlg")
69
104
  nlu = read_endpoint_config(endpoint_file, endpoint_type="nlu")
70
105
  action = read_endpoint_config(endpoint_file, endpoint_type="action_endpoint")
@@ -75,6 +110,14 @@ class AvailableEndpoints:
75
110
  lock_store = read_endpoint_config(endpoint_file, endpoint_type="lock_store")
76
111
  event_broker = read_endpoint_config(endpoint_file, endpoint_type="event_broker")
77
112
  vector_store = read_endpoint_config(endpoint_file, endpoint_type="vector_store")
113
+ raw_mcp_servers = read_property_config_from_endpoints_file(
114
+ endpoint_file, property_name=MCP_SERVERS_KEY
115
+ )
116
+ mcp_servers = (
117
+ [MCPServerConfig(**server) for server in raw_mcp_servers]
118
+ if raw_mcp_servers
119
+ else None
120
+ )
78
121
  model_groups = read_property_config_from_endpoints_file(
79
122
  endpoint_file, property_name="model_groups"
80
123
  )
@@ -89,6 +132,7 @@ class AvailableEndpoints:
89
132
  )
90
133
 
91
134
  return cls(
135
+ endpoint_file,
92
136
  nlg,
93
137
  nlu,
94
138
  action,
@@ -97,6 +141,7 @@ class AvailableEndpoints:
97
141
  lock_store,
98
142
  event_broker,
99
143
  vector_store,
144
+ mcp_servers,
100
145
  model_groups,
101
146
  privacy,
102
147
  interaction_handling,
@@ -104,6 +149,7 @@ class AvailableEndpoints:
104
149
 
105
150
  def __init__(
106
151
  self,
152
+ config_file_path: Optional[Path] = None,
107
153
  nlg: Optional[EndpointConfig] = None,
108
154
  nlu: Optional[EndpointConfig] = None,
109
155
  action: Optional[EndpointConfig] = None,
@@ -112,6 +158,7 @@ class AvailableEndpoints:
112
158
  lock_store: Optional[EndpointConfig] = None,
113
159
  event_broker: Optional[EndpointConfig] = None,
114
160
  vector_store: Optional[EndpointConfig] = None,
161
+ mcp_servers: Optional[List[MCPServerConfig]] = None,
115
162
  model_groups: Optional[List[Dict[str, Any]]] = None,
116
163
  privacy: Optional[Dict[str, Any]] = None,
117
164
  interaction_handling: InteractionHandlingConfig = InteractionHandlingConfig(
@@ -119,6 +166,7 @@ class AvailableEndpoints:
119
166
  ),
120
167
  ) -> None:
121
168
  """Create an `AvailableEndpoints` object."""
169
+ self.config_file_path = config_file_path
122
170
  self.model = model
123
171
  self.action = action
124
172
  self.nlu = nlu
@@ -127,20 +175,7 @@ class AvailableEndpoints:
127
175
  self.lock_store = lock_store
128
176
  self.event_broker = event_broker
129
177
  self.vector_store = vector_store
178
+ self.mcp_servers = mcp_servers
130
179
  self.model_groups = model_groups
131
180
  self.privacy = privacy
132
181
  self.interaction_handling = interaction_handling
133
-
134
- @classmethod
135
- def get_instance(
136
- cls, endpoint_file: Optional[str] = DEFAULT_ENDPOINTS_PATH
137
- ) -> AvailableEndpoints:
138
- """Get the singleton instance of AvailableEndpoints."""
139
- # Ensure that the instance is initialized only once.
140
- if cls._instance is None:
141
- cls._instance = cls.read_endpoints(endpoint_file)
142
- return cls._instance
143
-
144
- @classmethod
145
- def reset_instance(cls) -> None:
146
- cls._instance = None