rasa-pro 3.13.12__py3-none-any.whl → 3.14.0__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 (586) 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 +213 -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 +889 -0
  13. rasa/agents/protocol/mcp/__init__.py +0 -0
  14. rasa/agents/protocol/mcp/mcp_base_agent.py +778 -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 +228 -0
  26. rasa/agents/validation.py +538 -0
  27. rasa/api.py +23 -9
  28. rasa/builder/README.md +120 -0
  29. rasa/builder/__init__.py +0 -0
  30. rasa/builder/auth.py +176 -0
  31. rasa/builder/config.py +96 -0
  32. rasa/builder/copilot/__init__.py +0 -0
  33. rasa/builder/copilot/constants.py +38 -0
  34. rasa/builder/copilot/copilot.py +562 -0
  35. rasa/builder/copilot/copilot_response_handler.py +522 -0
  36. rasa/builder/copilot/copilot_templated_message_provider.py +81 -0
  37. rasa/builder/copilot/exceptions.py +32 -0
  38. rasa/builder/copilot/models.py +690 -0
  39. rasa/builder/copilot/prompts/__init__.py +0 -0
  40. rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +787 -0
  41. rasa/builder/copilot/prompts/copilot_training_error_handler_prompt.jinja2 +53 -0
  42. rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +91 -0
  43. rasa/builder/copilot/signing.py +305 -0
  44. rasa/builder/copilot/telemetry.py +234 -0
  45. rasa/builder/copilot/templated_messages/__init__.py +0 -0
  46. rasa/builder/copilot/templated_messages/copilot_internal_messages_templates.yml +16 -0
  47. rasa/builder/copilot/templated_messages/copilot_templated_responses.yml +41 -0
  48. rasa/builder/copilot/templated_messages/copilot_welcome_messages.yml +56 -0
  49. rasa/builder/document_retrieval/__init__.py +0 -0
  50. rasa/builder/document_retrieval/constants.py +15 -0
  51. rasa/builder/document_retrieval/inkeep-rag-response-schema.json +64 -0
  52. rasa/builder/document_retrieval/inkeep_document_retrieval.py +238 -0
  53. rasa/builder/document_retrieval/models.py +62 -0
  54. rasa/builder/download.py +140 -0
  55. rasa/builder/exceptions.py +91 -0
  56. rasa/builder/guardrails/__init__.py +1 -0
  57. rasa/builder/guardrails/clients.py +256 -0
  58. rasa/builder/guardrails/constants.py +12 -0
  59. rasa/builder/guardrails/exceptions.py +4 -0
  60. rasa/builder/guardrails/models.py +266 -0
  61. rasa/builder/guardrails/policy_checker.py +324 -0
  62. rasa/builder/guardrails/store.py +238 -0
  63. rasa/builder/guardrails/utils.py +94 -0
  64. rasa/builder/job_manager.py +87 -0
  65. rasa/builder/jobs.py +609 -0
  66. rasa/builder/llm_service.py +273 -0
  67. rasa/builder/logging_utils.py +265 -0
  68. rasa/builder/main.py +234 -0
  69. rasa/builder/models.py +229 -0
  70. rasa/builder/project_generator.py +463 -0
  71. rasa/builder/project_info.py +72 -0
  72. rasa/builder/service.py +1367 -0
  73. rasa/builder/shared/tracker_context.py +212 -0
  74. rasa/builder/skill_to_bot_prompt.jinja2 +164 -0
  75. rasa/builder/template_cache.py +69 -0
  76. rasa/builder/training_service.py +188 -0
  77. rasa/builder/validation_service.py +101 -0
  78. rasa/cli/arguments/data.py +9 -0
  79. rasa/cli/arguments/default_arguments.py +12 -0
  80. rasa/cli/arguments/run.py +2 -0
  81. rasa/cli/arguments/train.py +2 -0
  82. rasa/cli/data.py +78 -10
  83. rasa/cli/dialogue_understanding_test.py +11 -7
  84. rasa/cli/e2e_test.py +10 -6
  85. rasa/cli/evaluate.py +4 -2
  86. rasa/cli/export.py +5 -2
  87. rasa/cli/inspect.py +9 -4
  88. rasa/cli/interactive.py +8 -4
  89. rasa/cli/llm_fine_tuning.py +12 -6
  90. rasa/cli/project_templates/basic/README.md +23 -0
  91. rasa/cli/project_templates/basic/actions/__init__ +0 -0
  92. rasa/cli/project_templates/basic/actions/action_human_handoff.py +40 -0
  93. rasa/cli/project_templates/basic/actions/actions.md +10 -0
  94. rasa/cli/project_templates/basic/config.yml +29 -0
  95. rasa/cli/project_templates/basic/credentials.yml +33 -0
  96. rasa/cli/project_templates/basic/data/data.md +8 -0
  97. rasa/cli/project_templates/basic/data/general/feedback.yml +21 -0
  98. rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
  99. rasa/cli/project_templates/basic/data/general/hello.yml +6 -0
  100. rasa/cli/project_templates/basic/data/general/help.yml +6 -0
  101. rasa/cli/project_templates/basic/data/general/human_handoff.yml +16 -0
  102. rasa/cli/project_templates/basic/data/general/show_faqs.yml +6 -0
  103. rasa/cli/project_templates/basic/data/system/patterns/pattern_cannot_handle.yml +7 -0
  104. rasa/cli/project_templates/basic/data/system/patterns/pattern_completed.yml +7 -0
  105. rasa/cli/project_templates/basic/data/system/patterns/pattern_correction.yml +7 -0
  106. rasa/cli/project_templates/basic/data/system/patterns/pattern_search.yml +8 -0
  107. rasa/cli/project_templates/basic/data/system/patterns/pattern_session_start.yml +8 -0
  108. rasa/cli/project_templates/basic/docs/docs.md +5 -0
  109. rasa/cli/project_templates/basic/docs/template.txt +28 -0
  110. rasa/cli/project_templates/basic/domain/domain.md +11 -0
  111. rasa/cli/project_templates/basic/domain/general/feedback.yml +25 -0
  112. rasa/cli/project_templates/basic/domain/general/goodbye.yml +9 -0
  113. rasa/cli/project_templates/basic/domain/general/hello.yml +7 -0
  114. rasa/cli/project_templates/basic/domain/general/help.yml +21 -0
  115. rasa/cli/project_templates/basic/domain/general/human_handoff.yml +32 -0
  116. rasa/cli/project_templates/basic/domain/general/show_faqs.yml +14 -0
  117. rasa/cli/project_templates/basic/domain/system/patterns/pattern_cannot_handle.yml +5 -0
  118. rasa/cli/project_templates/basic/domain/system/patterns/pattern_session_start.yml +19 -0
  119. rasa/cli/project_templates/basic/endpoints.yml +67 -0
  120. rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +38 -0
  121. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
  122. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
  123. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
  124. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/help.yml +8 -0
  125. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/human_handoff.yml +41 -0
  126. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/patterns.yml +32 -0
  127. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/show_faqs.yml +8 -0
  128. rasa/cli/project_templates/default/config.yml +4 -0
  129. rasa/cli/project_templates/default/endpoints.yml +4 -0
  130. rasa/cli/project_templates/defaults.py +1 -0
  131. rasa/cli/project_templates/finance/README.md +26 -0
  132. rasa/cli/project_templates/finance/actions/__init__.py +0 -0
  133. rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
  134. rasa/cli/project_templates/finance/actions/accounts/check_balance.py +18 -0
  135. rasa/cli/project_templates/finance/actions/actions.md +15 -0
  136. rasa/cli/project_templates/finance/actions/cards/__init__.py +0 -0
  137. rasa/cli/project_templates/finance/actions/cards/check_that_card_exists.py +21 -0
  138. rasa/cli/project_templates/finance/actions/cards/list_cards.py +22 -0
  139. rasa/cli/project_templates/finance/actions/contacts/__init__.py +0 -0
  140. rasa/cli/project_templates/finance/actions/contacts/add_contact.py +30 -0
  141. rasa/cli/project_templates/finance/actions/contacts/list_contacts.py +22 -0
  142. rasa/cli/project_templates/finance/actions/contacts/remove_contact.py +35 -0
  143. rasa/cli/project_templates/finance/actions/db.py +117 -0
  144. rasa/cli/project_templates/finance/actions/general/__init__.py +0 -0
  145. rasa/cli/project_templates/finance/actions/general/action_human_handoff.py +49 -0
  146. rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
  147. rasa/cli/project_templates/finance/actions/transfers/check_transfer_funds.py +27 -0
  148. rasa/cli/project_templates/finance/actions/transfers/check_transfer_limit.py +36 -0
  149. rasa/cli/project_templates/finance/actions/transfers/execute_recurrent_payment.py +20 -0
  150. rasa/cli/project_templates/finance/actions/transfers/execute_transfer.py +45 -0
  151. rasa/cli/project_templates/finance/actions/transfers/list_transactions.py +32 -0
  152. rasa/cli/project_templates/finance/config.yml +29 -0
  153. rasa/cli/project_templates/finance/credentials.yml +33 -0
  154. rasa/cli/project_templates/finance/data/accounts/check_balance.yml +9 -0
  155. rasa/cli/project_templates/finance/data/accounts/download_statements.yml +26 -0
  156. rasa/cli/project_templates/finance/data/bills/bill_pay_reminder.yml +25 -0
  157. rasa/cli/project_templates/finance/data/cards/activate_card.yml +35 -0
  158. rasa/cli/project_templates/finance/data/cards/block_card.yml +45 -0
  159. rasa/cli/project_templates/finance/data/cards/list_cards.yml +14 -0
  160. rasa/cli/project_templates/finance/data/cards/replace_card.yml +16 -0
  161. rasa/cli/project_templates/finance/data/cards/replace_eligible_card.yml +29 -0
  162. rasa/cli/project_templates/finance/data/contacts/add_contact.yml +33 -0
  163. rasa/cli/project_templates/finance/data/contacts/list_contacts.yml +14 -0
  164. rasa/cli/project_templates/finance/data/contacts/remove_contact.yml +31 -0
  165. rasa/cli/project_templates/finance/data/data.md +14 -0
  166. rasa/cli/project_templates/finance/data/general/bot_challenge.yml +6 -0
  167. rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
  168. rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
  169. rasa/cli/project_templates/finance/data/general/hello.yml +6 -0
  170. rasa/cli/project_templates/finance/data/general/help.yml +9 -0
  171. rasa/cli/project_templates/finance/data/general/human_handoff.yml +16 -0
  172. rasa/cli/project_templates/finance/data/general/welcome.yml +9 -0
  173. rasa/cli/project_templates/finance/data/system/patterns/pattern_completed.yml +7 -0
  174. rasa/cli/project_templates/finance/data/system/patterns/pattern_correction.yml +7 -0
  175. rasa/cli/project_templates/finance/data/system/patterns/pattern_search.yml +8 -0
  176. rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +8 -0
  177. rasa/cli/project_templates/finance/data/transfers/check_transfer_limit.yml +18 -0
  178. rasa/cli/project_templates/finance/data/transfers/list_transactions.yml +46 -0
  179. rasa/cli/project_templates/finance/data/transfers/move_money_between_accounts.yml +51 -0
  180. rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +34 -0
  181. rasa/cli/project_templates/finance/data/transfers/transfer_money_to_a_third_party.yml +175 -0
  182. rasa/cli/project_templates/finance/db/cards.json +18 -0
  183. rasa/cli/project_templates/finance/db/contacts.json +10 -0
  184. rasa/cli/project_templates/finance/db/my_account.json +6 -0
  185. rasa/cli/project_templates/finance/db/transactions.json +22 -0
  186. rasa/cli/project_templates/finance/docs/docs.md +8 -0
  187. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/budgeting_analytics.txt +22 -0
  188. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/multi_currency_accounts.txt +19 -0
  189. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/premium_benefits.txt +19 -0
  190. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/contactless_limits.txt +16 -0
  191. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/freeze_unfreeze_card.txt +16 -0
  192. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/lost_stolen_card.txt +19 -0
  193. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/money_transfers/instant_payments.txt +19 -0
  194. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/money_transfers/international_transfers.txt +19 -0
  195. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/security_fraud/fraud_protection.txt +22 -0
  196. rasa/cli/project_templates/finance/docs/fenlo_banking_faq/security_fraud/secure_payments.txt +22 -0
  197. rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +15 -0
  198. rasa/cli/project_templates/finance/domain/accounts/download_statements.yml +40 -0
  199. rasa/cli/project_templates/finance/domain/bills/bill_pay_reminder.yml +49 -0
  200. rasa/cli/project_templates/finance/domain/cards/activate_card.yml +24 -0
  201. rasa/cli/project_templates/finance/domain/cards/block_card.yml +44 -0
  202. rasa/cli/project_templates/finance/domain/cards/list_cards.yml +16 -0
  203. rasa/cli/project_templates/finance/domain/cards/replace_card.yml +43 -0
  204. rasa/cli/project_templates/finance/domain/cards/shared.yml +15 -0
  205. rasa/cli/project_templates/finance/domain/contacts/add_contact.yml +37 -0
  206. rasa/cli/project_templates/finance/domain/contacts/list_contacts.yml +16 -0
  207. rasa/cli/project_templates/finance/domain/contacts/remove_contact.yml +32 -0
  208. rasa/cli/project_templates/finance/domain/domain.md +18 -0
  209. rasa/cli/project_templates/finance/domain/general/_shared.yml +39 -0
  210. rasa/cli/project_templates/finance/domain/general/bot_challenge.yml +4 -0
  211. rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +8 -0
  212. rasa/cli/project_templates/finance/domain/general/feedback.yml +25 -0
  213. rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
  214. rasa/cli/project_templates/finance/domain/general/help.yml +0 -0
  215. rasa/cli/project_templates/finance/domain/general/human_handoff.yml +31 -0
  216. rasa/cli/project_templates/finance/domain/general/welcome.yml +39 -0
  217. rasa/cli/project_templates/finance/domain/transfers/check_transfer_limit.yml +32 -0
  218. rasa/cli/project_templates/finance/domain/transfers/list_transactions.yml +44 -0
  219. rasa/cli/project_templates/finance/domain/transfers/shared.yml +17 -0
  220. rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +221 -0
  221. rasa/cli/project_templates/finance/endpoints.yml +67 -0
  222. rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +38 -0
  223. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/accounts/check_balance.yml +9 -0
  224. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/accounts/download_statements.yml +43 -0
  225. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/cards/block_card.yml +55 -0
  226. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/bot_challenge.yml +8 -0
  227. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
  228. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
  229. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
  230. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/human_handoff.yml +35 -0
  231. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/patterns.yml +22 -0
  232. rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/transfers/transfer_money.yml +56 -0
  233. rasa/cli/project_templates/telco/README.md +25 -0
  234. rasa/cli/project_templates/telco/actions/__init__.py +0 -0
  235. rasa/cli/project_templates/telco/actions/actions.md +12 -0
  236. rasa/cli/project_templates/telco/actions/billing/__init__.py +0 -0
  237. rasa/cli/project_templates/telco/actions/billing/actions_billing.py +204 -0
  238. rasa/cli/project_templates/telco/actions/general/__init__.py +0 -0
  239. rasa/cli/project_templates/telco/actions/general/action_human_handoff.py +49 -0
  240. rasa/cli/project_templates/telco/actions/network/__init__.py +0 -0
  241. rasa/cli/project_templates/telco/actions/network/actions_get_data_from_db.py +48 -0
  242. rasa/cli/project_templates/telco/actions/network/actions_run_diagnostics.py +28 -0
  243. rasa/cli/project_templates/telco/actions/network/actions_session_start.py +18 -0
  244. rasa/cli/project_templates/telco/config.yml +29 -0
  245. rasa/cli/project_templates/telco/credentials.yml +33 -0
  246. rasa/cli/project_templates/telco/csvs/billing.csv +19 -0
  247. rasa/cli/project_templates/telco/csvs/customers.csv +5 -0
  248. rasa/cli/project_templates/telco/data/billing/flow_understand_bill.yml +45 -0
  249. rasa/cli/project_templates/telco/data/data.md +11 -0
  250. rasa/cli/project_templates/telco/data/general/bot_challenge.yml +6 -0
  251. rasa/cli/project_templates/telco/data/general/feedback.yml +20 -0
  252. rasa/cli/project_templates/telco/data/general/goodbye.yml +6 -0
  253. rasa/cli/project_templates/telco/data/general/hello.yml +6 -0
  254. rasa/cli/project_templates/telco/data/general/human_handoff.yml +16 -0
  255. rasa/cli/project_templates/telco/data/general/patterns.yml +30 -0
  256. rasa/cli/project_templates/telco/data/network/flow_reboot_router.yml +8 -0
  257. rasa/cli/project_templates/telco/data/network/flow_reset_router.yml +7 -0
  258. rasa/cli/project_templates/telco/data/network/flow_solve_internet_issue.yml +73 -0
  259. rasa/cli/project_templates/telco/docs/docs.md +8 -0
  260. rasa/cli/project_templates/telco/docs/network/reset_vs_rboot_router.txt +1 -0
  261. rasa/cli/project_templates/telco/docs/network/restart_router.txt +6 -0
  262. rasa/cli/project_templates/telco/docs/network/run_speed_test.txt +6 -0
  263. rasa/cli/project_templates/telco/domain/billing/understand_bill.yml +102 -0
  264. rasa/cli/project_templates/telco/domain/domain.md +13 -0
  265. rasa/cli/project_templates/telco/domain/general/bot_challenge.yml +4 -0
  266. rasa/cli/project_templates/telco/domain/general/feedback.yml +25 -0
  267. rasa/cli/project_templates/telco/domain/general/goodbye.yml +7 -0
  268. rasa/cli/project_templates/telco/domain/general/hello.yml +5 -0
  269. rasa/cli/project_templates/telco/domain/general/human_handoff.yml +26 -0
  270. rasa/cli/project_templates/telco/domain/general/patterns.yml +33 -0
  271. rasa/cli/project_templates/telco/domain/network/reboot_router.yml +21 -0
  272. rasa/cli/project_templates/telco/domain/network/reset_router.yml +12 -0
  273. rasa/cli/project_templates/telco/domain/network/run_speed_test.yml +25 -0
  274. rasa/cli/project_templates/telco/domain/network/solve_internet_issue.yml +74 -0
  275. rasa/cli/project_templates/telco/domain/shared.yml +129 -0
  276. rasa/cli/project_templates/telco/endpoints.yml +67 -0
  277. rasa/cli/project_templates/telco/prompts/rephraser_demo_personality_prompt.jinja2 +40 -0
  278. rasa/cli/project_templates/telco/tests/e2e_test_cases/with_stub/network/solve_internet_not_slow.yml +33 -0
  279. rasa/cli/project_templates/telco/tests/e2e_test_cases/with_stub/network/solve_internet_slow.yml +47 -0
  280. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/billing/understand_bill.yml +67 -0
  281. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/bot_challenge.yml +8 -0
  282. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
  283. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
  284. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
  285. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/human_handoff.yml +35 -0
  286. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/patterns.yml +23 -0
  287. rasa/cli/project_templates/tutorial/config.yml +2 -1
  288. rasa/cli/project_templates/tutorial/credentials.yml +10 -0
  289. rasa/cli/run.py +8 -10
  290. rasa/cli/scaffold.py +50 -6
  291. rasa/cli/shell.py +10 -5
  292. rasa/cli/studio/studio.py +1 -1
  293. rasa/cli/test.py +34 -14
  294. rasa/cli/train.py +44 -30
  295. rasa/cli/utils.py +1 -393
  296. rasa/cli/validation/__init__.py +0 -0
  297. rasa/cli/validation/bot_config.py +232 -0
  298. rasa/cli/validation/config_path_validation.py +257 -0
  299. rasa/cli/x.py +8 -4
  300. rasa/constants.py +7 -1
  301. rasa/core/actions/action.py +53 -13
  302. rasa/core/actions/action_exceptions.py +1 -1
  303. rasa/core/actions/action_run_slot_rejections.py +1 -1
  304. rasa/core/actions/grpc_custom_action_executor.py +1 -1
  305. rasa/core/agent.py +22 -2
  306. rasa/core/available_agents.py +239 -0
  307. rasa/core/brokers/broker.py +1 -1
  308. rasa/core/brokers/kafka.py +56 -8
  309. rasa/core/channels/__init__.py +82 -35
  310. rasa/core/channels/channel.py +4 -3
  311. rasa/core/channels/constants.py +3 -0
  312. rasa/core/channels/development_inspector.py +29 -16
  313. rasa/core/channels/hangouts.py +2 -2
  314. rasa/core/channels/inspector/README.md +25 -13
  315. rasa/core/channels/inspector/dist/assets/{arc-0b11fe30.js → arc-6177260a.js} +1 -1
  316. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-9eef30a7.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
  317. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-03e94f28.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
  318. rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
  319. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-95c09eba.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
  320. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-38e8446c.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
  321. rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
  322. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-57dc3038.js → createText-2e5e7dd3-088372e2.js} +1 -1
  323. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-4bac0545.js → edges-e0da2a9e-58676240.js} +1 -1
  324. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-81795c90.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
  325. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-89489ae6.js → flowDb-956e92f1-ea63f85c.js} +1 -1
  326. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-cd152627.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
  327. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
  328. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-3da369bc.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
  329. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-85ec16f8.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
  330. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-495bc140.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
  331. rasa/core/channels/inspector/dist/assets/{graph-1ec4d266.js → graph-0a6f8466.js} +1 -1
  332. rasa/core/channels/inspector/dist/assets/{index-3862675e-0a0e97c9.js → index-3862675e-7610671a.js} +1 -1
  333. rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
  334. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-4d54bcde.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
  335. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-dc097114.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
  336. rasa/core/channels/inspector/dist/assets/{layout-1a08981e.js → layout-e7fbc2bf.js} +1 -1
  337. rasa/core/channels/inspector/dist/assets/{line-95f7f1d3.js → line-a8aa457c.js} +1 -1
  338. rasa/core/channels/inspector/dist/assets/{linear-97e69543.js → linear-3351e0d2.js} +1 -1
  339. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-8c71ff03.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
  340. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-f14c71c7.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
  341. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-f1d3c9ff.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
  342. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-bfa2412f.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
  343. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-53f2c97b.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
  344. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-319d7c0e.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
  345. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-76a09418.js → stateDiagram-587899a1-0e770395.js} +1 -1
  346. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-a67f15d4.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
  347. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0654e7c3.js → styles-6aaf32cf-36a9e70d.js} +1 -1
  348. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-1394bb9d.js → styles-9a916d00-884a8b5b.js} +1 -1
  349. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-e4c5bdae.js → styles-c10674c1-dc097813.js} +1 -1
  350. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-50957104.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
  351. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-b0885a6a.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
  352. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-79e6541a.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
  353. rasa/core/channels/inspector/dist/index.html +1 -1
  354. rasa/core/channels/inspector/package.json +18 -18
  355. rasa/core/channels/inspector/src/App.tsx +56 -12
  356. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +1 -1
  357. rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
  358. rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
  359. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +20 -3
  360. rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +296 -0
  361. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -2
  362. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +26 -4
  363. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
  364. rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
  365. rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
  366. rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
  367. rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
  368. rasa/core/channels/inspector/src/types.ts +55 -1
  369. rasa/core/channels/inspector/yarn.lock +336 -189
  370. rasa/core/channels/socketio.py +212 -51
  371. rasa/core/channels/studio_chat.py +82 -32
  372. rasa/core/channels/telegram.py +4 -9
  373. rasa/core/channels/voice_ready/twilio_voice.py +1 -1
  374. rasa/core/channels/voice_stream/asr/asr_event.py +1 -1
  375. rasa/core/channels/voice_stream/asr/azure.py +6 -3
  376. rasa/core/channels/voice_stream/asr/deepgram.py +1 -1
  377. rasa/core/channels/voice_stream/audiocodes.py +11 -6
  378. rasa/core/channels/voice_stream/browser_audio.py +91 -4
  379. rasa/core/channels/voice_stream/call_state.py +13 -2
  380. rasa/core/channels/voice_stream/genesys.py +19 -15
  381. rasa/core/channels/voice_stream/jambonz.py +22 -12
  382. rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
  383. rasa/core/channels/voice_stream/twilio_media_streams.py +35 -14
  384. rasa/core/channels/voice_stream/util.py +11 -1
  385. rasa/core/channels/voice_stream/voice_channel.py +170 -32
  386. rasa/core/concurrent_lock_store.py +83 -16
  387. rasa/core/config/__init__.py +0 -0
  388. rasa/core/{available_endpoints.py → config/available_endpoints.py} +56 -18
  389. rasa/core/config/configuration.py +295 -0
  390. rasa/core/config/credentials.py +19 -0
  391. rasa/core/config/message_procesing_config.py +34 -0
  392. rasa/core/constants.py +17 -0
  393. rasa/core/exceptions.py +1 -1
  394. rasa/core/featurizers/tracker_featurizers.py +3 -2
  395. rasa/core/iam_credentials_providers/__init__.py +0 -0
  396. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +291 -0
  397. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +91 -0
  398. rasa/core/lock_store.py +50 -10
  399. rasa/core/nlg/contextual_response_rephraser.py +5 -0
  400. rasa/core/nlg/generator.py +1 -1
  401. rasa/core/persistor.py +7 -7
  402. rasa/core/policies/enterprise_search_policy.py +9 -10
  403. rasa/core/policies/flow_policy.py +4 -4
  404. rasa/core/policies/flows/agent_executor.py +720 -0
  405. rasa/core/policies/flows/flow_exceptions.py +5 -2
  406. rasa/core/policies/flows/flow_executor.py +146 -77
  407. rasa/core/policies/flows/mcp_tool_executor.py +304 -0
  408. rasa/core/policies/intentless_policy.py +1 -1
  409. rasa/core/policies/rule_policy.py +1 -1
  410. rasa/core/policies/ted_policy.py +20 -12
  411. rasa/core/policies/unexpected_intent_policy.py +6 -0
  412. rasa/core/processor.py +100 -44
  413. rasa/core/redis_connection_factory.py +474 -0
  414. rasa/core/run.py +49 -10
  415. rasa/core/test.py +4 -0
  416. rasa/core/tracker_stores/redis_tracker_store.py +36 -14
  417. rasa/core/tracker_stores/sql_tracker_store.py +59 -1
  418. rasa/core/tracker_stores/tracker_store.py +3 -7
  419. rasa/core/train.py +1 -1
  420. rasa/core/training/interactive.py +20 -18
  421. rasa/core/training/story_conflict.py +5 -5
  422. rasa/core/utils.py +22 -23
  423. rasa/dialogue_understanding/commands/__init__.py +8 -0
  424. rasa/dialogue_understanding/commands/cancel_flow_command.py +20 -6
  425. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
  426. rasa/dialogue_understanding/commands/clarify_command.py +20 -2
  427. rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
  428. rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
  429. rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
  430. rasa/dialogue_understanding/commands/start_flow_command.py +75 -7
  431. rasa/dialogue_understanding/commands/utils.py +135 -2
  432. rasa/dialogue_understanding/generator/command_parser.py +4 -0
  433. rasa/dialogue_understanding/generator/flow_retrieval.py +0 -9
  434. rasa/dialogue_understanding/generator/llm_based_command_generator.py +52 -12
  435. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  436. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
  437. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
  438. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
  439. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
  440. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
  441. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
  442. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
  443. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
  444. rasa/dialogue_understanding/patterns/cancel.py +27 -6
  445. rasa/dialogue_understanding/patterns/clarify.py +3 -14
  446. rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
  447. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +49 -9
  448. rasa/dialogue_understanding/processor/command_processor.py +136 -15
  449. rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
  450. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
  451. rasa/dialogue_understanding/stack/utils.py +57 -3
  452. rasa/dialogue_understanding/utils.py +24 -4
  453. rasa/dialogue_understanding_test/du_test_runner.py +8 -3
  454. rasa/e2e_test/e2e_test_runner.py +13 -3
  455. rasa/engine/caching.py +2 -2
  456. rasa/engine/constants.py +1 -1
  457. rasa/engine/graph.py +5 -1
  458. rasa/engine/loader.py +12 -0
  459. rasa/engine/recipes/default_components.py +138 -49
  460. rasa/engine/recipes/default_recipe.py +108 -11
  461. rasa/engine/runner/dask.py +8 -5
  462. rasa/engine/validation.py +25 -8
  463. rasa/graph_components/validators/default_recipe_validator.py +86 -28
  464. rasa/hooks.py +5 -5
  465. rasa/llm_fine_tuning/utils.py +2 -2
  466. rasa/model_manager/model_api.py +4 -5
  467. rasa/model_manager/runner_service.py +2 -2
  468. rasa/model_manager/socket_bridge.py +21 -17
  469. rasa/model_manager/trainer_service.py +12 -9
  470. rasa/model_manager/utils.py +1 -29
  471. rasa/model_manager/warm_rasa_process.py +13 -3
  472. rasa/model_training.py +60 -47
  473. rasa/nlu/classifiers/diet_classifier.py +198 -98
  474. rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
  475. rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
  476. rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
  477. rasa/nlu/extractors/crf_entity_extractor.py +9 -10
  478. rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
  479. rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
  480. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
  481. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
  482. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
  483. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
  484. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
  485. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
  486. rasa/nlu/selectors/response_selector.py +10 -2
  487. rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
  488. rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
  489. rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
  490. rasa/nlu/utils/mitie_utils.py +3 -0
  491. rasa/nlu/utils/spacy_utils.py +3 -2
  492. rasa/plugin.py +8 -8
  493. rasa/privacy/privacy_config.py +1 -1
  494. rasa/privacy/privacy_manager.py +12 -3
  495. rasa/server.py +15 -3
  496. rasa/shared/agents/__init__.py +0 -0
  497. rasa/shared/agents/auth/__init__.py +0 -0
  498. rasa/shared/agents/auth/agent_auth_factory.py +105 -0
  499. rasa/shared/agents/auth/agent_auth_manager.py +92 -0
  500. rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
  501. rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
  502. rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
  503. rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
  504. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +170 -0
  505. rasa/shared/agents/auth/constants.py +13 -0
  506. rasa/shared/agents/auth/types.py +12 -0
  507. rasa/shared/agents/auth/utils.py +85 -0
  508. rasa/shared/agents/utils.py +35 -0
  509. rasa/shared/constants.py +11 -0
  510. rasa/shared/core/constants.py +17 -1
  511. rasa/shared/core/domain.py +62 -22
  512. rasa/shared/core/events.py +329 -0
  513. rasa/shared/core/flows/constants.py +5 -0
  514. rasa/shared/core/flows/flow.py +1 -1
  515. rasa/shared/core/flows/flow_step.py +7 -1
  516. rasa/shared/core/flows/flows_list.py +21 -5
  517. rasa/shared/core/flows/flows_yaml_schema.json +119 -184
  518. rasa/shared/core/flows/steps/call.py +57 -6
  519. rasa/shared/core/flows/steps/collect.py +98 -13
  520. rasa/shared/core/flows/validation.py +372 -8
  521. rasa/shared/core/flows/yaml_flows_io.py +19 -10
  522. rasa/shared/core/slots.py +6 -2
  523. rasa/shared/core/trackers.py +5 -2
  524. rasa/shared/core/training_data/story_reader/story_reader.py +1 -1
  525. rasa/shared/exceptions.py +39 -2
  526. rasa/shared/importers/importer.py +6 -0
  527. rasa/shared/importers/rasa.py +1 -1
  528. rasa/shared/importers/utils.py +86 -4
  529. rasa/shared/nlu/training_data/schemas/responses.yml +3 -0
  530. rasa/shared/providers/llm/_base_litellm_client.py +41 -9
  531. rasa/shared/providers/llm/litellm_router_llm_client.py +10 -6
  532. rasa/shared/providers/llm/llm_client.py +7 -3
  533. rasa/shared/providers/llm/llm_response.py +66 -0
  534. rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
  535. rasa/shared/utils/common.py +26 -1
  536. rasa/shared/utils/health_check/health_check.py +7 -3
  537. rasa/shared/utils/llm.py +92 -19
  538. rasa/shared/utils/mcp/__init__.py +0 -0
  539. rasa/shared/utils/mcp/server_connection.py +250 -0
  540. rasa/shared/utils/mcp/utils.py +20 -0
  541. rasa/shared/utils/schemas/events.py +42 -0
  542. rasa/shared/utils/yaml.py +3 -1
  543. rasa/studio/download.py +3 -0
  544. rasa/studio/prompts.py +1 -0
  545. rasa/studio/pull/pull.py +3 -2
  546. rasa/studio/train.py +8 -7
  547. rasa/studio/upload.py +19 -52
  548. rasa/telemetry.py +166 -28
  549. rasa/tracing/config.py +45 -12
  550. rasa/tracing/constants.py +14 -0
  551. rasa/tracing/instrumentation/attribute_extractors.py +142 -9
  552. rasa/tracing/instrumentation/instrumentation.py +626 -21
  553. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
  554. rasa/tracing/instrumentation/metrics.py +32 -0
  555. rasa/tracing/metric_instrument_provider.py +68 -0
  556. rasa/utils/common.py +92 -1
  557. rasa/utils/endpoints.py +11 -2
  558. rasa/utils/io.py +27 -9
  559. rasa/utils/json_utils.py +6 -1
  560. rasa/utils/log_utils.py +121 -7
  561. rasa/utils/ml_utils.py +1 -1
  562. rasa/utils/openapi.py +144 -0
  563. rasa/utils/plotting.py +1 -1
  564. rasa/utils/pypred.py +45 -0
  565. rasa/utils/tensorflow/__init__.py +7 -0
  566. rasa/utils/tensorflow/callback.py +136 -101
  567. rasa/utils/tensorflow/crf.py +1 -1
  568. rasa/utils/tensorflow/data_generator.py +21 -8
  569. rasa/utils/tensorflow/layers.py +21 -11
  570. rasa/utils/tensorflow/metrics.py +7 -3
  571. rasa/utils/tensorflow/models.py +56 -8
  572. rasa/utils/tensorflow/rasa_layers.py +8 -6
  573. rasa/utils/tensorflow/transformer.py +2 -3
  574. rasa/utils/train_utils.py +54 -24
  575. rasa/validator.py +149 -16
  576. rasa/version.py +1 -1
  577. rasa_pro-3.14.0.dist-info/METADATA +212 -0
  578. {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/RECORD +581 -269
  579. rasa/core/channels/inspector/dist/assets/channel-51d02e9e.js +0 -1
  580. rasa/core/channels/inspector/dist/assets/clone-cc738fa6.js +0 -1
  581. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-0c716443.js +0 -1
  582. rasa/core/channels/inspector/dist/assets/index-c804b295.js +0 -1335
  583. rasa_pro-3.13.12.dist-info/METADATA +0 -192
  584. {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/NOTICE +0 -0
  585. {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/WHEEL +0 -0
  586. {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,296 @@
1
+ import {
2
+ Box,
3
+ Flex,
4
+ FlexProps,
5
+ Table,
6
+ Tbody,
7
+ Td,
8
+ Text,
9
+ Tooltip,
10
+ Tr,
11
+ useColorModeValue,
12
+ } from '@chakra-ui/react'
13
+ import { useOurTheme } from '../theme'
14
+ import {
15
+ isRasaLatency,
16
+ isVoiceLatency,
17
+ RasaLatency,
18
+ VoiceLatency,
19
+ } from '../types'
20
+
21
+ interface MinimalDisplayProps extends FlexProps {
22
+ latency: RasaLatency
23
+ }
24
+
25
+ /**
26
+ * Simple latency display for text-only conversations.
27
+ * Shows a single response time value.
28
+ */
29
+ const MinimalDisplay = ({ latency, sx, ...props }: MinimalDisplayProps) => {
30
+ const containerSx = {
31
+ ...sx,
32
+ display: 'flex',
33
+ alignItems: 'center',
34
+ }
35
+
36
+ const getLatencyColor = (latency: number) => {
37
+ if (latency < 1500) return 'green.500'
38
+ if (latency < 2500) return 'orange.500'
39
+ return 'red.500'
40
+ }
41
+
42
+ const value = Math.round(
43
+ (latency.command_processor || 0) + (latency.prediction_loop || 0),
44
+ )
45
+ const color = getLatencyColor(value)
46
+
47
+ return (
48
+ <Flex sx={containerSx} {...props}>
49
+ <Text fontSize="md" color={useColorModeValue('gray.700', 'gray.300')}>
50
+ Response latency:
51
+ <Text as="span" ml={2} fontWeight="bold" color={color}>
52
+ {value}ms
53
+ </Text>
54
+ </Text>
55
+ </Flex>
56
+ )
57
+ }
58
+
59
+ interface WaterfallDisplayProps extends FlexProps {
60
+ latency: VoiceLatency
61
+ }
62
+
63
+ /**
64
+ * Detailed latency waterfall chart for voice conversations.
65
+ * Displays processing times for ASR, Rasa, and TTS components.
66
+ */
67
+ const WaterfallDisplay = ({ latency, sx, ...props }: WaterfallDisplayProps) => {
68
+ const { rasaSpace } = useOurTheme()
69
+
70
+ const containerSx = {
71
+ ...sx,
72
+ flexDirection: 'column',
73
+ gap: rasaSpace[1],
74
+ }
75
+
76
+ const headerSx = {
77
+ fontSize: 'sm',
78
+ fontWeight: 'bold',
79
+ color: useColorModeValue('gray.700', 'gray.300'),
80
+ }
81
+
82
+ const waterfallBarSx = {
83
+ height: '24px',
84
+ borderRadius: '4px',
85
+ overflow: 'hidden',
86
+ border: '1px solid',
87
+ borderColor: useColorModeValue('gray.200', 'gray.600'),
88
+ }
89
+
90
+ const legendTableSx = {
91
+ size: 'sm',
92
+ mt: rasaSpace[0.5],
93
+ }
94
+
95
+ const getLatencyColor = (type: string) => {
96
+ const colors: { [key: string]: string } = {
97
+ asr: 'blue.500',
98
+ rasa: 'purple.500',
99
+ tts_first: 'orange.500',
100
+ tts_complete: 'green.500',
101
+ }
102
+ return colors[type] || 'gray.500'
103
+ }
104
+
105
+ const getLatencyDescription = (type: string) => {
106
+ const descriptions: { [key: string]: string } = {
107
+ asr: 'Time from the first Partial Transcript event to the Final Transcript event from Speech Recognition. It also includes the time taken by the user to speak.',
108
+ rasa: 'Time taken by Rasa to process the text from the Final Transcript event from Speech Recognition until a text response is generated.',
109
+ tts_first:
110
+ 'Time between the request sent to Text-to-Speech processing and the first byte of audio received by Rasa.',
111
+ tts_complete:
112
+ 'Time taken by Text-to-Speech to complete audio generation. It depends on the length of the text and could overlap with the Bot speaking time.',
113
+ }
114
+ return descriptions[type] || ''
115
+ }
116
+
117
+ // Metrics for proportional display (only actual processing latencies)
118
+ const chartMetrics = [
119
+ latency.asr_latency_ms && {
120
+ type: 'asr',
121
+ label: 'ASR',
122
+ value: latency.asr_latency_ms,
123
+ },
124
+ latency.rasa_processing_latency_ms && {
125
+ type: 'rasa',
126
+ label: 'Rasa',
127
+ value: latency.rasa_processing_latency_ms,
128
+ },
129
+ latency.tts_complete_latency_ms && {
130
+ type: 'tts_complete',
131
+ label: 'TTS',
132
+ value: latency.tts_complete_latency_ms,
133
+ },
134
+ ].filter(Boolean)
135
+
136
+ // All metrics for legend display
137
+ const allMetrics = [
138
+ latency.asr_latency_ms && {
139
+ type: 'asr',
140
+ label: 'ASR',
141
+ value: latency.asr_latency_ms,
142
+ },
143
+ latency.rasa_processing_latency_ms && {
144
+ type: 'rasa',
145
+ label: 'Rasa',
146
+ value: latency.rasa_processing_latency_ms,
147
+ },
148
+ latency.tts_first_byte_latency_ms && {
149
+ type: 'tts_first',
150
+ label: 'TTS First Byte',
151
+ value: latency.tts_first_byte_latency_ms,
152
+ },
153
+ latency.tts_complete_latency_ms && {
154
+ type: 'tts_complete',
155
+ label: 'TTS Complete',
156
+ value: latency.tts_complete_latency_ms,
157
+ },
158
+ ].filter(Boolean)
159
+
160
+ // Calculate total for proportional sizing (only processing latencies)
161
+ const totalLatency = chartMetrics.reduce(
162
+ (sum: number, metric: any) => sum + metric.value,
163
+ 0,
164
+ )
165
+
166
+ // Calculate total latency for title (Rasa + TTS First Byte)
167
+ const totalDisplayLatency =
168
+ (latency.rasa_processing_latency_ms || 0) +
169
+ (latency.tts_first_byte_latency_ms || 0)
170
+
171
+ return (
172
+ <Flex sx={containerSx} {...props}>
173
+ <Text sx={headerSx}>
174
+ Response latency: ~{Math.round(totalDisplayLatency)}ms
175
+ </Text>
176
+
177
+ {/* Waterfall Bar */}
178
+ <Box>
179
+ <Flex sx={waterfallBarSx}>
180
+ {chartMetrics.map((metric: any) => {
181
+ const widthPercentage =
182
+ totalLatency > 0 ? (metric.value / totalLatency) * 100 : 0
183
+ return (
184
+ <Tooltip
185
+ key={metric.type}
186
+ label={
187
+ <Box>
188
+ <Text fontWeight="bold">
189
+ {metric.label}: {Math.round(metric.value)}ms
190
+ </Text>
191
+ <Text fontSize="xs" mt={1}>
192
+ {getLatencyDescription(metric.type)}
193
+ </Text>
194
+ </Box>
195
+ }
196
+ hasArrow
197
+ placement="top"
198
+ >
199
+ <Box
200
+ bg={getLatencyColor(metric.type)}
201
+ width={`${widthPercentage}%`}
202
+ height="100%"
203
+ minWidth="40px" // Increased minimum width for better visibility
204
+ cursor="pointer"
205
+ _hover={{ opacity: 0.8 }}
206
+ />
207
+ </Tooltip>
208
+ )
209
+ })}
210
+ </Flex>
211
+
212
+ {/* Legend */}
213
+ <Table sx={legendTableSx}>
214
+ <Tbody>
215
+ {/* Split metrics into pairs for 2x2 table */}
216
+ {Array.from(
217
+ { length: Math.ceil(allMetrics.length / 2) },
218
+ (_, rowIndex) => (
219
+ <Tr key={rowIndex}>
220
+ {allMetrics
221
+ .slice(rowIndex * 2, rowIndex * 2 + 2)
222
+ .map((metric: any) => (
223
+ <Td key={metric.type} p={rasaSpace[0.25]} border="none">
224
+ <Flex align="center" gap={rasaSpace[0.25]}>
225
+ <Box
226
+ width="8px"
227
+ height="8px"
228
+ bg={getLatencyColor(metric.type)}
229
+ borderRadius="2px"
230
+ flexShrink={0}
231
+ />
232
+ <Text
233
+ fontSize="xs"
234
+ color={useColorModeValue('gray.600', 'gray.400')}
235
+ noOfLines={1}
236
+ >
237
+ {metric.label}: {Math.round(metric.value)}ms
238
+ </Text>
239
+ </Flex>
240
+ </Td>
241
+ ))}
242
+ {/* Fill empty cell if odd number of metrics */}
243
+ {allMetrics.length % 2 !== 0 &&
244
+ rowIndex === Math.ceil(allMetrics.length / 2) - 1 && (
245
+ <Td p={rasaSpace[0.25]} border="none" />
246
+ )}
247
+ </Tr>
248
+ ),
249
+ )}
250
+ </Tbody>
251
+ </Table>
252
+ </Box>
253
+ </Flex>
254
+ )
255
+ }
256
+
257
+ interface LatencyDisplayProps extends FlexProps {
258
+ voiceLatency?: any
259
+ rasaLatency?: any
260
+ }
261
+
262
+ /**
263
+ * Displays processing latency information for the conversation.
264
+ * Shows either a detailed waterfall chart for voice conversations or
265
+ * a simpler display for text-only conversations.
266
+ */
267
+ export const LatencyDisplay = ({
268
+ sx,
269
+ voiceLatency,
270
+ rasaLatency,
271
+ ...props
272
+ }: LatencyDisplayProps) => {
273
+ // We give priority to voice latency as most comprehensive.
274
+ if (isVoiceLatency(voiceLatency)) {
275
+ return <WaterfallDisplay latency={voiceLatency} sx={sx} {...props} />
276
+ }
277
+
278
+ // If voice latency is not available, we use rasa latency.
279
+ if (isRasaLatency(rasaLatency)) {
280
+ return <MinimalDisplay latency={rasaLatency} sx={sx} {...props} />
281
+ }
282
+
283
+ // If rasa latency is not available, we are either waiting for first data from voice stream or the conversation is not started yet.
284
+ if (!rasaLatency) {
285
+ return <Text>Rasa latency data is not available yet</Text>
286
+ }
287
+
288
+ // If rasa latency is available but did not pass type guard, we are in an unexpected state
289
+ // and we should log an error but gracefully fallback to showing no data.
290
+ console.warn(
291
+ `Latency data has unexpected format. Raw data of rasaLatency: ${rasaLatency},
292
+ raw data of voice latency: ${voiceLatency}`,
293
+ )
294
+
295
+ return <Text>Latency data is not available yet</Text>
296
+ }
@@ -8,7 +8,11 @@ import {
8
8
  import { useOurTheme } from '../theme'
9
9
  import { createAudioConnection } from '../helpers/audio/audiostream.ts'
10
10
 
11
- export const LoadingSpinner = () => {
11
+ interface LoadingSpinnerProps {
12
+ onLatencyUpdate?: (latency: any) => void
13
+ }
14
+
15
+ export const LoadingSpinner = ({ onLatencyUpdate }: LoadingSpinnerProps) => {
12
16
  const { rasaSpace } = useOurTheme()
13
17
  const isVoice = window.location.href.includes('browser_audio')
14
18
  const text = isVoice
@@ -27,7 +31,7 @@ export const LoadingSpinner = () => {
27
31
  {isVoice ? (
28
32
  <Button
29
33
  onClick={async () =>
30
- await createAudioConnection(window.location.href)
34
+ await createAudioConnection(window.location.href, onLatencyUpdate)
31
35
  }
32
36
  >
33
37
  Go
@@ -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
@@ -52,6 +52,7 @@ interface AudioQueue {
52
52
  addMarker: (id: string) => void
53
53
  reduceMarkers: (bytesRead: number) => void
54
54
  popMarkers: () => void
55
+ clear: () => void
55
56
  }
56
57
 
57
58
  const createAudioQueue = (socket: WebSocket): AudioQueue => {
@@ -108,6 +109,14 @@ const createAudioQueue = (socket: WebSocket): AudioQueue => {
108
109
  }
109
110
  })
110
111
  },
112
+
113
+ /**
114
+ * Clears the audio queue, removing all buffered audio and markers.
115
+ */
116
+ clear: function () {
117
+ this.buffer = new Float32Array(0)
118
+ this.marks = []
119
+ },
111
120
  }
112
121
  }
113
122
 
@@ -187,7 +196,8 @@ const setupAudioPlayback = async (socket: WebSocket): Promise<AudioQueue> => {
187
196
  }
188
197
 
189
198
  const addDataToAudioQueue =
190
- (audioQueue: AudioQueue) => (message: MessageEvent<any>) => {
199
+ (audioQueue: AudioQueue, onLatencyUpdate?: (latency: any) => void) =>
200
+ (message: MessageEvent<any>) => {
191
201
  try {
192
202
  const data = JSON.parse(message.data.toString())
193
203
  if (data['error']) {
@@ -199,7 +209,15 @@ const addDataToAudioQueue =
199
209
  const audioData = intToFloatArray(int32Data)
200
210
  audioQueue.write(audioData)
201
211
  } else if (data['marker']) {
212
+ if (data['latency'] && onLatencyUpdate) {
213
+ onLatencyUpdate(data['latency'])
214
+ }
215
+ console.log('Voice Latency Metrics:', data['latency'])
202
216
  audioQueue.addMarker(data['marker'])
217
+ } else if (data['interruptPlayback']) {
218
+ // User interrupted the bot, immediately clear the audio queue
219
+ audioQueue.clear()
220
+ console.log('Audio queue cleared due to user interruption.')
203
221
  }
204
222
  } catch (error) {
205
223
  console.error('Error processing server incoming audio data:', error)
@@ -231,8 +249,12 @@ function getWebSocketUrl(baseUrl: string) {
231
249
  * Creates a WebSocket connection for browser audio and streams microphone input to the server
232
250
  *
233
251
  * @param baseUrl - The base URL (e.g., "https://example.com" or "http://localhost:5005")
252
+ * @param onLatencyUpdate - Optional callback function to receive latency updates
234
253
  */
235
- export async function createAudioConnection(baseUrl: string) {
254
+ export async function createAudioConnection(
255
+ baseUrl: string,
256
+ onLatencyUpdate?: (latency: any) => void,
257
+ ) {
236
258
  const websocketURL = getWebSocketUrl(baseUrl)
237
259
  const socket = new WebSocket(websocketURL)
238
260
 
@@ -241,5 +263,5 @@ export async function createAudioConnection(baseUrl: string) {
241
263
  }
242
264
 
243
265
  const audioQueue = await setupAudioPlayback(socket)
244
- socket.onmessage = addDataToAudioQueue(audioQueue)
266
+ socket.onmessage = addDataToAudioQueue(audioQueue, onLatencyUpdate)
245
267
  }
@@ -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
+ }