rasa-pro 3.13.1a18__py3-none-any.whl → 3.13.3__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 (261) hide show
  1. rasa/cli/project_templates/defaults.py +25 -3
  2. rasa/cli/scaffold.py +3 -22
  3. rasa/core/actions/action.py +2 -4
  4. rasa/core/channels/studio_chat.py +10 -34
  5. rasa/core/channels/voice_stream/asr/asr_engine.py +5 -1
  6. rasa/core/channels/voice_stream/asr/deepgram.py +5 -0
  7. rasa/core/channels/voice_stream/audiocodes.py +9 -4
  8. rasa/core/channels/voice_stream/jambonz.py +1 -1
  9. rasa/core/channels/voice_stream/voice_channel.py +7 -0
  10. rasa/core/nlg/callback.py +1 -1
  11. rasa/core/policies/enterprise_search_policy.py +9 -8
  12. rasa/core/policies/flows/flow_executor.py +1 -8
  13. rasa/dialogue_understanding/commands/correct_slots_command.py +0 -10
  14. rasa/dialogue_understanding/generator/command_generator.py +5 -5
  15. rasa/dialogue_understanding/generator/flow_retrieval.py +9 -10
  16. rasa/dialogue_understanding/processor/command_processor.py +6 -1
  17. rasa/model_manager/model_api.py +3 -2
  18. rasa/model_manager/runner_service.py +1 -1
  19. rasa/model_manager/trainer_service.py +9 -12
  20. rasa/model_manager/utils.py +29 -1
  21. rasa/shared/core/domain.py +15 -62
  22. rasa/shared/core/flows/flow_step.py +1 -7
  23. rasa/shared/core/flows/yaml_flows_io.py +8 -16
  24. rasa/shared/core/slots.py +0 -4
  25. rasa/shared/importers/importer.py +0 -6
  26. rasa/shared/importers/utils.py +1 -77
  27. rasa/studio/upload.py +45 -10
  28. rasa/telemetry.py +1 -2
  29. rasa/utils/io.py +9 -27
  30. rasa/utils/json_utils.py +1 -6
  31. rasa/utils/log_utils.py +1 -5
  32. rasa/utils/plotting.py +1 -1
  33. rasa/validator.py +3 -7
  34. rasa/version.py +1 -1
  35. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.3.dist-info}/METADATA +8 -9
  36. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.3.dist-info}/RECORD +39 -261
  37. rasa/builder/README.md +0 -120
  38. rasa/builder/__init__.py +0 -0
  39. rasa/builder/config.py +0 -79
  40. rasa/builder/create_openai_vector_store.py +0 -228
  41. rasa/builder/exceptions.py +0 -55
  42. rasa/builder/inkeep-rag-response-schema.json +0 -64
  43. rasa/builder/inkeep_document_retrieval.py +0 -212
  44. rasa/builder/llm-helper-schema.json +0 -69
  45. rasa/builder/llm_context.py +0 -81
  46. rasa/builder/llm_helper_prompt.jinja2 +0 -245
  47. rasa/builder/llm_service.py +0 -317
  48. rasa/builder/logging_utils.py +0 -51
  49. rasa/builder/main.py +0 -147
  50. rasa/builder/models.py +0 -225
  51. rasa/builder/project_generator.py +0 -282
  52. rasa/builder/scrape_rasa_docs.py +0 -97
  53. rasa/builder/service.py +0 -742
  54. rasa/builder/skill_to_bot_prompt.jinja2 +0 -164
  55. rasa/builder/training_service.py +0 -132
  56. rasa/builder/validation_service.py +0 -93
  57. rasa/cli/project_templates/finance/actions/__init__.py +0 -0
  58. rasa/cli/project_templates/finance/actions/action_add_payee.py +0 -47
  59. rasa/cli/project_templates/finance/actions/action_ask_account.py +0 -50
  60. rasa/cli/project_templates/finance/actions/action_ask_account_from.py +0 -50
  61. rasa/cli/project_templates/finance/actions/action_ask_card.py +0 -47
  62. rasa/cli/project_templates/finance/actions/action_check_balance.py +0 -40
  63. rasa/cli/project_templates/finance/actions/action_check_card_existence.py +0 -35
  64. rasa/cli/project_templates/finance/actions/action_check_payee_existence.py +0 -40
  65. rasa/cli/project_templates/finance/actions/action_check_sufficient_funds.py +0 -41
  66. rasa/cli/project_templates/finance/actions/action_list_payees.py +0 -45
  67. rasa/cli/project_templates/finance/actions/action_process_immediate_payment.py +0 -18
  68. rasa/cli/project_templates/finance/actions/action_remove_payee.py +0 -49
  69. rasa/cli/project_templates/finance/actions/action_schedule_payment.py +0 -19
  70. rasa/cli/project_templates/finance/actions/action_session_start.py +0 -69
  71. rasa/cli/project_templates/finance/actions/action_update_card_status.py +0 -45
  72. rasa/cli/project_templates/finance/actions/action_validate_payment_date.py +0 -36
  73. rasa/cli/project_templates/finance/actions/database.py +0 -276
  74. rasa/cli/project_templates/finance/config.yml +0 -32
  75. rasa/cli/project_templates/finance/credentials.yml +0 -33
  76. rasa/cli/project_templates/finance/csvs/accounts.csv +0 -8
  77. rasa/cli/project_templates/finance/csvs/advisors.csv +0 -7
  78. rasa/cli/project_templates/finance/csvs/appointments.csv +0 -211
  79. rasa/cli/project_templates/finance/csvs/branches.csv +0 -10
  80. rasa/cli/project_templates/finance/csvs/cards.csv +0 -11
  81. rasa/cli/project_templates/finance/csvs/payees.csv +0 -10
  82. rasa/cli/project_templates/finance/csvs/transactions.csv +0 -71
  83. rasa/cli/project_templates/finance/csvs/users.csv +0 -4
  84. rasa/cli/project_templates/finance/data/flows/add_payee.yml +0 -29
  85. rasa/cli/project_templates/finance/data/flows/block_card.yml +0 -66
  86. rasa/cli/project_templates/finance/data/flows/check_balance.yml +0 -9
  87. rasa/cli/project_templates/finance/data/flows/list_payees.yml +0 -5
  88. rasa/cli/project_templates/finance/data/flows/remove_payee.yml +0 -21
  89. rasa/cli/project_templates/finance/data/flows/select_card.yml +0 -12
  90. rasa/cli/project_templates/finance/data/flows/transfer_money.yml +0 -67
  91. rasa/cli/project_templates/finance/data/flows/welcome.yml +0 -14
  92. rasa/cli/project_templates/finance/data/nlu.yml +0 -29
  93. rasa/cli/project_templates/finance/data/patterns/pattern_chitchat.yml +0 -7
  94. rasa/cli/project_templates/finance/data/patterns/pattern_completed.yml +0 -6
  95. rasa/cli/project_templates/finance/data/patterns/pattern_search.yml +0 -5
  96. rasa/cli/project_templates/finance/data/patterns/pattern_session_start.yml +0 -9
  97. rasa/cli/project_templates/finance/data/source/accounts.json +0 -51
  98. rasa/cli/project_templates/finance/data/source/advisors.json +0 -44
  99. rasa/cli/project_templates/finance/data/source/appointments.json +0 -1474
  100. rasa/cli/project_templates/finance/data/source/branches.json +0 -47
  101. rasa/cli/project_templates/finance/data/source/cards.json +0 -72
  102. rasa/cli/project_templates/finance/data/source/payees.json +0 -74
  103. rasa/cli/project_templates/finance/data/source/transactions.json +0 -492
  104. rasa/cli/project_templates/finance/data/source/users.json +0 -29
  105. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +0 -8
  106. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +0 -8
  107. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +0 -8
  108. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +0 -8
  109. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +0 -8
  110. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +0 -7
  111. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +0 -8
  112. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +0 -8
  113. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +0 -8
  114. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +0 -8
  115. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +0 -8
  116. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +0 -8
  117. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +0 -8
  118. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +0 -8
  119. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +0 -8
  120. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +0 -8
  121. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +0 -8
  122. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +0 -8
  123. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +0 -8
  124. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +0 -8
  125. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +0 -50
  126. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +0 -50
  127. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +0 -48
  128. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +0 -50
  129. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +0 -50
  130. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +0 -47
  131. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +0 -50
  132. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +0 -50
  133. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +0 -47
  134. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +0 -50
  135. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +0 -50
  136. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +0 -50
  137. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +0 -47
  138. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +0 -50
  139. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +0 -50
  140. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +0 -47
  141. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +0 -50
  142. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +0 -50
  143. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +0 -47
  144. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +0 -50
  145. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +0 -50
  146. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +0 -47
  147. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +0 -47
  148. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +0 -50
  149. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +0 -50
  150. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +0 -47
  151. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +0 -50
  152. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +0 -50
  153. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +0 -47
  154. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +0 -50
  155. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +0 -50
  156. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +0 -47
  157. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +0 -50
  158. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +0 -50
  159. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +0 -50
  160. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +0 -47
  161. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +0 -50
  162. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +0 -50
  163. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +0 -47
  164. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +0 -50
  165. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +0 -50
  166. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +0 -47
  167. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +0 -50
  168. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +0 -50
  169. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +0 -50
  170. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +0 -47
  171. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +0 -50
  172. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +0 -50
  173. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +0 -47
  174. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +0 -50
  175. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +0 -50
  176. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +0 -47
  177. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +0 -50
  178. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +0 -50
  179. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +0 -47
  180. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +0 -47
  181. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +0 -50
  182. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +0 -50
  183. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +0 -50
  184. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +0 -50
  185. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +0 -47
  186. rasa/cli/project_templates/finance/domain/add_payee.yml +0 -47
  187. rasa/cli/project_templates/finance/domain/block_card.yml +0 -101
  188. rasa/cli/project_templates/finance/domain/check_balance.yml +0 -9
  189. rasa/cli/project_templates/finance/domain/default_actions.yml +0 -16
  190. rasa/cli/project_templates/finance/domain/default_flows.yml +0 -33
  191. rasa/cli/project_templates/finance/domain/list_payees.yml +0 -4
  192. rasa/cli/project_templates/finance/domain/remove_payee.yml +0 -16
  193. rasa/cli/project_templates/finance/domain/select_card.yml +0 -12
  194. rasa/cli/project_templates/finance/domain/transfer_money.yml +0 -79
  195. rasa/cli/project_templates/finance/endpoints.yml +0 -62
  196. rasa/cli/project_templates/finance/prompts/command-generator.jinja2 +0 -57
  197. rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +0 -19
  198. rasa/cli/project_templates/finance/tests/conversation_repair/cancellations.yml +0 -12
  199. rasa/cli/project_templates/finance/tests/conversation_repair/cannot_handle.yml +0 -7
  200. rasa/cli/project_templates/finance/tests/conversation_repair/chitchat.yml +0 -7
  201. rasa/cli/project_templates/finance/tests/conversation_repair/clarification.yml +0 -9
  202. rasa/cli/project_templates/finance/tests/conversation_repair/completion.yml +0 -18
  203. rasa/cli/project_templates/finance/tests/conversation_repair/corrections.yml +0 -17
  204. rasa/cli/project_templates/finance/tests/conversation_repair/digressions.yml +0 -32
  205. rasa/cli/project_templates/finance/tests/conversation_repair/human_handoff.yml +0 -21
  206. rasa/cli/project_templates/finance/tests/conversation_repair/skipping_collect_steps.yml +0 -16
  207. rasa/cli/project_templates/finance/tests/demo_scripts/main.yml +0 -16
  208. rasa/cli/project_templates/finance/tests/happy_paths/balance_verification.yml +0 -15
  209. rasa/cli/project_templates/finance/tests/happy_paths/banking_questions.yml +0 -12
  210. rasa/cli/project_templates/finance/tests/happy_paths/card_blocking.yml +0 -52
  211. rasa/cli/project_templates/finance/tests/happy_paths/money_transfer.yml +0 -136
  212. rasa/cli/project_templates/finance/tests/happy_paths/payee_management.yml +0 -27
  213. rasa/cli/project_templates/finance/tests/happy_paths/user_greeted.yml +0 -5
  214. rasa/cli/project_templates/plain/actions/__init__.py +0 -0
  215. rasa/cli/project_templates/plain/config.yml +0 -17
  216. rasa/cli/project_templates/plain/credentials.yml +0 -33
  217. rasa/cli/project_templates/plain/data/patterns/pattern_session_start.yml +0 -7
  218. rasa/cli/project_templates/plain/domain.yml +0 -5
  219. rasa/cli/project_templates/plain/endpoints.yml +0 -58
  220. rasa/cli/project_templates/telco/actions/__init__.py +0 -0
  221. rasa/cli/project_templates/telco/actions/actions_billing.py +0 -197
  222. rasa/cli/project_templates/telco/actions/actions_get_data_from_db.py +0 -43
  223. rasa/cli/project_templates/telco/actions/actions_run_diagnostics.py +0 -23
  224. rasa/cli/project_templates/telco/actions/actions_session_start.py +0 -13
  225. rasa/cli/project_templates/telco/config.yml +0 -25
  226. rasa/cli/project_templates/telco/credentials.yml +0 -33
  227. rasa/cli/project_templates/telco/csvs/billing.csv +0 -10
  228. rasa/cli/project_templates/telco/csvs/customers.csv +0 -5
  229. rasa/cli/project_templates/telco/data/flows/flow_global.yml +0 -5
  230. rasa/cli/project_templates/telco/data/flows/flow_reboot_router.yml +0 -8
  231. rasa/cli/project_templates/telco/data/flows/flow_reset_router.yml +0 -7
  232. rasa/cli/project_templates/telco/data/flows/flow_solve_internet_issue.yml +0 -73
  233. rasa/cli/project_templates/telco/data/flows/flow_undertand_bill.yml +0 -45
  234. rasa/cli/project_templates/telco/data/patterns/pattern_completed.yml +0 -7
  235. rasa/cli/project_templates/telco/data/patterns/pattern_human_handoff.yml +0 -6
  236. rasa/cli/project_templates/telco/data/patterns/pattern_search.yml +0 -7
  237. rasa/cli/project_templates/telco/data/patterns/pattern_session_start.yml +0 -9
  238. rasa/cli/project_templates/telco/docs/reset_vs_rboot_router.txt +0 -1
  239. rasa/cli/project_templates/telco/docs/restart_router.txt +0 -6
  240. rasa/cli/project_templates/telco/docs/run_speed_test.txt +0 -6
  241. rasa/cli/project_templates/telco/domain/domain_global.yml +0 -29
  242. rasa/cli/project_templates/telco/domain/domain_patterns.yml +0 -17
  243. rasa/cli/project_templates/telco/domain/domain_reboot_router.yml +0 -20
  244. rasa/cli/project_templates/telco/domain/domain_reset_router.yml +0 -11
  245. rasa/cli/project_templates/telco/domain/domain_run_speed_test.yml +0 -24
  246. rasa/cli/project_templates/telco/domain/domain_solve_internet_issue.yml +0 -74
  247. rasa/cli/project_templates/telco/domain/domain_undertand_bill.yml +0 -102
  248. rasa/cli/project_templates/telco/endpoints.yml +0 -60
  249. rasa/cli/project_templates/telco/prompts/command-generator.jinja2 +0 -57
  250. rasa/cli/project_templates/telco/tests/e2e_results_failed.yml +0 -62
  251. rasa/cli/project_templates/telco/tests/e2e_results_passed.yml +0 -130
  252. rasa/cli/project_templates/telco/tests/e2e_test_cases/billing_test_cases.yml +0 -68
  253. rasa/cli/project_templates/telco/tests/e2e_test_cases/global_test_cases.yml +0 -13
  254. rasa/cli/project_templates/telco/tests/e2e_test_cases/internet_slow_test_case.yml +0 -47
  255. rasa/cli/project_templates/telco/tests/e2e_test_cases/out_of_scope_test_case.yml +0 -21
  256. rasa/cli/project_templates/telco/tests/e2e_test_cases/patterns_test_cases.yml +0 -15
  257. rasa/shared/importers/static.py +0 -63
  258. rasa/utils/openapi.py +0 -144
  259. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.3.dist-info}/NOTICE +0 -0
  260. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.3.dist-info}/WHEEL +0 -0
  261. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.3.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import os
3
4
  import tempfile
4
5
  from typing import Any, Dict, List, Optional, Text
5
6
 
@@ -78,14 +79,35 @@ def _get_domain_from_importer(config: Dict[Text, Any]) -> Domain:
78
79
  Returns:
79
80
  A Domain object .
80
81
  """
81
- with tempfile.NamedTemporaryFile("w+", suffix=".yml") as tmp:
82
- write_yaml(config, tmp.name)
82
+ # We create the file with delete=False so that it can be re-opened on
83
+ # Windows. If delete=True, the file is opened with the _O_TEMPORARY flag
84
+ # which blocks any second open() call.
85
+ tmp = tempfile.NamedTemporaryFile("w+", suffix=".yml", delete=False)
86
+
87
+ try:
88
+ path = tmp.name
89
+
90
+ # write_yaml() re-opens the same path. On Windows an already-open
91
+ # handle keeps the file locked for further opens, so we close
92
+ # the first handle before we call write_yaml().
93
+ tmp.close()
94
+ write_yaml(config, path)
95
+
83
96
  importer = TrainingDataImporter.load_from_config(
84
97
  domain_path=FlowSyncImporter.default_pattern_path(),
85
- config_path=tmp.name,
98
+ config_path=path,
86
99
  )
87
100
  return importer.get_domain()
88
101
 
102
+ finally:
103
+ # Because we passed delete=False above, Python will not clean the file
104
+ # To avoid leaving garbage in the temp directory after the tests run,
105
+ # we remove it explicitly.
106
+ try:
107
+ os.remove(path)
108
+ except FileNotFoundError:
109
+ pass
110
+
89
111
 
90
112
  def get_pattern_defaults(config: Dict[Text, Any]) -> PatternDefaults:
91
113
  """Get the default flows, responses and slots for patterns.
rasa/cli/scaffold.py CHANGED
@@ -24,21 +24,10 @@ class ProjectTemplateName(Enum):
24
24
 
25
25
  DEFAULT = "default"
26
26
  TUTORIAL = "tutorial"
27
- PLAIN = "plain"
28
- FINANCE = "finance"
29
- TELCO = "telco"
30
27
 
31
28
  def __str__(self) -> str:
32
29
  return self.value
33
30
 
34
- @classmethod
35
- def get_all_values(cls) -> List[str]:
36
- return [name.value for name in cls]
37
-
38
- @classmethod
39
- def supported_values(cls) -> str:
40
- return ", ".join(cls.get_all_values())
41
-
42
31
 
43
32
  template_domain_path = defaultdict(lambda: DEFAULT_DOMAIN_PATH)
44
33
  template_domain_path[ProjectTemplateName.DEFAULT] = "domain"
@@ -170,17 +159,9 @@ def create_initial_project(
170
159
  path: Text, template: ProjectTemplateName = ProjectTemplateName.DEFAULT
171
160
  ) -> None:
172
161
  """Creates directory structure and templates for initial project."""
173
- import distutils.dir_util as dir_util
174
-
175
- # clear the cache of the copy_tree function, this avoids issues if
176
- # a project directory existed before and we removed folders in it
177
- # with shutil.rmtree. see
178
- # https://stackoverflow.com/questions/9160227/dir-util-copy-tree-fails-after-shutil-rmtree
179
- if hasattr(dir_util, "_path_created"):
180
- dir_util._path_created.clear()
181
- else:
182
- dir_util.SkipRepeatAbsolutePaths.clear()
183
- dir_util.copy_tree(scaffold_path(template), path)
162
+ from distutils.dir_util import copy_tree
163
+
164
+ copy_tree(scaffold_path(template), path)
184
165
 
185
166
 
186
167
  def scaffold_path(template: ProjectTemplateName) -> Text:
@@ -908,12 +908,10 @@ class RemoteAction(Action):
908
908
  draft.setdefault("buttons", [])
909
909
  draft["buttons"].extend(buttons)
910
910
 
911
+ # Avoid overwriting `draft` values with empty values
911
912
  response = {k: v for k, v in response.items() if v}
912
-
913
913
  response.update(draft)
914
- bot_messages.append(
915
- create_bot_utterance(response, tracker.current_language)
916
- )
914
+ bot_messages.append(create_bot_utterance(response))
917
915
 
918
916
  return bot_messages
919
917
 
@@ -42,14 +42,14 @@ if TYPE_CHECKING:
42
42
  from sanic import Sanic, Websocket # type: ignore[attr-defined]
43
43
  from socketio import AsyncServer
44
44
 
45
- from rasa.core.channels.channel import UserMessage
45
+ from rasa.core.channels.channel import InputChannel, UserMessage
46
46
  from rasa.shared.core.trackers import DialogueStateTracker
47
47
 
48
48
 
49
49
  structlogger = structlog.get_logger()
50
50
 
51
51
 
52
- def tracker_as_dump(tracker: "DialogueStateTracker") -> Dict[str, Any]:
52
+ def tracker_as_dump(tracker: "DialogueStateTracker") -> str:
53
53
  """Create a dump of the tracker state."""
54
54
  from rasa.shared.core.trackers import get_trackers_for_conversation_sessions
55
55
 
@@ -60,9 +60,8 @@ def tracker_as_dump(tracker: "DialogueStateTracker") -> Dict[str, Any]:
60
60
  else:
61
61
  last_tracker = multiple_tracker_sessions[-1]
62
62
 
63
- # TODO: this is a bug: the bridge converts this back to json, but it
64
- # should be json in the first place
65
- return last_tracker.current_state(EventVerbosity.AFTER_RESTART)
63
+ state = last_tracker.current_state(EventVerbosity.AFTER_RESTART)
64
+ return json.dumps(state)
66
65
 
67
66
 
68
67
  def does_need_action_prediction(tracker: "DialogueStateTracker") -> bool:
@@ -149,7 +148,6 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
149
148
  from rasa.core.agent import Agent
150
149
 
151
150
  self.agent: Optional[Agent] = None
152
- self.latest_tracker_session_id = None
153
151
 
154
152
  # Initialize the SocketIO input channel
155
153
  SocketIOInput.__init__(
@@ -181,9 +179,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
181
179
  self._register_tracker_update_hook()
182
180
 
183
181
  @classmethod
184
- def from_credentials(
185
- cls, credentials: Optional[Dict[Text, Any]]
186
- ) -> "StudioChatInput":
182
+ def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> "InputChannel":
187
183
  """Creates a StudioChatInput channel from credentials."""
188
184
  credentials = credentials or {}
189
185
 
@@ -215,11 +211,6 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
215
211
  if not self.sio:
216
212
  structlogger.error("studio_chat.on_tracker_updated.sio_not_initialized")
217
213
  return
218
-
219
- # we need the latest session id to use it for the llm helper to get the
220
- # most recent conversation the user had with the bot.
221
- self.latest_tracker_session_id = sender_id
222
-
223
214
  await self.sio.emit("tracker", tracker_dump, room=sender_id)
224
215
 
225
216
  async def on_message_proxy(
@@ -231,14 +222,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
231
222
 
232
223
  Triggers a tracker update notification after processing the message.
233
224
  """
234
- try:
235
- await on_new_message(message)
236
- except Exception as e:
237
- structlogger.exception(
238
- "studio_chat.on_new_message.error",
239
- error=str(e),
240
- sender_id=message.sender_id,
241
- )
225
+ await on_new_message(message)
242
226
 
243
227
  if not self.agent:
244
228
  structlogger.error("studio_chat.on_message_proxy.agent_not_initialized")
@@ -291,7 +275,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
291
275
  async def collect_call_parameters(
292
276
  self, channel_websocket: "Websocket"
293
277
  ) -> Optional[CallParameters]:
294
- """Voice method to collect call parameters."""
278
+ """Voice method to collect call parameters"""
295
279
  session_id = channel_websocket.session_id
296
280
  return CallParameters(session_id, "local", "local", stream_id=session_id)
297
281
 
@@ -321,7 +305,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
321
305
  def create_output_channel(
322
306
  self, voice_websocket: "Websocket", tts_engine: TTSEngine
323
307
  ) -> VoiceOutputChannel:
324
- """Create a voice output channel."""
308
+ """Create a voice output channel"""
325
309
  return StudioVoiceOutputChannel(
326
310
  voice_websocket,
327
311
  tts_engine,
@@ -448,16 +432,8 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
448
432
  ws.put_message(data)
449
433
  return
450
434
 
451
- try:
452
- # Handle text messages
453
- await self.handle_user_message(sid, data, on_new_message)
454
- except Exception as e:
455
- structlogger.exception(
456
- "studio_chat.sio.handle_message.error",
457
- error=str(e),
458
- sid=sid,
459
- )
460
- await self.sio.emit("error", str(e), room=sid)
435
+ # Handle text messages
436
+ await self.handle_user_message(sid, data, on_new_message)
461
437
 
462
438
  @self.sio.on("update_tracker", namespace=self.namespace)
463
439
  async def on_update_tracker(sid: Text, data: Dict) -> None:
@@ -26,7 +26,7 @@ logger = structlog.get_logger(__name__)
26
26
 
27
27
  @dataclass
28
28
  class ASREngineConfig(MergeableConfig):
29
- pass
29
+ keep_alive_interval: int = 5 # seconds
30
30
 
31
31
 
32
32
  class ASREngine(Generic[T]):
@@ -93,3 +93,7 @@ class ASREngine(Generic[T]):
93
93
  def get_default_config() -> T:
94
94
  """Get the default config for this component."""
95
95
  raise NotImplementedError
96
+
97
+ async def send_keep_alive(self) -> None:
98
+ """Send a keep-alive message to the ASR system if supported."""
99
+ pass
@@ -145,3 +145,8 @@ class DeepgramASR(ASREngine[DeepgramASRConfig]):
145
145
  def concatenate_transcripts(t1: str, t2: str) -> str:
146
146
  """Concatenate two transcripts making sure there is a space between them."""
147
147
  return (t1.strip() + " " + t2.strip()).strip()
148
+
149
+ async def send_keep_alive(self) -> None:
150
+ """Send a keep-alive message to the Deepgram websocket connection."""
151
+ if self.asr_socket is not None:
152
+ await self.asr_socket.send(json.dumps({"type": "KeepAlive"}))
@@ -81,6 +81,12 @@ class AudiocodesVoiceOutputChannel(VoiceOutputChannel):
81
81
  logger.debug("Sending start marker", stream_id=self._get_stream_id())
82
82
  await self.voice_websocket.send(media_message)
83
83
 
84
+ # This should be set when the bot actually starts speaking
85
+ # however, Audiocodes does not have an event to indicate that.
86
+ # This is an approximation, as the bot will be sent the audio chunks next
87
+ # which are played to the user immediately.
88
+ call_state.is_bot_speaking = True # type: ignore[attr-defined]
89
+
84
90
  async def send_intermediate_marker(self, recipient_id: str) -> None:
85
91
  """Audiocodes doesn't need intermediate markers, so do nothing."""
86
92
  pass
@@ -170,21 +176,20 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
170
176
  if data["type"] == "activities":
171
177
  activities = data["activities"]
172
178
  for activity in activities:
173
- logger.debug("audiocodes_stream.activity", data=activity)
174
179
  if activity["name"] == "start":
175
- # already handled in collect_call_parameters
180
+ # handled in collect_call_parameters
176
181
  pass
177
182
  elif activity["name"] == "dtmf":
178
- # TODO: handle DTMF input
183
+ logger.info("audiocodes_stream.dtmf_ignored", data=activity)
179
184
  pass
180
185
  elif activity["name"] == "playFinished":
181
186
  logger.debug("audiocodes_stream.playFinished", data=activity)
187
+ call_state.is_bot_speaking = False # type: ignore[attr-defined]
182
188
  if call_state.should_hangup:
183
189
  logger.info("audiocodes_stream.hangup")
184
190
  self._send_hangup(ws, data)
185
191
  # the conversation should continue until
186
192
  # we receive a end message from audiocodes
187
- pass
188
193
  else:
189
194
  logger.warning("audiocodes_stream.unknown_activity", data=activity)
190
195
  elif data["type"] == "userStream.start":
@@ -31,7 +31,7 @@ from rasa.core.channels.voice_stream.voice_channel import (
31
31
 
32
32
  logger = structlog.get_logger()
33
33
 
34
- JAMBONZ_STREAMS_WEBSOCKET_PATH = "webhooks/jambonz_streams/websocket"
34
+ JAMBONZ_STREAMS_WEBSOCKET_PATH = "webhooks/jambonz_stream/websocket"
35
35
 
36
36
 
37
37
  def map_call_params(data: Dict[Text, str]) -> CallParameters:
@@ -468,10 +468,17 @@ class VoiceInputChannel(InputChannel):
468
468
  call_parameters,
469
469
  )
470
470
 
471
+ async def asr_keep_alive_task() -> None:
472
+ interval = getattr(asr_engine.config, "keep_alive_interval", 5)
473
+ while True:
474
+ await asyncio.sleep(interval)
475
+ await asr_engine.send_keep_alive()
476
+
471
477
  tasks = [
472
478
  asyncio.create_task(consume_audio_bytes()),
473
479
  asyncio.create_task(receive_asr_events()),
474
480
  asyncio.create_task(handle_asr_events()),
481
+ asyncio.create_task(asr_keep_alive_task()),
475
482
  ]
476
483
  await asyncio.wait(
477
484
  tasks,
rasa/core/nlg/callback.py CHANGED
@@ -19,7 +19,7 @@ def nlg_response_format_spec() -> Dict[Text, Any]:
19
19
  return {
20
20
  "type": "object",
21
21
  "properties": {
22
- "text": {"type": "string"},
22
+ "text": {"type": ["string", "null"]},
23
23
  "id": {"type": ["string", "null"]},
24
24
  "buttons": {"type": ["array", "null"], "items": {"type": "object"}},
25
25
  "elements": {"type": ["array", "null"], "items": {"type": "object"}},
@@ -679,7 +679,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
679
679
  answer_relevant = not _ENTERPRISE_SEARCH_ANSWER_NOT_RELEVANT_PATTERN.search(
680
680
  llm_answer
681
681
  )
682
- structlogger.debug("")
682
+
683
683
  return _RelevancyCheckResponse(
684
684
  answer=llm_answer if answer_relevant else None,
685
685
  relevant=answer_relevant,
@@ -784,19 +784,17 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
784
784
  if not os.path.exists(docs_folder) or not os.path.isdir(docs_folder):
785
785
  error_message = (
786
786
  f"Document source directory does not exist or is not a "
787
- f"directory: '{os.path.abspath(docs_folder)}'. "
787
+ f"directory: '{docs_folder}'. "
788
788
  "Please specify a valid path to the documents source directory in the "
789
789
  "vector_store configuration."
790
790
  )
791
791
  structlogger.error(
792
792
  "enterprise_search_policy.train.faiss.invalid_source_directory",
793
793
  message=error_message,
794
- docs_folder={os.path.abspath(docs_folder)},
795
- configuration_value=docs_folder,
796
794
  )
797
795
  print_error_and_exit(error_message)
798
796
 
799
- docs = glob.glob(os.path.join(docs_folder, "**/*.txt"), recursive=True)
797
+ docs = glob.glob(os.path.join(docs_folder, "*.txt"), recursive=True)
800
798
  if not docs or len(docs) < 1:
801
799
  error_message = (
802
800
  f"Document source directory is empty: '{docs_folder}'. "
@@ -1135,7 +1133,8 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
1135
1133
  embeddings_config: Dict[Text, Any],
1136
1134
  log_source_method: str,
1137
1135
  ) -> None:
1138
- """Perform the health checks using resolved LLM and embeddings configurations.
1136
+ """
1137
+ Perform the health checks using resolved LLM and embeddings configurations.
1139
1138
  Resolved means the configuration is either:
1140
1139
  - A reference to a model group that has already been expanded into
1141
1140
  its corresponding configuration using the information from
@@ -1164,7 +1163,8 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
1164
1163
 
1165
1164
  @classmethod
1166
1165
  def get_system_default_prompt_based_on_config(cls, config: Dict[str, Any]) -> str:
1167
- """Resolves the default prompt template for Enterprise Search Policy based on
1166
+ """
1167
+ Resolves the default prompt template for Enterprise Search Policy based on
1168
1168
  the component's configuration.
1169
1169
 
1170
1170
  - The old prompt is selected when both citation and relevancy check are either
@@ -1195,7 +1195,8 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
1195
1195
  relevancy_check_enabled: bool,
1196
1196
  citation_enabled: bool,
1197
1197
  ) -> str:
1198
- """Returns the appropriate default prompt template based on the feature flags.
1198
+ """
1199
+ Returns the appropriate default prompt template based on the feature flags.
1199
1200
 
1200
1201
  The selection follows this priority:
1201
1202
  1. If relevancy check is enabled, return the prompt that includes both relevancy
@@ -740,14 +740,7 @@ def _run_action_step(
740
740
  # do not log about non-existing validation actions of collect steps
741
741
  utter_action_name = render_template_variables("{{context.utter}}", context)
742
742
  if utter_action_name not in available_actions:
743
- structlogger.warning(
744
- "flow.step.run.action.unknown",
745
- action=action_name,
746
- event_info=(
747
- f"The action '{action_name}' is not defined in the domain but "
748
- f"getting triggered by the flow '{step.flow_id}'."
749
- ),
750
- )
743
+ structlogger.warning("flow.step.run.action.unknown", action=action_name)
751
744
  return ContinueFlowWithNextStep(events=initial_events)
752
745
 
753
746
 
@@ -232,16 +232,6 @@ class CorrectSlotsCommand(Command):
232
232
  proposed_slots, all_flows, tracker
233
233
  )
234
234
 
235
- if not earliest_collect and not is_reset_only:
236
- # if we could not find any step in the flow, where the slots were
237
- # previously set, and we also don't want to reset the slots, do
238
- # not correct the slots.
239
- structlogger.debug(
240
- "correct_slots_command.skip_correction",
241
- is_reset_only=is_reset_only,
242
- )
243
- return None
244
-
245
235
  return CorrectionPatternFlowStackFrame(
246
236
  is_reset_only=is_reset_only,
247
237
  corrected_slots=proposed_slots,
@@ -114,7 +114,7 @@ class CommandGenerator:
114
114
  # slot asked by the active collect step.
115
115
  # Or return a CannotHandleCommand if no matching command is found.
116
116
  commands = self._filter_commands_during_force_slot_filling(
117
- commands, available_flows, tracker
117
+ commands, flows, tracker
118
118
  )
119
119
 
120
120
  commands_dicts = [command.as_dict() for command in commands]
@@ -385,14 +385,14 @@ class CommandGenerator:
385
385
  @staticmethod
386
386
  def _filter_commands_during_force_slot_filling(
387
387
  commands: List[Command],
388
- available_flows: FlowsList,
388
+ flows: FlowsList,
389
389
  tracker: Optional[DialogueStateTracker] = None,
390
390
  ) -> List[Command]:
391
391
  """Filter commands during a collect step that has set `force_slot_filling`.
392
392
 
393
393
  Args:
394
394
  commands: The commands to filter.
395
- available_flows: The available flows.
395
+ flows: All flows.
396
396
  tracker: The tracker.
397
397
 
398
398
  Returns:
@@ -409,7 +409,7 @@ class CommandGenerator:
409
409
  )
410
410
  return commands
411
411
 
412
- updated_flows = find_updated_flows(tracker, available_flows)
412
+ updated_flows = find_updated_flows(tracker, flows)
413
413
  if updated_flows:
414
414
  structlogger.debug(
415
415
  "command_generator.filter_commands_during_force_slot_filling.running_flows_were_updated",
@@ -418,7 +418,7 @@ class CommandGenerator:
418
418
  return [HandleCodeChangeCommand()]
419
419
 
420
420
  stack = tracker.stack
421
- step = get_current_collect_step(stack, available_flows)
421
+ step = get_current_collect_step(stack, flows)
422
422
 
423
423
  if step is None or not step.force_slot_filling:
424
424
  return commands
@@ -219,6 +219,11 @@ class FlowRetrieval(EmbeddingsHealthCheckMixin):
219
219
  if self.vector_store is not None:
220
220
  with self._model_storage.write_to(self._resource) as model_path:
221
221
  self.vector_store.save_local(model_path)
222
+ else:
223
+ structlogger.warning(
224
+ "flow_retrieval.persist_vector_store.not_initialized",
225
+ event_info="Vector store is None, not persisted.",
226
+ )
222
227
 
223
228
  def _persist_config(self) -> None:
224
229
  with self._model_storage.write_to(self._resource) as path:
@@ -244,16 +249,6 @@ class FlowRetrieval(EmbeddingsHealthCheckMixin):
244
249
  )
245
250
 
246
251
  flows_to_embedd = flows.exclude_link_only_flows()
247
-
248
- if not flows_to_embedd:
249
- structlogger.debug(
250
- "flow_retrieval.populate_vector_store.no_flows_to_embed",
251
- event_info=(
252
- "No flows to embed in the vector store, skipping population."
253
- ),
254
- )
255
- return
256
-
257
252
  embeddings = self._create_embedder(self.config)
258
253
  documents = self._generate_flow_documents(flows_to_embedd, domain)
259
254
  try:
@@ -425,6 +420,10 @@ class FlowRetrieval(EmbeddingsHealthCheckMixin):
425
420
  The top k documents with similarity scores.
426
421
  """
427
422
  if self.vector_store is None:
423
+ structlogger.error(
424
+ "flow_retrieval.query_vector_store.vector_store_not_configured",
425
+ event_info="Vector store is not configured",
426
+ )
428
427
  return []
429
428
  try:
430
429
  documents_with_scores = (
@@ -398,7 +398,12 @@ def clean_up_commands(
398
398
  """
399
399
  domain = domain if domain else Domain.empty()
400
400
 
401
- slots_so_far, active_flow = filled_slots_for_active_flow(tracker, all_flows)
401
+ slots_so_far, _ = filled_slots_for_active_flow(tracker, all_flows)
402
+
403
+ # update the slots so far with the slots that were set in the tracker
404
+ slots_so_far.update(
405
+ {event.key for event in tracker.events if isinstance(event, SlotSet)}
406
+ )
402
407
 
403
408
  clean_commands: List[Command] = []
404
409
 
@@ -39,9 +39,11 @@ from rasa.model_manager.trainer_service import (
39
39
  update_training_status,
40
40
  )
41
41
  from rasa.model_manager.utils import (
42
+ InvalidPathException,
42
43
  get_logs_content,
43
44
  logs_base_path,
44
45
  models_base_path,
46
+ subpath,
45
47
  )
46
48
  from rasa.model_manager.warm_rasa_process import (
47
49
  initialize_warm_rasa_process,
@@ -51,7 +53,6 @@ from rasa.server import ErrorResponse
51
53
  from rasa.shared.exceptions import InvalidConfigException
52
54
  from rasa.shared.utils.yaml import dump_obj_as_yaml_to_string
53
55
  from rasa.studio.upload import build_calm_import_parts
54
- from rasa.utils.io import InvalidPathException, subpath
55
56
 
56
57
  dotenv.load_dotenv()
57
58
 
@@ -104,7 +105,7 @@ async def update_status_of_all_bots() -> None:
104
105
  await update_bot_status(bot)
105
106
 
106
107
 
107
- def base_server_url(request: Optional[Request]) -> str:
108
+ def base_server_url(request: Request) -> str:
108
109
  """Return the base URL of the server."""
109
110
  if SERVER_BASE_URL:
110
111
  return SERVER_BASE_URL.rstrip("/")
@@ -15,11 +15,11 @@ from rasa.model_manager import config
15
15
  from rasa.model_manager.utils import (
16
16
  logs_path,
17
17
  models_base_path,
18
+ subpath,
18
19
  write_encoded_data_to_file,
19
20
  )
20
21
  from rasa.model_manager.warm_rasa_process import start_rasa_process
21
22
  from rasa.studio.prompts import handle_prompts
22
- from rasa.utils.io import subpath
23
23
 
24
24
  structlogger = structlog.get_logger()
25
25
 
@@ -14,6 +14,7 @@ from rasa.model_manager.utils import (
14
14
  ensure_base_directory_exists,
15
15
  logs_path,
16
16
  models_base_path,
17
+ subpath,
17
18
  write_encoded_data_to_file,
18
19
  )
19
20
  from rasa.model_manager.warm_rasa_process import (
@@ -21,7 +22,6 @@ from rasa.model_manager.warm_rasa_process import (
21
22
  )
22
23
  from rasa.model_training import generate_random_model_name
23
24
  from rasa.studio.prompts import handle_prompts
24
- from rasa.utils.io import subpath
25
25
 
26
26
  structlogger = structlog.get_logger()
27
27
 
@@ -53,15 +53,6 @@ class TrainingSession(BaseModel):
53
53
  """Check if the training is running."""
54
54
  return self.status == TrainingSessionStatus.RUNNING
55
55
 
56
- def has_just_finished(self) -> bool:
57
- if not self.is_status_indicating_alive():
58
- # skip if the training is not running
59
- return False
60
- if self.process.poll() is None:
61
- # process is still running
62
- return False
63
- return True
64
-
65
56
  def model_path(self) -> str:
66
57
  """Return the path to the model."""
67
58
  return subpath(models_base_path(), f"{self.model_name}.tar.gz")
@@ -98,8 +89,14 @@ def terminate_training(training: TrainingSession) -> None:
98
89
 
99
90
 
100
91
  def update_training_status(training: TrainingSession) -> None:
101
- if training.has_just_finished():
102
- complete_training(training)
92
+ if not training.is_status_indicating_alive():
93
+ # skip if the training is not running
94
+ return
95
+ if training.process.poll() is None:
96
+ # process is still running
97
+ return
98
+
99
+ complete_training(training)
103
100
 
104
101
 
105
102
  def complete_training(training: TrainingSession) -> None:
@@ -5,11 +5,15 @@ from typing import Optional
5
5
  import structlog
6
6
 
7
7
  from rasa.model_manager import config
8
- from rasa.utils.io import subpath
8
+ from rasa.shared.exceptions import RasaException
9
9
 
10
10
  structlogger = structlog.get_logger()
11
11
 
12
12
 
13
+ class InvalidPathException(RasaException):
14
+ """Raised if a path is invalid - e.g. path traversal is detected."""
15
+
16
+
13
17
  def write_encoded_data_to_file(encoded_data: bytes, file: str) -> None:
14
18
  """Write base64 encoded data to a file."""
15
19
  # create the directory if it does not exist of the parent directory
@@ -49,6 +53,30 @@ def logs_path(action_id: str) -> str:
49
53
  return subpath(logs_base_path(), f"{action_id}.txt")
50
54
 
51
55
 
56
+ def subpath(parent: str, child: str) -> str:
57
+ """Return the path to the child directory of the parent directory.
58
+
59
+ Ensures, that child doesn't navigate to parent directories. Prevents
60
+ path traversal. Raises an InvalidPathException if the path is invalid.
61
+
62
+ Based on Snyk's directory traversal mitigation:
63
+ https://learn.snyk.io/lesson/directory-traversal/
64
+ """
65
+ safe_path = os.path.abspath(os.path.join(parent, child))
66
+ parent = os.path.abspath(parent)
67
+
68
+ common_base = os.path.commonpath([parent, safe_path])
69
+ if common_base != parent:
70
+ raise InvalidPathException(f"Invalid path: {safe_path}")
71
+
72
+ if os.path.basename(safe_path) != child:
73
+ raise InvalidPathException(
74
+ f"Invalid path - path traversal detected: {safe_path}"
75
+ )
76
+
77
+ return safe_path
78
+
79
+
52
80
  def get_logs_content(action_id: str) -> Optional[str]:
53
81
  """Return the content of the log file for a given action id."""
54
82
  try: