rasa-pro 3.14.0.dev3__py3-none-any.whl → 3.14.0.dev5__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 (437) hide show
  1. rasa/api.py +0 -5
  2. rasa/builder/README.md +120 -0
  3. rasa/builder/auth.py +176 -0
  4. rasa/builder/config.py +115 -0
  5. rasa/builder/copilot/constants.py +25 -0
  6. rasa/builder/copilot/copilot.py +372 -0
  7. rasa/builder/copilot/copilot_response_handler.py +487 -0
  8. rasa/builder/copilot/copilot_templated_message_provider.py +58 -0
  9. rasa/builder/copilot/exceptions.py +20 -0
  10. rasa/builder/copilot/models.py +431 -0
  11. rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +726 -0
  12. rasa/builder/copilot/telemetry.py +195 -0
  13. rasa/builder/copilot/templated_messages/copilot_internal_messages_templates.yml +16 -0
  14. rasa/builder/copilot/templated_messages/copilot_templated_responses.yml +26 -0
  15. rasa/builder/document_retrieval/constants.py +15 -0
  16. rasa/builder/document_retrieval/inkeep-rag-response-schema.json +64 -0
  17. rasa/builder/document_retrieval/inkeep_document_retrieval.py +238 -0
  18. rasa/builder/document_retrieval/models.py +62 -0
  19. rasa/builder/download.py +140 -0
  20. rasa/builder/exceptions.py +55 -0
  21. rasa/builder/guardrails/__init__.py +1 -0
  22. rasa/builder/guardrails/constants.py +3 -0
  23. rasa/builder/guardrails/exceptions.py +4 -0
  24. rasa/builder/guardrails/lakera.py +206 -0
  25. rasa/builder/guardrails/models.py +199 -0
  26. rasa/builder/guardrails/utils.py +305 -0
  27. rasa/builder/job_manager.py +87 -0
  28. rasa/builder/jobs.py +234 -0
  29. rasa/builder/llm_service.py +246 -0
  30. rasa/builder/logging_utils.py +209 -0
  31. rasa/builder/main.py +174 -0
  32. rasa/builder/models.py +197 -0
  33. rasa/builder/project_generator.py +450 -0
  34. rasa/builder/project_info.py +72 -0
  35. rasa/builder/scrape_rasa_docs.py +97 -0
  36. rasa/builder/service.py +1142 -0
  37. rasa/builder/shared/tracker_context.py +212 -0
  38. rasa/builder/skill_to_bot_prompt.jinja2 +164 -0
  39. rasa/builder/training_service.py +132 -0
  40. rasa/builder/validation_service.py +93 -0
  41. rasa/cli/arguments/default_arguments.py +0 -12
  42. rasa/cli/arguments/run.py +0 -2
  43. rasa/cli/dialogue_understanding_test.py +0 -4
  44. rasa/cli/e2e_test.py +0 -4
  45. rasa/cli/inspect.py +0 -3
  46. rasa/cli/llm_fine_tuning.py +0 -5
  47. rasa/cli/project_templates/basic/actions/action_api.py +15 -0
  48. rasa/cli/project_templates/basic/actions/action_human_handoff.py +44 -0
  49. rasa/cli/project_templates/basic/config.yml +23 -0
  50. rasa/cli/project_templates/basic/credentials.yml +34 -0
  51. rasa/cli/project_templates/basic/data/general/feedback.yml +20 -0
  52. rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
  53. rasa/cli/project_templates/basic/data/general/hello.yml +7 -0
  54. rasa/cli/project_templates/basic/data/general/help.yml +6 -0
  55. rasa/cli/project_templates/basic/data/general/human_handoff.yml +16 -0
  56. rasa/cli/project_templates/basic/data/general/welcome.yml +9 -0
  57. rasa/cli/project_templates/basic/data/system/pattern_completed.yml +7 -0
  58. rasa/cli/project_templates/basic/data/system/pattern_correction.yml +7 -0
  59. rasa/cli/project_templates/basic/data/system/pattern_search.yml +8 -0
  60. rasa/cli/project_templates/basic/data/system/pattern_session_start.yml +8 -0
  61. rasa/cli/project_templates/basic/docs/rasa_assistant_qa.txt +65 -0
  62. rasa/cli/project_templates/basic/docs/template.txt +7 -0
  63. rasa/cli/project_templates/basic/domain/general/assistant_details.yml +12 -0
  64. rasa/cli/project_templates/basic/domain/general/bot_identity.yml +5 -0
  65. rasa/cli/project_templates/basic/domain/general/cannot_handle.yml +5 -0
  66. rasa/cli/project_templates/basic/domain/general/feedback.yml +28 -0
  67. rasa/cli/project_templates/basic/domain/general/goodbye.yml +7 -0
  68. rasa/cli/project_templates/basic/domain/general/help.yml +5 -0
  69. rasa/cli/project_templates/basic/domain/general/human_handoff_domain.yml +35 -0
  70. rasa/cli/project_templates/basic/domain/general/utils.yml +13 -0
  71. rasa/cli/project_templates/basic/domain/general/welcome.yml +7 -0
  72. rasa/cli/project_templates/basic/endpoints.yml +73 -0
  73. rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
  74. rasa/cli/project_templates/finance/actions/__init__.py +46 -0
  75. rasa/cli/project_templates/finance/actions/accounts/action_ask_account.py +47 -0
  76. rasa/cli/project_templates/finance/actions/accounts/action_check_balance.py +40 -0
  77. rasa/cli/project_templates/finance/actions/action_session_start.py +74 -0
  78. rasa/cli/project_templates/finance/actions/cards/action_ask_card.py +48 -0
  79. rasa/cli/project_templates/finance/actions/cards/action_check_card_existence.py +36 -0
  80. rasa/cli/project_templates/finance/actions/cards/action_update_card_status.py +54 -0
  81. rasa/cli/project_templates/finance/actions/database.py +277 -0
  82. rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
  83. rasa/cli/project_templates/finance/actions/transfers/action_add_payee.py +52 -0
  84. rasa/cli/project_templates/finance/actions/transfers/action_ask_account_from.py +51 -0
  85. rasa/cli/project_templates/finance/actions/transfers/action_check_payee_existence.py +40 -0
  86. rasa/cli/project_templates/finance/actions/transfers/action_check_sufficient_funds.py +40 -0
  87. rasa/cli/project_templates/finance/actions/transfers/action_list_payees.py +46 -0
  88. rasa/cli/project_templates/finance/actions/transfers/action_process_immediate_payment.py +18 -0
  89. rasa/cli/project_templates/finance/actions/transfers/action_remove_payee.py +49 -0
  90. rasa/cli/project_templates/finance/actions/transfers/action_schedule_payment.py +19 -0
  91. rasa/cli/project_templates/finance/actions/transfers/action_validate_payment_date.py +36 -0
  92. rasa/cli/project_templates/finance/config.yml +21 -0
  93. rasa/cli/project_templates/finance/credentials.yml +32 -0
  94. rasa/cli/project_templates/finance/csvs/accounts.csv +8 -0
  95. rasa/cli/project_templates/finance/csvs/advisors.csv +7 -0
  96. rasa/cli/project_templates/finance/csvs/appointments.csv +211 -0
  97. rasa/cli/project_templates/finance/csvs/branches.csv +10 -0
  98. rasa/cli/project_templates/finance/csvs/cards.csv +11 -0
  99. rasa/cli/project_templates/finance/csvs/payees.csv +11 -0
  100. rasa/cli/project_templates/finance/csvs/transactions.csv +71 -0
  101. rasa/cli/project_templates/finance/csvs/users.csv +4 -0
  102. rasa/cli/project_templates/finance/data/accounts/check_balance.yml +10 -0
  103. rasa/cli/project_templates/finance/data/cards/block_card.yml +66 -0
  104. rasa/cli/project_templates/finance/data/cards/select_card.yml +12 -0
  105. rasa/cli/project_templates/finance/data/general/bot_identity.yml +6 -0
  106. rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
  107. rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
  108. rasa/cli/project_templates/finance/data/general/hello.yml +7 -0
  109. rasa/cli/project_templates/finance/data/general/help.yml +9 -0
  110. rasa/cli/project_templates/finance/data/general/human_handoff.yml +16 -0
  111. rasa/cli/project_templates/finance/data/general/welcome.yml +9 -0
  112. rasa/cli/project_templates/finance/data/system/patterns/pattern_chitchat.yml +5 -0
  113. rasa/cli/project_templates/finance/data/system/patterns/pattern_completed.yml +7 -0
  114. rasa/cli/project_templates/finance/data/system/patterns/pattern_correction.yml +7 -0
  115. rasa/cli/project_templates/finance/data/system/patterns/pattern_search.yml +8 -0
  116. rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +8 -0
  117. rasa/cli/project_templates/finance/data/system/source/accounts.json +51 -0
  118. rasa/cli/project_templates/finance/data/system/source/advisors.json +44 -0
  119. rasa/cli/project_templates/finance/data/system/source/appointments.json +1474 -0
  120. rasa/cli/project_templates/finance/data/system/source/branches.json +47 -0
  121. rasa/cli/project_templates/finance/data/system/source/cards.json +72 -0
  122. rasa/cli/project_templates/finance/data/system/source/payees.json +74 -0
  123. rasa/cli/project_templates/finance/data/system/source/transactions.json +492 -0
  124. rasa/cli/project_templates/finance/data/system/source/users.json +29 -0
  125. rasa/cli/project_templates/finance/data/transfers/add_payee.yml +29 -0
  126. rasa/cli/project_templates/finance/data/transfers/list_payees.yml +5 -0
  127. rasa/cli/project_templates/finance/data/transfers/remove_payee.yml +21 -0
  128. rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +67 -0
  129. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +8 -0
  130. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +8 -0
  131. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +8 -0
  132. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +8 -0
  133. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +8 -0
  134. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +7 -0
  135. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +8 -0
  136. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +8 -0
  137. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +8 -0
  138. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +8 -0
  139. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +8 -0
  140. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +8 -0
  141. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +8 -0
  142. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +8 -0
  143. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +8 -0
  144. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +8 -0
  145. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +8 -0
  146. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +8 -0
  147. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +8 -0
  148. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +8 -0
  149. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +50 -0
  150. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +50 -0
  151. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +48 -0
  152. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +50 -0
  153. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +50 -0
  154. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +47 -0
  155. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +50 -0
  156. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +50 -0
  157. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +47 -0
  158. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +50 -0
  159. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +50 -0
  160. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +50 -0
  161. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +47 -0
  162. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +50 -0
  163. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +50 -0
  164. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +47 -0
  165. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +50 -0
  166. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +50 -0
  167. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +47 -0
  168. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +50 -0
  169. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +50 -0
  170. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +47 -0
  171. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +47 -0
  172. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +50 -0
  173. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +50 -0
  174. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +47 -0
  175. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +50 -0
  176. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +50 -0
  177. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +47 -0
  178. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +50 -0
  179. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +50 -0
  180. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +47 -0
  181. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +50 -0
  182. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +50 -0
  183. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +50 -0
  184. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +47 -0
  185. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +50 -0
  186. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +50 -0
  187. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +47 -0
  188. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +50 -0
  189. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +50 -0
  190. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +47 -0
  191. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +50 -0
  192. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +50 -0
  193. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +50 -0
  194. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +47 -0
  195. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +50 -0
  196. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +50 -0
  197. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +47 -0
  198. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +50 -0
  199. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +50 -0
  200. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +47 -0
  201. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +50 -0
  202. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +50 -0
  203. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +47 -0
  204. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +47 -0
  205. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +50 -0
  206. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +50 -0
  207. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +50 -0
  208. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +50 -0
  209. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +47 -0
  210. rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +11 -0
  211. rasa/cli/project_templates/finance/domain/cards/block_card.yml +101 -0
  212. rasa/cli/project_templates/finance/domain/cards/select_card.yml +12 -0
  213. rasa/cli/project_templates/finance/domain/general/assistant_details.yml +12 -0
  214. rasa/cli/project_templates/finance/domain/general/bot_identity.yml +5 -0
  215. rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -0
  216. rasa/cli/project_templates/finance/domain/general/defaults.yml +24 -0
  217. rasa/cli/project_templates/finance/domain/general/feedback.yml +28 -0
  218. rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
  219. rasa/cli/project_templates/finance/domain/general/help.yml +5 -0
  220. rasa/cli/project_templates/finance/domain/general/human_handoff.yml +30 -0
  221. rasa/cli/project_templates/finance/domain/general/utils.yml +13 -0
  222. rasa/cli/project_templates/finance/domain/general/welcome.yml +8 -0
  223. rasa/cli/project_templates/finance/domain/transfers/add_payee.yml +47 -0
  224. rasa/cli/project_templates/finance/domain/transfers/list_payees.yml +4 -0
  225. rasa/cli/project_templates/finance/domain/transfers/remove_payee.yml +16 -0
  226. rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +79 -0
  227. rasa/cli/project_templates/finance/endpoints.yml +63 -0
  228. rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
  229. rasa/cli/project_templates/telco/actions/__init__.py +0 -0
  230. rasa/cli/project_templates/telco/actions/actions_billing.py +204 -0
  231. rasa/cli/project_templates/telco/actions/actions_get_data_from_db.py +48 -0
  232. rasa/cli/project_templates/telco/actions/actions_run_diagnostics.py +28 -0
  233. rasa/cli/project_templates/telco/actions/actions_session_start.py +18 -0
  234. rasa/cli/project_templates/telco/config.yml +25 -0
  235. rasa/cli/project_templates/telco/credentials.yml +33 -0
  236. rasa/cli/project_templates/telco/csvs/billing.csv +10 -0
  237. rasa/cli/project_templates/telco/csvs/customers.csv +5 -0
  238. rasa/cli/project_templates/telco/data/flows/flow_global.yml +5 -0
  239. rasa/cli/project_templates/telco/data/flows/flow_reboot_router.yml +8 -0
  240. rasa/cli/project_templates/telco/data/flows/flow_reset_router.yml +7 -0
  241. rasa/cli/project_templates/telco/data/flows/flow_solve_internet_issue.yml +73 -0
  242. rasa/cli/project_templates/telco/data/flows/flow_undertand_bill.yml +45 -0
  243. rasa/cli/project_templates/telco/data/patterns/pattern_completed.yml +7 -0
  244. rasa/cli/project_templates/telco/data/patterns/pattern_human_handoff.yml +6 -0
  245. rasa/cli/project_templates/telco/data/patterns/pattern_search.yml +7 -0
  246. rasa/cli/project_templates/telco/data/patterns/pattern_session_start.yml +9 -0
  247. rasa/cli/project_templates/telco/docs/reset_vs_rboot_router.txt +1 -0
  248. rasa/cli/project_templates/telco/docs/restart_router.txt +6 -0
  249. rasa/cli/project_templates/telco/docs/run_speed_test.txt +6 -0
  250. rasa/cli/project_templates/telco/domain/domain_global.yml +29 -0
  251. rasa/cli/project_templates/telco/domain/domain_patterns.yml +17 -0
  252. rasa/cli/project_templates/telco/domain/domain_reboot_router.yml +20 -0
  253. rasa/cli/project_templates/telco/domain/domain_reset_router.yml +11 -0
  254. rasa/cli/project_templates/telco/domain/domain_run_speed_test.yml +24 -0
  255. rasa/cli/project_templates/telco/domain/domain_solve_internet_issue.yml +74 -0
  256. rasa/cli/project_templates/telco/domain/domain_undertand_bill.yml +102 -0
  257. rasa/cli/project_templates/telco/endpoints.yml +60 -0
  258. rasa/{dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 → cli/project_templates/telco/prompts/command-generator.jinja2} +3 -7
  259. rasa/cli/project_templates/telco/tests/e2e_results_failed.yml +62 -0
  260. rasa/cli/project_templates/telco/tests/e2e_results_passed.yml +130 -0
  261. rasa/cli/project_templates/telco/tests/e2e_test_cases/billing_test_cases.yml +68 -0
  262. rasa/cli/project_templates/telco/tests/e2e_test_cases/global_test_cases.yml +13 -0
  263. rasa/cli/project_templates/telco/tests/e2e_test_cases/internet_slow_test_case.yml +47 -0
  264. rasa/cli/project_templates/telco/tests/e2e_test_cases/out_of_scope_test_case.yml +21 -0
  265. rasa/cli/project_templates/telco/tests/e2e_test_cases/patterns_test_cases.yml +15 -0
  266. rasa/cli/project_templates/tutorial/config.yml +2 -1
  267. rasa/cli/run.py +0 -4
  268. rasa/cli/scaffold.py +46 -2
  269. rasa/cli/shell.py +0 -3
  270. rasa/constants.py +0 -6
  271. rasa/core/actions/action.py +2 -43
  272. rasa/core/agent.py +0 -16
  273. rasa/core/available_endpoints.py +0 -30
  274. rasa/core/channels/channel.py +4 -3
  275. rasa/core/channels/constants.py +3 -0
  276. rasa/core/channels/development_inspector.py +1 -1
  277. rasa/core/channels/inspector/dist/assets/{arc-2e78c586.js → arc-18042c22.js} +1 -1
  278. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-806b712e.js → blockDiagram-38ab4fdb-fdd6bcfa.js} +1 -1
  279. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0745efa9.js → c4Diagram-3d4e48cf-f5ae6786.js} +1 -1
  280. rasa/core/channels/inspector/dist/assets/channel-b9b536fc.js +1 -0
  281. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-7bd1082b.js → classDiagram-70f12bd4-81efba3e.js} +1 -1
  282. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-d937ba49.js → classDiagram-v2-f2320105-3b6b6a92.js} +1 -1
  283. rasa/core/channels/inspector/dist/assets/clone-78d2ddcf.js +1 -0
  284. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-a2a564ca.js → createText-2e5e7dd3-31422447.js} +1 -1
  285. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-b5256940.js → edges-e0da2a9e-518a90db.js} +1 -1
  286. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-e6883ad2.js → erDiagram-9861fffd-a6d3c25a.js} +1 -1
  287. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-e576fc02.js → flowDb-956e92f1-e048c2be.js} +1 -1
  288. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-2e298d01.js → flowDiagram-66a62f08-c7474c91.js} +1 -1
  289. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-8b09c060.js +1 -0
  290. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-dd7b150a.js → flowchart-elk-definition-4a651766-cb4d8723.js} +1 -1
  291. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-5b79575c.js → ganttDiagram-c361ad54-346636a2.js} +1 -1
  292. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-3016f40a.js → gitGraphDiagram-72cf32ee-7c508874.js} +1 -1
  293. rasa/core/channels/inspector/dist/assets/{graph-3e19170f.js → graph-14702d8a.js} +1 -1
  294. rasa/core/channels/inspector/dist/assets/{index-3862675e-eb9c86de.js → index-3862675e-f18b534b.js} +1 -1
  295. rasa/core/channels/inspector/dist/assets/index-4d4bdf3a.js +1335 -0
  296. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-b4280e4d.js → infoDiagram-f8f76790-64154b83.js} +1 -1
  297. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-556091f8.js → journeyDiagram-49397b02-833a5f95.js} +1 -1
  298. rasa/core/channels/inspector/dist/assets/{layout-08436411.js → layout-5a3b2123.js} +1 -1
  299. rasa/core/channels/inspector/dist/assets/{line-683c4f3b.js → line-2272a8c7.js} +1 -1
  300. rasa/core/channels/inspector/dist/assets/{linear-cee6d791.js → linear-35bcf273.js} +1 -1
  301. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-a0bf0b1a.js → mindmap-definition-fc14e90a-92dcb0e9.js} +1 -1
  302. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-3730d5c4.js → pieDiagram-8a3498a8-94dbc900.js} +1 -1
  303. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-12a20fed.js → quadrantDiagram-120e2f19-8b7a9c33.js} +1 -1
  304. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-b9732102.js → requirementDiagram-deff3bca-6f7eab81.js} +1 -1
  305. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-a2e72776.js → sankeyDiagram-04a897e0-f43e581d.js} +1 -1
  306. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-8b7a76bb.js → sequenceDiagram-704730f1-0bcbefc3.js} +1 -1
  307. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-e65853ac.js → stateDiagram-587899a1-b8a74083.js} +1 -1
  308. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-6f58a44b.js → stateDiagram-v2-d93cdb3a-2070218f.js} +1 -1
  309. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-df25b934.js → styles-6aaf32cf-f1d54e34.js} +1 -1
  310. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-88357141.js → styles-9a916d00-980de489.js} +1 -1
  311. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-d600174d.js → styles-c10674c1-3c03abde.js} +1 -1
  312. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-4adc3e0b.js → svgDrawCommon-08f97a94-46ba068f.js} +1 -1
  313. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-42816fa1.js → timeline-definition-85554ec2-901f5e3d.js} +1 -1
  314. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-621eb66a.js → xychartDiagram-e933f94c-acbc628a.js} +1 -1
  315. rasa/core/channels/inspector/dist/index.html +2 -2
  316. rasa/core/channels/inspector/index.html +1 -1
  317. rasa/core/channels/inspector/src/App.tsx +10 -11
  318. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +12 -3
  319. rasa/core/channels/inspector/src/components/DialogueStack.tsx +5 -7
  320. rasa/core/channels/inspector/src/helpers/formatters.ts +3 -24
  321. rasa/core/channels/inspector/src/theme/base/styles.ts +1 -19
  322. rasa/core/channels/inspector/src/types.ts +0 -4
  323. rasa/core/channels/socketio.py +212 -51
  324. rasa/core/channels/studio_chat.py +43 -23
  325. rasa/core/channels/voice_stream/voice_channel.py +5 -3
  326. rasa/core/constants.py +0 -4
  327. rasa/core/policies/enterprise_search_policy.py +6 -11
  328. rasa/core/policies/flow_policy.py +4 -4
  329. rasa/core/policies/flows/flow_executor.py +45 -415
  330. rasa/core/processor.py +1 -6
  331. rasa/core/run.py +14 -11
  332. rasa/core/utils.py +1 -21
  333. rasa/dialogue_understanding/commands/__init__.py +0 -8
  334. rasa/dialogue_understanding/commands/cancel_flow_command.py +4 -97
  335. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +0 -11
  336. rasa/dialogue_understanding/commands/clarify_command.py +0 -10
  337. rasa/dialogue_understanding/commands/knowledge_answer_command.py +0 -11
  338. rasa/dialogue_understanding/commands/start_flow_command.py +8 -164
  339. rasa/dialogue_understanding/commands/utils.py +2 -6
  340. rasa/dialogue_understanding/generator/command_parser.py +0 -4
  341. rasa/dialogue_understanding/generator/flow_retrieval.py +10 -9
  342. rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -50
  343. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +6 -7
  344. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +6 -7
  345. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +2 -41
  346. rasa/dialogue_understanding/patterns/continue_interrupted.py +1 -163
  347. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +8 -52
  348. rasa/dialogue_understanding/processor/command_processor.py +15 -31
  349. rasa/dialogue_understanding/stack/dialogue_stack.py +2 -123
  350. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +0 -57
  351. rasa/dialogue_understanding/stack/utils.py +2 -17
  352. rasa/dialogue_understanding_test/du_test_runner.py +2 -7
  353. rasa/e2e_test/e2e_test_runner.py +0 -5
  354. rasa/engine/storage/local_model_storage.py +45 -2
  355. rasa/model_manager/model_api.py +4 -5
  356. rasa/model_manager/runner_service.py +1 -1
  357. rasa/model_manager/socket_bridge.py +20 -14
  358. rasa/model_manager/trainer_service.py +12 -9
  359. rasa/model_manager/utils.py +1 -29
  360. rasa/server.py +0 -10
  361. rasa/shared/constants.py +0 -5
  362. rasa/shared/core/constants.py +1 -12
  363. rasa/shared/core/domain.py +58 -11
  364. rasa/shared/core/events.py +0 -319
  365. rasa/shared/core/flows/flow_step.py +7 -1
  366. rasa/shared/core/flows/flows_list.py +2 -2
  367. rasa/shared/core/flows/flows_yaml_schema.json +186 -112
  368. rasa/shared/core/flows/steps/call.py +5 -53
  369. rasa/shared/core/flows/validation.py +7 -46
  370. rasa/shared/core/flows/yaml_flows_io.py +16 -8
  371. rasa/shared/core/slots.py +4 -0
  372. rasa/shared/importers/importer.py +6 -0
  373. rasa/shared/importers/utils.py +77 -1
  374. rasa/shared/providers/_utils.py +60 -44
  375. rasa/shared/providers/embedding/default_litellm_embedding_client.py +2 -0
  376. rasa/shared/providers/llm/_base_litellm_client.py +7 -39
  377. rasa/shared/providers/llm/default_litellm_llm_client.py +2 -0
  378. rasa/shared/providers/llm/litellm_router_llm_client.py +4 -8
  379. rasa/shared/providers/llm/llm_client.py +3 -7
  380. rasa/shared/providers/llm/llm_response.py +0 -49
  381. rasa/shared/providers/llm/self_hosted_llm_client.py +4 -8
  382. rasa/shared/utils/llm.py +5 -28
  383. rasa/shared/utils/schemas/events.py +0 -42
  384. rasa/studio/upload.py +16 -47
  385. rasa/telemetry.py +97 -23
  386. rasa/tracing/instrumentation/instrumentation.py +2 -4
  387. rasa/utils/common.py +0 -79
  388. rasa/utils/io.py +27 -9
  389. rasa/utils/json_utils.py +6 -1
  390. rasa/utils/log_utils.py +5 -1
  391. rasa/utils/openapi.py +144 -0
  392. rasa/validator.py +7 -3
  393. rasa/version.py +1 -1
  394. {rasa_pro-3.14.0.dev3.dist-info → rasa_pro-3.14.0.dev5.dist-info}/METADATA +3 -3
  395. {rasa_pro-3.14.0.dev3.dist-info → rasa_pro-3.14.0.dev5.dist-info}/RECORD +405 -174
  396. rasa/agents/agent_factory.py +0 -122
  397. rasa/agents/agent_manager.py +0 -162
  398. rasa/agents/constants.py +0 -32
  399. rasa/agents/core/agent_protocol.py +0 -108
  400. rasa/agents/core/types.py +0 -70
  401. rasa/agents/exceptions.py +0 -8
  402. rasa/agents/protocol/__init__.py +0 -5
  403. rasa/agents/protocol/a2a/a2a_agent.py +0 -51
  404. rasa/agents/protocol/mcp/mcp_base_agent.py +0 -674
  405. rasa/agents/protocol/mcp/mcp_open_agent.py +0 -276
  406. rasa/agents/protocol/mcp/mcp_task_agent.py +0 -469
  407. rasa/agents/schemas/__init__.py +0 -12
  408. rasa/agents/schemas/agent_input.py +0 -38
  409. rasa/agents/schemas/agent_output.py +0 -26
  410. rasa/agents/schemas/agent_tool_result.py +0 -51
  411. rasa/agents/schemas/agent_tool_schema.py +0 -134
  412. rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +0 -15
  413. rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +0 -17
  414. rasa/agents/utils.py +0 -72
  415. rasa/core/available_agents.py +0 -196
  416. rasa/core/channels/inspector/dist/assets/channel-c436ca7c.js +0 -1
  417. rasa/core/channels/inspector/dist/assets/clone-50dd656b.js +0 -1
  418. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b2aeaf8.js +0 -1
  419. rasa/core/channels/inspector/dist/assets/index-1bd9135e.js +0 -1353
  420. rasa/core/policies/flows/mcp_tool_executor.py +0 -277
  421. rasa/dialogue_understanding/commands/continue_agent_command.py +0 -91
  422. rasa/dialogue_understanding/commands/restart_agent_command.py +0 -162
  423. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +0 -61
  424. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +0 -81
  425. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +0 -81
  426. rasa/shared/agents/utils.py +0 -35
  427. rasa/shared/utils/mcp/server_connection.py +0 -157
  428. /rasa/{agents → builder}/__init__.py +0 -0
  429. /rasa/{agents/core → builder/copilot}/__init__.py +0 -0
  430. /rasa/{agents/protocol/a2a → builder/copilot/prompts}/__init__.py +0 -0
  431. /rasa/{agents/protocol/mcp → builder/copilot/templated_messages}/__init__.py +0 -0
  432. /rasa/{agents/templates → builder/document_retrieval}/__init__.py +0 -0
  433. /rasa/{shared/agents → cli/project_templates/finance/actions/accounts}/__init__.py +0 -0
  434. /rasa/{shared/utils/mcp → cli/project_templates/finance/actions/cards}/__init__.py +0 -0
  435. {rasa_pro-3.14.0.dev3.dist-info → rasa_pro-3.14.0.dev5.dist-info}/NOTICE +0 -0
  436. {rasa_pro-3.14.0.dev3.dist-info → rasa_pro-3.14.0.dev5.dist-info}/WHEEL +0 -0
  437. {rasa_pro-3.14.0.dev3.dist-info → rasa_pro-3.14.0.dev5.dist-info}/entry_points.txt +0 -0
rasa/builder/models.py ADDED
@@ -0,0 +1,197 @@
1
+ """Pydantic models for request/response validation."""
2
+
3
+ import json
4
+ from enum import Enum
5
+ from typing import Any, Dict, List, Literal, Optional
6
+
7
+ import structlog
8
+ from pydantic import BaseModel, Field, validator
9
+
10
+ from rasa.cli.scaffold import ProjectTemplateName
11
+
12
+ structlogger = structlog.get_logger()
13
+
14
+
15
+ class PromptRequest(BaseModel):
16
+ """Request model for prompt-to-bot endpoint."""
17
+
18
+ prompt: str = Field(
19
+ ..., min_length=1, max_length=10000, description="The skill description prompt"
20
+ )
21
+
22
+ @validator("prompt")
23
+ def validate_prompt(cls, v: str) -> str:
24
+ if not v.strip():
25
+ raise ValueError("Prompt cannot be empty or whitespace only")
26
+ return v.strip()
27
+
28
+
29
+ class TemplateRequest(BaseModel):
30
+ """Request model for template-to-bot endpoint."""
31
+
32
+ template_name: ProjectTemplateName = Field(
33
+ ...,
34
+ description=(
35
+ f"The template name to use ({ProjectTemplateName.supported_values()})"
36
+ ),
37
+ )
38
+
39
+ @validator("template_name")
40
+ def validate_template_name(cls, v: Any) -> Any:
41
+ if v not in ProjectTemplateName:
42
+ raise ValueError(
43
+ f"Template name must be one of {ProjectTemplateName.supported_values()}"
44
+ )
45
+ return v
46
+
47
+
48
+ class BotDataUpdateRequest(BaseModel):
49
+ """Request model for bot data updates."""
50
+
51
+ domain_yml: Optional[str] = Field(None, alias="domain.yml")
52
+ flows_yml: Optional[str] = Field(None, alias="flows.yml")
53
+ config_yml: Optional[str] = Field(None, alias="config.yml")
54
+
55
+ class Config:
56
+ """Config for BotDataUpdateRequest."""
57
+
58
+ allow_population_by_field_name = True
59
+
60
+
61
+ class BotData(BaseModel):
62
+ """Data of a running assistant."""
63
+
64
+ domain: Dict[str, Any] = Field(..., description="The domain of the assistant.")
65
+ flows: Dict[str, Any] = Field(..., description="The flows of the assistant.")
66
+
67
+
68
+ class AssistantInfo(BaseModel):
69
+ """Basic information about the loaded assistant."""
70
+
71
+ assistant_id: Optional[str] = Field(
72
+ None,
73
+ description=(
74
+ "Assistant identifier coming from `assistant_id` in the model "
75
+ "metadata (config.yml)."
76
+ ),
77
+ )
78
+
79
+
80
+ class ApiErrorResponse(BaseModel):
81
+ """API error response model."""
82
+
83
+ status: Literal["error"] = "error"
84
+ error: str = Field(...)
85
+ details: Optional[Dict[str, Any]] = Field(None)
86
+
87
+
88
+ class ServerSentEventType(str, Enum):
89
+ progress = "progress"
90
+ error = "error"
91
+ _EOF = "_EOF"
92
+
93
+
94
+ class ServerSentEvent(BaseModel):
95
+ """Generic Server-Sent Event payload."""
96
+
97
+ event: str = Field(..., description="SSE event name / type")
98
+ data: Dict[str, Any] = Field(
99
+ default_factory=dict,
100
+ description="Arbitrary JSON-serializable payload",
101
+ )
102
+
103
+ @classmethod
104
+ def build(cls, event: str, data: Any) -> "ServerSentEvent":
105
+ """General-purpose constructor.
106
+
107
+ Args:
108
+ event: The event name (e.g. "progress", "error").
109
+ data: Arbitrary key-value pairs to include in the payload.
110
+
111
+ Returns:
112
+ A ServerSentEvent instance with the specified event and data.
113
+ """
114
+ return cls(event=event, data=data)
115
+
116
+ @classmethod
117
+ def eof(cls) -> "ServerSentEvent":
118
+ """Helper that returns the special end-of-stream marker."""
119
+ return cls(event=ServerSentEventType._EOF.value, data={})
120
+
121
+ def format(self) -> str:
122
+ """Return the text representation used by SSE protocols."""
123
+ return (
124
+ f"event: {self.event}\n"
125
+ f"data: {json.dumps(self.data, separators=(', ', ': '))}\n\n"
126
+ )
127
+
128
+
129
+ class JobStatusEvent(ServerSentEvent):
130
+ """Job status event with special handling for progress and error states."""
131
+
132
+ @classmethod
133
+ def from_status(
134
+ cls,
135
+ status: str,
136
+ message: Optional[str] = None,
137
+ ) -> "JobStatusEvent":
138
+ """Factory for job-status events.
139
+
140
+ Args:
141
+ status: The job status (e.g. "training", "train_success").
142
+ message: Optional error message for error events.
143
+
144
+ Returns:
145
+ A JobStatusEvent instance with the appropriate event type and data.
146
+ """
147
+ event_type = (
148
+ ServerSentEventType.error if message else ServerSentEventType.progress
149
+ )
150
+
151
+ payload: Dict[str, Any] = {"status": status}
152
+ if message:
153
+ payload["message"] = message
154
+
155
+ return cls(event=event_type.value, data=payload)
156
+
157
+
158
+ class ValidationResult(BaseModel):
159
+ """Result of validation operation."""
160
+
161
+ is_valid: bool = Field(...)
162
+ errors: Optional[List[str]] = Field(None)
163
+ warnings: Optional[List[str]] = Field(None)
164
+
165
+
166
+ class TrainingResult(BaseModel):
167
+ """Result of training operation."""
168
+
169
+ success: bool = Field(...)
170
+ model_path: Optional[str] = Field(None)
171
+ error: Optional[str] = Field(None)
172
+
173
+
174
+ BotFiles = Dict[str, Optional[str]]
175
+
176
+
177
+ class JobStatus(str, Enum):
178
+ received = "received"
179
+ done = "done"
180
+ error = "error"
181
+
182
+ generating = "generating"
183
+ generation_success = "generation_success"
184
+ generation_error = "generation_error"
185
+
186
+ training = "training"
187
+ train_success = "train_success"
188
+ train_error = "train_error"
189
+
190
+ validating = "validating"
191
+ validation_success = "validation_success"
192
+ validation_error = "validation_error"
193
+
194
+
195
+ class JobCreateResponse(BaseModel):
196
+ job_id: str = Field(...)
197
+ status: JobStatus = JobStatus.received
@@ -0,0 +1,450 @@
1
+ """Service for generating Rasa projects from prompts."""
2
+
3
+ import json
4
+ import os
5
+ import shutil
6
+ import tarfile
7
+ import tempfile
8
+ from pathlib import Path
9
+ from textwrap import dedent
10
+ from typing import Any, Dict, Generator, List, Optional
11
+
12
+ import aiofiles
13
+ import aiohttp
14
+ import structlog
15
+
16
+ import rasa.version
17
+ from rasa.builder import config
18
+ from rasa.builder.exceptions import ProjectGenerationError, ValidationError
19
+ from rasa.builder.llm_service import get_skill_generation_messages, llm_service
20
+ from rasa.builder.logging_utils import capture_exception_with_context
21
+ from rasa.builder.models import BotFiles
22
+ from rasa.builder.project_info import ProjectInfo, ensure_first_used, load_project_info
23
+ from rasa.builder.validation_service import validate_project
24
+ from rasa.cli.scaffold import ProjectTemplateName, create_initial_project
25
+ from rasa.shared.core.flows import yaml_flows_io
26
+ from rasa.shared.importers.importer import TrainingDataImporter
27
+ from rasa.shared.utils.yaml import dump_obj_as_yaml_to_string
28
+ from rasa.utils.io import subpath
29
+
30
+ structlogger = structlog.get_logger()
31
+
32
+
33
+ class ProjectGenerator:
34
+ """Service for generating Rasa projects from skill descriptions."""
35
+
36
+ def __init__(self, project_folder: str) -> None:
37
+ """Initialize the project generator with a folder for file persistence.
38
+
39
+ Args:
40
+ project_folder: Path to the folder where project files will be stored
41
+ """
42
+ self.project_folder = Path(project_folder)
43
+ self.project_folder.mkdir(parents=True, exist_ok=True)
44
+
45
+ @property
46
+ def project_info(self) -> ProjectInfo:
47
+ """Get the project info."""
48
+ return load_project_info(self.project_folder)
49
+
50
+ async def init_from_template(self, template: ProjectTemplateName) -> None:
51
+ """Create the initial project files."""
52
+ self.cleanup()
53
+ create_initial_project(self.project_folder.as_posix(), template)
54
+ await download_cache_for_template(template, self.project_folder.as_posix())
55
+ # needs to happen after caching, as we download .rasa and that would
56
+ # overwrite the project info file in .rasa
57
+ ensure_first_used(self.project_folder)
58
+
59
+ async def generate_project_with_retries(
60
+ self,
61
+ skill_description: str,
62
+ template: ProjectTemplateName,
63
+ max_retries: Optional[int] = None,
64
+ ) -> Dict[str, Optional[str]]:
65
+ """Generate a Rasa project with retry logic for validation failures.
66
+
67
+ Args:
68
+ skill_description: Natural language description of the skill
69
+ rasa_config: Rasa configuration dictionary
70
+ template: Project template to use for the initial project
71
+ max_retries: Maximum number of retry attempts
72
+
73
+ Returns:
74
+ Dictionary of generated file contents (filename -> content)
75
+
76
+ Raises:
77
+ ProjectGenerationError: If generation fails after all retries
78
+ """
79
+ if max_retries is None:
80
+ max_retries = config.MAX_RETRIES
81
+
82
+ # if ever we do not use the template, we need to ensure first_used is set
83
+ # separately!
84
+ await self.init_from_template(template)
85
+
86
+ project_data = self._get_bot_data_for_llm()
87
+
88
+ initial_messages = get_skill_generation_messages(
89
+ skill_description, project_data
90
+ )
91
+
92
+ async def _generate_with_retry(
93
+ messages: List[Dict[str, Any]], attempts_left: int
94
+ ) -> Dict[str, Optional[str]]:
95
+ try:
96
+ # Generate project data using LLM
97
+ project_data = await llm_service.generate_rasa_project(messages)
98
+
99
+ # Update stored bot data
100
+ self._update_bot_files_from_llm_response(project_data)
101
+
102
+ bot_files = self.get_bot_files()
103
+ structlogger.info(
104
+ "project_generator.generated_project",
105
+ attempts_left=attempts_left,
106
+ files=list(bot_files.keys()),
107
+ )
108
+
109
+ # Validate the generated project
110
+ await self._validate_generated_project()
111
+
112
+ structlogger.info(
113
+ "project_generator.validation_success", attempts_left=attempts_left
114
+ )
115
+
116
+ return bot_files
117
+
118
+ except ValidationError as e:
119
+ structlogger.error(
120
+ "project_generator.validation_error",
121
+ error=str(e),
122
+ attempts_left=attempts_left,
123
+ )
124
+
125
+ if attempts_left <= 0:
126
+ raise ProjectGenerationError(
127
+ f"Failed to generate valid Rasa project: {e}", max_retries
128
+ )
129
+
130
+ # Create error feedback for next attempt
131
+ error_feedback_messages = messages + [
132
+ {
133
+ "role": "assistant",
134
+ "content": json.dumps(project_data),
135
+ },
136
+ {
137
+ "role": "user",
138
+ "content": dedent(f"""
139
+ Previous attempt failed validation with error: {e}
140
+
141
+ Please fix the issues and generate a valid Rasa project.
142
+ Pay special attention to:
143
+ - Proper YAML syntax
144
+ - Required fields in domain and flows
145
+ - Consistent naming between flows and domain
146
+ - Valid slot types and mappings
147
+ """).strip(),
148
+ },
149
+ ]
150
+
151
+ return await _generate_with_retry(
152
+ error_feedback_messages, attempts_left - 1
153
+ )
154
+
155
+ except Exception as e:
156
+ structlogger.error(
157
+ "project_generator.generation_error",
158
+ error=str(e),
159
+ attempts_left=attempts_left,
160
+ )
161
+
162
+ if attempts_left <= 0:
163
+ raise ProjectGenerationError(
164
+ f"Failed to generate Rasa project: {e}", max_retries
165
+ )
166
+
167
+ # For non-validation errors, retry with original messages
168
+ return await _generate_with_retry(initial_messages, attempts_left - 1)
169
+
170
+ return await _generate_with_retry(initial_messages, max_retries)
171
+
172
+ async def _validate_generated_project(self) -> None:
173
+ """Validate the generated project using the validation service."""
174
+ importer = self._create_importer()
175
+ validation_error = await validate_project(importer)
176
+
177
+ if validation_error:
178
+ raise ValidationError(validation_error)
179
+
180
+ def _create_importer(self) -> TrainingDataImporter:
181
+ """Create a training data importer from the current bot files."""
182
+ try:
183
+ if (self.project_folder / "domain.yml").exists():
184
+ domain_path = self.project_folder / "domain.yml"
185
+ else:
186
+ domain_path = self.project_folder / "domain"
187
+
188
+ return TrainingDataImporter.load_from_config(
189
+ config_path=str(self.project_folder / "config.yml"),
190
+ domain_path=str(domain_path),
191
+ training_data_paths=[str(self.project_folder / "data")],
192
+ args={},
193
+ )
194
+
195
+ except Exception as e:
196
+ raise ValidationError(f"Failed to create importer: {e}")
197
+
198
+ def get_bot_files(
199
+ self,
200
+ allowed_file_extensions: Optional[List[str]] = None,
201
+ exclude_docs_directory: bool = False,
202
+ ) -> BotFiles:
203
+ """Get the current bot files by reading from disk.
204
+
205
+ Args:
206
+ allowed_file_extensions: Optional list of file extensions to include.
207
+ If None, fetch all files. If provided, only fetch files with matching
208
+ extensions. Use `""` empty string to allow files with no extensions.
209
+ exclude_docs_directory: Optional boolean indicating whether to exclude.
210
+
211
+ Returns:
212
+ Dictionary of file contents with relative paths as keys
213
+ """
214
+ bot_files: BotFiles = {}
215
+
216
+ for file in self.project_folder.glob("**/*"):
217
+ # Skip directories
218
+ if not file.is_file():
219
+ continue
220
+
221
+ relative_path = file.relative_to(self.project_folder)
222
+
223
+ # Skip hidden files and directories (any path component starting with '.')
224
+ # as well as `__pycache__` folders
225
+ if any(part.startswith(".") for part in relative_path.parts):
226
+ continue
227
+
228
+ if "__pycache__" in relative_path.parts:
229
+ continue
230
+
231
+ # exclude the project_folder / models folder
232
+ if relative_path.parts[0] == "models":
233
+ continue
234
+
235
+ # Exclude the docs directory if specified
236
+ if exclude_docs_directory and relative_path.parts[0] == "docs":
237
+ continue
238
+
239
+ # Exclude the files by file extensions if specified
240
+ if allowed_file_extensions is not None:
241
+ allowed_file_extensions = [
242
+ ext.lower() for ext in allowed_file_extensions
243
+ ]
244
+ if file.suffix.lstrip(".").lower() not in allowed_file_extensions:
245
+ continue
246
+
247
+ # Read file content and store with relative path as key
248
+ try:
249
+ bot_files[relative_path.as_posix()] = file.read_text(encoding="utf-8")
250
+ except Exception as e:
251
+ structlogger.debug(
252
+ "project_generator.get_bot_files.error",
253
+ error=str(e),
254
+ file_path=file.as_posix(),
255
+ )
256
+ bot_files[relative_path.as_posix()] = None
257
+
258
+ return bot_files
259
+
260
+ def _get_bot_data_for_llm(self) -> Dict[str, Any]:
261
+ """Get the current bot data for the LLM."""
262
+ file_importer = self._create_importer()
263
+
264
+ # only include data created by the user (or the builder llm)
265
+ # avoid including to many defaults that are not customized
266
+ domain = file_importer.get_user_domain()
267
+ flows = file_importer.get_user_flows()
268
+
269
+ return {
270
+ "domain": domain.as_dict(should_clean_json=True),
271
+ "flows": yaml_flows_io.get_flows_as_json(flows, should_clean_json=True),
272
+ }
273
+
274
+ def _path_for_flow(self, flow_id: str) -> str:
275
+ """Get the path for a flow."""
276
+ if flow_id.startswith("pattern_"):
277
+ return f"data/patterns/{flow_id}.yml"
278
+ else:
279
+ return f"data/flows/{flow_id}.yml"
280
+
281
+ def _update_bot_files_from_llm_response(self, project_data: Dict[str, Any]) -> None:
282
+ """Update the bot files with generated data by writing to disk."""
283
+ files = {"domain.yml": dump_obj_as_yaml_to_string(project_data["domain"])}
284
+ # split up flows into one file per flow in the /flows folder
285
+ for flow_id, flow_data in project_data["flows"].get("flows", {}).items():
286
+ flow_file_path = self._path_for_flow(flow_id)
287
+ single_flow_file_data = {"flows": {flow_id: flow_data}}
288
+ files[flow_file_path] = dump_obj_as_yaml_to_string(single_flow_file_data)
289
+
290
+ # removes any other flows that the LLM didn't generate
291
+ self._cleanup_flows()
292
+ self.update_bot_files(files)
293
+
294
+ def _cleanup_flows(self) -> None:
295
+ """Cleanup the flows folder."""
296
+ flows_folder = self.project_folder / "data" / "flows"
297
+ if flows_folder.exists():
298
+ shutil.rmtree(flows_folder)
299
+ flows_folder.mkdir(parents=True, exist_ok=True)
300
+
301
+ def update_bot_files(self, files: Dict[str, Optional[str]]) -> None:
302
+ """Update bot files with new content by writing to disk."""
303
+ for filename, content in files.items():
304
+ file_path = Path(subpath(self.project_folder, filename))
305
+ # Disallow updates inside .rasa project metadata directory
306
+ if any(
307
+ part.startswith(".")
308
+ for part in file_path.relative_to(self.project_folder).parts
309
+ ):
310
+ # silently ignore hidden paths
311
+ continue
312
+ file_path.parent.mkdir(parents=True, exist_ok=True)
313
+ file_path.write_text(content, encoding="utf-8")
314
+
315
+ def cleanup(self) -> None:
316
+ """Cleanup the project folder."""
317
+ # remove all the files and folders in the project folder resulting
318
+ # in an empty folder
319
+ for filename in os.listdir(self.project_folder):
320
+ file_path = os.path.join(self.project_folder, filename)
321
+ try:
322
+ if os.path.isfile(file_path) or os.path.islink(file_path):
323
+ os.unlink(file_path)
324
+ elif os.path.isdir(file_path):
325
+ shutil.rmtree(file_path)
326
+ except Exception as e:
327
+ structlogger.error(
328
+ "project_generator.cleanup_error",
329
+ error=str(e),
330
+ file_path=file_path,
331
+ )
332
+
333
+
334
+ CACHE_BUCKET_URL = "https://trained-templates.s3.us-east-1.amazonaws.com"
335
+
336
+
337
+ def _safe_tar_members(
338
+ tar: tarfile.TarFile, destination_directory: Path
339
+ ) -> Generator[tarfile.TarInfo, None, None]:
340
+ """Yield safe members for extraction to prevent path traversal and links.
341
+
342
+ Args:
343
+ tar: Open tar file handle
344
+ destination_directory: Directory to which files will be extracted
345
+
346
+ Yields:
347
+ Members that are safe to extract within destination_directory
348
+ """
349
+ base_path = destination_directory.resolve()
350
+
351
+ for member in tar.getmembers():
352
+ name = member.name
353
+ # Skip empty names and absolute paths
354
+ if not name or name.startswith("/") or name.startswith("\\"):
355
+ continue
356
+
357
+ # Disallow symlinks and hardlinks
358
+ if member.issym() or member.islnk():
359
+ continue
360
+
361
+ # Compute the final path and ensure it's within base_path
362
+ target_path = (base_path / name).resolve()
363
+ try:
364
+ target_path.relative_to(base_path)
365
+ except ValueError:
366
+ # Member would escape the destination directory
367
+ continue
368
+
369
+ yield member
370
+
371
+
372
+ async def download_cache_for_template(
373
+ template: ProjectTemplateName, project_folder: str
374
+ ) -> None:
375
+ # get a temp path for the cache file download
376
+ temporary_cache_file = tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False)
377
+
378
+ try:
379
+ url = f"{CACHE_BUCKET_URL}/{rasa.version.__version__}-{template.value}.tar.gz"
380
+ async with aiohttp.ClientSession() as session:
381
+ async with session.get(url) as response:
382
+ response.raise_for_status()
383
+ async with aiofiles.open(temporary_cache_file.name, "wb") as f:
384
+ async for chunk in response.content.iter_chunked(1024 * 1024):
385
+ await f.write(chunk)
386
+
387
+ # extract the cache to the project folder using safe member filtering
388
+ with tarfile.open(temporary_cache_file.name, "r:gz") as tar:
389
+ destination = Path(project_folder)
390
+ destination.mkdir(parents=True, exist_ok=True)
391
+ tar.extractall(
392
+ path=destination,
393
+ members=_safe_tar_members(tar, destination),
394
+ )
395
+
396
+ structlogger.info(
397
+ "project_generator.download_cache_for_template.success",
398
+ template=template,
399
+ event_info=(
400
+ f"Downloaded cache for template, extracted to {project_folder}."
401
+ ),
402
+ )
403
+ except aiohttp.ClientResponseError as e:
404
+ if e.status == 403:
405
+ structlogger.debug(
406
+ "project_generator.download_cache_for_template.no_cache_found",
407
+ template=template,
408
+ event_info=("No cache found for template, continuing without it."),
409
+ )
410
+ else:
411
+ structlogger.debug(
412
+ "project_generator.download_cache_for_template.response_error",
413
+ error=str(e),
414
+ status=e.status,
415
+ template=template,
416
+ event_info=(
417
+ "Failed to download cache for template, continuing without it."
418
+ ),
419
+ )
420
+ capture_exception_with_context(
421
+ e,
422
+ "project_generator.download_cache_for_template.response_error",
423
+ tags={"template": template.value, "status": str(e.status)},
424
+ )
425
+ except Exception as exc:
426
+ structlogger.debug(
427
+ "project_generator.download_cache_for_template.unexpected_error",
428
+ error=str(exc),
429
+ template=template,
430
+ event_info=(
431
+ "Unexpected error when downloading cache for template, "
432
+ "continuing without it."
433
+ ),
434
+ )
435
+ capture_exception_with_context(
436
+ exc,
437
+ "project_generator.download_cache_for_template.unexpected_error",
438
+ tags={"template": template.value},
439
+ )
440
+ finally:
441
+ # Clean up the temporary file
442
+ try:
443
+ Path(temporary_cache_file.name).unlink(missing_ok=True)
444
+ except Exception as exc:
445
+ structlogger.debug(
446
+ "project_generator.download_cache_for_template.cleanup_error",
447
+ error=str(exc),
448
+ template=template,
449
+ event_info=("Failed to cleanup cache for template, ignoring."),
450
+ )