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

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

Potentially problematic release.


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

Files changed (304) hide show
  1. rasa/__main__.py +15 -3
  2. rasa/agents/__init__.py +0 -0
  3. rasa/agents/agent_factory.py +122 -0
  4. rasa/agents/agent_manager.py +211 -0
  5. rasa/agents/constants.py +43 -0
  6. rasa/agents/core/__init__.py +0 -0
  7. rasa/agents/core/agent_protocol.py +107 -0
  8. rasa/agents/core/types.py +81 -0
  9. rasa/agents/exceptions.py +38 -0
  10. rasa/agents/protocol/__init__.py +5 -0
  11. rasa/agents/protocol/a2a/__init__.py +0 -0
  12. rasa/agents/protocol/a2a/a2a_agent.py +879 -0
  13. rasa/agents/protocol/mcp/__init__.py +0 -0
  14. rasa/agents/protocol/mcp/mcp_base_agent.py +726 -0
  15. rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
  16. rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
  17. rasa/agents/schemas/__init__.py +13 -0
  18. rasa/agents/schemas/agent_input.py +38 -0
  19. rasa/agents/schemas/agent_output.py +26 -0
  20. rasa/agents/schemas/agent_tool_result.py +65 -0
  21. rasa/agents/schemas/agent_tool_schema.py +186 -0
  22. rasa/agents/templates/__init__.py +0 -0
  23. rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
  24. rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
  25. rasa/agents/utils.py +206 -0
  26. rasa/agents/validation.py +485 -0
  27. rasa/api.py +24 -9
  28. rasa/builder/config.py +6 -2
  29. rasa/builder/copilot/constants.py +4 -1
  30. rasa/builder/copilot/copilot.py +155 -79
  31. rasa/builder/copilot/models.py +304 -108
  32. rasa/builder/copilot/prompts/copilot_training_error_handler_prompt.jinja2 +53 -0
  33. rasa/builder/guardrails/{lakera.py → clients.py} +55 -5
  34. rasa/builder/guardrails/constants.py +3 -0
  35. rasa/builder/guardrails/models.py +45 -10
  36. rasa/builder/guardrails/policy_checker.py +324 -0
  37. rasa/builder/guardrails/utils.py +42 -276
  38. rasa/builder/jobs.py +182 -12
  39. rasa/builder/llm_service.py +32 -5
  40. rasa/builder/models.py +13 -3
  41. rasa/builder/project_generator.py +6 -1
  42. rasa/builder/service.py +31 -15
  43. rasa/builder/training_service.py +18 -24
  44. rasa/builder/validation_service.py +1 -1
  45. rasa/cli/arguments/default_arguments.py +12 -0
  46. rasa/cli/arguments/run.py +2 -0
  47. rasa/cli/arguments/train.py +2 -0
  48. rasa/cli/data.py +10 -8
  49. rasa/cli/dialogue_understanding_test.py +10 -7
  50. rasa/cli/e2e_test.py +9 -6
  51. rasa/cli/evaluate.py +4 -2
  52. rasa/cli/export.py +5 -2
  53. rasa/cli/inspect.py +8 -4
  54. rasa/cli/interactive.py +5 -4
  55. rasa/cli/llm_fine_tuning.py +11 -6
  56. rasa/cli/project_templates/finance/domain/general/help.yml +0 -0
  57. rasa/cli/project_templates/tutorial/credentials.yml +10 -0
  58. rasa/cli/run.py +12 -10
  59. rasa/cli/scaffold.py +4 -4
  60. rasa/cli/shell.py +9 -5
  61. rasa/cli/studio/studio.py +1 -1
  62. rasa/cli/test.py +34 -14
  63. rasa/cli/train.py +41 -28
  64. rasa/cli/utils.py +1 -393
  65. rasa/cli/validation/__init__.py +0 -0
  66. rasa/cli/validation/bot_config.py +223 -0
  67. rasa/cli/validation/config_path_validation.py +257 -0
  68. rasa/cli/x.py +8 -4
  69. rasa/constants.py +7 -1
  70. rasa/core/actions/action.py +51 -10
  71. rasa/core/actions/grpc_custom_action_executor.py +1 -1
  72. rasa/core/agent.py +19 -2
  73. rasa/core/available_agents.py +229 -0
  74. rasa/core/brokers/kafka.py +5 -1
  75. rasa/core/channels/__init__.py +82 -35
  76. rasa/core/channels/development_inspector.py +3 -3
  77. rasa/core/channels/inspector/README.md +25 -13
  78. rasa/core/channels/inspector/dist/assets/{arc-35222594.js → arc-6177260a.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-a0efbfd3.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0584c0f2.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
  82. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-39f40dbe.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-1ad755f3.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
  85. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-b0f4f0fe.js → createText-2e5e7dd3-088372e2.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-9039bff9.js → edges-e0da2a9e-58676240.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-65c9b127.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4f08b38e.js → flowDb-956e92f1-ea63f85c.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-e95c362a.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
  91. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-703c3015.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
  92. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-699328ea.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
  93. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-04cf4b05.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
  94. rasa/core/channels/inspector/dist/assets/{graph-ee94449e.js → graph-0a6f8466.js} +1 -1
  95. rasa/core/channels/inspector/dist/assets/{index-3862675e-940162b4.js → index-3862675e-7610671a.js} +1 -1
  96. rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
  97. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-c79c2866.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
  98. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-84489d30.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
  99. rasa/core/channels/inspector/dist/assets/{layout-a9aa9858.js → layout-e7fbc2bf.js} +1 -1
  100. rasa/core/channels/inspector/dist/assets/{line-eb73cf26.js → line-a8aa457c.js} +1 -1
  101. rasa/core/channels/inspector/dist/assets/{linear-b3399f9a.js → linear-3351e0d2.js} +1 -1
  102. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-b095bf1a.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
  103. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-07644b66.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
  104. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-573a3f9c.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
  105. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d457e1e1.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
  106. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-9d26e1a2.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
  107. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3a9cde10.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
  108. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-4f3e8cec.js → stateDiagram-587899a1-0e770395.js} +1 -1
  109. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e617e5bf.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
  110. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-eab30d2f.js → styles-6aaf32cf-36a9e70d.js} +1 -1
  111. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-09994be2.js → styles-9a916d00-884a8b5b.js} +1 -1
  112. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-b7110364.js → styles-c10674c1-dc097813.js} +1 -1
  113. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-3ebc92ad.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
  114. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-7d13d2f2.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
  115. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-488385e1.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
  116. rasa/core/channels/inspector/dist/index.html +1 -1
  117. rasa/core/channels/inspector/package.json +18 -18
  118. rasa/core/channels/inspector/src/App.tsx +29 -4
  119. rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
  120. rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
  121. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +7 -4
  122. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
  123. rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
  124. rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
  125. rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
  126. rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
  127. rasa/core/channels/inspector/src/types.ts +21 -0
  128. rasa/core/channels/inspector/yarn.lock +336 -189
  129. rasa/core/channels/studio_chat.py +6 -6
  130. rasa/core/channels/telegram.py +4 -9
  131. rasa/core/channels/voice_stream/genesys.py +1 -1
  132. rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
  133. rasa/core/channels/voice_stream/twilio_media_streams.py +5 -1
  134. rasa/core/channels/voice_stream/voice_channel.py +3 -0
  135. rasa/core/concurrent_lock_store.py +38 -21
  136. rasa/core/config/__init__.py +0 -0
  137. rasa/core/{available_endpoints.py → config/available_endpoints.py} +51 -16
  138. rasa/core/config/configuration.py +260 -0
  139. rasa/core/config/credentials.py +19 -0
  140. rasa/core/config/message_procesing_config.py +34 -0
  141. rasa/core/constants.py +10 -0
  142. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +69 -4
  143. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +2 -1
  144. rasa/core/lock_store.py +4 -0
  145. rasa/core/policies/enterprise_search_policy.py +5 -3
  146. rasa/core/policies/flow_policy.py +4 -4
  147. rasa/core/policies/flows/agent_executor.py +632 -0
  148. rasa/core/policies/flows/flow_executor.py +136 -75
  149. rasa/core/policies/flows/mcp_tool_executor.py +298 -0
  150. rasa/core/policies/intentless_policy.py +1 -1
  151. rasa/core/policies/ted_policy.py +20 -12
  152. rasa/core/policies/unexpected_intent_policy.py +6 -0
  153. rasa/core/processor.py +68 -44
  154. rasa/core/redis_connection_factory.py +7 -2
  155. rasa/core/run.py +37 -8
  156. rasa/core/test.py +4 -0
  157. rasa/core/tracker_stores/redis_tracker_store.py +4 -0
  158. rasa/core/tracker_stores/sql_tracker_store.py +3 -1
  159. rasa/core/tracker_stores/tracker_store.py +3 -7
  160. rasa/core/train.py +1 -1
  161. rasa/core/training/interactive.py +20 -18
  162. rasa/core/training/story_conflict.py +5 -5
  163. rasa/core/utils.py +22 -23
  164. rasa/dialogue_understanding/commands/__init__.py +8 -0
  165. rasa/dialogue_understanding/commands/cancel_flow_command.py +19 -5
  166. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
  167. rasa/dialogue_understanding/commands/clarify_command.py +20 -2
  168. rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
  169. rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
  170. rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
  171. rasa/dialogue_understanding/commands/start_flow_command.py +68 -7
  172. rasa/dialogue_understanding/commands/utils.py +124 -2
  173. rasa/dialogue_understanding/generator/command_parser.py +4 -0
  174. rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
  175. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  176. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
  177. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
  178. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
  179. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
  180. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
  181. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
  182. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
  183. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
  184. rasa/dialogue_understanding/patterns/cancel.py +27 -6
  185. rasa/dialogue_understanding/patterns/clarify.py +3 -14
  186. rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
  187. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +46 -8
  188. rasa/dialogue_understanding/processor/command_processor.py +136 -15
  189. rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
  190. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
  191. rasa/dialogue_understanding/stack/utils.py +57 -3
  192. rasa/dialogue_understanding/utils.py +24 -4
  193. rasa/dialogue_understanding_test/du_test_runner.py +8 -3
  194. rasa/e2e_test/e2e_test_runner.py +13 -3
  195. rasa/engine/caching.py +2 -2
  196. rasa/engine/constants.py +1 -1
  197. rasa/engine/recipes/default_components.py +138 -49
  198. rasa/engine/recipes/default_recipe.py +108 -11
  199. rasa/engine/runner/dask.py +8 -5
  200. rasa/engine/validation.py +19 -6
  201. rasa/graph_components/validators/default_recipe_validator.py +86 -28
  202. rasa/hooks.py +5 -5
  203. rasa/llm_fine_tuning/utils.py +2 -2
  204. rasa/model_training.py +60 -47
  205. rasa/nlu/classifiers/diet_classifier.py +198 -98
  206. rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
  207. rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
  208. rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
  209. rasa/nlu/extractors/crf_entity_extractor.py +9 -10
  210. rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
  211. rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
  212. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
  213. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
  214. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
  215. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
  216. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
  217. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
  218. rasa/nlu/selectors/response_selector.py +10 -2
  219. rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
  220. rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
  221. rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
  222. rasa/nlu/utils/mitie_utils.py +3 -0
  223. rasa/nlu/utils/spacy_utils.py +3 -2
  224. rasa/plugin.py +8 -8
  225. rasa/privacy/privacy_manager.py +12 -3
  226. rasa/server.py +15 -3
  227. rasa/shared/agents/__init__.py +0 -0
  228. rasa/shared/agents/auth/__init__.py +0 -0
  229. rasa/shared/agents/auth/agent_auth_factory.py +105 -0
  230. rasa/shared/agents/auth/agent_auth_manager.py +92 -0
  231. rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
  232. rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
  233. rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
  234. rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
  235. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +167 -0
  236. rasa/shared/agents/auth/constants.py +12 -0
  237. rasa/shared/agents/auth/types.py +12 -0
  238. rasa/shared/agents/utils.py +35 -0
  239. rasa/shared/constants.py +8 -0
  240. rasa/shared/core/constants.py +16 -1
  241. rasa/shared/core/domain.py +0 -7
  242. rasa/shared/core/events.py +327 -0
  243. rasa/shared/core/flows/constants.py +5 -0
  244. rasa/shared/core/flows/flows_list.py +21 -5
  245. rasa/shared/core/flows/flows_yaml_schema.json +119 -184
  246. rasa/shared/core/flows/steps/call.py +49 -5
  247. rasa/shared/core/flows/steps/collect.py +98 -13
  248. rasa/shared/core/flows/validation.py +372 -8
  249. rasa/shared/core/flows/yaml_flows_io.py +3 -2
  250. rasa/shared/core/slots.py +2 -2
  251. rasa/shared/core/trackers.py +5 -2
  252. rasa/shared/exceptions.py +16 -0
  253. rasa/shared/importers/rasa.py +1 -1
  254. rasa/shared/importers/utils.py +9 -3
  255. rasa/shared/providers/llm/_base_litellm_client.py +41 -9
  256. rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
  257. rasa/shared/providers/llm/llm_client.py +7 -3
  258. rasa/shared/providers/llm/llm_response.py +66 -0
  259. rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
  260. rasa/shared/utils/common.py +24 -0
  261. rasa/shared/utils/health_check/health_check.py +7 -3
  262. rasa/shared/utils/llm.py +39 -16
  263. rasa/shared/utils/mcp/__init__.py +0 -0
  264. rasa/shared/utils/mcp/server_connection.py +247 -0
  265. rasa/shared/utils/mcp/utils.py +20 -0
  266. rasa/shared/utils/schemas/events.py +42 -0
  267. rasa/shared/utils/yaml.py +3 -1
  268. rasa/studio/pull/pull.py +3 -2
  269. rasa/studio/train.py +8 -7
  270. rasa/studio/upload.py +3 -6
  271. rasa/telemetry.py +69 -5
  272. rasa/tracing/config.py +45 -12
  273. rasa/tracing/constants.py +14 -0
  274. rasa/tracing/instrumentation/attribute_extractors.py +142 -9
  275. rasa/tracing/instrumentation/instrumentation.py +626 -21
  276. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
  277. rasa/tracing/instrumentation/metrics.py +32 -0
  278. rasa/tracing/metric_instrument_provider.py +68 -0
  279. rasa/utils/common.py +92 -1
  280. rasa/utils/endpoints.py +11 -2
  281. rasa/utils/log_utils.py +96 -5
  282. rasa/utils/ml_utils.py +1 -1
  283. rasa/utils/tensorflow/__init__.py +7 -0
  284. rasa/utils/tensorflow/callback.py +136 -101
  285. rasa/utils/tensorflow/crf.py +1 -1
  286. rasa/utils/tensorflow/data_generator.py +21 -8
  287. rasa/utils/tensorflow/layers.py +21 -11
  288. rasa/utils/tensorflow/metrics.py +7 -3
  289. rasa/utils/tensorflow/models.py +56 -8
  290. rasa/utils/tensorflow/rasa_layers.py +8 -6
  291. rasa/utils/tensorflow/transformer.py +2 -3
  292. rasa/utils/train_utils.py +54 -24
  293. rasa/validator.py +5 -5
  294. rasa/version.py +1 -1
  295. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/METADATA +47 -41
  296. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/RECORD +299 -238
  297. rasa/builder/scrape_rasa_docs.py +0 -97
  298. rasa/core/channels/inspector/dist/assets/channel-8e08bed9.js +0 -1
  299. rasa/core/channels/inspector/dist/assets/clone-78c82dea.js +0 -1
  300. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b08f601.js +0 -1
  301. rasa/core/channels/inspector/dist/assets/index-c941dcb3.js +0 -1336
  302. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/NOTICE +0 -0
  303. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/WHEEL +0 -0
  304. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc2.dist-info}/entry_points.txt +0 -0
@@ -16,48 +16,48 @@
16
16
  "dependencies": {
17
17
  "@chakra-ui/icons": "^2.2.4",
18
18
  "@chakra-ui/react": "2.8.1",
19
- "@emotion/react": "11.11.1",
20
- "@emotion/styled": "11.11.0",
21
- "axios": "1.8.2",
22
- "deep-chat-react": "2.0.1",
19
+ "@emotion/react": "11.14.0",
20
+ "@emotion/styled": "11.14.1",
21
+ "axios": "1.12.2",
22
+ "deep-chat-react": "2.2.2",
23
23
  "framer-motion": "10.16.4",
24
- "immutable-json-patch": "^6.0.1",
24
+ "immutable-json-patch": "^6.0.2",
25
25
  "mermaid": "10.9.3",
26
- "query-string": "^9.0.0",
26
+ "query-string": "^9.3.1",
27
27
  "react": "18.2.0",
28
28
  "react-dom": "18.2.0",
29
- "react-syntax-highlighter": "15.5.0",
30
- "react-use-websocket": "^4.8.1",
29
+ "react-syntax-highlighter": "15.6.6",
30
+ "react-use-websocket": "^4.13.0",
31
31
  "usehooks-ts": "2.9.1"
32
32
  },
33
33
  "devDependencies": {
34
- "@testing-library/jest-dom": "6.1.4",
34
+ "@testing-library/jest-dom": "6.8.0",
35
35
  "@testing-library/react": "14.0.0",
36
36
  "@types/jest": "29.5.6",
37
37
  "@types/node": "16",
38
38
  "@types/react": "^18.2.15",
39
39
  "@types/react-dom": "18.2.7",
40
- "@types/react-syntax-highlighter": "15.5.9",
40
+ "@types/react-syntax-highlighter": "15.5.13",
41
41
  "@typescript-eslint/eslint-plugin": "6.0.0",
42
42
  "@typescript-eslint/parser": "6.0.0",
43
43
  "@vitejs/plugin-react": "4.0.3",
44
44
  "eslint": "8.45.0",
45
45
  "eslint-plugin-react-hooks": "4.6.0",
46
- "eslint-plugin-react-refresh": "0.4.3",
46
+ "eslint-plugin-react-refresh": "0.4.21",
47
47
  "jest": "29.7.0",
48
48
  "jest-environment-jsdom": "29.7.0",
49
- "prettier": "^3.5.3",
50
- "ts-jest": "29.1.1",
51
- "ts-node": "10.9.1",
52
- "typescript": "5.0.2",
49
+ "prettier": "^3.6.2",
50
+ "ts-jest": "29.4.4",
51
+ "ts-node": "10.9.2",
52
+ "typescript": "5.9.2",
53
53
  "vite": "4.5.12"
54
54
  },
55
55
  "resolutions": {
56
- "cross-spawn": "7.0.5",
56
+ "cross-spawn": "7.0.6",
57
57
  "dompurify": "3.1.3",
58
58
  "braces": "3.0.3",
59
- "ws": "8.17.1",
59
+ "ws": "8.18.3",
60
60
  "rollup": "3.29.5",
61
- "@adobe/css-tools": "^4.3.2"
61
+ "@adobe/css-tools": "^4.4.4"
62
62
  }
63
63
  }
@@ -12,24 +12,27 @@ import useWebSocket, { ReadyState } from 'react-use-websocket'
12
12
  import { Chat } from './components/Chat'
13
13
  import { DiagramFlow } from './components/DiagramFlow'
14
14
  import { DialougeInformation } from './components/DialogueInformation'
15
- import { DialogueStack } from './components/DialogueStack'
15
+ import { DialogueHistoryStack } from './components/DialogueHistoryStack'
16
16
  import { LoadingSpinner } from './components/LoadingSpinner'
17
17
  import { RecruitmentPanel } from './components/RecruitmentPanel'
18
18
  import { Welcome } from './components/Welcome'
19
19
  import { formatSlots } from './helpers/formatters'
20
20
  import {
21
21
  createHistoricalStack,
22
- flowStepTrail,
22
+ flowStepTrail, updateAgentsStatus,
23
23
  updatedActiveFrame,
24
24
  } from './helpers/utils'
25
25
  import { useOurTheme } from './theme'
26
- import { Event, Flow, SelectedStack, Slot, Stack, Tracker } from './types'
26
+ import { Event, Flow, SelectedStack, Slot, Stack, Tracker, Agent } from './types'
27
+ import {DialogueAgentStack} from "./components/DialogueAgentStack.tsx";
28
+
27
29
 
28
30
  export function App() {
29
31
  const toast = useToast()
30
32
  const { rasaSpace, rasaRadii } = useOurTheme()
31
33
  const [rasaChatSessionId, setRasaChatSessionId] = useState<string>('')
32
34
  const [flows, setFlows] = useState<Flow[]>([])
35
+ const [agents, setAgents] = useState<Agent[]>([])
33
36
  const [slots, setSlots] = useState<Slot[]>([])
34
37
  const [events, setEvents] = useState<Event[]>([])
35
38
  const [story, setStory] = useState<string>('')
@@ -101,6 +104,23 @@ export function App() {
101
104
  })
102
105
  }, [toast])
103
106
 
107
+ useEffect(() => {
108
+ axios
109
+ .get('/sub-agents', { params: { token } })
110
+ .then((response) => setAgents((response.data)))
111
+ .catch((error) => {
112
+ if (toast.isActive('agents')) return
113
+ toast({
114
+ id: 'agents',
115
+ title: 'Agents could not be retrieved',
116
+ description: error?.message || 'An unknown error happened.',
117
+ status: 'error',
118
+ duration: 4000,
119
+ isClosable: true,
120
+ })
121
+ })
122
+ }, [toast])
123
+
104
124
  function fetchStory() {
105
125
  axios
106
126
  .get(`/conversations/${rasaChatSessionId}/story`, { params: { token } })
@@ -134,6 +154,7 @@ export function App() {
134
154
  lastJsonMessage.stack,
135
155
  lastJsonMessage.events,
136
156
  )
157
+ setAgents(prevAgents => updateAgentsStatus(prevAgents, lastJsonMessage.events))
137
158
  setStack(updatedStack)
138
159
  setFrame(updatedActiveFrame(frame, updatedStack, lastJsonMessage.events))
139
160
  setRasaChatSessionId(lastJsonMessage.sender_id)
@@ -217,12 +238,16 @@ export function App() {
217
238
  {showRecruitmentPanel && (
218
239
  <RecruitmentPanel onClose={handleCloseRecruitmentPanel} />
219
240
  )}
220
- <DialogueStack
241
+ <DialogueHistoryStack
221
242
  sx={boxSx}
222
243
  stack={stack}
223
244
  active={frame?.stack}
224
245
  onItemClick={onFrameSelected}
225
246
  />
247
+ {agents.length > 0 ? (<DialogueAgentStack
248
+ sx={boxSx}
249
+ agents={agents}
250
+ />):null}
226
251
  <DialougeInformation
227
252
  sx={boxSx}
228
253
  rasaChatSessionId={rasaChatSessionId}
@@ -0,0 +1,108 @@
1
+ import {
2
+ Box,
3
+ FlexProps,
4
+ Heading,
5
+ Table,
6
+ Thead,
7
+ Tbody,
8
+ Tr,
9
+ Th,
10
+ Td,
11
+ Text,
12
+ Flex,
13
+ } from '@chakra-ui/react'
14
+ import { useOurTheme } from '../theme'
15
+ import {Agent, Stack} from '../types'
16
+
17
+ function mapStatusToHumanReadableName(status: Agent['status']) {
18
+ switch (status) {
19
+ case 'running':
20
+ return 'Running'
21
+ case 'completed':
22
+ return 'Completed'
23
+ case 'interrupted':
24
+ return 'Interrupted'
25
+ case 'cancelled':
26
+ return 'Cancelled'
27
+ default:
28
+ return '-'
29
+ }
30
+ }
31
+
32
+ interface Props extends FlexProps {
33
+ agents: Agent[]
34
+ active?: Stack
35
+ onItemClick?: (stack: Stack) => void
36
+ }
37
+
38
+ function AgentRow({
39
+ agent,
40
+ }: {
41
+ agent: Agent
42
+ }) {
43
+
44
+ return (
45
+ <Tr>
46
+ <Td>
47
+ <Text noOfLines={1}>{agent.name}</Text>
48
+ </Td>
49
+ <Td>
50
+ <Text noOfLines={1}>{mapStatusToHumanReadableName(agent.status)}</Text>
51
+ </Td>
52
+ </Tr>
53
+ )
54
+ }
55
+
56
+ export const DialogueAgentStack = ({
57
+ sx,
58
+ agents,
59
+ active,
60
+ onItemClick,
61
+ ...props
62
+ }: Props) => {
63
+ const { rasaSpace } = useOurTheme()
64
+
65
+ const containerSx = {
66
+ ...sx,
67
+ pr: 0,
68
+ pb: 0,
69
+ flexDirection: 'column',
70
+ }
71
+ const overflowBox = {
72
+ height: '100%',
73
+ overflow: 'auto',
74
+ pr: rasaSpace[1],
75
+ pb: rasaSpace[0.5],
76
+ }
77
+
78
+ return (
79
+ <Flex sx={containerSx} {...props}>
80
+ <Flex>
81
+ <Heading size="lg" mb={rasaSpace[0.5]}>
82
+ Agents
83
+ </Heading>
84
+ <Text ml={rasaSpace[0.25]}>({agents.length} {agents.length === 1 ? 'agent' : 'agents'})</Text>
85
+ </Flex>
86
+ <Box sx={overflowBox}>
87
+ <Table width="100%" layout="fixed">
88
+ <Thead>
89
+ <Tr>
90
+ <Th>Name</Th>
91
+ <Th width="40%">Status</Th>
92
+ </Tr>
93
+ </Thead>
94
+ <Tbody>
95
+ {agents.length > 0 &&
96
+ [...agents]
97
+ .reverse()
98
+ .map((agent) => (
99
+ <AgentRow
100
+ agent={agent}
101
+ />
102
+ ))}
103
+ </Tbody>
104
+ </Table>
105
+ </Box>
106
+ </Flex>
107
+ )
108
+ }
@@ -77,7 +77,7 @@ function StackRow({
77
77
  )
78
78
  }
79
79
 
80
- export const DialogueStack = ({
80
+ export const DialogueHistoryStack = ({
81
81
  sx,
82
82
  stack,
83
83
  active,
@@ -105,7 +105,7 @@ export const DialogueStack = ({
105
105
  <Heading size="lg" mb={rasaSpace[0.5]}>
106
106
  History
107
107
  </Heading>
108
- <Text ml={rasaSpace[0.25]}>({stack.length} flows)</Text>
108
+ <Text ml={rasaSpace[0.25]}>({stack.length} {stack.length === 1 ? 'flow' : 'flows'})</Text>
109
109
  </Flex>
110
110
  <Box sx={overflowBox}>
111
111
  <Table width="100%" layout="fixed">
@@ -118,6 +118,7 @@ export const DialogueStack = ({
118
118
  <Tbody>
119
119
  {stack.length > 0 &&
120
120
  [...stack]
121
+ .filter(frame => !frame.agent_id)
121
122
  .reverse()
122
123
  .map((stack) => (
123
124
  <StackRow
@@ -134,6 +135,7 @@ export const DialogueStack = ({
134
135
  flow_id: '-',
135
136
  step_id: '-',
136
137
  ended: false,
138
+ type: "flow"
137
139
  }}
138
140
  />
139
141
  )}
@@ -8,7 +8,7 @@ const audioOptions = {
8
8
  },
9
9
  }
10
10
 
11
- const arrayBufferToBase64 = (buffer: ArrayBuffer): string => {
11
+ const arrayBufferToBase64 = (buffer: ArrayBufferLike): string => {
12
12
  let binary = ''
13
13
  const bytes = new Uint8Array(buffer)
14
14
  const len = bytes.byteLength
@@ -196,7 +196,8 @@ const setupAudioPlayback = async (socket: WebSocket): Promise<AudioQueue> => {
196
196
  }
197
197
 
198
198
  const addDataToAudioQueue =
199
- (audioQueue: AudioQueue, onLatencyUpdate?: (latency: any) => void) => (message: MessageEvent<any>) => {
199
+ (audioQueue: AudioQueue, onLatencyUpdate?: (latency: any) => void) =>
200
+ (message: MessageEvent<any>) => {
200
201
  try {
201
202
  const data = JSON.parse(message.data.toString())
202
203
  if (data['error']) {
@@ -218,7 +219,6 @@ const addDataToAudioQueue =
218
219
  audioQueue.clear()
219
220
  console.log('Audio queue cleared due to user interruption.')
220
221
  }
221
-
222
222
  } catch (error) {
223
223
  console.error('Error processing server incoming audio data:', error)
224
224
  }
@@ -251,7 +251,10 @@ function getWebSocketUrl(baseUrl: string) {
251
251
  * @param baseUrl - The base URL (e.g., "https://example.com" or "http://localhost:5005")
252
252
  * @param onLatencyUpdate - Optional callback function to receive latency updates
253
253
  */
254
- export async function createAudioConnection(baseUrl: string, onLatencyUpdate?: (latency: any) => void) {
254
+ export async function createAudioConnection(
255
+ baseUrl: string,
256
+ onLatencyUpdate?: (latency: any) => void,
257
+ ) {
255
258
  const websocketURL = getWebSocketUrl(baseUrl)
256
259
  const socket = new WebSocket(websocketURL)
257
260
 
@@ -294,6 +294,7 @@ describe('helpers', () => {
294
294
  step_id: 'step_id',
295
295
  collect: fieldValue,
296
296
  ended: false,
297
+ type: 'flow',
297
298
  }),
298
299
  ).toEqual(fieldValue)
299
300
  })
@@ -307,6 +308,7 @@ describe('helpers', () => {
307
308
  flow_id: 'flow_id',
308
309
  step_id: 'step_id',
309
310
  ended: false,
311
+ type: 'flow',
310
312
  }),
311
313
  ).toEqual(fieldValue)
312
314
  })
@@ -321,6 +323,7 @@ describe('helpers', () => {
321
323
  step_id: 'step_id',
322
324
  collect: fieldValue,
323
325
  ended: false,
326
+ type: 'flow',
324
327
  }),
325
328
  ).toEqual(`${fieldValue} is not null`)
326
329
  })
@@ -335,6 +338,7 @@ describe('helpers', () => {
335
338
  step_id: 'step_id',
336
339
  collect: fieldValue,
337
340
  ended: false,
341
+ type: 'flow',
338
342
  }),
339
343
  ).toEqual(`not ${fieldValue}`)
340
344
  })
@@ -1,5 +1,5 @@
1
- import { rasaColors } from '../theme/base/colors'
2
- import type { Event, Flow, Slot, Stack } from '../types'
1
+ import {rasaColors} from '../theme/base/colors'
2
+ import type {Event, Flow, Slot, Stack} from '../types'
3
3
 
4
4
  export function formatSlots(slots: { [key: string]: unknown }) {
5
5
  if (!slots) {
@@ -13,7 +13,7 @@ export function formatSlots(slots: { [key: string]: unknown }) {
13
13
  slotDuple[0] !== 'flow_hashes' &&
14
14
  slotDuple[1] != null,
15
15
  )
16
- .map((slotDuple) => ({ name: slotDuple[0], value: slotDuple[1] }))
16
+ .map((slotDuple) => ({name: slotDuple[0], value: slotDuple[1]}))
17
17
  }
18
18
 
19
19
  export const formatTestCases = (events: Event[], sessionId: string) => {
@@ -85,11 +85,14 @@ export const formatFlow = (
85
85
  `flowchart TD
86
86
  classDef collect stroke-width:1px
87
87
  classDef action fill:#FBFCFD,stroke:#A0B8CF
88
+ classDef noop fill:#FBFCFD
89
+ classDef callstep fill:#FBFCFD
88
90
  classDef link fill:#f43
89
91
  classDef slot fill:#e8f3db,stroke:#c5e1a5
90
92
  classDef endstep fill:#ccc,stroke:#444
91
93
  classDef previous stroke:${rasaColors.rasaOrange[400]},stroke-width:1px
92
94
  classDef active stroke:${rasaColors.rasaOrange[400]},stroke-width:3px,fill:${rasaColors.warning[50]}
95
+ classDef pulse animation:pulse 2s infinite
93
96
  `,
94
97
  ]
95
98
  try {
@@ -210,6 +213,24 @@ function renderStepSequence(
210
213
  )}"]:::slot\n`
211
214
  }
212
215
 
216
+ if (step.call) {
217
+ const isAgentWaitingOnInput = !!currentStack?.agent_id && currentStack?.state === 'waiting_for_input'
218
+ mermaidTextFragment += `${mermaidId}["${encodeDoubleQuotes(
219
+ stepId,
220
+ )} 🤖"]:::callstep\n`
221
+
222
+ if (isAgentWaitingOnInput) {
223
+ mermaidTextFragment += `class ${mermaidId} pulse\n`
224
+ }
225
+ }
226
+
227
+ if (step.noop) {
228
+ mermaidTextFragment += `${mermaidId}["${parseFieldUsingStack(
229
+ stepId,
230
+ currentStack
231
+ )}"]:::noop\n`
232
+ }
233
+
213
234
  if (activeStep && stepId === activeStep) {
214
235
  mermaidTextFragment += `class ${mermaidId} active\n`
215
236
  } else if (stepTrail?.includes(stepId)) {
@@ -0,0 +1,127 @@
1
+ import { updateAgentsStatus } from './utils'
2
+ import type { Agent, Event } from '../types'
3
+
4
+ // Helper to clone agents (immutability check)
5
+ const clone = <T>(x: T): T => JSON.parse(JSON.stringify(x))
6
+
7
+ describe('updateAgentsStatus', () => {
8
+ test('returns empty array when agents undefined', () => {
9
+ // @ts-expect-error testing runtime behavior with undefined
10
+ expect(updateAgentsStatus(undefined, [])).toEqual([])
11
+ })
12
+
13
+ test('returns same agents when agents empty', () => {
14
+ const agents: Agent[] = []
15
+ const events: Event[] = [
16
+ { event: 'agent_started', timestamp: '1' } as any,
17
+ ]
18
+ expect(updateAgentsStatus(agents, events)).toEqual([])
19
+ })
20
+
21
+ test('returns same agents when events empty', () => {
22
+ const agents: Agent[] = [
23
+ { name: 'alpha', status: 'completed' },
24
+ ]
25
+ const events: Event[] = []
26
+ expect(updateAgentsStatus(clone(agents), events)).toEqual(agents)
27
+ })
28
+
29
+ test('ignores non-agent events', () => {
30
+ const agents: Agent[] = [
31
+ { name: 'alpha', status: 'completed' },
32
+ ]
33
+ const events: Event[] = [
34
+ { event: 'user', text: 'hi', timestamp: '1' } as any,
35
+ { event: 'bot', text: 'hey', timestamp: '2' } as any,
36
+ ]
37
+ expect(updateAgentsStatus(clone(agents), events)).toEqual(agents)
38
+ })
39
+
40
+ test('uses latest event by timestamp per agent', () => {
41
+ const agents: Agent[] = [
42
+ { name: 'alpha', status: 'completed' },
43
+ { name: 'beta', status: 'completed' },
44
+ ]
45
+
46
+ const events: Event[] = [
47
+ { event: 'agent_started', agent_id: 'alpha', timestamp: 1 } as any,
48
+ { event: 'agent_interrupted', agent_id: 'alpha', timestamp: 2 } as any,
49
+ { event: 'agent_resumed', agent_id: 'alpha', timestamp: 3 } as any,
50
+ { event: 'agent_cancelled', agent_id: 'beta', timestamp: 5 } as any,
51
+ ]
52
+
53
+ const result = updateAgentsStatus(clone(agents), events)
54
+ expect(result).toEqual([
55
+ { name: 'alpha', status: 'running' },
56
+ { name: 'beta', status: 'cancelled' },
57
+ ])
58
+ })
59
+
60
+ test('later event wins when timestamps missing', () => {
61
+ const agents: Agent[] = [
62
+ { name: 'alpha', status: 'completed' },
63
+ ]
64
+
65
+ const events: Event[] = [
66
+ { event: 'agent_started', agent_id: 'alpha', timestamp: null } as any,
67
+ { event: 'agent_interrupted', agent_id: 'alpha', timestamp: null } as any,
68
+ ]
69
+
70
+ const result = updateAgentsStatus(clone(agents), events)
71
+ expect(result).toEqual([
72
+ { name: 'alpha', status: 'interrupted' },
73
+ ])
74
+ })
75
+
76
+ test('agent_completed maps to provided status and falls back to completed', () => {
77
+ const agents: Agent[] = [
78
+ { name: 'alpha', status: 'running' },
79
+ { name: 'beta', status: 'running' },
80
+ ]
81
+
82
+ const events: Event[] = [
83
+ { event: 'agent_completed', agent_id: 'alpha', status: 'completed', timestamp: 10 } as any,
84
+ { event: 'agent_completed', agent_id: 'beta', timestamp: 10 } as any,
85
+ ]
86
+
87
+ const result = updateAgentsStatus(clone(agents), events)
88
+ expect(result).toEqual([
89
+ { name: 'alpha', status: 'completed' },
90
+ { name: 'beta', status: 'completed' },
91
+ ])
92
+ })
93
+
94
+ test('unmatched agents remain unchanged', () => {
95
+ const agents: Agent[] = [
96
+ { name: 'alpha', status: 'running' },
97
+ { name: 'gamma', status: 'interrupted' },
98
+ ]
99
+
100
+ const events: Event[] = [
101
+ { event: 'agent_resumed', agent_id: 'alpha', timestamp: 1 } as any,
102
+ { event: 'agent_cancelled', agent_id: 'beta', timestamp: 2 } as any, // beta not in agents list
103
+ ]
104
+
105
+ const result = updateAgentsStatus(clone(agents), events)
106
+ expect(result).toEqual([
107
+ { name: 'alpha', status: 'running' },
108
+ { name: 'gamma', status: 'interrupted' },
109
+ ])
110
+ })
111
+
112
+ test('handles mixed timestamp types (string/number)', () => {
113
+ const agents: Agent[] = [
114
+ { name: 'alpha', status: 'completed' },
115
+ ]
116
+
117
+ const events: Event[] = [
118
+ { event: 'agent_started', agent_id: 'alpha', timestamp: '1' } as any,
119
+ { event: 'agent_interrupted', agent_id: 'alpha', timestamp: 2 } as any,
120
+ ]
121
+
122
+ const result = updateAgentsStatus(clone(agents), events)
123
+ expect(result).toEqual([
124
+ { name: 'alpha', status: 'interrupted' },
125
+ ])
126
+ })
127
+ })
@@ -1,4 +1,4 @@
1
- import { SelectedStack, Stack, Event } from '../types'
1
+ import {SelectedStack, Stack, Event, Agent, AGENT_EVENT_TYPES} from '../types'
2
2
  import { immutableJSONPatch } from 'immutable-json-patch'
3
3
 
4
4
  export const shouldShowTooltip = (text: string) => {
@@ -146,3 +146,68 @@ export const updatedActiveFrame = (
146
146
  return previous
147
147
  }
148
148
  }
149
+
150
+ export function updateAgentsStatus(agents: Agent[], events: Event[]): Agent[] {
151
+ if (!agents || agents.length === 0 || !events || events.length === 0) {
152
+ return agents || []
153
+ }
154
+
155
+ const agentEventTypes = new Set<Event['event']>(AGENT_EVENT_TYPES as unknown as Event['event'][] )
156
+
157
+ type AgentEventLite = Agent & {
158
+ agent_id: string
159
+ event: Event['event']
160
+ timestamp?: string | number | null
161
+ }
162
+
163
+ const latestByAgent = new Map<string, AgentEventLite>()
164
+
165
+ for (let i = 0; i < events.length; i++) {
166
+ const event = events[i] as unknown as AgentEventLite
167
+ if (!event || !agentEventTypes.has(event.event)) continue
168
+
169
+ const agentId = event.agent_id
170
+ if (!agentId) continue
171
+
172
+ const previousEvent = latestByAgent.get(agentId)
173
+
174
+ const currentTimestamp = event.timestamp == null ? undefined : Number(event.timestamp)
175
+ const previousTimestamp = previousEvent?.timestamp == null ? undefined : Number(previousEvent.timestamp)
176
+
177
+ const isNewer =
178
+ previousEvent == null ||
179
+ (currentTimestamp != null && previousTimestamp != null && currentTimestamp > previousTimestamp) ||
180
+ (currentTimestamp != null && previousTimestamp == null)
181
+ // If both timestamps are missing, prefer later in the array (current)
182
+
183
+ if (isNewer || (currentTimestamp == null && previousTimestamp == null)) {
184
+ latestByAgent.set(agentId, event)
185
+ }
186
+ }
187
+
188
+ return agents.map((agent) => {
189
+ const latest = latestByAgent.get(agent.name)
190
+ if (!latest) return agent
191
+
192
+ let status = agent.status
193
+ switch (latest.event) {
194
+ case 'agent_started':
195
+ case 'agent_resumed':
196
+ status = 'running'
197
+ break
198
+ case 'agent_interrupted':
199
+ status = 'interrupted'
200
+ break
201
+ case 'agent_cancelled':
202
+ status = 'cancelled'
203
+ break
204
+ case 'agent_completed':
205
+ status = latest.status || 'completed'
206
+ break
207
+ default:
208
+ break
209
+ }
210
+
211
+ return { ...agent, status }
212
+ })
213
+ }
@@ -1,4 +1,19 @@
1
- import { mode, StyleFunctionProps } from '@chakra-ui/theme-tools'
1
+ import {mode, StyleFunctionProps} from '@chakra-ui/theme-tools'
2
+ import {keyframes} from "@chakra-ui/react";
3
+
4
+
5
+ const pulse = keyframes`
6
+ 0% {
7
+ opacity: 1;
8
+ }
9
+ 50% {
10
+ opacity: 0.5;
11
+ }
12
+ 100% {
13
+ opacity: 1;
14
+ }
15
+ `;
16
+
2
17
 
3
18
  export const styles = {
4
19
  global: {
@@ -9,5 +24,8 @@ export const styles = {
9
24
  fontSize: theme.rasaFontSizes.md,
10
25
  letterSpacing: '0.025rem',
11
26
  }),
27
+ '.pulse': {
28
+ animation: `${pulse} 2s infinite`,
29
+ },
12
30
  },
13
31
  }