rasa-pro 3.14.0.dev20250901__py3-none-any.whl → 3.14.0rc1__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.
- rasa/__main__.py +15 -3
- rasa/agents/__init__.py +0 -0
- rasa/agents/agent_factory.py +122 -0
- rasa/agents/agent_manager.py +211 -0
- rasa/agents/constants.py +43 -0
- rasa/agents/core/__init__.py +0 -0
- rasa/agents/core/agent_protocol.py +107 -0
- rasa/agents/core/types.py +81 -0
- rasa/agents/exceptions.py +38 -0
- rasa/agents/protocol/__init__.py +5 -0
- rasa/agents/protocol/a2a/__init__.py +0 -0
- rasa/agents/protocol/a2a/a2a_agent.py +879 -0
- rasa/agents/protocol/mcp/__init__.py +0 -0
- rasa/agents/protocol/mcp/mcp_base_agent.py +726 -0
- rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
- rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
- rasa/agents/schemas/__init__.py +13 -0
- rasa/agents/schemas/agent_input.py +38 -0
- rasa/agents/schemas/agent_output.py +26 -0
- rasa/agents/schemas/agent_tool_result.py +65 -0
- rasa/agents/schemas/agent_tool_schema.py +186 -0
- rasa/agents/templates/__init__.py +0 -0
- rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
- rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
- rasa/agents/utils.py +206 -0
- rasa/agents/validation.py +485 -0
- rasa/api.py +24 -9
- rasa/builder/config.py +7 -2
- rasa/builder/copilot/constants.py +3 -0
- rasa/builder/copilot/copilot.py +128 -54
- rasa/builder/copilot/models.py +39 -3
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +183 -188
- rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +61 -0
- rasa/builder/copilot/telemetry.py +46 -20
- rasa/builder/document_retrieval/models.py +3 -3
- rasa/builder/download.py +1 -8
- rasa/builder/guardrails/{lakera.py → clients.py} +55 -5
- rasa/builder/guardrails/constants.py +3 -0
- rasa/builder/guardrails/models.py +45 -10
- rasa/builder/guardrails/policy_checker.py +324 -0
- rasa/builder/guardrails/utils.py +42 -276
- rasa/builder/jobs.py +33 -21
- rasa/builder/llm_service.py +32 -5
- rasa/builder/main.py +38 -62
- rasa/builder/models.py +8 -7
- rasa/builder/project_generator.py +149 -148
- rasa/builder/service.py +58 -40
- rasa/builder/template_cache.py +69 -0
- rasa/builder/training_service.py +84 -20
- rasa/builder/validation_service.py +1 -1
- rasa/cli/arguments/default_arguments.py +12 -0
- rasa/cli/arguments/run.py +2 -0
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/data.py +10 -8
- rasa/cli/dialogue_understanding_test.py +10 -7
- rasa/cli/e2e_test.py +9 -6
- rasa/cli/evaluate.py +4 -2
- rasa/cli/export.py +5 -2
- rasa/cli/inspect.py +8 -4
- rasa/cli/interactive.py +5 -4
- rasa/cli/llm_fine_tuning.py +11 -6
- rasa/cli/project_templates/basic/README.md +23 -0
- rasa/cli/project_templates/basic/actions/actions.md +10 -0
- rasa/cli/project_templates/basic/config.yml +6 -4
- rasa/cli/project_templates/basic/data/data.md +5 -6
- rasa/cli/project_templates/basic/domain/domain.md +7 -5
- rasa/cli/project_templates/basic/domain/general/show_faqs.yml +1 -1
- rasa/cli/project_templates/basic/endpoints.yml +5 -1
- rasa/cli/project_templates/default/config.yml +4 -0
- rasa/cli/project_templates/default/endpoints.yml +4 -0
- rasa/cli/project_templates/finance/README.md +26 -0
- rasa/cli/project_templates/finance/actions/__init__.py +0 -46
- rasa/cli/project_templates/finance/actions/accounts/check_balance.py +18 -0
- rasa/cli/project_templates/finance/actions/actions.md +15 -0
- rasa/cli/project_templates/finance/actions/{transfers/action_process_immediate_payment.py → cards/check_that_card_exists.py} +6 -3
- rasa/cli/project_templates/finance/actions/cards/list_cards.py +22 -0
- rasa/cli/project_templates/finance/actions/contacts/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/contacts/add_contact.py +30 -0
- rasa/cli/project_templates/finance/actions/contacts/list_contacts.py +22 -0
- rasa/cli/project_templates/finance/actions/contacts/remove_contact.py +35 -0
- rasa/cli/project_templates/finance/actions/db.py +117 -0
- rasa/cli/project_templates/finance/actions/general/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/general/action_human_handoff.py +49 -0
- rasa/cli/project_templates/finance/actions/transfers/check_transfer_funds.py +27 -0
- rasa/cli/project_templates/finance/actions/transfers/check_transfer_limit.py +36 -0
- rasa/cli/project_templates/finance/actions/transfers/execute_recurrent_payment.py +20 -0
- rasa/cli/project_templates/finance/actions/transfers/execute_transfer.py +45 -0
- rasa/cli/project_templates/finance/actions/transfers/list_transactions.py +32 -0
- rasa/cli/project_templates/finance/config.yml +8 -0
- rasa/cli/project_templates/finance/credentials.yml +7 -6
- rasa/cli/project_templates/finance/data/accounts/check_balance.yml +3 -4
- rasa/cli/project_templates/finance/data/accounts/download_statements.yml +26 -0
- rasa/cli/project_templates/finance/data/bills/bill_pay_reminder.yml +25 -0
- rasa/cli/project_templates/finance/data/cards/activate_card.yml +35 -0
- rasa/cli/project_templates/finance/data/cards/block_card.yml +37 -58
- rasa/cli/project_templates/finance/data/cards/list_cards.yml +14 -0
- rasa/cli/project_templates/finance/data/cards/replace_card.yml +16 -0
- rasa/cli/project_templates/finance/data/cards/replace_eligible_card.yml +29 -0
- rasa/cli/project_templates/finance/data/contacts/add_contact.yml +33 -0
- rasa/cli/project_templates/finance/data/contacts/list_contacts.yml +14 -0
- rasa/cli/project_templates/finance/data/contacts/remove_contact.yml +31 -0
- rasa/cli/project_templates/finance/data/data.md +14 -0
- rasa/cli/project_templates/finance/data/general/bot_challenge.yml +6 -0
- rasa/cli/project_templates/finance/data/general/goodbye.yml +1 -1
- rasa/cli/project_templates/finance/data/general/hello.yml +1 -2
- rasa/cli/project_templates/finance/data/general/help.yml +2 -2
- rasa/cli/project_templates/finance/data/general/human_handoff.yml +2 -2
- rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +1 -1
- rasa/cli/project_templates/finance/data/transfers/check_transfer_limit.yml +18 -0
- rasa/cli/project_templates/finance/data/transfers/list_transactions.yml +46 -0
- rasa/cli/project_templates/finance/data/transfers/move_money_between_accounts.yml +51 -0
- rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +29 -62
- rasa/cli/project_templates/finance/data/transfers/transfer_money_to_a_third_party.yml +175 -0
- rasa/cli/project_templates/finance/db/cards.json +18 -0
- rasa/cli/project_templates/finance/db/contacts.json +10 -0
- rasa/cli/project_templates/finance/db/my_account.json +6 -0
- rasa/cli/project_templates/finance/db/transactions.json +22 -0
- rasa/cli/project_templates/finance/docs/docs.md +8 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/budgeting_analytics.txt +22 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/multi_currency_accounts.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/premium_benefits.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/contactless_limits.txt +16 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/freeze_unfreeze_card.txt +16 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/lost_stolen_card.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/money_transfers/instant_payments.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/money_transfers/international_transfers.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/security_fraud/fraud_protection.txt +22 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/security_fraud/secure_payments.txt +22 -0
- rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +9 -5
- rasa/cli/project_templates/finance/domain/accounts/download_statements.yml +40 -0
- rasa/cli/project_templates/finance/domain/bills/bill_pay_reminder.yml +49 -0
- rasa/cli/project_templates/finance/domain/cards/activate_card.yml +24 -0
- rasa/cli/project_templates/finance/domain/cards/block_card.yml +33 -90
- rasa/cli/project_templates/finance/domain/cards/list_cards.yml +16 -0
- rasa/cli/project_templates/finance/domain/cards/replace_card.yml +43 -0
- rasa/cli/project_templates/finance/domain/cards/shared.yml +15 -0
- rasa/cli/project_templates/finance/domain/contacts/add_contact.yml +37 -0
- rasa/cli/project_templates/finance/domain/contacts/list_contacts.yml +16 -0
- rasa/cli/project_templates/finance/domain/contacts/remove_contact.yml +32 -0
- rasa/cli/project_templates/finance/domain/domain.md +18 -0
- rasa/cli/project_templates/finance/domain/general/_shared.yml +39 -0
- rasa/cli/project_templates/finance/domain/general/bot_challenge.yml +4 -0
- rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -2
- rasa/cli/project_templates/finance/domain/general/feedback.yml +0 -3
- rasa/cli/project_templates/finance/domain/general/goodbye.yml +6 -6
- rasa/cli/project_templates/finance/domain/general/human_handoff.yml +10 -9
- rasa/cli/project_templates/finance/domain/general/welcome.yml +33 -2
- rasa/cli/project_templates/finance/domain/transfers/check_transfer_limit.yml +32 -0
- rasa/cli/project_templates/finance/domain/transfers/list_transactions.yml +44 -0
- rasa/cli/project_templates/finance/domain/transfers/shared.yml +17 -0
- rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +203 -61
- rasa/cli/project_templates/finance/endpoints.yml +8 -4
- rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +31 -12
- rasa/cli/project_templates/finance/tests/e2e_test_cases/accounts/check_balance.yml +9 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/accounts/download_statements.yml +43 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/cards/block_card.yml +55 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/general/feedback.yml +46 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/general/goodbye.yml +9 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/general/hello.yml +8 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/general/human_handoff.yml +35 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/general/patterns.yml +22 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/transfers/transfer_money.yml +56 -0
- rasa/cli/project_templates/telco/README.md +25 -0
- rasa/cli/project_templates/telco/actions/actions.md +12 -0
- rasa/cli/project_templates/telco/config.yml +6 -4
- rasa/cli/project_templates/telco/data/data.md +11 -0
- rasa/cli/project_templates/telco/data/general/human_handoff.yml +1 -1
- rasa/cli/project_templates/telco/docs/docs.md +3 -0
- rasa/cli/project_templates/telco/domain/domain.md +13 -0
- rasa/cli/project_templates/telco/domain/general/human_handoff.yml +3 -6
- rasa/cli/project_templates/telco/endpoints.yml +5 -1
- rasa/cli/project_templates/telco/prompts/rephraser_demo_personality_prompt.jinja2 +1 -1
- rasa/cli/project_templates/telco/tests/e2e_test_cases/billing/understand_bill.yml +67 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +46 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/goodbye.yml +9 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +35 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +23 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +57 -0
- rasa/cli/project_templates/tutorial/credentials.yml +10 -0
- rasa/cli/run.py +12 -10
- rasa/cli/scaffold.py +4 -4
- rasa/cli/shell.py +9 -5
- rasa/cli/studio/studio.py +1 -1
- rasa/cli/test.py +34 -14
- rasa/cli/train.py +41 -28
- rasa/cli/utils.py +1 -393
- rasa/cli/validation/__init__.py +0 -0
- rasa/cli/validation/bot_config.py +223 -0
- rasa/cli/validation/config_path_validation.py +257 -0
- rasa/cli/x.py +8 -4
- rasa/constants.py +7 -1
- rasa/core/actions/action.py +51 -10
- rasa/core/actions/action_run_slot_rejections.py +1 -1
- rasa/core/actions/direct_custom_actions_executor.py +9 -2
- rasa/core/actions/grpc_custom_action_executor.py +1 -1
- rasa/core/agent.py +19 -2
- rasa/core/available_agents.py +229 -0
- rasa/core/brokers/broker.py +1 -1
- rasa/core/brokers/kafka.py +52 -8
- rasa/core/channels/__init__.py +82 -35
- rasa/core/channels/development_inspector.py +4 -24
- rasa/core/channels/hangouts.py +2 -2
- rasa/core/channels/inspector/README.md +25 -13
- rasa/core/channels/inspector/dist/assets/{arc-18042c22.js → arc-6177260a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-fdd6bcfa.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-f5ae6786.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-81efba3e.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-3b6b6a92.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-31422447.js → createText-2e5e7dd3-088372e2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-518a90db.js → edges-e0da2a9e-58676240.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-a6d3c25a.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-e048c2be.js → flowDb-956e92f1-ea63f85c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-c7474c91.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-cb4d8723.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-346636a2.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-7c508874.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-14702d8a.js → graph-0a6f8466.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-f18b534b.js → index-3862675e-7610671a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-64154b83.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-833a5f95.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-5a3b2123.js → layout-e7fbc2bf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-2272a8c7.js → line-a8aa457c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-35bcf273.js → linear-3351e0d2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-92dcb0e9.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-94dbc900.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-8b7a9c33.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-6f7eab81.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-f43e581d.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-0bcbefc3.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-b8a74083.js → stateDiagram-587899a1-0e770395.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-2070218f.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-f1d54e34.js → styles-6aaf32cf-36a9e70d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-980de489.js → styles-9a916d00-884a8b5b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-3c03abde.js → styles-c10674c1-dc097813.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-46ba068f.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-901f5e3d.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-acbc628a.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/package.json +18 -18
- rasa/core/channels/inspector/src/App.tsx +34 -35
- rasa/core/channels/inspector/src/components/Chat.tsx +2 -3
- rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
- rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +9 -1
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +63 -35
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +20 -3
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
- rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
- rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
- rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
- rasa/core/channels/inspector/src/types.ts +53 -7
- rasa/core/channels/inspector/yarn.lock +336 -189
- rasa/core/channels/studio_chat.py +29 -47
- rasa/core/channels/telegram.py +4 -9
- rasa/core/channels/voice_stream/asr/asr_event.py +1 -1
- rasa/core/channels/voice_stream/asr/azure.py +6 -3
- rasa/core/channels/voice_stream/asr/deepgram.py +1 -1
- rasa/core/channels/voice_stream/audiocodes.py +3 -0
- rasa/core/channels/voice_stream/browser_audio.py +55 -3
- rasa/core/channels/voice_stream/genesys.py +3 -2
- rasa/core/channels/voice_stream/jambonz.py +9 -1
- rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +21 -1
- rasa/core/channels/voice_stream/voice_channel.py +64 -0
- rasa/core/concurrent_lock_store.py +66 -16
- rasa/core/config/__init__.py +0 -0
- rasa/core/{available_endpoints.py → config/available_endpoints.py} +51 -16
- rasa/core/config/configuration.py +260 -0
- rasa/core/config/credentials.py +19 -0
- rasa/core/config/message_procesing_config.py +34 -0
- rasa/core/constants.py +11 -0
- rasa/core/iam_credentials_providers/__init__.py +0 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +226 -0
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +90 -0
- rasa/core/lock_store.py +46 -10
- rasa/core/nlg/generator.py +1 -1
- rasa/core/policies/enterprise_search_policy.py +5 -3
- rasa/core/policies/flow_policy.py +4 -4
- rasa/core/policies/flows/agent_executor.py +632 -0
- rasa/core/policies/flows/flow_executor.py +137 -76
- rasa/core/policies/flows/mcp_tool_executor.py +298 -0
- rasa/core/policies/intentless_policy.py +1 -1
- rasa/core/policies/ted_policy.py +20 -12
- rasa/core/policies/unexpected_intent_policy.py +6 -0
- rasa/core/processor.py +100 -44
- rasa/core/redis_connection_factory.py +469 -0
- rasa/core/run.py +37 -8
- rasa/core/test.py +4 -0
- rasa/core/tracker_stores/redis_tracker_store.py +32 -14
- rasa/core/tracker_stores/sql_tracker_store.py +57 -1
- rasa/core/tracker_stores/tracker_store.py +3 -7
- rasa/core/train.py +1 -1
- rasa/core/training/interactive.py +20 -18
- rasa/core/training/story_conflict.py +5 -5
- rasa/core/utils.py +22 -23
- rasa/dialogue_understanding/commands/__init__.py +8 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +19 -5
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
- rasa/dialogue_understanding/commands/clarify_command.py +20 -2
- rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
- rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +68 -7
- rasa/dialogue_understanding/commands/utils.py +124 -2
- rasa/dialogue_understanding/generator/command_parser.py +4 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
- rasa/dialogue_understanding/patterns/cancel.py +27 -6
- rasa/dialogue_understanding/patterns/clarify.py +3 -14
- rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +46 -8
- rasa/dialogue_understanding/processor/command_processor.py +136 -15
- rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
- rasa/dialogue_understanding/stack/utils.py +57 -3
- rasa/dialogue_understanding/utils.py +24 -4
- rasa/dialogue_understanding_test/du_test_runner.py +8 -3
- rasa/e2e_test/e2e_test_runner.py +13 -3
- rasa/engine/caching.py +2 -2
- rasa/engine/constants.py +1 -1
- rasa/engine/graph.py +5 -1
- rasa/engine/loader.py +12 -0
- rasa/engine/recipes/default_components.py +138 -49
- rasa/engine/recipes/default_recipe.py +108 -11
- rasa/engine/runner/dask.py +8 -5
- rasa/engine/storage/local_model_storage.py +41 -4
- rasa/engine/validation.py +19 -6
- rasa/graph_components/validators/default_recipe_validator.py +86 -28
- rasa/hooks.py +5 -5
- rasa/llm_fine_tuning/utils.py +2 -2
- rasa/model_manager/socket_bridge.py +1 -2
- rasa/model_manager/warm_rasa_process.py +13 -3
- rasa/model_training.py +60 -47
- rasa/nlu/classifiers/diet_classifier.py +198 -98
- rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
- rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
- rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
- rasa/nlu/extractors/crf_entity_extractor.py +9 -10
- rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
- rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
- rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
- rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
- rasa/nlu/selectors/response_selector.py +10 -2
- rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
- rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
- rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
- rasa/nlu/utils/mitie_utils.py +3 -0
- rasa/nlu/utils/spacy_utils.py +3 -2
- rasa/plugin.py +8 -8
- rasa/privacy/privacy_manager.py +12 -3
- rasa/server.py +15 -3
- rasa/shared/agents/__init__.py +0 -0
- rasa/shared/agents/auth/__init__.py +0 -0
- rasa/shared/agents/auth/agent_auth_factory.py +105 -0
- rasa/shared/agents/auth/agent_auth_manager.py +92 -0
- rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
- rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
- rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
- rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
- rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +167 -0
- rasa/shared/agents/auth/constants.py +12 -0
- rasa/shared/agents/auth/types.py +12 -0
- rasa/shared/agents/utils.py +35 -0
- rasa/shared/constants.py +8 -0
- rasa/shared/core/constants.py +17 -1
- rasa/shared/core/domain.py +0 -7
- rasa/shared/core/events.py +329 -0
- rasa/shared/core/flows/constants.py +5 -0
- rasa/shared/core/flows/flow.py +1 -1
- rasa/shared/core/flows/flows_list.py +21 -5
- rasa/shared/core/flows/flows_yaml_schema.json +119 -184
- rasa/shared/core/flows/steps/call.py +49 -5
- rasa/shared/core/flows/steps/collect.py +98 -13
- rasa/shared/core/flows/validation.py +372 -8
- rasa/shared/core/flows/yaml_flows_io.py +3 -2
- rasa/shared/core/slots.py +2 -2
- rasa/shared/core/trackers.py +5 -2
- rasa/shared/exceptions.py +16 -0
- rasa/shared/importers/rasa.py +1 -1
- rasa/shared/importers/utils.py +9 -3
- rasa/shared/nlu/training_data/schemas/responses.yml +3 -0
- rasa/shared/providers/llm/_base_litellm_client.py +41 -9
- rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
- rasa/shared/providers/llm/llm_client.py +7 -3
- rasa/shared/providers/llm/llm_response.py +66 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
- rasa/shared/utils/common.py +24 -0
- rasa/shared/utils/health_check/health_check.py +7 -3
- rasa/shared/utils/llm.py +39 -16
- rasa/shared/utils/mcp/__init__.py +0 -0
- rasa/shared/utils/mcp/server_connection.py +247 -0
- rasa/shared/utils/mcp/utils.py +20 -0
- rasa/shared/utils/schemas/events.py +42 -0
- rasa/shared/utils/yaml.py +3 -1
- rasa/studio/pull/pull.py +3 -2
- rasa/studio/train.py +8 -7
- rasa/studio/upload.py +3 -6
- rasa/telemetry.py +69 -5
- rasa/tracing/config.py +45 -12
- rasa/tracing/constants.py +14 -0
- rasa/tracing/instrumentation/attribute_extractors.py +142 -9
- rasa/tracing/instrumentation/instrumentation.py +626 -21
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
- rasa/tracing/instrumentation/metrics.py +32 -0
- rasa/tracing/metric_instrument_provider.py +68 -0
- rasa/utils/common.py +92 -1
- rasa/utils/endpoints.py +11 -2
- rasa/utils/log_utils.py +96 -5
- rasa/utils/ml_utils.py +1 -1
- rasa/utils/pypred.py +38 -0
- rasa/utils/tensorflow/__init__.py +7 -0
- rasa/utils/tensorflow/callback.py +136 -101
- rasa/utils/tensorflow/crf.py +1 -1
- rasa/utils/tensorflow/data_generator.py +21 -8
- rasa/utils/tensorflow/layers.py +21 -11
- rasa/utils/tensorflow/metrics.py +7 -3
- rasa/utils/tensorflow/models.py +56 -8
- rasa/utils/tensorflow/rasa_layers.py +8 -6
- rasa/utils/tensorflow/transformer.py +2 -3
- rasa/utils/train_utils.py +54 -24
- rasa/validator.py +17 -13
- rasa/version.py +1 -1
- {rasa_pro-3.14.0.dev20250901.dist-info → rasa_pro-3.14.0rc1.dist-info}/METADATA +59 -51
- {rasa_pro-3.14.0.dev20250901.dist-info → rasa_pro-3.14.0rc1.dist-info}/RECORD +452 -428
- rasa/builder/scrape_rasa_docs.py +0 -97
- rasa/cli/project_templates/finance/actions/accounts/action_ask_account.py +0 -47
- rasa/cli/project_templates/finance/actions/accounts/action_check_balance.py +0 -40
- rasa/cli/project_templates/finance/actions/action_session_start.py +0 -74
- rasa/cli/project_templates/finance/actions/cards/action_ask_card.py +0 -48
- rasa/cli/project_templates/finance/actions/cards/action_check_card_existence.py +0 -36
- rasa/cli/project_templates/finance/actions/cards/action_update_card_status.py +0 -54
- rasa/cli/project_templates/finance/actions/database.py +0 -277
- rasa/cli/project_templates/finance/actions/transfers/action_add_payee.py +0 -52
- rasa/cli/project_templates/finance/actions/transfers/action_ask_account_from.py +0 -51
- rasa/cli/project_templates/finance/actions/transfers/action_check_payee_existence.py +0 -40
- rasa/cli/project_templates/finance/actions/transfers/action_check_sufficient_funds.py +0 -40
- rasa/cli/project_templates/finance/actions/transfers/action_list_payees.py +0 -46
- rasa/cli/project_templates/finance/actions/transfers/action_remove_payee.py +0 -49
- rasa/cli/project_templates/finance/actions/transfers/action_schedule_payment.py +0 -19
- rasa/cli/project_templates/finance/actions/transfers/action_validate_payment_date.py +0 -36
- rasa/cli/project_templates/finance/csvs/accounts.csv +0 -8
- rasa/cli/project_templates/finance/csvs/advisors.csv +0 -7
- rasa/cli/project_templates/finance/csvs/appointments.csv +0 -211
- rasa/cli/project_templates/finance/csvs/branches.csv +0 -10
- rasa/cli/project_templates/finance/csvs/cards.csv +0 -11
- rasa/cli/project_templates/finance/csvs/payees.csv +0 -11
- rasa/cli/project_templates/finance/csvs/transactions.csv +0 -71
- rasa/cli/project_templates/finance/csvs/users.csv +0 -4
- rasa/cli/project_templates/finance/data/cards/select_card.yml +0 -12
- rasa/cli/project_templates/finance/data/general/bot_identity.yml +0 -6
- rasa/cli/project_templates/finance/data/system/patterns/pattern_chitchat.yml +0 -5
- rasa/cli/project_templates/finance/data/system/source/accounts.json +0 -51
- rasa/cli/project_templates/finance/data/system/source/advisors.json +0 -44
- rasa/cli/project_templates/finance/data/system/source/appointments.json +0 -1474
- rasa/cli/project_templates/finance/data/system/source/branches.json +0 -47
- rasa/cli/project_templates/finance/data/system/source/cards.json +0 -72
- rasa/cli/project_templates/finance/data/system/source/payees.json +0 -74
- rasa/cli/project_templates/finance/data/system/source/transactions.json +0 -492
- rasa/cli/project_templates/finance/data/system/source/users.json +0 -29
- rasa/cli/project_templates/finance/data/transfers/add_payee.yml +0 -29
- rasa/cli/project_templates/finance/data/transfers/list_payees.yml +0 -5
- rasa/cli/project_templates/finance/data/transfers/remove_payee.yml +0 -21
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +0 -7
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +0 -8
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +0 -48
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +0 -47
- rasa/cli/project_templates/finance/domain/cards/select_card.yml +0 -12
- rasa/cli/project_templates/finance/domain/general/assistant_details.yml +0 -12
- rasa/cli/project_templates/finance/domain/general/bot_identity.yml +0 -5
- rasa/cli/project_templates/finance/domain/general/defaults.yml +0 -24
- rasa/cli/project_templates/finance/domain/general/help.yml +0 -5
- rasa/cli/project_templates/finance/domain/general/utils.yml +0 -13
- rasa/cli/project_templates/finance/domain/transfers/add_payee.yml +0 -47
- rasa/cli/project_templates/finance/domain/transfers/list_payees.yml +0 -4
- rasa/cli/project_templates/finance/domain/transfers/remove_payee.yml +0 -16
- rasa/core/channels/inspector/dist/assets/channel-b9b536fc.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-78d2ddcf.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-8b09c060.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-4d4bdf3a.js +0 -1335
- /rasa/cli/project_templates/telco/domain/billing/{domain_undertand_bill.yml → understand_bill.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_reboot_router.yml → reboot_router.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_reset_router.yml → reset_router.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_run_speed_test.yml → run_speed_test.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_solve_internet_issue.yml → solve_internet_issue.yml} +0 -0
- {rasa_pro-3.14.0.dev20250901.dist-info → rasa_pro-3.14.0rc1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0.dev20250901.dist-info → rasa_pro-3.14.0rc1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0.dev20250901.dist-info → rasa_pro-3.14.0rc1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,879 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
import uuid
|
|
6
|
+
from typing import Any, ClassVar, Dict, List, Optional
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
import structlog
|
|
11
|
+
from a2a.client import (
|
|
12
|
+
A2ACardResolver,
|
|
13
|
+
A2AClientError,
|
|
14
|
+
A2AClientHTTPError,
|
|
15
|
+
A2AClientJSONError,
|
|
16
|
+
Client,
|
|
17
|
+
ClientConfig,
|
|
18
|
+
ClientEvent,
|
|
19
|
+
ClientFactory,
|
|
20
|
+
)
|
|
21
|
+
from a2a.client.errors import A2AClientJSONRPCError
|
|
22
|
+
from a2a.types import (
|
|
23
|
+
AgentCard,
|
|
24
|
+
Artifact,
|
|
25
|
+
DataPart,
|
|
26
|
+
FilePart,
|
|
27
|
+
FileWithUri,
|
|
28
|
+
InternalError,
|
|
29
|
+
InvalidAgentResponseError,
|
|
30
|
+
Message,
|
|
31
|
+
Part,
|
|
32
|
+
Role,
|
|
33
|
+
Task,
|
|
34
|
+
TaskQueryParams,
|
|
35
|
+
TaskState,
|
|
36
|
+
TextPart,
|
|
37
|
+
TransportProtocol,
|
|
38
|
+
)
|
|
39
|
+
from pydantic import ValidationError
|
|
40
|
+
|
|
41
|
+
from rasa.agents.constants import (
|
|
42
|
+
A2A_AGENT_CONTEXT_ID_KEY,
|
|
43
|
+
A2A_AGENT_TASK_ID_KEY,
|
|
44
|
+
AGENT_DEFAULT_MAX_RETRIES,
|
|
45
|
+
AGENT_DEFAULT_TIMEOUT_SECONDS,
|
|
46
|
+
AGENT_METADATA_STRUCTURED_RESULTS_KEY,
|
|
47
|
+
MAX_AGENT_RETRY_DELAY_SECONDS,
|
|
48
|
+
)
|
|
49
|
+
from rasa.agents.core.agent_protocol import AgentProtocol
|
|
50
|
+
from rasa.agents.core.types import AgentStatus, ProtocolType
|
|
51
|
+
from rasa.agents.schemas import AgentInput, AgentOutput
|
|
52
|
+
from rasa.core.available_agents import AgentConfig
|
|
53
|
+
from rasa.shared.agents.auth.agent_auth_manager import AgentAuthManager
|
|
54
|
+
from rasa.shared.exceptions import (
|
|
55
|
+
AgentInitializationException,
|
|
56
|
+
InvalidParameterException,
|
|
57
|
+
RasaException,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
A2A_TASK_POOLING_INITIAL_DELAY = 0.5
|
|
61
|
+
A2A_TASK_POOLING_MAX_WAIT = 60
|
|
62
|
+
|
|
63
|
+
structlogger = structlog.get_logger()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class A2AAgent(AgentProtocol):
|
|
67
|
+
"""A2A client implementation"""
|
|
68
|
+
|
|
69
|
+
__SUPPORTED_OUTPUT_MODES: ClassVar[list[str]] = [
|
|
70
|
+
"text",
|
|
71
|
+
"text/plain",
|
|
72
|
+
"application/json",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
# ============================================================================
|
|
76
|
+
# Initialization & Setup
|
|
77
|
+
# ============================================================================
|
|
78
|
+
|
|
79
|
+
def __init__(
|
|
80
|
+
self,
|
|
81
|
+
name: str,
|
|
82
|
+
description: str,
|
|
83
|
+
agent_card_path: str,
|
|
84
|
+
timeout: int,
|
|
85
|
+
max_retries: int,
|
|
86
|
+
auth_config: Optional[Dict[str, Any]] = None,
|
|
87
|
+
) -> None:
|
|
88
|
+
self._name = name
|
|
89
|
+
self._description = description
|
|
90
|
+
self._agent_card_path = agent_card_path
|
|
91
|
+
self._timeout = timeout
|
|
92
|
+
self._max_retries = max_retries
|
|
93
|
+
self._auth_config = auth_config
|
|
94
|
+
|
|
95
|
+
self.agent_card: Optional[AgentCard] = None
|
|
96
|
+
self._client: Optional[Client] = None
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def from_config(cls, config: AgentConfig) -> AgentProtocol:
|
|
100
|
+
"""Initialize the A2A Agent with the given configuration."""
|
|
101
|
+
agent_card_path = (
|
|
102
|
+
config.configuration.agent_card if config.configuration else None
|
|
103
|
+
)
|
|
104
|
+
if not agent_card_path:
|
|
105
|
+
raise InvalidParameterException(
|
|
106
|
+
"Agent card path or URL must be provided in the configuration "
|
|
107
|
+
"for A2A agents."
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
timeout = (
|
|
111
|
+
config.configuration.timeout
|
|
112
|
+
if config.configuration and config.configuration.timeout
|
|
113
|
+
else AGENT_DEFAULT_TIMEOUT_SECONDS
|
|
114
|
+
)
|
|
115
|
+
max_retries = (
|
|
116
|
+
config.configuration.max_retries
|
|
117
|
+
if config.configuration and config.configuration.max_retries
|
|
118
|
+
else AGENT_DEFAULT_MAX_RETRIES
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
_auth_config = config.configuration.auth if config.configuration else None
|
|
122
|
+
return cls(
|
|
123
|
+
name=config.agent.name,
|
|
124
|
+
description=config.agent.description,
|
|
125
|
+
agent_card_path=agent_card_path,
|
|
126
|
+
timeout=timeout,
|
|
127
|
+
max_retries=max_retries,
|
|
128
|
+
auth_config=_auth_config,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def protocol_type(self) -> ProtocolType:
|
|
133
|
+
return ProtocolType.A2A
|
|
134
|
+
|
|
135
|
+
# ============================================================================
|
|
136
|
+
# Connection Management
|
|
137
|
+
# ============================================================================
|
|
138
|
+
|
|
139
|
+
async def connect(self) -> None:
|
|
140
|
+
"""Fetch the AgentCard and initialize the A2A client."""
|
|
141
|
+
from rasa.nlu.utils import is_url
|
|
142
|
+
|
|
143
|
+
if is_url(self._agent_card_path):
|
|
144
|
+
self.agent_card = await A2AAgent._resolve_agent_card_with_retry(
|
|
145
|
+
self._agent_card_path, self._timeout, self._max_retries
|
|
146
|
+
)
|
|
147
|
+
else:
|
|
148
|
+
self.agent_card = A2AAgent._load_agent_card_from_file(self._agent_card_path)
|
|
149
|
+
structlogger.debug(
|
|
150
|
+
"a2a_agent.from_config",
|
|
151
|
+
event_info=f"Loaded agent card from {self._agent_card_path}",
|
|
152
|
+
agent_card=self.agent_card.model_dump(),
|
|
153
|
+
json_formatting=["agent_card"],
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
self._client = self._init_client()
|
|
158
|
+
structlogger.debug(
|
|
159
|
+
"a2a_agent.connect.agent_client_initialized",
|
|
160
|
+
event_info=f"Initialized A2A client for agent '{self._name}'. "
|
|
161
|
+
f"Performing health check using the URL {self.agent_card.url}",
|
|
162
|
+
)
|
|
163
|
+
except Exception as exception:
|
|
164
|
+
structlogger.error(
|
|
165
|
+
"a2a_agent.connect.error",
|
|
166
|
+
event_info="Failed to initialize A2A client",
|
|
167
|
+
agent_name=self._name,
|
|
168
|
+
error=str(exception),
|
|
169
|
+
)
|
|
170
|
+
raise AgentInitializationException(
|
|
171
|
+
f"Failed to initialize A2A client for agent "
|
|
172
|
+
f"'{self._name}': {exception}"
|
|
173
|
+
) from exception
|
|
174
|
+
|
|
175
|
+
await self._perform_health_check()
|
|
176
|
+
structlogger.debug(
|
|
177
|
+
"a2a_agent.connect.success",
|
|
178
|
+
event_info=f"Connected to A2A server '{self._name}' "
|
|
179
|
+
f"at {self.agent_card.url}",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
async def disconnect(self) -> None:
|
|
183
|
+
"""We don't need to explicitly disconnect the A2A client"""
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
# ============================================================================
|
|
187
|
+
# Core Protocol Methods
|
|
188
|
+
# ============================================================================
|
|
189
|
+
|
|
190
|
+
async def process_input(self, agent_input: AgentInput) -> AgentInput:
|
|
191
|
+
"""Pre-process the input before sending it to the agent."""
|
|
192
|
+
# A2A-specific input processing logic
|
|
193
|
+
return agent_input
|
|
194
|
+
|
|
195
|
+
async def run(self, agent_input: AgentInput) -> AgentOutput:
|
|
196
|
+
"""Send a message to Agent/server and return response."""
|
|
197
|
+
if not self._client or not self.agent_card:
|
|
198
|
+
structlogger.error(
|
|
199
|
+
"a2a_agent.run.error",
|
|
200
|
+
event_info="A2A client is not initialized. Call connect() first.",
|
|
201
|
+
)
|
|
202
|
+
return AgentOutput(
|
|
203
|
+
id=agent_input.id,
|
|
204
|
+
status=AgentStatus.FATAL_ERROR,
|
|
205
|
+
error_message="Client not initialized",
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
structlogger.info(
|
|
209
|
+
"a2a_agent.run.start",
|
|
210
|
+
event_info="Running A2A agent",
|
|
211
|
+
agent_name=self._name,
|
|
212
|
+
)
|
|
213
|
+
message = self._prepare_message(agent_input)
|
|
214
|
+
|
|
215
|
+
task_id: Optional[str] = None
|
|
216
|
+
events_received = 0
|
|
217
|
+
try:
|
|
218
|
+
async for event in self._client.send_message(message):
|
|
219
|
+
events_received += 1
|
|
220
|
+
agent_output = self._handle_send_message_response(agent_input, event)
|
|
221
|
+
if agent_output is not None:
|
|
222
|
+
return agent_output
|
|
223
|
+
else:
|
|
224
|
+
# Not a terminal response, save taskID (in case that's the only
|
|
225
|
+
# event, and we need to pool) and continue waiting for next events
|
|
226
|
+
if (
|
|
227
|
+
isinstance(event, tuple)
|
|
228
|
+
and len(event) == 2
|
|
229
|
+
and isinstance(event[0], Task)
|
|
230
|
+
):
|
|
231
|
+
task_id = event[0].id
|
|
232
|
+
continue
|
|
233
|
+
except A2AClientJSONRPCError as e:
|
|
234
|
+
return self._handle_json_rpc_error_response(agent_input, e.error)
|
|
235
|
+
except A2AClientError as exception:
|
|
236
|
+
structlogger.error(
|
|
237
|
+
"a2a_agent.run.send_message.error",
|
|
238
|
+
event_info="Error during sending message to A2A agent",
|
|
239
|
+
agent_name=self._name,
|
|
240
|
+
error=str(exception),
|
|
241
|
+
)
|
|
242
|
+
return AgentOutput(
|
|
243
|
+
id=agent_input.id,
|
|
244
|
+
status=AgentStatus.FATAL_ERROR,
|
|
245
|
+
error_message=f"Send message error: {exception!s}",
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# The stream has ended, but we didn't get a terminal response.
|
|
249
|
+
# Check if we received any events at all.
|
|
250
|
+
if events_received == 0:
|
|
251
|
+
structlogger.error(
|
|
252
|
+
"a2a_agent.run.no_events_received",
|
|
253
|
+
event_info="No events received from A2A agent after sending message",
|
|
254
|
+
agent_name=self._name,
|
|
255
|
+
)
|
|
256
|
+
return AgentOutput(
|
|
257
|
+
id=agent_input.id,
|
|
258
|
+
status=AgentStatus.RECOVERABLE_ERROR,
|
|
259
|
+
error_message="No events received from A2A agent",
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# Now we need to poll the task until it reaches a terminal state.
|
|
263
|
+
if not task_id:
|
|
264
|
+
structlogger.error(
|
|
265
|
+
"a2a_agent.run.pooling.missing_id",
|
|
266
|
+
event_info="Missing task_id for polling",
|
|
267
|
+
agent_name=self._name,
|
|
268
|
+
task_id=task_id,
|
|
269
|
+
)
|
|
270
|
+
return AgentOutput(
|
|
271
|
+
id=agent_input.id,
|
|
272
|
+
status=AgentStatus.FATAL_ERROR,
|
|
273
|
+
error_message="Missing task_id for polling",
|
|
274
|
+
)
|
|
275
|
+
return await self._pool_task_until_terminal(
|
|
276
|
+
agent_input=agent_input,
|
|
277
|
+
task_id=task_id,
|
|
278
|
+
max_wait=A2A_TASK_POOLING_MAX_WAIT,
|
|
279
|
+
initial_delay=A2A_TASK_POOLING_INITIAL_DELAY,
|
|
280
|
+
max_delay=MAX_AGENT_RETRY_DELAY_SECONDS,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
async def process_output(self, output: AgentOutput) -> AgentOutput:
|
|
284
|
+
"""Post-process the output before returning it to Rasa."""
|
|
285
|
+
# A2A-specific output processing logic
|
|
286
|
+
return output
|
|
287
|
+
|
|
288
|
+
# ============================================================================
|
|
289
|
+
# Message Processing & Response Handling
|
|
290
|
+
# ============================================================================
|
|
291
|
+
|
|
292
|
+
def _handle_send_message_response(
|
|
293
|
+
self, agent_input: AgentInput, response: ClientEvent | Message
|
|
294
|
+
) -> Optional[AgentOutput]:
|
|
295
|
+
"""Handle possible response types from the A2A client:
|
|
296
|
+
|
|
297
|
+
In case of streaming, the response can be either exactly *one* Message,
|
|
298
|
+
or a *series* of tuples of (Task, Optional[TaskUpdateEvent]).
|
|
299
|
+
|
|
300
|
+
In case of pooling, the response can be either exactly *one* Message,
|
|
301
|
+
or exactly *one* tuple of (Task, None).
|
|
302
|
+
|
|
303
|
+
If the agent response is terminal (i.e., completed, failed, etc.),
|
|
304
|
+
this method will return an AgentOutput.
|
|
305
|
+
Otherwise, the task is still in progress (i.e., submitted, working), so this
|
|
306
|
+
method will return None, so that the streaming or pooling agent can continue
|
|
307
|
+
to wait for updates.
|
|
308
|
+
"""
|
|
309
|
+
if isinstance(response, Message):
|
|
310
|
+
return self._handle_message_response(agent_input, response)
|
|
311
|
+
elif (
|
|
312
|
+
isinstance(response, tuple)
|
|
313
|
+
and len(response) == 2
|
|
314
|
+
and isinstance(response[0], Task)
|
|
315
|
+
):
|
|
316
|
+
return self._handle_client_event(agent_input, response)
|
|
317
|
+
else:
|
|
318
|
+
# Currently, no other response types exist, so this branch is
|
|
319
|
+
# unreachable. It is kept as a safeguard against future changes
|
|
320
|
+
# to the A2A protocol: if new response types are introduced,
|
|
321
|
+
# the agent will log an error instead of crashing.
|
|
322
|
+
return self._handle_unexpected_response_type(agent_input, response)
|
|
323
|
+
|
|
324
|
+
def _handle_json_rpc_error_response(
|
|
325
|
+
self, agent_input: AgentInput, error: Any
|
|
326
|
+
) -> AgentOutput:
|
|
327
|
+
structlogger.error(
|
|
328
|
+
"a2a_agent.run.error",
|
|
329
|
+
event_info="Received JSON-RPC error response from A2A agent",
|
|
330
|
+
agent_name=self._name,
|
|
331
|
+
error=str(error),
|
|
332
|
+
)
|
|
333
|
+
if isinstance(
|
|
334
|
+
error,
|
|
335
|
+
(
|
|
336
|
+
InternalError,
|
|
337
|
+
InvalidAgentResponseError,
|
|
338
|
+
),
|
|
339
|
+
):
|
|
340
|
+
return AgentOutput(
|
|
341
|
+
id=agent_input.id,
|
|
342
|
+
status=AgentStatus.RECOVERABLE_ERROR,
|
|
343
|
+
error_message=str(error),
|
|
344
|
+
)
|
|
345
|
+
else:
|
|
346
|
+
return AgentOutput(
|
|
347
|
+
id=agent_input.id,
|
|
348
|
+
status=AgentStatus.FATAL_ERROR,
|
|
349
|
+
error_message=str(error),
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
def _handle_client_event(
|
|
353
|
+
self, agent_input: AgentInput, client_event: ClientEvent
|
|
354
|
+
) -> Optional[AgentOutput]:
|
|
355
|
+
task = client_event[0]
|
|
356
|
+
update_event = client_event[1]
|
|
357
|
+
structlogger.debug(
|
|
358
|
+
"a2a_agent.run.client_event_received",
|
|
359
|
+
event_info="Received client event from A2A",
|
|
360
|
+
task=task.model_dump() if task else None,
|
|
361
|
+
update_event=update_event.model_dump() if update_event else None,
|
|
362
|
+
json_formatting=["task", "update_event"],
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
return self._handle_task(agent_input=agent_input, task=task)
|
|
366
|
+
|
|
367
|
+
def _handle_message_response(
|
|
368
|
+
self, agent_input: AgentInput, message: Message
|
|
369
|
+
) -> Optional[AgentOutput]:
|
|
370
|
+
structlogger.debug(
|
|
371
|
+
"a2a_agent.run.message_received",
|
|
372
|
+
event_info="Received message from A2A",
|
|
373
|
+
agent_name=self._name,
|
|
374
|
+
message=message.model_dump(),
|
|
375
|
+
json_formatting=["message"],
|
|
376
|
+
)
|
|
377
|
+
metadata = agent_input.metadata or {}
|
|
378
|
+
metadata[A2A_AGENT_CONTEXT_ID_KEY] = message.context_id
|
|
379
|
+
|
|
380
|
+
return AgentOutput(
|
|
381
|
+
id=agent_input.id,
|
|
382
|
+
status=AgentStatus.INPUT_REQUIRED,
|
|
383
|
+
response_message=self._generate_response_message_from_parts(message.parts),
|
|
384
|
+
metadata=metadata,
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
def _handle_unexpected_response_type(
|
|
388
|
+
self, agent_input: AgentInput, response_result: Any
|
|
389
|
+
) -> AgentOutput:
|
|
390
|
+
structlogger.error(
|
|
391
|
+
"a2a_agent.run.unexpected_response_type",
|
|
392
|
+
event_info="Received unexpected response type from A2A server "
|
|
393
|
+
"during streaming",
|
|
394
|
+
agent_name=self._name,
|
|
395
|
+
response_type=type(response_result),
|
|
396
|
+
)
|
|
397
|
+
return AgentOutput(
|
|
398
|
+
id=agent_input.id,
|
|
399
|
+
status=AgentStatus.FATAL_ERROR,
|
|
400
|
+
error_message=f"Unexpected response type: {type(response_result)}",
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
def _handle_task(
|
|
404
|
+
self,
|
|
405
|
+
agent_input: AgentInput,
|
|
406
|
+
task: Task,
|
|
407
|
+
) -> Optional[AgentOutput]:
|
|
408
|
+
"""If the task status is terminal (i.e., completed, failed, etc.),
|
|
409
|
+
return an AgentOutput.
|
|
410
|
+
If the task is still in progress (i.e., submitted, working), return None,
|
|
411
|
+
so that the streaming or pooling agent can continue to wait for updates.
|
|
412
|
+
"""
|
|
413
|
+
state = task.status.state
|
|
414
|
+
|
|
415
|
+
metadata = agent_input.metadata or {}
|
|
416
|
+
metadata[A2A_AGENT_CONTEXT_ID_KEY] = task.context_id
|
|
417
|
+
metadata[A2A_AGENT_TASK_ID_KEY] = task.id
|
|
418
|
+
|
|
419
|
+
if state == TaskState.input_required:
|
|
420
|
+
response_message = (
|
|
421
|
+
self._generate_response_message_from_parts(task.status.message.parts)
|
|
422
|
+
if task.status.message
|
|
423
|
+
else ""
|
|
424
|
+
) # This should not happen, but as type of message property
|
|
425
|
+
# is optional, so we need to handle it
|
|
426
|
+
return AgentOutput(
|
|
427
|
+
id=agent_input.id,
|
|
428
|
+
status=AgentStatus.INPUT_REQUIRED,
|
|
429
|
+
response_message=response_message,
|
|
430
|
+
metadata=metadata,
|
|
431
|
+
)
|
|
432
|
+
elif state == TaskState.completed:
|
|
433
|
+
response_message = self._generate_completed_response_message(task)
|
|
434
|
+
structured_results = (
|
|
435
|
+
self._generate_structured_results_from_artifacts(
|
|
436
|
+
agent_input, task.artifacts
|
|
437
|
+
)
|
|
438
|
+
if task.artifacts
|
|
439
|
+
else None
|
|
440
|
+
)
|
|
441
|
+
return AgentOutput(
|
|
442
|
+
id=agent_input.id,
|
|
443
|
+
status=AgentStatus.COMPLETED,
|
|
444
|
+
response_message=response_message,
|
|
445
|
+
structured_results=structured_results,
|
|
446
|
+
metadata=metadata,
|
|
447
|
+
)
|
|
448
|
+
elif (
|
|
449
|
+
state == TaskState.failed
|
|
450
|
+
or state == TaskState.canceled
|
|
451
|
+
or state == TaskState.rejected
|
|
452
|
+
or state == TaskState.auth_required
|
|
453
|
+
):
|
|
454
|
+
structlogger.error(
|
|
455
|
+
"a2a_agent.run_streaming_agent.unsuccessful_task_state",
|
|
456
|
+
event_info="Task execution finished with an unsuccessful state",
|
|
457
|
+
agent_name=self._name,
|
|
458
|
+
state=state,
|
|
459
|
+
)
|
|
460
|
+
return AgentOutput(
|
|
461
|
+
id=agent_input.id,
|
|
462
|
+
status=AgentStatus.RECOVERABLE_ERROR,
|
|
463
|
+
error_message=f"Task state: {state}",
|
|
464
|
+
metadata=metadata,
|
|
465
|
+
)
|
|
466
|
+
elif state == TaskState.submitted or state == TaskState.working:
|
|
467
|
+
# The task is still in progress, return None to continue waiting for updates
|
|
468
|
+
return None
|
|
469
|
+
elif state == TaskState.unknown:
|
|
470
|
+
# The task has an unknown state. Perhaps this is a transient condition.
|
|
471
|
+
# Return None to continue waiting for updates
|
|
472
|
+
structlogger.warning(
|
|
473
|
+
"a2a_agent.run_streaming_agent.unknown_task_state",
|
|
474
|
+
event_info="Task is in unknown state, continuing to wait for updates",
|
|
475
|
+
agent_name=self._name,
|
|
476
|
+
state=state,
|
|
477
|
+
)
|
|
478
|
+
return None
|
|
479
|
+
else:
|
|
480
|
+
structlogger.error(
|
|
481
|
+
"a2a_agent.run_streaming_agent.unexpected_task_state",
|
|
482
|
+
event_info="Unexpected task state received from A2A",
|
|
483
|
+
agent_name=self._name,
|
|
484
|
+
state=state,
|
|
485
|
+
)
|
|
486
|
+
return AgentOutput(
|
|
487
|
+
id=agent_input.id,
|
|
488
|
+
status=AgentStatus.FATAL_ERROR,
|
|
489
|
+
error_message=f"Unexpected task state: {state}",
|
|
490
|
+
metadata=metadata,
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
# ============================================================================
|
|
494
|
+
# Message Preparation & Formatting
|
|
495
|
+
# ============================================================================
|
|
496
|
+
|
|
497
|
+
@staticmethod
|
|
498
|
+
def _prepare_message(agent_input: AgentInput) -> Message:
|
|
499
|
+
parts: List[Part] = []
|
|
500
|
+
if agent_input.metadata and A2A_AGENT_CONTEXT_ID_KEY in agent_input.metadata:
|
|
501
|
+
# Agent knows the conversation history already, send the last
|
|
502
|
+
# user message only
|
|
503
|
+
parts.append(Part(root=TextPart(text=agent_input.user_message)))
|
|
504
|
+
else:
|
|
505
|
+
# Send the full conversation history
|
|
506
|
+
parts.append(Part(root=TextPart(text=agent_input.conversation_history)))
|
|
507
|
+
|
|
508
|
+
if len(agent_input.slots) > 0:
|
|
509
|
+
slots_dict: Dict[str, Any] = {
|
|
510
|
+
"slots": [
|
|
511
|
+
slot.model_dump(exclude={"type", "allowed_values"})
|
|
512
|
+
for slot in agent_input.slots
|
|
513
|
+
if slot.value is not None
|
|
514
|
+
]
|
|
515
|
+
}
|
|
516
|
+
parts.append(Part(root=DataPart(data=slots_dict)))
|
|
517
|
+
|
|
518
|
+
agent_message = Message(
|
|
519
|
+
role=Role.user,
|
|
520
|
+
parts=parts,
|
|
521
|
+
message_id=str(uuid.uuid4()),
|
|
522
|
+
context_id=agent_input.metadata.get(A2A_AGENT_CONTEXT_ID_KEY, None),
|
|
523
|
+
task_id=agent_input.metadata.get(A2A_AGENT_TASK_ID_KEY, None),
|
|
524
|
+
)
|
|
525
|
+
structlogger.debug(
|
|
526
|
+
"a2a_agent.prepare_message",
|
|
527
|
+
event_info="Prepared message to send to A2A server",
|
|
528
|
+
agent_name=agent_input.id,
|
|
529
|
+
message=agent_message.model_dump(),
|
|
530
|
+
json_formatting=["message"],
|
|
531
|
+
)
|
|
532
|
+
return agent_message
|
|
533
|
+
|
|
534
|
+
# ============================================================================
|
|
535
|
+
# Task Management & Polling
|
|
536
|
+
# ============================================================================
|
|
537
|
+
|
|
538
|
+
async def _pool_task_until_terminal(
|
|
539
|
+
self,
|
|
540
|
+
agent_input: AgentInput,
|
|
541
|
+
task_id: str,
|
|
542
|
+
max_wait: int,
|
|
543
|
+
initial_delay: float,
|
|
544
|
+
max_delay: int,
|
|
545
|
+
) -> AgentOutput:
|
|
546
|
+
"""Poll the task status until it reaches a terminal state or times out."""
|
|
547
|
+
if not self._client:
|
|
548
|
+
structlogger.error(
|
|
549
|
+
"a2a_agent.pool_task_until_terminal.error",
|
|
550
|
+
event_info="A2A client is not initialized. Call connect() first.",
|
|
551
|
+
)
|
|
552
|
+
return AgentOutput(
|
|
553
|
+
id=agent_input.id,
|
|
554
|
+
status=AgentStatus.FATAL_ERROR,
|
|
555
|
+
error_message="Client not initialized",
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
structlogger.debug(
|
|
559
|
+
"a2a_agent.pool_task_until_terminal.start",
|
|
560
|
+
event_info="Start polling task from A2A server",
|
|
561
|
+
agent_name=self._name,
|
|
562
|
+
task_id=task_id,
|
|
563
|
+
max_wait=max_wait,
|
|
564
|
+
initial_delay=initial_delay,
|
|
565
|
+
max_delay=max_delay,
|
|
566
|
+
)
|
|
567
|
+
start_time = time.monotonic()
|
|
568
|
+
delay = initial_delay
|
|
569
|
+
|
|
570
|
+
while True:
|
|
571
|
+
try:
|
|
572
|
+
task = await self._client.get_task(TaskQueryParams(id=task_id))
|
|
573
|
+
agent_output = self._handle_task(agent_input=agent_input, task=task)
|
|
574
|
+
if agent_output is not None:
|
|
575
|
+
# Reached a terminal state, return the output
|
|
576
|
+
return agent_output
|
|
577
|
+
|
|
578
|
+
elapsed = time.monotonic() - start_time
|
|
579
|
+
if elapsed >= max_wait:
|
|
580
|
+
structlogger.debug(
|
|
581
|
+
"a2a_agent.pool_task_until_terminal.timeout",
|
|
582
|
+
event_info="Polling task from A2A server timed out",
|
|
583
|
+
agent_name=self._name,
|
|
584
|
+
task_id=task_id,
|
|
585
|
+
elapsed=elapsed,
|
|
586
|
+
max_wait=max_wait,
|
|
587
|
+
)
|
|
588
|
+
return AgentOutput(
|
|
589
|
+
id=agent_input.id,
|
|
590
|
+
status=AgentStatus.FATAL_ERROR,
|
|
591
|
+
error_message="Polling timed out",
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
structlogger.error(
|
|
595
|
+
"a2a_agent.pool_task_until_terminal.waiting",
|
|
596
|
+
event_info="Task not in terminal state yet, waiting to poll again",
|
|
597
|
+
delay=delay,
|
|
598
|
+
agent_name=self._name,
|
|
599
|
+
task_id=task_id,
|
|
600
|
+
elapsed=elapsed,
|
|
601
|
+
max_wait=max_wait,
|
|
602
|
+
)
|
|
603
|
+
await asyncio.sleep(delay)
|
|
604
|
+
# Exponential backoff with cap
|
|
605
|
+
delay = min(delay * 2, max_delay)
|
|
606
|
+
|
|
607
|
+
except A2AClientError as exception:
|
|
608
|
+
structlogger.error(
|
|
609
|
+
"a2a_agent.pool_task_until_terminal.error",
|
|
610
|
+
event_info="Error during polling task from A2A server",
|
|
611
|
+
agent_name=self._name,
|
|
612
|
+
error=str(exception),
|
|
613
|
+
)
|
|
614
|
+
return AgentOutput(
|
|
615
|
+
id=agent_input.id,
|
|
616
|
+
status=AgentStatus.FATAL_ERROR,
|
|
617
|
+
error_message=f"Polling error: {exception!s}",
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
# ============================================================================
|
|
621
|
+
# Response Generation & Formatting
|
|
622
|
+
# ============================================================================
|
|
623
|
+
|
|
624
|
+
@staticmethod
|
|
625
|
+
def _generate_response_message_from_parts(parts: Optional[List[Part]]) -> str:
|
|
626
|
+
"""Convert a list of Part objects to a single string message."""
|
|
627
|
+
result = ""
|
|
628
|
+
if not parts:
|
|
629
|
+
return result
|
|
630
|
+
for part in parts:
|
|
631
|
+
if isinstance(part.root, TextPart):
|
|
632
|
+
result += part.root.text + "\n"
|
|
633
|
+
elif isinstance(part.root, DataPart):
|
|
634
|
+
# DataPart results will be returned as a part of the structured results,
|
|
635
|
+
# we don't need to include it in the response message
|
|
636
|
+
continue
|
|
637
|
+
elif isinstance(part.root, FilePart) and isinstance(
|
|
638
|
+
part.root.file, FileWithUri
|
|
639
|
+
):
|
|
640
|
+
# If the file is a FileWithUri, we can include the URI
|
|
641
|
+
result += f"File: {part.root.file.uri}\n"
|
|
642
|
+
else:
|
|
643
|
+
structlogger.warning(
|
|
644
|
+
"a2a_agent._parts_to_single_message.warning",
|
|
645
|
+
event_info="Unsupported part type encountered",
|
|
646
|
+
part_type=type(part.root),
|
|
647
|
+
)
|
|
648
|
+
return result.strip()
|
|
649
|
+
|
|
650
|
+
@staticmethod
|
|
651
|
+
def _generate_completed_response_message(task: Task) -> str:
|
|
652
|
+
"""Generate a response message for a completed task.
|
|
653
|
+
In case of completed tasks, the final message might be in
|
|
654
|
+
the task status message or in the artifacts (or both).
|
|
655
|
+
"""
|
|
656
|
+
# We need to preserve the order of the message,
|
|
657
|
+
# but also make sure to remove any duplicates.
|
|
658
|
+
result: List[str] = []
|
|
659
|
+
if task.status.message:
|
|
660
|
+
message = A2AAgent._generate_response_message_from_parts(
|
|
661
|
+
task.status.message.parts
|
|
662
|
+
)
|
|
663
|
+
if message and message not in result:
|
|
664
|
+
result.append(message)
|
|
665
|
+
if task.artifacts:
|
|
666
|
+
for artifact in task.artifacts:
|
|
667
|
+
message = A2AAgent._generate_response_message_from_parts(artifact.parts)
|
|
668
|
+
if message and message not in result:
|
|
669
|
+
result.append(message)
|
|
670
|
+
return "\n".join(result)
|
|
671
|
+
|
|
672
|
+
@staticmethod
|
|
673
|
+
def _generate_structured_results_from_artifacts(
|
|
674
|
+
agent_input: AgentInput, artifacts: List[Artifact]
|
|
675
|
+
) -> Optional[List[List[Dict[str, Any]]]]:
|
|
676
|
+
structured_results_of_current_iteration: List[Dict[str, Any]] = []
|
|
677
|
+
# There might be multiple artifacts in the response, each of them might
|
|
678
|
+
# contain multiple parts. We will treat each DataPart in each artifact
|
|
679
|
+
# as a separate tool result. The tool name will be the agent ID + index
|
|
680
|
+
# of the artifact + index of the part.
|
|
681
|
+
# E.g., foo_0_1, foo_0_2, foo_1_0, etc.
|
|
682
|
+
for artifact_index, artifact in enumerate(artifacts):
|
|
683
|
+
for part_index, part in enumerate(artifact.parts):
|
|
684
|
+
if isinstance(part.root, DataPart) and len(part.root.data) > 0:
|
|
685
|
+
structured_result = {
|
|
686
|
+
"name": f"{agent_input.id}_{artifact_index}_{part_index}",
|
|
687
|
+
"type": "data",
|
|
688
|
+
"result": part.root.data,
|
|
689
|
+
}
|
|
690
|
+
structured_results_of_current_iteration.append(structured_result)
|
|
691
|
+
elif isinstance(part.root, FilePart) and isinstance(
|
|
692
|
+
part.root.file, FileWithUri
|
|
693
|
+
):
|
|
694
|
+
structured_result = {
|
|
695
|
+
"name": f"{agent_input.id}_{artifact_index}_{part_index}",
|
|
696
|
+
"type": "file",
|
|
697
|
+
"result ": {
|
|
698
|
+
"uri": part.root.file.uri,
|
|
699
|
+
"name": part.root.file.name,
|
|
700
|
+
"mime_type": part.root.file.mime_type,
|
|
701
|
+
},
|
|
702
|
+
}
|
|
703
|
+
structured_results_of_current_iteration.append(structured_result)
|
|
704
|
+
|
|
705
|
+
previous_structured_results: List[List[Dict[str, Any]]] = (
|
|
706
|
+
agent_input.metadata.get(AGENT_METADATA_STRUCTURED_RESULTS_KEY, []) or []
|
|
707
|
+
)
|
|
708
|
+
previous_structured_results.append(structured_results_of_current_iteration)
|
|
709
|
+
|
|
710
|
+
return previous_structured_results
|
|
711
|
+
|
|
712
|
+
# ============================================================================
|
|
713
|
+
# Agent Card Management
|
|
714
|
+
# ============================================================================
|
|
715
|
+
|
|
716
|
+
@staticmethod
|
|
717
|
+
def _load_agent_card_from_file(agent_card_path: str) -> AgentCard:
|
|
718
|
+
"""Load agent card from JSON file."""
|
|
719
|
+
try:
|
|
720
|
+
with open(os.path.abspath(agent_card_path), "r") as f:
|
|
721
|
+
card_data = json.load(f)
|
|
722
|
+
return AgentCard.model_validate(card_data)
|
|
723
|
+
|
|
724
|
+
except FileNotFoundError as e:
|
|
725
|
+
raise AgentInitializationException(
|
|
726
|
+
f"Agent card file not found: {agent_card_path}"
|
|
727
|
+
) from e
|
|
728
|
+
except (IOError, PermissionError) as e:
|
|
729
|
+
raise AgentInitializationException(
|
|
730
|
+
f"Error reading agent card file {agent_card_path}: {e}"
|
|
731
|
+
) from e
|
|
732
|
+
except json.JSONDecodeError as e:
|
|
733
|
+
raise AgentInitializationException(
|
|
734
|
+
f"Invalid JSON in agent card file {agent_card_path}: {e}"
|
|
735
|
+
) from e
|
|
736
|
+
except ValidationError as e:
|
|
737
|
+
raise AgentInitializationException(
|
|
738
|
+
f"Failed to load agent card from {agent_card_path}: {e}"
|
|
739
|
+
) from e
|
|
740
|
+
|
|
741
|
+
@staticmethod
|
|
742
|
+
async def _resolve_agent_card_with_retry(
|
|
743
|
+
agent_card_path: str, timeout: int, max_retries: int
|
|
744
|
+
) -> AgentCard:
|
|
745
|
+
"""Resolve the agent card from a given path or URL."""
|
|
746
|
+
# split agent_card_path into base URL and path
|
|
747
|
+
try:
|
|
748
|
+
url_parts = urlparse(agent_card_path)
|
|
749
|
+
base_url = f"{url_parts.scheme}://{url_parts.netloc}"
|
|
750
|
+
path = url_parts.path
|
|
751
|
+
except ValueError:
|
|
752
|
+
raise RasaException(f"Could not parse the URL: '{agent_card_path}'.")
|
|
753
|
+
structlogger.debug(
|
|
754
|
+
"a2a_agent.resolve_agent_card",
|
|
755
|
+
event_info="Resolving agent card from remote URL",
|
|
756
|
+
agent_card_path=agent_card_path,
|
|
757
|
+
base_url=base_url,
|
|
758
|
+
path=path,
|
|
759
|
+
timeout=timeout,
|
|
760
|
+
)
|
|
761
|
+
|
|
762
|
+
for attempt in range(max_retries):
|
|
763
|
+
if attempt > 0:
|
|
764
|
+
structlogger.debug(
|
|
765
|
+
"a2a_agent.resolve_agent_card.retrying",
|
|
766
|
+
agent_card_path=f"{base_url}/{path}",
|
|
767
|
+
attempt=attempt + 1,
|
|
768
|
+
num_retries=max_retries,
|
|
769
|
+
)
|
|
770
|
+
|
|
771
|
+
try:
|
|
772
|
+
agent_card = await A2ACardResolver(
|
|
773
|
+
httpx.AsyncClient(timeout=timeout),
|
|
774
|
+
base_url=base_url,
|
|
775
|
+
agent_card_path=path,
|
|
776
|
+
).get_agent_card()
|
|
777
|
+
|
|
778
|
+
if agent_card:
|
|
779
|
+
return agent_card
|
|
780
|
+
except (A2AClientHTTPError, A2AClientJSONError) as exception:
|
|
781
|
+
structlogger.warning(
|
|
782
|
+
"a2a_agent.resolve_agent_card.error",
|
|
783
|
+
event_info="Error while resolving agent card",
|
|
784
|
+
agent_card_path=agent_card_path,
|
|
785
|
+
attempt=attempt + 1,
|
|
786
|
+
num_retries=max_retries,
|
|
787
|
+
error=str(exception),
|
|
788
|
+
)
|
|
789
|
+
if attempt < max_retries - 1:
|
|
790
|
+
# exponential backoff - wait longer with each retry
|
|
791
|
+
# 1 second, 2 seconds, 4 seconds, etc.
|
|
792
|
+
await asyncio.sleep(min(2**attempt, MAX_AGENT_RETRY_DELAY_SECONDS))
|
|
793
|
+
|
|
794
|
+
raise AgentInitializationException(
|
|
795
|
+
f"Failed to resolve agent card from {agent_card_path} after "
|
|
796
|
+
f"{max_retries} attempts."
|
|
797
|
+
)
|
|
798
|
+
|
|
799
|
+
# ============================================================================
|
|
800
|
+
# Client Initialization & Health Checks
|
|
801
|
+
# ============================================================================
|
|
802
|
+
|
|
803
|
+
def _init_client(self) -> Client:
|
|
804
|
+
_agent_manager = AgentAuthManager.load_auth(self._auth_config)
|
|
805
|
+
auth_strategy = _agent_manager.get_auth() if _agent_manager else None
|
|
806
|
+
factory = ClientFactory(
|
|
807
|
+
config=ClientConfig(
|
|
808
|
+
httpx_client=httpx.AsyncClient(
|
|
809
|
+
timeout=self._timeout, auth=auth_strategy
|
|
810
|
+
),
|
|
811
|
+
streaming=True,
|
|
812
|
+
supported_transports=[
|
|
813
|
+
TransportProtocol.jsonrpc,
|
|
814
|
+
TransportProtocol.http_json,
|
|
815
|
+
TransportProtocol.grpc,
|
|
816
|
+
],
|
|
817
|
+
accepted_output_modes=self.__SUPPORTED_OUTPUT_MODES,
|
|
818
|
+
)
|
|
819
|
+
)
|
|
820
|
+
return factory.create(self.agent_card)
|
|
821
|
+
|
|
822
|
+
async def _perform_health_check(self) -> None:
|
|
823
|
+
if not self._client or not self.agent_card:
|
|
824
|
+
structlogger.error(
|
|
825
|
+
"a2a_agent.health_check.error",
|
|
826
|
+
event_info="A2A client is not initialized. Call connect() first.",
|
|
827
|
+
)
|
|
828
|
+
raise AgentInitializationException("Client not initialized")
|
|
829
|
+
|
|
830
|
+
try:
|
|
831
|
+
test_message = Message(
|
|
832
|
+
role=Role.user,
|
|
833
|
+
parts=[Part(root=TextPart(text="hello"))],
|
|
834
|
+
message_id=str(uuid.uuid4()),
|
|
835
|
+
)
|
|
836
|
+
async for event in self._client.send_message(test_message):
|
|
837
|
+
if (
|
|
838
|
+
isinstance(event, Message)
|
|
839
|
+
or isinstance(event, tuple)
|
|
840
|
+
and len(event) == 2
|
|
841
|
+
and isinstance(event[0], Task)
|
|
842
|
+
):
|
|
843
|
+
# We got a valid response, health check succeeded
|
|
844
|
+
return
|
|
845
|
+
|
|
846
|
+
event_info = "Unexpected response type during health check"
|
|
847
|
+
structlogger.error(
|
|
848
|
+
"a2a_agent.health_check.unexpected_response",
|
|
849
|
+
event_info=event_info,
|
|
850
|
+
agent_name=self._name,
|
|
851
|
+
response=event,
|
|
852
|
+
url=str(self.agent_card.url),
|
|
853
|
+
)
|
|
854
|
+
raise AgentInitializationException(f"{event_info}: {event}")
|
|
855
|
+
# If the loop completes with no return, no events were received
|
|
856
|
+
event_info = (
|
|
857
|
+
f"Health check failed for A2A agent '{self._name}' "
|
|
858
|
+
f"at {self.agent_card.url}: no events received"
|
|
859
|
+
)
|
|
860
|
+
structlogger.error(
|
|
861
|
+
"a2a_agent.health_check.no_events",
|
|
862
|
+
event_info=event_info,
|
|
863
|
+
agent_name=self._name,
|
|
864
|
+
url=str(self.agent_card.url),
|
|
865
|
+
)
|
|
866
|
+
raise AgentInitializationException(event_info)
|
|
867
|
+
except Exception as exception:
|
|
868
|
+
event_info = (
|
|
869
|
+
f"Health check failed for A2A agent '{self._name}' at "
|
|
870
|
+
f"{self.agent_card.url}: {exception!s}"
|
|
871
|
+
)
|
|
872
|
+
structlogger.error(
|
|
873
|
+
"a2a_agent.health_check.failed",
|
|
874
|
+
event_info=event_info,
|
|
875
|
+
agent_name=self._name,
|
|
876
|
+
error=str(exception),
|
|
877
|
+
url=str(self.agent_card.url),
|
|
878
|
+
)
|
|
879
|
+
raise AgentInitializationException(event_info) from exception
|