rasa-pro 3.12.18.dev1__py3-none-any.whl → 3.13.0a1.dev2__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 (341) hide show
  1. rasa/__init__.py +0 -6
  2. rasa/__main__.py +3 -4
  3. rasa/api.py +1 -1
  4. rasa/builder/create_openai_vector_store.py +69 -0
  5. rasa/builder/llm-helper-schema.json +69 -0
  6. rasa/builder/prompt_to_bot.py +650 -0
  7. rasa/builder/scrape_rasa_docs.py +97 -0
  8. rasa/builder/skill_to_bot_prompt.jinja +158 -0
  9. rasa/cli/dialogue_understanding_test.py +1 -1
  10. rasa/cli/e2e_test.py +1 -1
  11. rasa/cli/evaluate.py +2 -2
  12. rasa/cli/export.py +3 -3
  13. rasa/cli/llm_fine_tuning.py +1 -1
  14. rasa/cli/project_templates/default/config.yml +5 -32
  15. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_cancels_during_a_correction.yml +1 -1
  16. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +1 -1
  17. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_handle.yml +1 -1
  18. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_name.yml +1 -1
  19. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +1 -1
  20. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_lists_contacts.yml +1 -1
  21. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact.yml +1 -1
  22. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact_from_list.yml +1 -1
  23. rasa/cli/project_templates/default/endpoints.yml +18 -2
  24. rasa/cli/project_templates/defaults.py +133 -0
  25. rasa/cli/run.py +1 -1
  26. rasa/cli/scaffold.py +2 -3
  27. rasa/cli/studio/download.py +1 -1
  28. rasa/cli/studio/link.py +53 -0
  29. rasa/cli/studio/pull.py +78 -0
  30. rasa/cli/studio/push.py +78 -0
  31. rasa/cli/studio/studio.py +12 -0
  32. rasa/cli/studio/upload.py +5 -3
  33. rasa/cli/train.py +1 -1
  34. rasa/cli/utils.py +1 -1
  35. rasa/cli/x.py +1 -1
  36. rasa/constants.py +2 -0
  37. rasa/core/__init__.py +0 -16
  38. rasa/core/actions/action.py +42 -31
  39. rasa/core/actions/action_repeat_bot_messages.py +18 -22
  40. rasa/core/actions/action_run_slot_rejections.py +1 -2
  41. rasa/core/agent.py +18 -3
  42. rasa/core/available_endpoints.py +146 -0
  43. rasa/core/brokers/kafka.py +4 -0
  44. rasa/core/brokers/pika.py +5 -2
  45. rasa/core/brokers/sql.py +1 -1
  46. rasa/core/channels/botframework.py +2 -2
  47. rasa/core/channels/channel.py +2 -2
  48. rasa/core/channels/development_inspector.py +1 -1
  49. rasa/core/channels/facebook.py +1 -4
  50. rasa/core/channels/hangouts.py +8 -5
  51. rasa/core/channels/inspector/.eslintrc.cjs +12 -6
  52. rasa/core/channels/inspector/.prettierrc +5 -0
  53. rasa/core/channels/inspector/README.md +11 -5
  54. rasa/core/channels/inspector/dist/assets/{arc-9f75cc3b.js → arc-02053cc1.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7f34db23.js → blockDiagram-38ab4fdb-008b6289.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-948bab2c.js → c4Diagram-3d4e48cf-fb2597be.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/channel-078dada8.js +1 -0
  58. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-53b0dd0e.js → classDiagram-70f12bd4-7f847e00.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-fdf789e7.js → classDiagram-v2-f2320105-ba1d689b.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/clone-5b4516de.js +1 -0
  61. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-87c4ece5.js → createText-2e5e7dd3-dd8e67c4.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-5a8b0749.js → edges-e0da2a9e-10784939.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-66da90e2.js → erDiagram-9861fffd-24947ae6.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-10044f05.js → flowDb-956e92f1-a9ced505.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f338f66a.js → flowDiagram-66a62f08-afda9c7c.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-f9613071.js +1 -0
  67. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-b13140aa.js → flowchart-elk-definition-4a651766-6ef530b8.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-f2b4a55a.js → ganttDiagram-c361ad54-0c7dd39a.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-dedc298d.js → gitGraphDiagram-72cf32ee-b57239d6.js} +1 -1
  70. rasa/core/channels/inspector/dist/assets/{graph-4ede11ff.js → graph-9ed57cec.js} +1 -1
  71. rasa/core/channels/inspector/dist/assets/{index-3862675e-65549d37.js → index-3862675e-233090de.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{index-3a23e736.js → index-72184470.js} +123 -123
  73. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-65439671.js → infoDiagram-f8f76790-aa116649.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-56d03d98.js → journeyDiagram-49397b02-e51877cc.js} +1 -1
  75. rasa/core/channels/inspector/dist/assets/{layout-dd48f7f4.js → layout-3ca3798c.js} +1 -1
  76. rasa/core/channels/inspector/dist/assets/{line-1569ad2c.js → line-26ee10d3.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/{linear-48bf4935.js → linear-aedded32.js} +1 -1
  78. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-688504c1.js → mindmap-definition-fc14e90a-d8957261.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78b6d7e6.js → pieDiagram-8a3498a8-d771f885.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-048b84b3.js → quadrantDiagram-120e2f19-09fdf50c.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dd67f107.js → requirementDiagram-deff3bca-9f0af02e.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-8128436e.js → sankeyDiagram-04a897e0-84415b37.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-1a0d1461.js → sequenceDiagram-704730f1-8dec4055.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-46d388ed.js → stateDiagram-587899a1-c5431d07.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-ea42951a.js → stateDiagram-v2-d93cdb3a-274e77d9.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-7427ed0c.js → styles-6aaf32cf-e364a1d7.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-ff5e5a16.js → styles-9a916d00-0dae36f6.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-7b3680cf.js → styles-c10674c1-c4641675.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f860f2ad.js → svgDrawCommon-08f97a94-831fe9a1.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-2eebf0c8.js → timeline-definition-85554ec2-c3304b3a.js} +1 -1
  91. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5d7f4e96.js → xychartDiagram-e933f94c-da799369.js} +1 -1
  92. rasa/core/channels/inspector/dist/index.html +1 -1
  93. rasa/core/channels/inspector/package.json +3 -1
  94. rasa/core/channels/inspector/src/App.tsx +91 -90
  95. rasa/core/channels/inspector/src/components/Chat.tsx +45 -41
  96. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -40
  97. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +57 -57
  98. rasa/core/channels/inspector/src/components/DialogueStack.tsx +36 -27
  99. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +4 -4
  100. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +7 -7
  101. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +28 -12
  102. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +9 -9
  103. rasa/core/channels/inspector/src/components/RasaLogo.tsx +5 -5
  104. rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +55 -60
  105. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +5 -5
  106. rasa/core/channels/inspector/src/components/Slots.tsx +22 -22
  107. rasa/core/channels/inspector/src/components/Welcome.tsx +28 -31
  108. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +245 -0
  109. rasa/core/channels/inspector/src/helpers/audio/microphone-processor.js +12 -0
  110. rasa/core/channels/inspector/src/helpers/audio/playback-processor.js +36 -0
  111. rasa/core/channels/inspector/src/helpers/conversation.ts +7 -7
  112. rasa/core/channels/inspector/src/helpers/formatters.test.ts +181 -181
  113. rasa/core/channels/inspector/src/helpers/formatters.ts +111 -111
  114. rasa/core/channels/inspector/src/helpers/utils.ts +78 -61
  115. rasa/core/channels/inspector/src/main.tsx +8 -8
  116. rasa/core/channels/inspector/src/theme/Button/Button.ts +8 -8
  117. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +7 -7
  118. rasa/core/channels/inspector/src/theme/Input/Input.ts +9 -9
  119. rasa/core/channels/inspector/src/theme/Link/Link.ts +6 -6
  120. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +13 -13
  121. rasa/core/channels/inspector/src/theme/Table/Table.tsx +10 -10
  122. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +5 -5
  123. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +7 -7
  124. rasa/core/channels/inspector/src/theme/base/colors.ts +64 -64
  125. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +21 -18
  126. rasa/core/channels/inspector/src/theme/base/radii.ts +8 -8
  127. rasa/core/channels/inspector/src/theme/base/shadows.ts +5 -5
  128. rasa/core/channels/inspector/src/theme/base/sizes.ts +5 -5
  129. rasa/core/channels/inspector/src/theme/base/space.ts +12 -12
  130. rasa/core/channels/inspector/src/theme/base/styles.ts +5 -5
  131. rasa/core/channels/inspector/src/theme/base/typography.ts +12 -12
  132. rasa/core/channels/inspector/src/theme/base/zIndices.ts +3 -3
  133. rasa/core/channels/inspector/src/theme/index.ts +38 -38
  134. rasa/core/channels/inspector/src/types.ts +56 -50
  135. rasa/core/channels/inspector/yarn.lock +5 -0
  136. rasa/core/channels/mattermost.py +1 -1
  137. rasa/core/channels/rasa_chat.py +2 -4
  138. rasa/core/channels/rest.py +5 -4
  139. rasa/core/channels/socketio.py +56 -41
  140. rasa/core/channels/studio_chat.py +337 -71
  141. rasa/core/channels/vier_cvg.py +1 -2
  142. rasa/core/channels/voice_ready/audiocodes.py +4 -11
  143. rasa/core/channels/voice_stream/audiocodes.py +8 -5
  144. rasa/core/channels/voice_stream/browser_audio.py +1 -1
  145. rasa/core/channels/voice_stream/genesys.py +2 -2
  146. rasa/core/channels/voice_stream/tts/__init__.py +8 -0
  147. rasa/core/channels/voice_stream/twilio_media_streams.py +10 -5
  148. rasa/core/channels/voice_stream/voice_channel.py +65 -23
  149. rasa/core/concurrent_lock_store.py +24 -10
  150. rasa/core/evaluation/marker_tracker_loader.py +1 -1
  151. rasa/core/exporter.py +1 -1
  152. rasa/core/http_interpreter.py +3 -7
  153. rasa/core/information_retrieval/faiss.py +18 -11
  154. rasa/core/information_retrieval/ingestion/__init__.py +0 -0
  155. rasa/core/information_retrieval/ingestion/faq_parser.py +158 -0
  156. rasa/core/jobs.py +2 -1
  157. rasa/core/lock_store.py +151 -60
  158. rasa/core/nlg/contextual_response_rephraser.py +17 -7
  159. rasa/core/nlg/generator.py +5 -22
  160. rasa/core/nlg/interpolator.py +2 -3
  161. rasa/core/nlg/response.py +6 -43
  162. rasa/core/nlg/summarize.py +1 -1
  163. rasa/core/nlg/translate.py +0 -8
  164. rasa/core/policies/enterprise_search_policy.py +262 -62
  165. rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +63 -0
  166. rasa/core/policies/flow_policy.py +1 -1
  167. rasa/core/policies/flows/flow_executor.py +96 -17
  168. rasa/core/policies/intentless_policy.py +57 -20
  169. rasa/core/processor.py +114 -54
  170. rasa/core/run.py +33 -11
  171. rasa/core/tracker_stores/__init__.py +0 -0
  172. rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +5 -1
  173. rasa/core/tracker_stores/dynamo_tracker_store.py +218 -0
  174. rasa/core/tracker_stores/mongo_tracker_store.py +206 -0
  175. rasa/core/tracker_stores/redis_tracker_store.py +219 -0
  176. rasa/core/tracker_stores/sql_tracker_store.py +555 -0
  177. rasa/core/tracker_stores/tracker_store.py +805 -0
  178. rasa/core/training/interactive.py +1 -1
  179. rasa/core/utils.py +24 -95
  180. rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
  181. rasa/dialogue_understanding/coexistence/llm_based_router.py +10 -6
  182. rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
  183. rasa/dialogue_understanding/commands/cancel_flow_command.py +5 -1
  184. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -0
  185. rasa/dialogue_understanding/commands/clarify_command.py +4 -0
  186. rasa/dialogue_understanding/commands/command_syntax_manager.py +1 -0
  187. rasa/dialogue_understanding/commands/correct_slots_command.py +1 -3
  188. rasa/dialogue_understanding/commands/human_handoff_command.py +2 -0
  189. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -0
  190. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -0
  191. rasa/dialogue_understanding/commands/set_slot_command.py +10 -0
  192. rasa/dialogue_understanding/commands/skip_question_command.py +2 -0
  193. rasa/dialogue_understanding/commands/start_flow_command.py +4 -0
  194. rasa/dialogue_understanding/commands/utils.py +26 -2
  195. rasa/dialogue_understanding/generator/__init__.py +7 -1
  196. rasa/dialogue_understanding/generator/command_generator.py +4 -2
  197. rasa/dialogue_understanding/generator/command_parser.py +2 -2
  198. rasa/dialogue_understanding/generator/command_parser_validator.py +63 -0
  199. rasa/dialogue_understanding/generator/llm_based_command_generator.py +5 -17
  200. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -3
  201. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +4 -44
  202. rasa/dialogue_understanding/generator/nlu_command_adapter.py +2 -2
  203. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +78 -0
  204. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +26 -474
  205. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +147 -0
  206. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +477 -0
  207. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +11 -64
  208. rasa/dialogue_understanding/patterns/cancel.py +1 -2
  209. rasa/dialogue_understanding/patterns/clarify.py +1 -1
  210. rasa/dialogue_understanding/patterns/correction.py +2 -2
  211. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +37 -25
  212. rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
  213. rasa/dialogue_understanding/processor/command_processor.py +6 -7
  214. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +17 -4
  215. rasa/dialogue_understanding/stack/utils.py +3 -1
  216. rasa/dialogue_understanding/utils.py +68 -12
  217. rasa/dialogue_understanding_test/command_metric_calculation.py +7 -40
  218. rasa/dialogue_understanding_test/command_metrics.py +38 -0
  219. rasa/dialogue_understanding_test/du_test_case.py +58 -25
  220. rasa/dialogue_understanding_test/du_test_result.py +228 -132
  221. rasa/dialogue_understanding_test/du_test_runner.py +11 -2
  222. rasa/dialogue_understanding_test/io.py +35 -8
  223. rasa/e2e_test/e2e_test_runner.py +1 -1
  224. rasa/engine/constants.py +1 -1
  225. rasa/engine/graph.py +2 -2
  226. rasa/engine/recipes/default_recipe.py +1 -1
  227. rasa/engine/validation.py +3 -2
  228. rasa/hooks.py +2 -85
  229. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +1 -5
  230. rasa/llm_fine_tuning/utils.py +2 -4
  231. rasa/model_manager/model_api.py +90 -2
  232. rasa/model_manager/socket_bridge.py +0 -7
  233. rasa/model_manager/trainer_service.py +15 -12
  234. rasa/plugin.py +2 -15
  235. rasa/privacy/__init__.py +0 -0
  236. rasa/privacy/constants.py +83 -0
  237. rasa/privacy/event_broker_utils.py +77 -0
  238. rasa/privacy/privacy_config.py +281 -0
  239. rasa/privacy/privacy_config_schema.json +86 -0
  240. rasa/privacy/privacy_filter.py +340 -0
  241. rasa/privacy/privacy_manager.py +576 -0
  242. rasa/server.py +23 -2
  243. rasa/shared/constants.py +13 -4
  244. rasa/shared/core/command_payload_reader.py +1 -5
  245. rasa/shared/core/constants.py +4 -3
  246. rasa/shared/core/domain.py +172 -11
  247. rasa/shared/core/events.py +100 -6
  248. rasa/shared/core/flows/flow.py +35 -8
  249. rasa/shared/core/flows/flow_step.py +26 -4
  250. rasa/shared/core/flows/flow_step_links.py +15 -0
  251. rasa/shared/core/flows/flow_step_sequence.py +6 -0
  252. rasa/shared/core/flows/flows_yaml_schema.json +3 -0
  253. rasa/shared/core/flows/nlu_trigger.py +13 -0
  254. rasa/shared/core/flows/steps/action.py +7 -4
  255. rasa/shared/core/flows/steps/call.py +11 -4
  256. rasa/shared/core/flows/steps/collect.py +71 -6
  257. rasa/shared/core/flows/steps/internal.py +6 -1
  258. rasa/shared/core/flows/steps/link.py +7 -4
  259. rasa/shared/core/flows/steps/no_operation.py +7 -4
  260. rasa/shared/core/flows/steps/set_slots.py +8 -4
  261. rasa/shared/core/flows/validation.py +16 -3
  262. rasa/shared/core/flows/yaml_flows_io.py +106 -5
  263. rasa/shared/core/slots.py +33 -1
  264. rasa/shared/core/trackers.py +4 -10
  265. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +1 -4
  266. rasa/shared/importers/importer.py +14 -0
  267. rasa/shared/importers/static.py +63 -0
  268. rasa/shared/providers/constants.py +0 -9
  269. rasa/shared/providers/llm/_base_litellm_client.py +4 -14
  270. rasa/shared/providers/llm/default_litellm_llm_client.py +2 -2
  271. rasa/shared/providers/llm/litellm_router_llm_client.py +7 -17
  272. rasa/shared/providers/llm/llm_client.py +15 -24
  273. rasa/shared/providers/llm/self_hosted_llm_client.py +2 -10
  274. rasa/shared/utils/common.py +43 -1
  275. rasa/shared/utils/llm.py +155 -3
  276. rasa/shared/utils/yaml.py +32 -0
  277. rasa/studio/data_handler.py +3 -3
  278. rasa/studio/download/__init__.py +0 -0
  279. rasa/studio/download/domains.py +49 -0
  280. rasa/studio/download/download.py +416 -0
  281. rasa/studio/download/flows.py +351 -0
  282. rasa/studio/link.py +200 -0
  283. rasa/studio/pull.py +94 -0
  284. rasa/studio/push.py +131 -0
  285. rasa/studio/results_logger.py +6 -1
  286. rasa/studio/upload.py +185 -71
  287. rasa/telemetry.py +83 -26
  288. rasa/tracing/config.py +4 -5
  289. rasa/tracing/constants.py +19 -1
  290. rasa/tracing/instrumentation/attribute_extractors.py +49 -11
  291. rasa/tracing/instrumentation/instrumentation.py +54 -3
  292. rasa/tracing/instrumentation/metrics.py +98 -15
  293. rasa/tracing/metric_instrument_provider.py +75 -3
  294. rasa/utils/common.py +37 -27
  295. rasa/utils/endpoints.py +22 -1
  296. rasa/utils/licensing.py +2 -3
  297. rasa/utils/log_utils.py +1 -45
  298. rasa/validator.py +9 -11
  299. rasa/version.py +1 -1
  300. {rasa_pro-3.12.18.dev1.dist-info → rasa_pro-3.13.0a1.dev2.dist-info}/METADATA +12 -14
  301. {rasa_pro-3.12.18.dev1.dist-info → rasa_pro-3.13.0a1.dev2.dist-info}/RECORD +318 -294
  302. rasa/anonymization/__init__.py +0 -2
  303. rasa/anonymization/anonymisation_rule_yaml_reader.py +0 -91
  304. rasa/anonymization/anonymization_pipeline.py +0 -286
  305. rasa/anonymization/anonymization_rule_executor.py +0 -266
  306. rasa/anonymization/anonymization_rule_orchestrator.py +0 -119
  307. rasa/anonymization/schemas/config.yml +0 -47
  308. rasa/anonymization/utils.py +0 -118
  309. rasa/cli/project_templates/calm/config.yml +0 -10
  310. rasa/cli/project_templates/calm/credentials.yml +0 -33
  311. rasa/cli/project_templates/calm/endpoints.yml +0 -58
  312. rasa/cli/project_templates/default/actions/actions.py +0 -27
  313. rasa/cli/project_templates/default/data/nlu.yml +0 -91
  314. rasa/cli/project_templates/default/data/rules.yml +0 -13
  315. rasa/cli/project_templates/default/data/stories.yml +0 -30
  316. rasa/cli/project_templates/default/domain.yml +0 -34
  317. rasa/cli/project_templates/default/tests/test_stories.yml +0 -91
  318. rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +0 -1
  319. rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +0 -1
  320. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +0 -1
  321. rasa/core/channels/inspector/src/helpers/audiostream.ts +0 -191
  322. rasa/core/tracker_store.py +0 -1792
  323. rasa/monkey_patches.py +0 -91
  324. rasa/studio/download.py +0 -489
  325. /rasa/{cli/project_templates/calm/actions → builder}/__init__.py +0 -0
  326. /rasa/cli/project_templates/{calm → default}/actions/action_template.py +0 -0
  327. /rasa/cli/project_templates/{calm → default}/actions/add_contact.py +0 -0
  328. /rasa/cli/project_templates/{calm → default}/actions/db.py +0 -0
  329. /rasa/cli/project_templates/{calm → default}/actions/list_contacts.py +0 -0
  330. /rasa/cli/project_templates/{calm → default}/actions/remove_contact.py +0 -0
  331. /rasa/cli/project_templates/{calm → default}/data/flows/add_contact.yml +0 -0
  332. /rasa/cli/project_templates/{calm → default}/data/flows/list_contacts.yml +0 -0
  333. /rasa/cli/project_templates/{calm → default}/data/flows/remove_contact.yml +0 -0
  334. /rasa/cli/project_templates/{calm → default}/db/contacts.json +0 -0
  335. /rasa/cli/project_templates/{calm → default}/domain/add_contact.yml +0 -0
  336. /rasa/cli/project_templates/{calm → default}/domain/list_contacts.yml +0 -0
  337. /rasa/cli/project_templates/{calm → default}/domain/remove_contact.yml +0 -0
  338. /rasa/cli/project_templates/{calm → default}/domain/shared.yml +0 -0
  339. {rasa_pro-3.12.18.dev1.dist-info → rasa_pro-3.13.0a1.dev2.dist-info}/NOTICE +0 -0
  340. {rasa_pro-3.12.18.dev1.dist-info → rasa_pro-3.13.0a1.dev2.dist-info}/WHEEL +0 -0
  341. {rasa_pro-3.12.18.dev1.dist-info → rasa_pro-3.13.0a1.dev2.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,351 @@
1
+ import logging
2
+ from pathlib import Path
3
+ from typing import Any, Dict, List, Set, Text
4
+
5
+ from rasa.shared.core.flows import Flow
6
+ from rasa.shared.core.flows.flow_step_links import StaticFlowStepLink
7
+ from rasa.shared.core.flows.flows_list import FlowsList
8
+ from rasa.shared.core.flows.yaml_flows_io import YAMLFlowsReader, YamlFlowsWriter
9
+ from rasa.shared.importers.importer import TrainingDataImporter
10
+ from rasa.shared.utils.yaml import read_yaml
11
+ from rasa.studio.constants import STUDIO_NLU_FILENAME
12
+ from rasa.studio.data_handler import StudioDataHandler
13
+ from rasa.utils.mapper import RasaPrimitiveStorageMapper
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ STUDIO_FLOWS_DIR_NAME = "studio_flows"
18
+
19
+
20
+ def merge_flows_with_overwrite(
21
+ data_path: Path,
22
+ handler: Any,
23
+ data_from_studio: TrainingDataImporter,
24
+ data_local: TrainingDataImporter,
25
+ mapper: RasaPrimitiveStorageMapper,
26
+ ) -> None:
27
+ """
28
+ Merges flows data from a file or directory when overwrite is enabled.
29
+
30
+ Args:
31
+ data_path: List of paths to the training data.
32
+ handler: The StudioDataHandler instance.
33
+ data_from_studio: The TrainingDataImporter instance for Studio data.
34
+ data_local: The TrainingDataImporter instance for local data.
35
+ mapper: The RasaPrimitiveStorageMapper instance for mapping.
36
+ """
37
+ if data_path.is_file():
38
+ merge_training_data_file(handler, data_from_studio, data_local, data_path)
39
+ elif data_path.is_dir():
40
+ merge_training_data_dir(
41
+ handler, data_from_studio, data_local, data_path, mapper
42
+ )
43
+ else:
44
+ raise ValueError("Provided data path is neither a file nor a directory.")
45
+
46
+
47
+ def merge_training_data_file(
48
+ handler: StudioDataHandler,
49
+ data_from_studio: TrainingDataImporter,
50
+ data_local: TrainingDataImporter,
51
+ file_path: Path,
52
+ ) -> None:
53
+ """
54
+ Merges NLU and flows data when training data is stored in a single file.
55
+
56
+ Args:
57
+ handler: The StudioDataHandler instance.
58
+ data_from_studio: The TrainingDataImporter instance for Studio data.
59
+ data_local: The TrainingDataImporter instance for local data.
60
+ file_path: The path to the training data file.
61
+ """
62
+ if handler.has_nlu():
63
+ nlu_data_merged = data_from_studio.get_nlu_data().merge(
64
+ data_local.get_nlu_data()
65
+ )
66
+ nlu_data_merged.persist_nlu(file_path)
67
+
68
+ if handler.has_flows():
69
+ flows_data_merged = data_from_studio.get_user_flows().merge(
70
+ data_local.get_user_flows()
71
+ )
72
+ YamlFlowsWriter.dump(
73
+ flows=flows_data_merged.underlying_flows,
74
+ filename=file_path,
75
+ should_clean_json=True,
76
+ )
77
+
78
+
79
+ def merge_training_data_dir(
80
+ handler: StudioDataHandler,
81
+ data_from_studio: TrainingDataImporter,
82
+ data_local: TrainingDataImporter,
83
+ data_path: Path,
84
+ mapper: RasaPrimitiveStorageMapper,
85
+ ) -> None:
86
+ """
87
+ Merges NLU and flows data when training data is stored in a directory.
88
+
89
+ Args:
90
+ handler: The StudioDataHandler instance.
91
+ data_from_studio: The TrainingDataImporter instance for Studio data.
92
+ data_local: The TrainingDataImporter instance for local data.
93
+ data_path: The path to the training data directory.
94
+ mapper: The RasaPrimitiveStorageMapper instance for mapping.
95
+ """
96
+ if handler.has_nlu():
97
+ merge_nlu_in_directory(data_from_studio, data_local, data_path, mapper)
98
+
99
+ if handler.has_flows():
100
+ merge_flows_in_directory(data_from_studio, data_path, mapper)
101
+
102
+
103
+ def merge_nlu_in_directory(
104
+ data_from_studio: TrainingDataImporter,
105
+ data_local: TrainingDataImporter,
106
+ data_path: Path,
107
+ mapper: RasaPrimitiveStorageMapper,
108
+ ) -> None:
109
+ """
110
+ Merges NLU data by checking for an existing NLU file in the directory.
111
+ If it exists, the new Studio data is merged with the local data.
112
+
113
+ Args:
114
+ data_from_studio: The TrainingDataImporter instance for Studio data.
115
+ data_local: The TrainingDataImporter instance for local data.
116
+ data_path: The path to the training data directory.
117
+ mapper: The RasaPrimitiveStorageMapper instance for mapping.
118
+ """
119
+ from rasa.studio.download.download import pretty_write_nlu_yaml
120
+
121
+ nlu_data = data_from_studio.get_nlu_data()
122
+ nlu_file_path = get_nlu_path(data_path, data_local, mapper)
123
+
124
+ if nlu_file_path.exists():
125
+ local_nlu = TrainingDataImporter.load_from_dict(
126
+ training_data_paths=[str(nlu_file_path)]
127
+ )
128
+ nlu_data = nlu_data.merge(local_nlu.get_nlu_data())
129
+
130
+ if nlu_yaml := nlu_data.nlu_as_yaml():
131
+ pretty_write_nlu_yaml(read_yaml(nlu_yaml), nlu_file_path)
132
+
133
+
134
+ def get_nlu_path(
135
+ base_path: Path,
136
+ data_local: TrainingDataImporter,
137
+ mapper: RasaPrimitiveStorageMapper,
138
+ ) -> Path:
139
+ """Determines where NLU data should be stored.
140
+
141
+ Args:
142
+ base_path: The base path for the training data.
143
+ data_local: The TrainingDataImporter instance for local data.
144
+ mapper: The RasaPrimitiveStorageMapper instance for mapping.
145
+
146
+ Returns:
147
+ The path where NLU data should be stored.
148
+ """
149
+ nlu_paths = set()
150
+ for intent in data_local.get_nlu_data().intents:
151
+ for p in mapper.get_file(intent, "intents").get("training", []):
152
+ nlu_paths.add(p)
153
+
154
+ return _select_path(nlu_paths, "nlu", base_path, STUDIO_NLU_FILENAME)
155
+
156
+
157
+ def get_flows_path(
158
+ base_path: Path,
159
+ data_local: TrainingDataImporter,
160
+ mapper: RasaPrimitiveStorageMapper,
161
+ ) -> Path:
162
+ """Determines where flows data should be stored.
163
+
164
+ Args:
165
+ base_path: The base path for the training data.
166
+ data_local: The TrainingDataImporter instance for local data.
167
+ mapper: The RasaPrimitiveStorageMapper instance for mapping.
168
+
169
+ Returns:
170
+ The path where flows data should be stored.
171
+ """
172
+ flow_paths = set()
173
+ for flow in data_local.get_user_flows().underlying_flows:
174
+ for p in mapper.get_file(flow.id, "flows").get("training", []):
175
+ flow_paths.add(p)
176
+
177
+ return _select_path(flow_paths, "flows", base_path, "flows.yml")
178
+
179
+
180
+ def merge_flows_in_directory(
181
+ data_from_studio: TrainingDataImporter,
182
+ data_path: Path,
183
+ mapper: RasaPrimitiveStorageMapper,
184
+ ) -> None:
185
+ """
186
+ Merges flows data by updating local flow files in a directory with any changes
187
+ from Studio, and then dumping any new flows that do not exist in any local file.
188
+
189
+ Args:
190
+ data_from_studio: Training data importer containing the flows from Studio.
191
+ data_path: The path to the directory where local flows reside.
192
+ mapper: Utility for mapping flow IDs to their respective file paths.
193
+ """
194
+ # Extract flows from Studio data and map flow IDs to their instances.
195
+ studio_flows = data_from_studio.get_user_flows()
196
+ studio_flow_map: Dict[Text, Flow] = {
197
+ flow.id: flow for flow in studio_flows.underlying_flows
198
+ }
199
+
200
+ # Load existing local flows from the specified directory.
201
+ local_flows_file = TrainingDataImporter.load_from_dict(
202
+ training_data_paths=[str(data_path)]
203
+ )
204
+ local_flows = local_flows_file.get_user_flows().underlying_flows
205
+
206
+ # Gather the unique file paths where each local flow is stored.
207
+ local_flow_paths: Set[Path] = _get_local_flow_paths(local_flows, mapper)
208
+
209
+ # Track updated flows and update local files with Studio flow data.
210
+ all_updated_flows_ids: List[Text] = []
211
+ for flow_file_path in local_flow_paths:
212
+ updated_flows_ids = _update_flow_file(flow_file_path, studio_flow_map)
213
+ all_updated_flows_ids.extend(updated_flows_ids)
214
+
215
+ # Identify new Studio flows and save them as separate files in the directory.
216
+ new_flows = [
217
+ flow
218
+ for flow_id, flow in studio_flow_map.items()
219
+ if flow_id not in all_updated_flows_ids
220
+ ]
221
+ _dump_flows_as_separate_files(new_flows, data_path)
222
+
223
+
224
+ def _get_local_flow_paths(
225
+ local_flows: List[Any],
226
+ mapper: RasaPrimitiveStorageMapper,
227
+ ) -> Set[Path]:
228
+ """
229
+ Args:
230
+ local_flows: List of local flows.
231
+ mapper: The RasaPrimitiveStorageMapper instance for mapping.
232
+
233
+ Returns:
234
+ A set of paths for the local flow files.
235
+ """
236
+ paths: Set[Path] = set()
237
+ for flow in local_flows:
238
+ paths.update(mapper.get_file(flow.id, "flows").get("training", []))
239
+ return paths
240
+
241
+
242
+ def _update_flow_file(
243
+ flow_file_path: Path, studio_flows_map: Dict[Text, Any]
244
+ ) -> List[Text]:
245
+ """
246
+ Reads a flow file, updates outdated flows, and replaces them with studio versions.
247
+
248
+ Args:
249
+ flow_file_path: The path to the flow file.
250
+ studio_flows_map: A dictionary mapping flow IDs to their updated versions.
251
+
252
+ Returns:
253
+ A list of Flows IDs from the updated flow file.
254
+ """
255
+ file_flows = YAMLFlowsReader.read_from_file(flow_file_path, False)
256
+
257
+ # Build a list of flows, replacing any outdated flow with its studio version
258
+ updated_flows = [
259
+ studio_flows_map.get(flow.id, flow) or flow
260
+ for flow in file_flows.underlying_flows
261
+ ]
262
+
263
+ # If the updated flows differ from the original file flows, write them back
264
+ if updated_flows != file_flows.underlying_flows:
265
+ YamlFlowsWriter.dump(
266
+ flows=updated_flows,
267
+ filename=flow_file_path,
268
+ should_clean_json=True,
269
+ )
270
+
271
+ return [flow.id for flow in updated_flows]
272
+
273
+
274
+ def _dump_flows_as_separate_files(flows: List[Any], data_path: Path) -> None:
275
+ """Dump flow into separate files within a directory.
276
+
277
+ Creates a new directory under the given data_path and writes each flow
278
+ into a separate YAML file. Each file is named after the flow's id.
279
+
280
+ Args:
281
+ flows: List of new flows to be dumped.
282
+ data_path: The path to the directory where the files will be created.
283
+ """
284
+ # If there are no flows, don't create a directory.
285
+ if not flows:
286
+ return
287
+
288
+ new_flows_dir = data_path / STUDIO_FLOWS_DIR_NAME
289
+ new_flows_dir.mkdir(parents=True, exist_ok=True)
290
+ for flow in flows:
291
+ file_name = f"{flow.id}.yml"
292
+ file_path = new_flows_dir / file_name
293
+ single_flow_list = FlowsList(underlying_flows=[flow])
294
+ YamlFlowsWriter.dump(
295
+ flows=single_flow_list.underlying_flows,
296
+ filename=file_path,
297
+ should_clean_json=True,
298
+ )
299
+
300
+
301
+ def strip_default_next_references(flows: FlowsList) -> FlowsList:
302
+ """Strips default next references from flows.
303
+
304
+ Args:
305
+ flows: The FlowsList instance containing the flows.
306
+
307
+ Returns:
308
+ An updated FlowsList instance with default next references removed.
309
+ """
310
+ default_step_ids = [step.default_id for flow in flows for step in flow.steps]
311
+ for flow in flows:
312
+ for step in flow.steps:
313
+ if (
314
+ step.next.links
315
+ and isinstance(step.next.links[0], StaticFlowStepLink)
316
+ and step.next.links[0].target in default_step_ids
317
+ ):
318
+ step.next.links = []
319
+ return flows
320
+
321
+
322
+ def _select_path(
323
+ paths: Set[Path], primitive_type: str, default_path: Path, default: str
324
+ ) -> Path:
325
+ """Selects a path from a set of paths.
326
+
327
+ If exactly one path exists, returns it.
328
+ If multiple exist, returns one with a warning.
329
+ If none exist, returns a default path.
330
+
331
+ Args:
332
+ paths: A set of paths.
333
+ primitive_type: The type of the primitive (e.g., "domain", "nlu").
334
+ default_path: The default path to use if no paths exist.
335
+ default: The default file name.
336
+
337
+ Returns:
338
+ The selected path.
339
+ """
340
+ if len(paths) == 1:
341
+ path = paths.pop()
342
+ elif len(paths) > 1:
343
+ path = paths.pop()
344
+ logger.warning(
345
+ f"Saving {primitive_type} to {path}. "
346
+ f"Please keep Studio-related {primitive_type} in a single file."
347
+ )
348
+ else:
349
+ path = default_path / Path(default)
350
+ logger.info(f"Saving {primitive_type} to {path}.")
351
+ return path
rasa/studio/link.py ADDED
@@ -0,0 +1,200 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import datetime
5
+ import sys
6
+ from pathlib import Path
7
+ from typing import Any, Dict, List, Optional, Text, Union
8
+
9
+ import questionary
10
+ import structlog
11
+ from pydantic import BaseModel, Field
12
+
13
+ import rasa.shared.utils.cli
14
+ from rasa.constants import RASA_DIR_NAME
15
+ from rasa.shared.utils.yaml import read_yaml_file, write_yaml
16
+ from rasa.studio.config import StudioConfig
17
+ from rasa.studio.upload import (
18
+ check_if_assistant_already_exists,
19
+ handle_upload,
20
+ is_auth_working,
21
+ )
22
+
23
+ structlogger = structlog.get_logger(__name__)
24
+
25
+ _LINK_FILE_NAME: Text = "studio.yml"
26
+
27
+
28
+ class AssistantLinkPayload(BaseModel):
29
+ assistant_name: Text
30
+ studio_url: Text
31
+ linked_at: Text = Field(
32
+ default_factory=lambda: datetime.datetime.utcnow().isoformat() + "Z"
33
+ )
34
+
35
+
36
+ def _link_file(project_root: Path) -> Path:
37
+ """Return `<project-root>/.rasa/studio.yml`.
38
+
39
+ Args:
40
+ project_root: The path to the project root.
41
+
42
+ Returns:
43
+ The path to the link file.
44
+ """
45
+ return project_root / RASA_DIR_NAME / _LINK_FILE_NAME
46
+
47
+
48
+ def _write_link_file(
49
+ project_root: Path, assistant_name: Text, studio_url: Text
50
+ ) -> None:
51
+ """Persist assistant information inside the project.
52
+
53
+ Args:
54
+ project_root: The path to the project root.
55
+ assistant_name: The name of the assistant.
56
+ studio_url: The URL of the Rasa Studio instance.
57
+ """
58
+ file_path = _link_file(project_root)
59
+ file_path.parent.mkdir(exist_ok=True, parents=True)
60
+
61
+ payload = AssistantLinkPayload(
62
+ assistant_name=assistant_name,
63
+ studio_url=studio_url,
64
+ )
65
+ write_yaml(payload.model_dump(), file_path)
66
+
67
+
68
+ def _read_link_file(
69
+ project_root: Path = Path.cwd(),
70
+ ) -> Optional[Union[List[Any], Dict[Text, Any]]]:
71
+ """Reads the link configuration file.
72
+
73
+ Args:
74
+ project_root: The path to the project root.
75
+
76
+ Returns:
77
+ The assistant information if the file exists, otherwise None.
78
+ """
79
+ file_path = _link_file(project_root)
80
+ if not file_path.is_file():
81
+ return None
82
+
83
+ return read_yaml_file(file_path)
84
+
85
+
86
+ def read_assistant_name(project_root: Path = Path.cwd()) -> Optional[Text]:
87
+ """Reads the assistant_name from the linked configuration file.
88
+
89
+ Args:
90
+ project_root: The path to the project root.
91
+
92
+ Returns:
93
+ The assistant name if the file exists, otherwise None.
94
+ """
95
+ linked = _read_link_file(project_root)
96
+ assistant_name = (
97
+ linked.get("assistant_name") if linked and isinstance(linked, dict) else None
98
+ )
99
+
100
+ if not assistant_name:
101
+ rasa.shared.utils.cli.print_error_and_exit(
102
+ "This project is not linked to any Rasa Studio assistant.\n"
103
+ "Run `rasa studio link <assistant-name>` first."
104
+ )
105
+
106
+ return assistant_name
107
+
108
+
109
+ def get_studio_config() -> StudioConfig:
110
+ """Get the StudioConfig object or exit with an error message.
111
+
112
+ Returns:
113
+ A valid StudioConfig object.
114
+ """
115
+ config = StudioConfig.read_config()
116
+ if not config.is_valid():
117
+ rasa.shared.utils.cli.print_error_and_exit(
118
+ "Rasa Studio is not configured correctly. Run `rasa studio config` first."
119
+ )
120
+ if not is_auth_working(config.studio_url, not config.disable_verify):
121
+ rasa.shared.utils.cli.print_error_and_exit(
122
+ "Authentication invalid or expired. Please run `rasa studio login`."
123
+ )
124
+ return config
125
+
126
+
127
+ def _ensure_assistant_exists(
128
+ assistant_name: Text,
129
+ studio_cfg: StudioConfig,
130
+ args: argparse.Namespace,
131
+ ) -> bool:
132
+ """Create the assistant on Studio if it does not yet exist.
133
+
134
+ Args:
135
+ assistant_name: The name the user provided on the CLI.
136
+ studio_cfg: The validated Studio configuration.
137
+ args: The original CLI args (needed for `handle_upload`).
138
+
139
+ Returns:
140
+ True if the assistant already exists or was created, False otherwise.
141
+ """
142
+ verify_ssl = not studio_cfg.disable_verify
143
+ assistant_already_exists = check_if_assistant_already_exists(
144
+ assistant_name, studio_cfg.studio_url, verify_ssl
145
+ )
146
+ if not assistant_already_exists:
147
+ should_create_assistant = questionary.confirm(
148
+ f"Assistant '{assistant_name}' was not found on Rasa Studio. "
149
+ f"Do you want to create it?"
150
+ ).ask()
151
+ if should_create_assistant:
152
+ # `handle_upload` expects the name to live in `args.assistant_name`
153
+ args.assistant_name = assistant_name
154
+ handle_upload(args)
155
+
156
+ rasa.shared.utils.cli.print_info(
157
+ f"Assistant {assistant_name} successfully created."
158
+ )
159
+ return should_create_assistant
160
+
161
+ return assistant_already_exists
162
+
163
+
164
+ def handle_link(args: argparse.Namespace) -> None:
165
+ """Implementation of `rasa studio link <assistant-name>` CLI command.
166
+
167
+ Args:
168
+ args: The command line arguments.
169
+ """
170
+ assistant_name: Text = args.assistant_name[0]
171
+ studio_cfg = get_studio_config()
172
+ assistant_exists = _ensure_assistant_exists(assistant_name, studio_cfg, args)
173
+ if not assistant_exists:
174
+ rasa.shared.utils.cli.print_error_and_exit(
175
+ "Project has not been linked with Studio assistant."
176
+ )
177
+
178
+ project_root = Path.cwd()
179
+ link_file = _link_file(project_root)
180
+
181
+ if link_file.exists():
182
+ overwrite = questionary.confirm(
183
+ f"This project is already linked " f"(link file '{link_file}').\nOverwrite?"
184
+ ).ask()
185
+ if not overwrite:
186
+ rasa.shared.utils.cli.print_info(
187
+ "Existing link kept – nothing was changed."
188
+ )
189
+ sys.exit(0)
190
+
191
+ _write_link_file(project_root, assistant_name, studio_cfg.studio_url)
192
+
193
+ structlogger.info(
194
+ "studio.link.success",
195
+ event_info=f"Project linked to Studio assistant '{assistant_name}'.",
196
+ assistant_name=assistant_name,
197
+ )
198
+ rasa.shared.utils.cli.print_success(
199
+ f"Project successfully linked to assistant '{assistant_name}'."
200
+ )
rasa/studio/pull.py ADDED
@@ -0,0 +1,94 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+ from typing import Text, Union
6
+
7
+ import structlog
8
+
9
+ import rasa.cli.utils
10
+ import rasa.shared.utils.cli
11
+ from rasa.shared.constants import DEFAULT_CONFIG_PATH, DEFAULT_ENDPOINTS_PATH
12
+ from rasa.shared.utils.io import write_text_file
13
+ from rasa.studio.data_handler import StudioDataHandler
14
+ from rasa.studio.download.download import handle_download
15
+ from rasa.studio.link import get_studio_config, read_assistant_name
16
+
17
+ structlogger = structlog.get_logger(__name__)
18
+
19
+
20
+ def _write_to_file(
21
+ content: Text, file_type: Text, file_path: Text, default_path: Text
22
+ ) -> None:
23
+ """Write the content to a file.
24
+
25
+ Args:
26
+ content: The content to write.
27
+ file_type: The type of file (e.g., "config" or "endpoints".).
28
+ file_path: The path to the file.
29
+ default_path: The default path to use file_path is not valid.
30
+ """
31
+ path: Union[Path, str, None] = rasa.cli.utils.get_validated_path(
32
+ file_path, file_type, default_path, none_is_valid=True
33
+ )
34
+ write_text_file(content, path, encoding="utf-8")
35
+ rasa.shared.utils.cli.print_success(f"Pulled {file_type} data from assistant.")
36
+
37
+
38
+ def handle_pull(args: argparse.Namespace) -> None:
39
+ """Pull all data and overwrite the local assistant.
40
+
41
+ Args:
42
+ args: The parsed arguments.
43
+ """
44
+ assistant_name = read_assistant_name()
45
+
46
+ # Use the CLI command logic to download with overwrite
47
+ download_args = argparse.Namespace(**vars(args))
48
+ download_args.assistant_name = [assistant_name]
49
+ download_args.overwrite = True
50
+
51
+ handle_download(download_args)
52
+ rasa.shared.utils.cli.print_success("Pulled the data from assistant.")
53
+
54
+
55
+ def handle_pull_config(args: argparse.Namespace) -> None:
56
+ """Pull just the assistant's `config.yml`.
57
+
58
+ Args:
59
+ args: The parsed arguments.
60
+ """
61
+ studio_cfg = get_studio_config()
62
+ assistant_name = read_assistant_name()
63
+
64
+ handler = StudioDataHandler(studio_cfg, assistant_name)
65
+ handler.request_all_data()
66
+
67
+ config_yaml = handler.get_config()
68
+ if not config_yaml:
69
+ rasa.shared.utils.cli.print_error_and_exit(
70
+ "No configuration data was found in the Studio assistant."
71
+ )
72
+
73
+ _write_to_file(config_yaml, "config", args.config, DEFAULT_CONFIG_PATH)
74
+
75
+
76
+ def handle_pull_endpoints(args: argparse.Namespace) -> None:
77
+ """Pull just the assistant's `endpoints.yml`.
78
+
79
+ Args:
80
+ args: The parsed arguments.
81
+ """
82
+ studio_cfg = get_studio_config()
83
+ assistant_name = read_assistant_name()
84
+
85
+ handler = StudioDataHandler(studio_cfg, assistant_name)
86
+ handler.request_all_data()
87
+
88
+ endpoints_yaml = handler.get_endpoints()
89
+ if not endpoints_yaml:
90
+ rasa.shared.utils.cli.print_error_and_exit(
91
+ "No endpoints data was found in the Studio assistant."
92
+ )
93
+
94
+ _write_to_file(endpoints_yaml, "endpoints", args.endpoints, DEFAULT_ENDPOINTS_PATH)