rasa-pro 3.13.0.dev3__py3-none-any.whl → 3.13.0.dev7__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 (228) hide show
  1. rasa/__main__.py +3 -1
  2. rasa/api.py +4 -0
  3. rasa/cli/arguments/default_arguments.py +13 -1
  4. rasa/cli/arguments/train.py +2 -0
  5. rasa/cli/evaluate.py +1 -1
  6. rasa/cli/export.py +2 -2
  7. rasa/cli/inspect.py +8 -4
  8. rasa/cli/project_templates/default/config.yml +5 -32
  9. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_cancels_during_a_correction.yml +1 -1
  10. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +1 -1
  11. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_handle.yml +1 -1
  12. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_name.yml +1 -1
  13. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +1 -1
  14. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_lists_contacts.yml +1 -1
  15. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact.yml +1 -1
  16. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact_from_list.yml +1 -1
  17. rasa/cli/project_templates/default/endpoints.yml +18 -2
  18. rasa/cli/scaffold.py +3 -4
  19. rasa/cli/studio/download.py +1 -1
  20. rasa/cli/studio/upload.py +0 -6
  21. rasa/cli/train.py +1 -0
  22. rasa/constants.py +2 -0
  23. rasa/core/agent.py +2 -2
  24. rasa/core/brokers/kafka.py +4 -0
  25. rasa/core/brokers/pika.py +4 -0
  26. rasa/core/brokers/sql.py +1 -1
  27. rasa/core/channels/channel.py +68 -5
  28. rasa/core/channels/inspector/.eslintrc.cjs +12 -6
  29. rasa/core/channels/inspector/.prettierrc +5 -0
  30. rasa/core/channels/inspector/README.md +10 -4
  31. rasa/core/channels/inspector/dist/assets/{arc-c7691751.js → arc-c4b064fc.js} +1 -1
  32. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-ab99dff7.js → blockDiagram-38ab4fdb-215b5026.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-08c35a6b.js → c4Diagram-3d4e48cf-2b54a0a3.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/channel-3730f5fd.js +1 -0
  35. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-9e9c71c9.js → classDiagram-70f12bd4-daacea5f.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-15e7e2bf.js → classDiagram-v2-f2320105-930d4dc2.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/clone-e847561e.js +1 -0
  38. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-9c105cb1.js → createText-2e5e7dd3-83c206ba.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-77e89e48.js → edges-e0da2a9e-b0eb01d0.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-7a011646.js → erDiagram-9861fffd-17586500.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-b6f105ac.js → flowDb-956e92f1-be2a1776.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-ce4f18c2.js → flowDiagram-66a62f08-c2120ebd.js} +1 -1
  43. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-efbbfe00.js +1 -0
  44. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-cb5f6da4.js → flowchart-elk-definition-4a651766-a6ab5c48.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-e4d19e28.js → ganttDiagram-c361ad54-ef613457.js} +1 -1
  46. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-727b1c33.js → gitGraphDiagram-72cf32ee-d59185b3.js} +1 -1
  47. rasa/core/channels/inspector/dist/assets/{graph-6e2ab9a7.js → graph-0f155405.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/{index-3862675e-84ec700f.js → index-3862675e-d5f1d1b7.js} +1 -1
  49. rasa/core/channels/inspector/dist/assets/{index-098a1a24.js → index-47737d3a.js} +162 -149
  50. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-78dda442.js → infoDiagram-f8f76790-b07d141f.js} +1 -1
  51. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-f1cc6dd1.js → journeyDiagram-49397b02-1936d429.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{layout-d98dcd0c.js → layout-dde8d0f3.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{line-838e3d82.js → line-0c2c7ee0.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{linear-eae72406.js → linear-35dd89a4.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-c96fd84b.js → mindmap-definition-fc14e90a-56192851.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-c936d4e2.js → pieDiagram-8a3498a8-fc21ed78.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-b338eb8f.js → quadrantDiagram-120e2f19-25e98518.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-c6b6c0d5.js → requirementDiagram-deff3bca-546ff1f5.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-b9372e19.js → sankeyDiagram-04a897e0-02d8b82d.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-479e0a3f.js → sequenceDiagram-704730f1-3ca5a92e.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-fd26eebc.js → stateDiagram-587899a1-128ea07c.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-3233e0ae.js → stateDiagram-v2-d93cdb3a-95f290af.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-1fdd392b.js → styles-6aaf32cf-4984898a.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-6d7bfa1b.js → styles-9a916d00-1bf266ba.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-f86aab11.js → styles-c10674c1-60521c63.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-e3e49d7a.js → svgDrawCommon-08f97a94-a25b6e12.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-6fe08b4d.js → timeline-definition-85554ec2-0fc086bf.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-c2e06fd6.js → xychartDiagram-e933f94c-44ee592e.js} +1 -1
  69. rasa/core/channels/inspector/dist/index.html +1 -1
  70. rasa/core/channels/inspector/package.json +3 -1
  71. rasa/core/channels/inspector/src/App.tsx +92 -90
  72. rasa/core/channels/inspector/src/components/Chat.tsx +61 -36
  73. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -43
  74. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +57 -57
  75. rasa/core/channels/inspector/src/components/DialogueStack.tsx +36 -27
  76. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +4 -4
  77. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +7 -7
  78. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +28 -12
  79. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +9 -9
  80. rasa/core/channels/inspector/src/components/RasaLogo.tsx +5 -5
  81. rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +55 -60
  82. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +5 -5
  83. rasa/core/channels/inspector/src/components/Slots.tsx +22 -22
  84. rasa/core/channels/inspector/src/components/Welcome.tsx +28 -31
  85. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +245 -0
  86. rasa/core/channels/inspector/src/helpers/audio/microphone-processor.js +12 -0
  87. rasa/core/channels/inspector/src/helpers/audio/playback-processor.js +36 -0
  88. rasa/core/channels/inspector/src/helpers/conversation.ts +16 -0
  89. rasa/core/channels/inspector/src/helpers/formatters.test.ts +181 -181
  90. rasa/core/channels/inspector/src/helpers/formatters.ts +111 -111
  91. rasa/core/channels/inspector/src/helpers/utils.ts +78 -61
  92. rasa/core/channels/inspector/src/main.tsx +8 -8
  93. rasa/core/channels/inspector/src/theme/Button/Button.ts +8 -8
  94. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +7 -7
  95. rasa/core/channels/inspector/src/theme/Input/Input.ts +9 -9
  96. rasa/core/channels/inspector/src/theme/Link/Link.ts +6 -6
  97. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +13 -13
  98. rasa/core/channels/inspector/src/theme/Table/Table.tsx +10 -10
  99. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +5 -5
  100. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +7 -7
  101. rasa/core/channels/inspector/src/theme/base/colors.ts +64 -64
  102. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +21 -18
  103. rasa/core/channels/inspector/src/theme/base/radii.ts +8 -8
  104. rasa/core/channels/inspector/src/theme/base/shadows.ts +5 -5
  105. rasa/core/channels/inspector/src/theme/base/sizes.ts +5 -5
  106. rasa/core/channels/inspector/src/theme/base/space.ts +12 -12
  107. rasa/core/channels/inspector/src/theme/base/styles.ts +5 -5
  108. rasa/core/channels/inspector/src/theme/base/typography.ts +12 -12
  109. rasa/core/channels/inspector/src/theme/base/zIndices.ts +3 -3
  110. rasa/core/channels/inspector/src/theme/index.ts +38 -38
  111. rasa/core/channels/inspector/src/types.ts +56 -50
  112. rasa/core/channels/inspector/yarn.lock +5 -0
  113. rasa/core/channels/voice_ready/audiocodes.py +75 -32
  114. rasa/core/channels/voice_ready/twilio_voice.py +48 -1
  115. rasa/core/channels/voice_stream/tts/azure.py +11 -2
  116. rasa/core/channels/voice_stream/twilio_media_streams.py +101 -26
  117. rasa/core/channels/voice_stream/voice_channel.py +28 -2
  118. rasa/core/concurrent_lock_store.py +24 -10
  119. rasa/core/evaluation/marker_tracker_loader.py +1 -1
  120. rasa/core/exporter.py +1 -1
  121. rasa/core/lock_store.py +151 -60
  122. rasa/core/nlg/contextual_response_rephraser.py +4 -2
  123. rasa/core/nlg/summarize.py +1 -1
  124. rasa/core/persistor.py +55 -20
  125. rasa/core/policies/enterprise_search_policy.py +7 -4
  126. rasa/core/policies/intentless_policy.py +15 -9
  127. rasa/core/processor.py +2 -2
  128. rasa/core/run.py +7 -2
  129. rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +5 -1
  130. rasa/core/tracker_stores/dynamo_tracker_store.py +218 -0
  131. rasa/core/tracker_stores/mongo_tracker_store.py +206 -0
  132. rasa/core/tracker_stores/redis_tracker_store.py +219 -0
  133. rasa/core/tracker_stores/sql_tracker_store.py +555 -0
  134. rasa/core/tracker_stores/tracker_store.py +805 -0
  135. rasa/core/utils.py +6 -0
  136. rasa/dialogue_understanding/coexistence/llm_based_router.py +8 -3
  137. rasa/dialogue_understanding/commands/clarify_command.py +2 -2
  138. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
  139. rasa/dialogue_understanding/generator/constants.py +2 -2
  140. rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -1
  141. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +33 -12
  142. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +2 -2
  143. rasa/dialogue_understanding_test/du_test_case.py +16 -8
  144. rasa/hooks.py +2 -2
  145. rasa/keys +1 -0
  146. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -2
  147. rasa/model_manager/config.py +3 -1
  148. rasa/model_manager/model_api.py +1 -2
  149. rasa/model_manager/runner_service.py +8 -4
  150. rasa/model_manager/trainer_service.py +1 -0
  151. rasa/model_training.py +12 -3
  152. rasa/nlu/extractors/crf_entity_extractor.py +66 -16
  153. rasa/plugin.py +1 -4
  154. rasa/server.py +6 -2
  155. rasa/shared/constants.py +4 -0
  156. rasa/shared/core/domain.py +165 -11
  157. rasa/shared/core/events.py +68 -2
  158. rasa/shared/core/flows/flow.py +155 -131
  159. rasa/shared/core/flows/flow_step.py +19 -3
  160. rasa/shared/core/flows/flow_step_links.py +15 -0
  161. rasa/shared/core/flows/flow_step_sequence.py +6 -0
  162. rasa/shared/core/flows/nlu_trigger.py +13 -0
  163. rasa/shared/core/flows/steps/action.py +7 -4
  164. rasa/shared/core/flows/steps/call.py +11 -4
  165. rasa/shared/core/flows/steps/collect.py +27 -6
  166. rasa/shared/core/flows/steps/internal.py +6 -1
  167. rasa/shared/core/flows/steps/link.py +7 -4
  168. rasa/shared/core/flows/steps/no_operation.py +7 -4
  169. rasa/shared/core/flows/steps/set_slots.py +8 -4
  170. rasa/shared/core/flows/yaml_flows_io.py +106 -5
  171. rasa/shared/importers/importer.py +8 -0
  172. rasa/shared/providers/_configs/azure_openai_client_config.py +4 -0
  173. rasa/shared/providers/_configs/openai_client_config.py +4 -0
  174. rasa/shared/providers/_utils.py +83 -0
  175. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +3 -0
  176. rasa/shared/providers/llm/_base_litellm_client.py +11 -5
  177. rasa/shared/providers/llm/azure_openai_llm_client.py +6 -68
  178. rasa/shared/providers/router/_base_litellm_router_client.py +53 -1
  179. rasa/shared/utils/common.py +42 -0
  180. rasa/studio/download/__init__.py +0 -0
  181. rasa/studio/download/domains.py +49 -0
  182. rasa/studio/download/download.py +439 -0
  183. rasa/studio/download/flows.py +359 -0
  184. rasa/studio/results_logger.py +6 -1
  185. rasa/studio/upload.py +69 -5
  186. rasa/telemetry.py +2 -2
  187. rasa/tracing/config.py +1 -1
  188. rasa/tracing/instrumentation/attribute_extractors.py +1 -1
  189. rasa/tracing/instrumentation/instrumentation.py +1 -1
  190. rasa/utils/common.py +36 -0
  191. rasa/utils/endpoints.py +22 -1
  192. rasa/utils/licensing.py +2 -3
  193. rasa/validator.py +1 -2
  194. rasa/version.py +1 -1
  195. {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/METADATA +10 -10
  196. {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/RECORD +213 -210
  197. rasa/cli/project_templates/calm/config.yml +0 -10
  198. rasa/cli/project_templates/calm/credentials.yml +0 -33
  199. rasa/cli/project_templates/calm/endpoints.yml +0 -58
  200. rasa/cli/project_templates/default/actions/actions.py +0 -27
  201. rasa/cli/project_templates/default/data/nlu.yml +0 -91
  202. rasa/cli/project_templates/default/data/rules.yml +0 -13
  203. rasa/cli/project_templates/default/data/stories.yml +0 -30
  204. rasa/cli/project_templates/default/domain.yml +0 -34
  205. rasa/cli/project_templates/default/tests/test_stories.yml +0 -91
  206. rasa/core/channels/inspector/dist/assets/channel-11268142.js +0 -1
  207. rasa/core/channels/inspector/dist/assets/clone-ff7f2ce7.js +0 -1
  208. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-cba7ae20.js +0 -1
  209. rasa/core/channels/inspector/src/helpers/audiostream.ts +0 -191
  210. rasa/core/tracker_store.py +0 -1792
  211. rasa/studio/download.py +0 -489
  212. /rasa/cli/project_templates/{calm → default}/actions/action_template.py +0 -0
  213. /rasa/cli/project_templates/{calm → default}/actions/add_contact.py +0 -0
  214. /rasa/cli/project_templates/{calm → default}/actions/db.py +0 -0
  215. /rasa/cli/project_templates/{calm → default}/actions/list_contacts.py +0 -0
  216. /rasa/cli/project_templates/{calm → default}/actions/remove_contact.py +0 -0
  217. /rasa/cli/project_templates/{calm → default}/data/flows/add_contact.yml +0 -0
  218. /rasa/cli/project_templates/{calm → default}/data/flows/list_contacts.yml +0 -0
  219. /rasa/cli/project_templates/{calm → default}/data/flows/remove_contact.yml +0 -0
  220. /rasa/cli/project_templates/{calm → default}/db/contacts.json +0 -0
  221. /rasa/cli/project_templates/{calm → default}/domain/add_contact.yml +0 -0
  222. /rasa/cli/project_templates/{calm → default}/domain/list_contacts.yml +0 -0
  223. /rasa/cli/project_templates/{calm → default}/domain/remove_contact.yml +0 -0
  224. /rasa/cli/project_templates/{calm → default}/domain/shared.yml +0 -0
  225. /rasa/{cli/project_templates/calm/actions → core/tracker_stores}/__init__.py +0 -0
  226. {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/NOTICE +0 -0
  227. {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/WHEEL +0 -0
  228. {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/entry_points.txt +0 -0
@@ -134,6 +134,22 @@ ALL_DOMAIN_KEYS = [
134
134
 
135
135
  PREV_PREFIX = "prev_"
136
136
 
137
+ MERGE_FUNC_MAPPING: Dict[Text, Callable[..., Any]] = {
138
+ KEY_ACTIONS: rasa.shared.utils.common.merge_lists_of_dicts,
139
+ KEY_RESPONSES: rasa.shared.utils.common.merge_dicts,
140
+ KEY_SLOTS: rasa.shared.utils.common.merge_dicts,
141
+ KEY_INTENTS: rasa.shared.utils.common.merge_lists_of_dicts,
142
+ KEY_ENTITIES: rasa.shared.utils.common.merge_lists_of_dicts,
143
+ KEY_E2E_ACTIONS: rasa.shared.utils.common.merge_lists,
144
+ KEY_FORMS: rasa.shared.utils.common.merge_dicts,
145
+ }
146
+
147
+ DICT_DATA_KEYS = [
148
+ key
149
+ for key, value in MERGE_FUNC_MAPPING.items()
150
+ if value == rasa.shared.utils.common.merge_dicts
151
+ ]
152
+
137
153
  # State is a dictionary with keys (USER, PREVIOUS_ACTION, SLOTS, ACTIVE_LOOP)
138
154
  # representing the origin of a SubState;
139
155
  # the values are SubStates, that contain the information needed for featurization
@@ -466,17 +482,7 @@ class Domain:
466
482
 
467
483
  duplicates: Dict[Text, List[Text]] = {}
468
484
 
469
- merge_func_mappings: Dict[Text, Callable[..., Any]] = {
470
- KEY_INTENTS: rasa.shared.utils.common.merge_lists_of_dicts,
471
- KEY_ENTITIES: rasa.shared.utils.common.merge_lists_of_dicts,
472
- KEY_ACTIONS: rasa.shared.utils.common.merge_lists_of_dicts,
473
- KEY_E2E_ACTIONS: rasa.shared.utils.common.merge_lists,
474
- KEY_FORMS: rasa.shared.utils.common.merge_dicts,
475
- KEY_RESPONSES: rasa.shared.utils.common.merge_dicts,
476
- KEY_SLOTS: rasa.shared.utils.common.merge_dicts,
477
- }
478
-
479
- for key, merge_func in merge_func_mappings.items():
485
+ for key, merge_func in MERGE_FUNC_MAPPING.items():
480
486
  duplicates[key] = rasa.shared.utils.common.extract_duplicates(
481
487
  combined.get(key, []), domain_dict.get(key, [])
482
488
  )
@@ -494,6 +500,74 @@ class Domain:
494
500
 
495
501
  return combined
496
502
 
503
+ def partial_merge(self, other: Domain) -> Domain:
504
+ """
505
+ Returns a new Domain with intersection-based merging:
506
+ - For each domain section only overwrite items that already exist in self.
507
+ - Brand-new items in `other` are ignored.
508
+
509
+ Args:
510
+ other: The domain to merge with.
511
+
512
+ Returns:
513
+ A new Domain object with the merged content.
514
+ """
515
+ updated_self = copy.deepcopy(self.as_dict())
516
+ other_dict = other.as_dict()
517
+
518
+ keys_to_merge = MERGE_FUNC_MAPPING.keys()
519
+ for key in keys_to_merge:
520
+ if key in DICT_DATA_KEYS:
521
+ # Merge dictionaries
522
+ self_val = updated_self.get(key, {})
523
+ other_val = other_dict.get(key, {})
524
+ updated_self[key] = rasa.shared.utils.common.partial_merge_dict(
525
+ self_val, other_val
526
+ )
527
+ else:
528
+ # Merge lists
529
+ self_val = updated_self.get(key, [])
530
+ other_val = other_dict.get(key, [])
531
+ is_same_item_fn = SAME_ITEM_FUNCTIONS.get(key, default_is_same_item)
532
+ updated_self[key] = rasa.shared.utils.common.partial_merge_list(
533
+ self_val, other_val, is_same_item_fn
534
+ )
535
+
536
+ return Domain.from_dict(updated_self)
537
+
538
+ def difference(self, other: Domain) -> Domain:
539
+ """
540
+ Returns a new Domain containing items in `self` that are NOT in `other`,
541
+ using simple equality checks for dict/list items.
542
+
543
+ Args:
544
+ other: The domain to compare with.
545
+
546
+ Returns:
547
+ A new Domain object with the difference content.
548
+ """
549
+ self_dict = self.as_dict()
550
+ other_dict = other.as_dict()
551
+
552
+ difference_dict = {}
553
+ for key in MERGE_FUNC_MAPPING.keys():
554
+ is_dict = key in DICT_DATA_KEYS
555
+ self_val = self_dict.get(key, {} if is_dict else [])
556
+ other_val = other_dict.get(key, {} if is_dict else [])
557
+
558
+ if is_dict and isinstance(self_val, dict) and isinstance(other_val, dict):
559
+ difference_dict[key] = {
560
+ k: v
561
+ for k, v in self_val.items()
562
+ if k not in other_val or v != other_val[k]
563
+ }
564
+ else:
565
+ difference_dict[key] = [
566
+ item for item in self_val if item not in other_val
567
+ ] # type: ignore[assignment]
568
+
569
+ return Domain.from_dict(difference_dict)
570
+
497
571
  def _preprocess_domain_dict(
498
572
  self,
499
573
  data: Dict,
@@ -2120,6 +2194,11 @@ class Domain:
2120
2194
  """Remove all builtin slots from the domain."""
2121
2195
  self.slots = [slot for slot in self.slots if not slot.is_builtin]
2122
2196
 
2197
+ def __eq__(self, other: object) -> bool:
2198
+ if isinstance(other, Domain):
2199
+ return self.as_dict() == other.as_dict()
2200
+ return False
2201
+
2123
2202
 
2124
2203
  def warn_about_duplicates_found_during_domain_merging(
2125
2204
  duplicates: Dict[Text, List[Text]],
@@ -2178,3 +2257,78 @@ def _validate_forms(forms: Union[Dict, List]) -> None:
2178
2257
  f"the keyword `{REQUIRED_SLOTS_KEY}` is required. "
2179
2258
  f"Please see {DOCS_URL_FORMS} for more information."
2180
2259
  )
2260
+
2261
+
2262
+ def is_same_entity(e1: Any, e2: Any) -> bool:
2263
+ """Check if two entities are the 'same' (string or dict).
2264
+
2265
+ Args:
2266
+ e1: First entity to compare.
2267
+ e2: Second entity to compare.
2268
+
2269
+ Returns:
2270
+ True if the entities are the same, False otherwise.
2271
+ """
2272
+ if isinstance(e1, str) and isinstance(e2, str):
2273
+ return e1 == e2
2274
+
2275
+ if isinstance(e1, dict) and isinstance(e2, dict):
2276
+ return (
2277
+ e1.get(ENTITY_ATTRIBUTE_TYPE) == e2.get(ENTITY_ATTRIBUTE_TYPE)
2278
+ and e1.get(ENTITY_ATTRIBUTE_ROLE) == e2.get(ENTITY_ATTRIBUTE_ROLE)
2279
+ and e1.get(ENTITY_ATTRIBUTE_GROUP) == e2.get(ENTITY_ATTRIBUTE_GROUP)
2280
+ )
2281
+
2282
+ return False
2283
+
2284
+
2285
+ def is_same_intent(i1: Any, i2: Any) -> bool:
2286
+ """Check if two intents are the 'same' (string or dict).
2287
+
2288
+ Args:
2289
+ i1: First intent to compare.
2290
+ i2: Second intent to compare.
2291
+
2292
+ Returns:
2293
+ True if the intents are the same, False otherwise.
2294
+ """
2295
+ if isinstance(i1, str) and isinstance(i2, str):
2296
+ return i1 == i2
2297
+
2298
+ if isinstance(i1, dict) and isinstance(i2, dict):
2299
+ key1, key2 = next(iter(i1.keys())), next(iter((i2.keys())))
2300
+ return key1 == key2
2301
+
2302
+ return False
2303
+
2304
+
2305
+ def is_same_action(a1: Any, a2: Any) -> bool:
2306
+ """Check if two actions are the 'same' (string or dict).
2307
+
2308
+ Args:
2309
+ a1: First action to compare.
2310
+ a2: Second action to compare.
2311
+
2312
+ Returns:
2313
+ True if the actions are the same, False otherwise.
2314
+ """
2315
+ if isinstance(a1, str) and isinstance(a2, str):
2316
+ return a1 == a2
2317
+
2318
+ if isinstance(a1, dict) and isinstance(a2, dict):
2319
+ key1, key2 = next(iter((a1.keys()))), next(iter((a2.keys())))
2320
+ return key1 == key2
2321
+
2322
+ return False
2323
+
2324
+
2325
+ def default_is_same_item(a: Any, b: Any) -> bool:
2326
+ """Fallback exact equality check if a key doesn't need special handling."""
2327
+ return a == b
2328
+
2329
+
2330
+ SAME_ITEM_FUNCTIONS: Dict[Text, Callable[[Any, Any], bool]] = {
2331
+ KEY_ENTITIES: is_same_entity,
2332
+ KEY_INTENTS: is_same_intent,
2333
+ KEY_ACTIONS: is_same_action,
2334
+ }
@@ -107,6 +107,8 @@ if TYPE_CHECKING:
107
107
  logger = logging.getLogger(__name__)
108
108
  structlogger = structlog.get_logger()
109
109
 
110
+ INVALID_DATETIME_ERROR_MESSAGE = "`anonymized_at` must be a datetime object."
111
+
110
112
 
111
113
  def deserialise_events(serialized_events: List[Dict[Text, Any]]) -> List["Event"]:
112
114
  """Convert a list of dictionaries to a list of corresponding events.
@@ -498,6 +500,23 @@ class UserUttered(Event):
498
500
  if parse_data:
499
501
  self.parse_data.update(**parse_data)
500
502
 
503
+ self._anonymized_at: Optional[datetime] = None
504
+
505
+ @property
506
+ def anonymized_at(self) -> Optional[datetime]:
507
+ """Returns the time when the event was anonymized in the tracker store.
508
+
509
+ If the event was not anonymized, it returns None.
510
+ """
511
+ return self._anonymized_at
512
+
513
+ @anonymized_at.setter
514
+ def anonymized_at(self, value: Optional[datetime]) -> None:
515
+ """Sets the time when the event was anonymized in the tracker store."""
516
+ if value is not None and not isinstance(value, datetime):
517
+ raise ValueError(INVALID_DATETIME_ERROR_MESSAGE)
518
+ self._anonymized_at = value
519
+
501
520
  @staticmethod
502
521
  def _from_parse_data(
503
522
  text: Text,
@@ -614,6 +633,7 @@ class UserUttered(Event):
614
633
  "input_channel": getattr(self, "input_channel", None),
615
634
  "message_id": getattr(self, "message_id", None),
616
635
  "metadata": self.metadata,
636
+ "anonymized_at": self.anonymized_at,
617
637
  }
618
638
  )
619
639
  return _dict
@@ -911,8 +931,24 @@ class BotUttered(SkipEventInMDStoryMixin):
911
931
  """
912
932
  self.text = text
913
933
  self.data = data or {}
934
+ self._anonymized_at: Optional[datetime] = None
914
935
  super().__init__(timestamp, metadata)
915
936
 
937
+ @property
938
+ def anonymized_at(self) -> Optional[datetime]:
939
+ """Returns the time when the event was anonymized in the tracker store.
940
+
941
+ If the event was not anonymized, it returns None.
942
+ """
943
+ return self._anonymized_at
944
+
945
+ @anonymized_at.setter
946
+ def anonymized_at(self, value: Optional[datetime]) -> None:
947
+ """Sets the time when the event was anonymized in the tracker store."""
948
+ if value is not None and not isinstance(value, datetime):
949
+ raise ValueError(INVALID_DATETIME_ERROR_MESSAGE)
950
+ self._anonymized_at = value
951
+
916
952
  def __members(self) -> Tuple[Optional[Text], Text, Text]:
917
953
  data_no_nones = {k: v for k, v in self.data.items() if v is not None}
918
954
  meta_no_nones = {k: v for k, v in self.metadata.items() if v is not None}
@@ -999,7 +1035,14 @@ class BotUttered(SkipEventInMDStoryMixin):
999
1035
  def as_dict(self) -> Dict[Text, Any]:
1000
1036
  """Returns serialized event."""
1001
1037
  d = super().as_dict()
1002
- d.update({"text": self.text, "data": self.data, "metadata": self.metadata})
1038
+ d.update(
1039
+ {
1040
+ "text": self.text,
1041
+ "data": self.data,
1042
+ "metadata": self.metadata,
1043
+ "anonymized_at": self.anonymized_at,
1044
+ }
1045
+ )
1003
1046
  return d
1004
1047
 
1005
1048
  @classmethod
@@ -1046,8 +1089,24 @@ class SlotSet(Event):
1046
1089
  self.key = key
1047
1090
  self.value = value
1048
1091
  self._filled_by = filled_by
1092
+ self._anonymized_at: Optional[datetime] = None
1049
1093
  super().__init__(timestamp, metadata)
1050
1094
 
1095
+ @property
1096
+ def anonymized_at(self) -> Optional[datetime]:
1097
+ """Returns the time when the event was anonymized in the tracker store.
1098
+
1099
+ If the event was not anonymized, it returns None.
1100
+ """
1101
+ return self._anonymized_at
1102
+
1103
+ @anonymized_at.setter
1104
+ def anonymized_at(self, value: Optional[datetime]) -> None:
1105
+ """Sets the time when the event was anonymized in the tracker store."""
1106
+ if value is not None and not isinstance(value, datetime):
1107
+ raise ValueError(INVALID_DATETIME_ERROR_MESSAGE)
1108
+ self._anonymized_at = value
1109
+
1051
1110
  def __repr__(self) -> Text:
1052
1111
  """Returns text representation of event."""
1053
1112
  return f"SlotSet(key: {self.key}, value: {self.value})"
@@ -1092,7 +1151,14 @@ class SlotSet(Event):
1092
1151
  def as_dict(self) -> Dict[Text, Any]:
1093
1152
  """Returns serialized event."""
1094
1153
  d = super().as_dict()
1095
- d.update({"name": self.key, "value": self.value, "filled_by": self.filled_by})
1154
+ d.update(
1155
+ {
1156
+ "name": self.key,
1157
+ "value": self.value,
1158
+ "filled_by": self.filled_by,
1159
+ "anonymized_at": self.anonymized_at,
1160
+ }
1161
+ )
1096
1162
  return d
1097
1163
 
1098
1164
  @classmethod