rasa-pro 3.14.0.dev7__py3-none-any.whl → 3.14.0.dev9__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/agents/agent_manager.py +1 -1
- rasa/agents/constants.py +2 -2
- rasa/agents/protocol/a2a/a2a_agent.py +385 -227
- rasa/agents/protocol/mcp/mcp_base_agent.py +30 -13
- rasa/agents/protocol/mcp/mcp_open_agent.py +31 -8
- rasa/agents/protocol/mcp/mcp_task_agent.py +32 -9
- rasa/agents/schemas/agent_output.py +1 -1
- rasa/agents/utils.py +90 -1
- rasa/builder/README.md +120 -0
- rasa/builder/__init__.py +0 -0
- rasa/builder/auth.py +176 -0
- rasa/builder/config.py +92 -0
- rasa/builder/copilot/__init__.py +0 -0
- rasa/builder/copilot/constants.py +31 -0
- rasa/builder/copilot/copilot.py +450 -0
- rasa/builder/copilot/copilot_response_handler.py +522 -0
- rasa/builder/copilot/copilot_templated_message_provider.py +58 -0
- rasa/builder/copilot/exceptions.py +32 -0
- rasa/builder/copilot/models.py +500 -0
- rasa/builder/copilot/prompts/__init__.py +0 -0
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +766 -0
- rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +61 -0
- rasa/builder/copilot/signing.py +305 -0
- rasa/builder/copilot/telemetry.py +210 -0
- rasa/builder/copilot/templated_messages/__init__.py +0 -0
- rasa/builder/copilot/templated_messages/copilot_internal_messages_templates.yml +16 -0
- rasa/builder/copilot/templated_messages/copilot_templated_responses.yml +38 -0
- rasa/builder/document_retrieval/__init__.py +0 -0
- rasa/builder/document_retrieval/constants.py +15 -0
- rasa/builder/document_retrieval/inkeep-rag-response-schema.json +64 -0
- rasa/builder/document_retrieval/inkeep_document_retrieval.py +238 -0
- rasa/builder/document_retrieval/models.py +62 -0
- rasa/builder/download.py +140 -0
- rasa/builder/exceptions.py +91 -0
- rasa/builder/guardrails/__init__.py +1 -0
- rasa/builder/guardrails/constants.py +9 -0
- rasa/builder/guardrails/exceptions.py +4 -0
- rasa/builder/guardrails/lakera.py +206 -0
- rasa/builder/guardrails/models.py +231 -0
- rasa/builder/guardrails/store.py +238 -0
- rasa/builder/guardrails/utils.py +328 -0
- rasa/builder/job_manager.py +87 -0
- rasa/builder/jobs.py +282 -0
- rasa/builder/llm_service.py +246 -0
- rasa/builder/logging_utils.py +265 -0
- rasa/builder/main.py +243 -0
- rasa/builder/models.py +216 -0
- rasa/builder/project_generator.py +458 -0
- rasa/builder/project_info.py +72 -0
- rasa/builder/scrape_rasa_docs.py +97 -0
- rasa/builder/service.py +1345 -0
- rasa/builder/shared/tracker_context.py +212 -0
- rasa/builder/skill_to_bot_prompt.jinja2 +164 -0
- rasa/builder/template_cache.py +244 -0
- rasa/builder/training_service.py +194 -0
- rasa/builder/validation_service.py +97 -0
- rasa/cli/project_templates/basic/README.md +23 -0
- rasa/cli/project_templates/basic/actions/__init__ +0 -0
- rasa/cli/project_templates/basic/actions/action_human_handoff.py +40 -0
- rasa/cli/project_templates/basic/actions/actions.md +10 -0
- rasa/cli/project_templates/basic/config.yml +29 -0
- rasa/cli/project_templates/basic/credentials.yml +33 -0
- rasa/cli/project_templates/basic/data/data.md +9 -0
- rasa/cli/project_templates/basic/data/general/feedback.yml +21 -0
- rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/basic/data/general/hello.yml +6 -0
- rasa/cli/project_templates/basic/data/general/help.yml +6 -0
- rasa/cli/project_templates/basic/data/general/human_handoff.yml +16 -0
- rasa/cli/project_templates/basic/data/general/show_faqs.yml +6 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_cannot_handle.yml +7 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_completed.yml +7 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_correction.yml +7 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_search.yml +8 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_session_start.yml +8 -0
- rasa/cli/project_templates/basic/docs/docs.md +5 -0
- rasa/cli/project_templates/basic/docs/template.txt +28 -0
- rasa/cli/project_templates/basic/domain/domain.md +8 -0
- rasa/cli/project_templates/basic/domain/general/feedback.yml +25 -0
- rasa/cli/project_templates/basic/domain/general/goodbye.yml +9 -0
- rasa/cli/project_templates/basic/domain/general/hello.yml +7 -0
- rasa/cli/project_templates/basic/domain/general/help.yml +21 -0
- rasa/cli/project_templates/basic/domain/general/human_handoff.yml +32 -0
- rasa/cli/project_templates/basic/domain/general/show_faqs.yml +14 -0
- rasa/cli/project_templates/basic/domain/system/patterns/pattern_cannot_handle.yml +5 -0
- rasa/cli/project_templates/basic/domain/system/patterns/pattern_session_start.yml +19 -0
- rasa/cli/project_templates/basic/endpoints.yml +67 -0
- rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +38 -0
- 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 +25 -0
- rasa/cli/project_templates/finance/actions/__init__.py +46 -0
- rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/accounts/action_ask_account.py +47 -0
- rasa/cli/project_templates/finance/actions/accounts/action_check_balance.py +40 -0
- rasa/cli/project_templates/finance/actions/action_session_start.py +74 -0
- rasa/cli/project_templates/finance/actions/actions.md +15 -0
- rasa/cli/project_templates/finance/actions/cards/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/cards/action_ask_card.py +48 -0
- rasa/cli/project_templates/finance/actions/cards/action_check_card_existence.py +36 -0
- rasa/cli/project_templates/finance/actions/cards/action_update_card_status.py +54 -0
- rasa/cli/project_templates/finance/actions/database.py +277 -0
- rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/transfers/action_add_payee.py +52 -0
- rasa/cli/project_templates/finance/actions/transfers/action_ask_account_from.py +51 -0
- rasa/cli/project_templates/finance/actions/transfers/action_check_payee_existence.py +40 -0
- rasa/cli/project_templates/finance/actions/transfers/action_check_sufficient_funds.py +40 -0
- rasa/cli/project_templates/finance/actions/transfers/action_list_payees.py +46 -0
- rasa/cli/project_templates/finance/actions/transfers/action_process_immediate_payment.py +18 -0
- rasa/cli/project_templates/finance/actions/transfers/action_remove_payee.py +49 -0
- rasa/cli/project_templates/finance/actions/transfers/action_schedule_payment.py +19 -0
- rasa/cli/project_templates/finance/actions/transfers/action_validate_payment_date.py +36 -0
- rasa/cli/project_templates/finance/config.yml +23 -0
- rasa/cli/project_templates/finance/credentials.yml +32 -0
- rasa/cli/project_templates/finance/csvs/accounts.csv +8 -0
- rasa/cli/project_templates/finance/csvs/advisors.csv +7 -0
- rasa/cli/project_templates/finance/csvs/appointments.csv +211 -0
- rasa/cli/project_templates/finance/csvs/branches.csv +10 -0
- rasa/cli/project_templates/finance/csvs/cards.csv +11 -0
- rasa/cli/project_templates/finance/csvs/payees.csv +11 -0
- rasa/cli/project_templates/finance/csvs/transactions.csv +71 -0
- rasa/cli/project_templates/finance/csvs/users.csv +4 -0
- rasa/cli/project_templates/finance/data/accounts/check_balance.yml +10 -0
- rasa/cli/project_templates/finance/data/cards/block_card.yml +66 -0
- rasa/cli/project_templates/finance/data/cards/select_card.yml +12 -0
- rasa/cli/project_templates/finance/data/data.md +11 -0
- rasa/cli/project_templates/finance/data/general/bot_identity.yml +6 -0
- rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
- rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/finance/data/general/hello.yml +7 -0
- rasa/cli/project_templates/finance/data/general/help.yml +9 -0
- rasa/cli/project_templates/finance/data/general/human_handoff.yml +16 -0
- rasa/cli/project_templates/finance/data/general/welcome.yml +9 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_chitchat.yml +5 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_completed.yml +7 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_correction.yml +7 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_search.yml +8 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +8 -0
- rasa/cli/project_templates/finance/data/system/source/accounts.json +51 -0
- rasa/cli/project_templates/finance/data/system/source/advisors.json +44 -0
- rasa/cli/project_templates/finance/data/system/source/appointments.json +1474 -0
- rasa/cli/project_templates/finance/data/system/source/branches.json +47 -0
- rasa/cli/project_templates/finance/data/system/source/cards.json +72 -0
- rasa/cli/project_templates/finance/data/system/source/payees.json +74 -0
- rasa/cli/project_templates/finance/data/system/source/transactions.json +492 -0
- rasa/cli/project_templates/finance/data/system/source/users.json +29 -0
- rasa/cli/project_templates/finance/data/transfers/add_payee.yml +29 -0
- rasa/cli/project_templates/finance/data/transfers/list_payees.yml +5 -0
- rasa/cli/project_templates/finance/data/transfers/remove_payee.yml +21 -0
- rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +67 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +7 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +8 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +48 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +47 -0
- rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +11 -0
- rasa/cli/project_templates/finance/domain/cards/block_card.yml +101 -0
- rasa/cli/project_templates/finance/domain/cards/select_card.yml +12 -0
- rasa/cli/project_templates/finance/domain/domain.md +10 -0
- rasa/cli/project_templates/finance/domain/general/agent_details.yml +12 -0
- rasa/cli/project_templates/finance/domain/general/bot_identity.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/defaults.yml +24 -0
- rasa/cli/project_templates/finance/domain/general/feedback.yml +28 -0
- rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/finance/domain/general/help.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/human_handoff.yml +30 -0
- rasa/cli/project_templates/finance/domain/general/utils.yml +13 -0
- rasa/cli/project_templates/finance/domain/general/welcome.yml +8 -0
- rasa/cli/project_templates/finance/domain/transfers/add_payee.yml +47 -0
- rasa/cli/project_templates/finance/domain/transfers/list_payees.yml +4 -0
- rasa/cli/project_templates/finance/domain/transfers/remove_payee.yml +16 -0
- rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +79 -0
- rasa/cli/project_templates/finance/endpoints.yml +66 -0
- rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
- rasa/cli/project_templates/telco/README.md +25 -0
- rasa/cli/project_templates/telco/actions/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/actions.md +12 -0
- rasa/cli/project_templates/telco/actions/billing/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/billing/actions_billing.py +204 -0
- rasa/cli/project_templates/telco/actions/general/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/general/action_human_handoff.py +49 -0
- rasa/cli/project_templates/telco/actions/network/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/network/actions_get_data_from_db.py +48 -0
- rasa/cli/project_templates/telco/actions/network/actions_run_diagnostics.py +28 -0
- rasa/cli/project_templates/telco/actions/network/actions_session_start.py +18 -0
- rasa/cli/project_templates/telco/config.yml +29 -0
- rasa/cli/project_templates/telco/credentials.yml +33 -0
- rasa/cli/project_templates/telco/csvs/billing.csv +19 -0
- rasa/cli/project_templates/telco/csvs/customers.csv +5 -0
- rasa/cli/project_templates/telco/data/billing/flow_understand_bill.yml +45 -0
- rasa/cli/project_templates/telco/data/data.md +11 -0
- rasa/cli/project_templates/telco/data/general/bot_challenge.yml +6 -0
- rasa/cli/project_templates/telco/data/general/feedback.yml +20 -0
- rasa/cli/project_templates/telco/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/telco/data/general/hello.yml +6 -0
- rasa/cli/project_templates/telco/data/general/human_handoff.yml +16 -0
- rasa/cli/project_templates/telco/data/general/patterns.yml +30 -0
- rasa/cli/project_templates/telco/data/network/flow_reboot_router.yml +8 -0
- rasa/cli/project_templates/telco/data/network/flow_reset_router.yml +7 -0
- rasa/cli/project_templates/telco/data/network/flow_solve_internet_issue.yml +73 -0
- rasa/cli/project_templates/telco/docs/docs.md +5 -0
- rasa/cli/project_templates/telco/docs/network/reset_vs_rboot_router.txt +1 -0
- rasa/cli/project_templates/telco/docs/network/restart_router.txt +6 -0
- rasa/cli/project_templates/telco/docs/network/run_speed_test.txt +6 -0
- rasa/cli/project_templates/telco/domain/billing/understand_bill.yml +102 -0
- rasa/cli/project_templates/telco/domain/domain.md +14 -0
- rasa/cli/project_templates/telco/domain/general/bot_challenge.yml +4 -0
- rasa/cli/project_templates/telco/domain/general/feedback.yml +25 -0
- rasa/cli/project_templates/telco/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/telco/domain/general/hello.yml +5 -0
- rasa/cli/project_templates/telco/domain/general/human_handoff.yml +26 -0
- rasa/cli/project_templates/telco/domain/general/patterns.yml +33 -0
- rasa/cli/project_templates/telco/domain/network/reboot_router.yml +21 -0
- rasa/cli/project_templates/telco/domain/network/reset_router.yml +12 -0
- rasa/cli/project_templates/telco/domain/network/run_speed_test.yml +25 -0
- rasa/cli/project_templates/telco/domain/network/solve_internet_issue.yml +75 -0
- rasa/cli/project_templates/telco/domain/shared.yml +129 -0
- rasa/cli/project_templates/telco/endpoints.yml +67 -0
- rasa/cli/project_templates/telco/prompts/rephraser_demo_personality_prompt.jinja2 +40 -0
- 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/config.yml +2 -1
- rasa/cli/scaffold.py +46 -2
- rasa/core/actions/action.py +0 -1
- rasa/core/available_agents.py +2 -0
- rasa/core/available_endpoints.py +17 -2
- rasa/core/channels/channel.py +4 -3
- rasa/core/channels/constants.py +3 -0
- rasa/core/channels/development_inspector.py +2 -22
- rasa/core/channels/inspector/README.md +26 -14
- rasa/core/channels/inspector/dist/assets/{arc-cce7e0a8.js → arc-edef10dd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-e2a49be7.js → blockDiagram-38ab4fdb-49f6762b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-3def7895.js → c4Diagram-3d4e48cf-313c08e6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-63aa27d1.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-e66fe4df.js → classDiagram-70f12bd4-35e41ce9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-eb874aaa.js → classDiagram-v2-f2320105-f346068d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-5566bae8.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-cf934643.js → createText-2e5e7dd3-7a44bce8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-8fdf9155.js → edges-e0da2a9e-d7cf78c7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-6106fb96.js → erDiagram-9861fffd-9813e81c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4c2bb040.js → flowDb-956e92f1-d8ba0870.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f0ff96af.js → flowDiagram-66a62f08-51f0db4d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-32936074.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-a21707ec.js → flowchart-elk-definition-4a651766-ff9ea384.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-c165acb1.js → ganttDiagram-c361ad54-a8e13b6b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-b0564cf1.js → gitGraphDiagram-72cf32ee-3b171c6d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-e557e67a.js → graph-790ef78b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-1ce60e9e.js → index-3862675e-ecdce073.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-d705da80.js +1352 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-893569e2.js → infoDiagram-f8f76790-f5a422fe.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-c29c864f.js → journeyDiagram-49397b02-3185b7ac.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-649a5eae.js → layout-837fd3aa.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-0e5685ed.js → line-7e05afcb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-eaa320bd.js → linear-162eb295.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-f35df9e6.js → mindmap-definition-fc14e90a-f4978aee.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78339e96.js → pieDiagram-8a3498a8-b25d0a52.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-9b5f2f14.js → quadrantDiagram-120e2f19-63db1afa.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d05ddb3a.js → requirementDiagram-deff3bca-1b486cc9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-d9be5dfd.js → sankeyDiagram-04a897e0-7e795291.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-0f1c4348.js → sequenceDiagram-704730f1-b8aba159.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-9ddf63b3.js → stateDiagram-587899a1-41529fd5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-bc2b81ed.js → stateDiagram-v2-d93cdb3a-b241043c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0a287936.js → styles-6aaf32cf-b5b53234.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-e3941990.js → styles-9a916d00-13d138e5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-ce4eca24.js → styles-c10674c1-94cbde3f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-d822b1a8.js → svgDrawCommon-08f97a94-453ae764.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-e144c7a7.js → timeline-definition-85554ec2-8dcb88a4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-ab7f4e14.js → xychartDiagram-e933f94c-376af5f0.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +2 -2
- rasa/core/channels/inspector/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +16 -42
- rasa/core/channels/inspector/src/components/Chat.tsx +2 -3
- rasa/core/channels/inspector/src/components/DialogueHistoryStack.tsx +1 -0
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +20 -3
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +63 -35
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +14 -0
- rasa/core/channels/inspector/src/types.ts +32 -7
- rasa/core/channels/socketio.py +212 -51
- rasa/core/channels/studio_chat.py +59 -57
- 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 +53 -3
- rasa/core/channels/voice_stream/genesys.py +2 -1
- rasa/core/channels/voice_stream/jambonz.py +9 -1
- rasa/core/channels/voice_stream/twilio_media_streams.py +16 -0
- rasa/core/channels/voice_stream/voice_channel.py +66 -3
- rasa/core/constants.py +6 -0
- rasa/core/iam_credentials_providers/__init__.py +0 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +66 -0
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +89 -0
- rasa/core/policies/enterprise_search_policy.py +4 -7
- rasa/core/policies/flows/flow_executor.py +14 -5
- rasa/core/policies/ted_policy.py +7 -5
- rasa/core/processor.py +32 -0
- rasa/core/redis_connection_factory.py +411 -0
- rasa/core/run.py +13 -3
- rasa/core/tracker_stores/redis_tracker_store.py +32 -14
- rasa/core/tracker_stores/sql_tracker_store.py +57 -1
- rasa/dialogue_understanding/generator/flow_retrieval.py +10 -9
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +10 -5
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +10 -5
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +20 -12
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +19 -12
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +6 -35
- rasa/dialogue_understanding/patterns/cancel.py +27 -6
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +1 -1
- rasa/dialogue_understanding/processor/command_processor.py +35 -0
- rasa/engine/graph.py +5 -1
- rasa/engine/recipes/default_components.py +78 -10
- rasa/engine/recipes/default_recipe.py +41 -1
- rasa/engine/storage/local_model_storage.py +83 -3
- rasa/graph_components/validators/default_recipe_validator.py +153 -135
- rasa/model_manager/model_api.py +4 -5
- rasa/model_manager/runner_service.py +1 -1
- rasa/model_manager/socket_bridge.py +20 -15
- rasa/model_manager/trainer_service.py +12 -9
- rasa/model_manager/utils.py +1 -29
- rasa/model_manager/warm_rasa_process.py +1 -1
- rasa/model_training.py +14 -0
- rasa/nlu/classifiers/diet_classifier.py +22 -6
- rasa/nlu/classifiers/logistic_regression_classifier.py +18 -0
- rasa/nlu/extractors/extractor.py +1 -2
- rasa/shared/agents/auth/__init__.py +0 -0
- rasa/shared/agents/auth/agent_auth_factory.py +74 -0
- rasa/shared/agents/auth/agent_auth_manager.py +86 -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 +159 -0
- rasa/shared/agents/auth/constants.py +11 -0
- rasa/shared/agents/auth/types.py +11 -0
- rasa/shared/core/constants.py +1 -0
- rasa/shared/core/domain.py +58 -11
- rasa/shared/core/events.py +2 -0
- rasa/shared/core/flows/constants.py +5 -0
- rasa/shared/core/flows/flow_step.py +7 -1
- rasa/shared/core/flows/flows_list.py +6 -0
- rasa/shared/core/flows/steps/call.py +15 -12
- rasa/shared/core/flows/validation.py +238 -44
- rasa/shared/core/flows/yaml_flows_io.py +15 -6
- rasa/shared/core/slots.py +4 -0
- rasa/shared/exceptions.py +12 -0
- rasa/shared/importers/importer.py +6 -0
- rasa/shared/importers/utils.py +77 -1
- rasa/shared/nlu/training_data/schemas/responses.yml +3 -0
- rasa/shared/providers/_utils.py +60 -44
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +2 -0
- rasa/shared/providers/llm/_base_litellm_client.py +2 -2
- rasa/shared/providers/llm/default_litellm_llm_client.py +2 -0
- rasa/shared/providers/llm/llm_response.py +4 -4
- rasa/shared/utils/common.py +24 -0
- rasa/shared/utils/llm.py +2 -1
- rasa/shared/utils/mcp/server_connection.py +84 -23
- rasa/shared/utils/mcp/utils.py +20 -0
- rasa/studio/upload.py +16 -47
- rasa/telemetry.py +97 -23
- rasa/tracing/config.py +38 -12
- rasa/tracing/instrumentation/attribute_extractors.py +5 -1
- rasa/tracing/instrumentation/instrumentation.py +85 -8
- rasa/utils/common.py +1 -1
- rasa/utils/io.py +27 -9
- rasa/utils/json_utils.py +6 -1
- rasa/utils/log_utils.py +5 -1
- rasa/utils/openapi.py +144 -0
- rasa/utils/tensorflow/__init__.py +29 -0
- rasa/utils/tensorflow/callback.py +1 -1
- rasa/utils/tensorflow/crf.py +1 -1
- rasa/utils/tensorflow/data_generator.py +21 -8
- rasa/utils/tensorflow/layers.py +11 -4
- rasa/utils/tensorflow/metrics.py +7 -3
- rasa/utils/tensorflow/models.py +41 -6
- rasa/utils/tensorflow/rasa_layers.py +6 -4
- rasa/utils/tensorflow/transformer.py +2 -3
- rasa/utils/train_utils.py +68 -38
- rasa/validator.py +18 -16
- rasa/version.py +1 -1
- rasa_pro-3.14.0.dev9.dist-info/METADATA +199 -0
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/RECORD +466 -156
- rasa/core/channels/inspector/dist/assets/channel-858c2c20.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-4b80996c.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-16f09b7a.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-996fe816.js +0 -1353
- rasa_pro-3.14.0.dev7.dist-info/METADATA +0 -190
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/entry_points.txt +0 -0
|
@@ -1,50 +1,49 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
+
import time
|
|
4
5
|
import uuid
|
|
5
|
-
from typing import Any, Dict, List, Optional
|
|
6
|
+
from typing import Any, ClassVar, Dict, List, Optional
|
|
6
7
|
from urllib.parse import urlparse
|
|
7
8
|
|
|
8
9
|
import httpx
|
|
9
10
|
import structlog
|
|
10
11
|
from a2a.client import (
|
|
11
12
|
A2ACardResolver,
|
|
12
|
-
A2AClient,
|
|
13
13
|
A2AClientError,
|
|
14
14
|
A2AClientHTTPError,
|
|
15
15
|
A2AClientJSONError,
|
|
16
|
+
Client,
|
|
17
|
+
ClientConfig,
|
|
18
|
+
ClientEvent,
|
|
19
|
+
ClientFactory,
|
|
16
20
|
)
|
|
21
|
+
from a2a.client.errors import A2AClientJSONRPCError
|
|
17
22
|
from a2a.types import (
|
|
18
|
-
AgentCapabilities,
|
|
19
23
|
AgentCard,
|
|
20
|
-
|
|
24
|
+
Artifact,
|
|
21
25
|
DataPart,
|
|
22
26
|
FilePart,
|
|
23
27
|
FileWithUri,
|
|
24
28
|
InternalError,
|
|
25
29
|
InvalidAgentResponseError,
|
|
26
|
-
JSONRPCErrorResponse,
|
|
27
30
|
Message,
|
|
28
|
-
MessageSendConfiguration,
|
|
29
|
-
MessageSendParams,
|
|
30
31
|
Part,
|
|
31
32
|
Role,
|
|
32
|
-
SendStreamingMessageRequest,
|
|
33
|
-
SendStreamingMessageResponse,
|
|
34
33
|
Task,
|
|
35
|
-
|
|
34
|
+
TaskQueryParams,
|
|
36
35
|
TaskState,
|
|
37
|
-
TaskStatus,
|
|
38
|
-
TaskStatusUpdateEvent,
|
|
39
36
|
TextPart,
|
|
37
|
+
TransportProtocol,
|
|
40
38
|
)
|
|
39
|
+
from pydantic import ValidationError
|
|
41
40
|
|
|
42
41
|
from rasa.agents.constants import (
|
|
43
42
|
A2A_AGENT_CONTEXT_ID_KEY,
|
|
44
43
|
A2A_AGENT_TASK_ID_KEY,
|
|
45
44
|
AGENT_DEFAULT_MAX_RETRIES,
|
|
46
45
|
AGENT_DEFAULT_TIMEOUT_SECONDS,
|
|
47
|
-
|
|
46
|
+
AGENT_METADATA_STRUCTURED_RESULTS_KEY,
|
|
48
47
|
MAX_AGENT_RETRY_DELAY_SECONDS,
|
|
49
48
|
)
|
|
50
49
|
from rasa.agents.core.agent_protocol import AgentProtocol
|
|
@@ -57,12 +56,21 @@ from rasa.shared.exceptions import (
|
|
|
57
56
|
RasaException,
|
|
58
57
|
)
|
|
59
58
|
|
|
59
|
+
A2A_TASK_POOLING_INITIAL_DELAY = 0.5
|
|
60
|
+
A2A_TASK_POOLING_MAX_WAIT = 60
|
|
61
|
+
|
|
60
62
|
structlogger = structlog.get_logger()
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
class A2AAgent(AgentProtocol):
|
|
64
66
|
"""A2A client implementation"""
|
|
65
67
|
|
|
68
|
+
__SUPPORTED_OUTPUT_MODES: ClassVar[list[str]] = [
|
|
69
|
+
"text",
|
|
70
|
+
"text/plain",
|
|
71
|
+
"application/json",
|
|
72
|
+
]
|
|
73
|
+
|
|
66
74
|
def __init__(
|
|
67
75
|
self,
|
|
68
76
|
name: str,
|
|
@@ -78,7 +86,7 @@ class A2AAgent(AgentProtocol):
|
|
|
78
86
|
self._max_retries = max_retries
|
|
79
87
|
|
|
80
88
|
self.agent_card: Optional[AgentCard] = None
|
|
81
|
-
self._client: Optional[
|
|
89
|
+
self._client: Optional[Client] = None
|
|
82
90
|
|
|
83
91
|
@classmethod
|
|
84
92
|
def from_config(cls, config: AgentConfig) -> AgentProtocol:
|
|
@@ -132,15 +140,12 @@ class A2AAgent(AgentProtocol):
|
|
|
132
140
|
)
|
|
133
141
|
|
|
134
142
|
try:
|
|
135
|
-
self._client =
|
|
136
|
-
httpx.AsyncClient(timeout=self._timeout), agent_card=self.agent_card
|
|
137
|
-
)
|
|
143
|
+
self._client = self._init_client()
|
|
138
144
|
structlogger.debug(
|
|
139
|
-
"a2a_agent.connect.
|
|
140
|
-
event_info=f"
|
|
141
|
-
f"
|
|
145
|
+
"a2a_agent.connect.agent_client_initialized",
|
|
146
|
+
event_info=f"Initialized A2A client for agent '{self._name}'. "
|
|
147
|
+
f"Performing health check using the URL {self.agent_card.url}",
|
|
142
148
|
)
|
|
143
|
-
# TODO: Make a test request to /tasks to verify the connection
|
|
144
149
|
except Exception as exception:
|
|
145
150
|
structlogger.error(
|
|
146
151
|
"a2a_agent.connect.error",
|
|
@@ -153,6 +158,13 @@ class A2AAgent(AgentProtocol):
|
|
|
153
158
|
f"'{self._name}': {exception}"
|
|
154
159
|
) from exception
|
|
155
160
|
|
|
161
|
+
await self._perform_health_check()
|
|
162
|
+
structlogger.debug(
|
|
163
|
+
"a2a_agent.connect.success",
|
|
164
|
+
event_info=f"Connected to A2A server '{self._name}' "
|
|
165
|
+
f"at {self.agent_card.url}",
|
|
166
|
+
)
|
|
167
|
+
|
|
156
168
|
async def disconnect(self) -> None:
|
|
157
169
|
"""We don't need to explicitly disconnect the A2A client"""
|
|
158
170
|
return
|
|
@@ -167,7 +179,7 @@ class A2AAgent(AgentProtocol):
|
|
|
167
179
|
if not self._client or not self.agent_card:
|
|
168
180
|
structlogger.error(
|
|
169
181
|
"a2a_agent.run.error",
|
|
170
|
-
event_info="A2A client is not initialized.
|
|
182
|
+
event_info="A2A client is not initialized. Call connect() first.",
|
|
171
183
|
)
|
|
172
184
|
return AgentOutput(
|
|
173
185
|
id=agent_input.id,
|
|
@@ -175,121 +187,129 @@ class A2AAgent(AgentProtocol):
|
|
|
175
187
|
error_message="Client not initialized",
|
|
176
188
|
)
|
|
177
189
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
190
|
+
structlogger.info(
|
|
191
|
+
"a2a_agent.run.start",
|
|
192
|
+
event_info="Running A2A agent",
|
|
193
|
+
agent_name=self._name,
|
|
194
|
+
)
|
|
195
|
+
message = self._prepare_message(agent_input)
|
|
196
|
+
|
|
197
|
+
task_id: Optional[str] = None
|
|
198
|
+
events_received = 0
|
|
199
|
+
try:
|
|
200
|
+
async for event in self._client.send_message(message):
|
|
201
|
+
events_received += 1
|
|
202
|
+
agent_output = self._handle_send_message_response(agent_input, event)
|
|
203
|
+
if agent_output is not None:
|
|
204
|
+
return agent_output
|
|
205
|
+
else:
|
|
206
|
+
# Not a terminal response, save taskID (in case that's the only
|
|
207
|
+
# event, and we need to pool) and continue waiting for next events
|
|
208
|
+
if (
|
|
209
|
+
isinstance(event, tuple)
|
|
210
|
+
and len(event) == 2
|
|
211
|
+
and isinstance(event[0], Task)
|
|
212
|
+
):
|
|
213
|
+
task_id = event[0].id
|
|
214
|
+
continue
|
|
215
|
+
except A2AClientJSONRPCError as e:
|
|
216
|
+
return self._handle_json_rpc_error_response(agent_input, e.error)
|
|
217
|
+
except A2AClientError as exception:
|
|
187
218
|
structlogger.error(
|
|
188
|
-
"a2a_agent.run.error",
|
|
189
|
-
event_info="
|
|
219
|
+
"a2a_agent.run.send_message.error",
|
|
220
|
+
event_info="Error during sending message to A2A agent",
|
|
190
221
|
agent_name=self._name,
|
|
222
|
+
error=str(exception),
|
|
191
223
|
)
|
|
192
224
|
return AgentOutput(
|
|
193
225
|
id=agent_input.id,
|
|
194
226
|
status=AgentStatus.FATAL_ERROR,
|
|
195
|
-
error_message="
|
|
227
|
+
error_message=f"Send message error: {exception!s}",
|
|
196
228
|
)
|
|
197
229
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return output
|
|
202
|
-
|
|
203
|
-
async def _run_streaming_agent(self, agent_input: AgentInput) -> AgentOutput:
|
|
204
|
-
if not self._client:
|
|
230
|
+
# The stream has ended, but we didn't get a terminal response.
|
|
231
|
+
# Check if we received any events at all.
|
|
232
|
+
if events_received == 0:
|
|
205
233
|
structlogger.error(
|
|
206
|
-
"a2a_agent.
|
|
207
|
-
event_info="
|
|
234
|
+
"a2a_agent.run.no_events_received",
|
|
235
|
+
event_info="No events received from A2A agent after sending message",
|
|
236
|
+
agent_name=self._name,
|
|
208
237
|
)
|
|
209
238
|
return AgentOutput(
|
|
210
239
|
id=agent_input.id,
|
|
211
|
-
status=AgentStatus.
|
|
212
|
-
error_message="
|
|
240
|
+
status=AgentStatus.RECOVERABLE_ERROR,
|
|
241
|
+
error_message="No events received from A2A agent",
|
|
213
242
|
)
|
|
214
|
-
message_send_params = self._prepare_message_send_params(agent_input)
|
|
215
|
-
|
|
216
|
-
try:
|
|
217
|
-
async for response in self._client.send_message_streaming(
|
|
218
|
-
SendStreamingMessageRequest(
|
|
219
|
-
id=str(uuid.uuid4()), params=message_send_params
|
|
220
|
-
)
|
|
221
|
-
):
|
|
222
|
-
agent_output = self._handle_streaming_response(agent_input, response)
|
|
223
|
-
if agent_output is not None:
|
|
224
|
-
return agent_output
|
|
225
|
-
else:
|
|
226
|
-
# Not a terminal response, continue waiting for next responses
|
|
227
|
-
continue
|
|
228
243
|
|
|
229
|
-
|
|
244
|
+
# Now we need to poll the task until it reaches a terminal state.
|
|
245
|
+
if not task_id:
|
|
230
246
|
structlogger.error(
|
|
231
|
-
"a2a_agent.
|
|
232
|
-
event_info="
|
|
247
|
+
"a2a_agent.run.pooling.missing_id",
|
|
248
|
+
event_info="Missing task_id for polling",
|
|
233
249
|
agent_name=self._name,
|
|
234
|
-
|
|
250
|
+
task_id=task_id,
|
|
235
251
|
)
|
|
236
252
|
return AgentOutput(
|
|
237
253
|
id=agent_input.id,
|
|
238
254
|
status=AgentStatus.FATAL_ERROR,
|
|
239
|
-
error_message=
|
|
255
|
+
error_message="Missing task_id for polling",
|
|
240
256
|
)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
)
|
|
248
|
-
return AgentOutput(
|
|
249
|
-
id=agent_input.id,
|
|
250
|
-
status=AgentStatus.FATAL_ERROR,
|
|
251
|
-
error_message="Unexpected end of streaming response",
|
|
257
|
+
return await self._pool_task_until_terminal(
|
|
258
|
+
agent_input=agent_input,
|
|
259
|
+
task_id=task_id,
|
|
260
|
+
max_wait=A2A_TASK_POOLING_MAX_WAIT,
|
|
261
|
+
initial_delay=A2A_TASK_POOLING_INITIAL_DELAY,
|
|
262
|
+
max_delay=MAX_AGENT_RETRY_DELAY_SECONDS,
|
|
252
263
|
)
|
|
253
264
|
|
|
254
|
-
def
|
|
255
|
-
|
|
265
|
+
async def process_output(self, output: AgentOutput) -> AgentOutput:
|
|
266
|
+
"""Post-process the output before returning it to Rasa."""
|
|
267
|
+
# A2A-specific output processing logic
|
|
268
|
+
return output
|
|
269
|
+
|
|
270
|
+
def _handle_send_message_response(
|
|
271
|
+
self, agent_input: AgentInput, response: ClientEvent | Message
|
|
256
272
|
) -> Optional[AgentOutput]:
|
|
257
|
-
"""
|
|
273
|
+
"""Handle possible response types from the A2A client:
|
|
274
|
+
|
|
275
|
+
In case of streaming, the response can be either exactly *one* Message,
|
|
276
|
+
or a *series* of tuples of (Task, Optional[TaskUpdateEvent]).
|
|
277
|
+
|
|
278
|
+
In case of pooling, the response can be either exactly *one* Message,
|
|
279
|
+
or exactly *one* tuple of (Task, None).
|
|
280
|
+
|
|
281
|
+
If the agent response is terminal (i.e., completed, failed, etc.),
|
|
258
282
|
this method will return an AgentOutput.
|
|
259
283
|
Otherwise, the task is still in progress (i.e., submitted, working), so this
|
|
260
284
|
method will return None, so that the streaming or pooling agent can continue
|
|
261
285
|
to wait for updates.
|
|
262
286
|
"""
|
|
263
|
-
if isinstance(response
|
|
264
|
-
return self.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
return self.
|
|
271
|
-
elif isinstance(response_result, TaskStatusUpdateEvent):
|
|
272
|
-
return self._handle_task_status_update_event(agent_input, response_result)
|
|
273
|
-
elif isinstance(response_result, TaskArtifactUpdateEvent):
|
|
274
|
-
return self._handle_task_artifact_update_event(agent_input, response_result)
|
|
287
|
+
if isinstance(response, Message):
|
|
288
|
+
return self._handle_message_response(agent_input, response)
|
|
289
|
+
elif (
|
|
290
|
+
isinstance(response, tuple)
|
|
291
|
+
and len(response) == 2
|
|
292
|
+
and isinstance(response[0], Task)
|
|
293
|
+
):
|
|
294
|
+
return self._handle_client_event(agent_input, response)
|
|
275
295
|
else:
|
|
276
296
|
# Currently, no other response types exist, so this branch is
|
|
277
297
|
# unreachable. It is kept as a safeguard against future changes
|
|
278
298
|
# to the A2A protocol: if new response types are introduced,
|
|
279
299
|
# the agent will log an error instead of crashing.
|
|
280
|
-
return self._handle_unexpected_response_type(agent_input,
|
|
300
|
+
return self._handle_unexpected_response_type(agent_input, response)
|
|
281
301
|
|
|
282
302
|
def _handle_json_rpc_error_response(
|
|
283
|
-
self, agent_input: AgentInput,
|
|
303
|
+
self, agent_input: AgentInput, error: Any
|
|
284
304
|
) -> AgentOutput:
|
|
285
305
|
structlogger.error(
|
|
286
|
-
"a2a_agent.
|
|
287
|
-
event_info="Received error response from A2A
|
|
306
|
+
"a2a_agent.run.error",
|
|
307
|
+
event_info="Received JSON-RPC error response from A2A agent",
|
|
288
308
|
agent_name=self._name,
|
|
289
|
-
error=str(
|
|
309
|
+
error=str(error),
|
|
290
310
|
)
|
|
291
311
|
if isinstance(
|
|
292
|
-
|
|
312
|
+
error,
|
|
293
313
|
(
|
|
294
314
|
InternalError,
|
|
295
315
|
InvalidAgentResponseError,
|
|
@@ -298,85 +318,53 @@ class A2AAgent(AgentProtocol):
|
|
|
298
318
|
return AgentOutput(
|
|
299
319
|
id=agent_input.id,
|
|
300
320
|
status=AgentStatus.RECOVERABLE_ERROR,
|
|
301
|
-
error_message=str(
|
|
321
|
+
error_message=str(error),
|
|
302
322
|
)
|
|
303
323
|
else:
|
|
304
324
|
return AgentOutput(
|
|
305
325
|
id=agent_input.id,
|
|
306
326
|
status=AgentStatus.FATAL_ERROR,
|
|
307
|
-
error_message=str(
|
|
327
|
+
error_message=str(error),
|
|
308
328
|
)
|
|
309
329
|
|
|
310
|
-
def
|
|
311
|
-
self, agent_input: AgentInput,
|
|
330
|
+
def _handle_client_event(
|
|
331
|
+
self, agent_input: AgentInput, client_event: ClientEvent
|
|
312
332
|
) -> Optional[AgentOutput]:
|
|
333
|
+
task = client_event[0]
|
|
334
|
+
update_event = client_event[1]
|
|
313
335
|
structlogger.debug(
|
|
314
|
-
"a2a_agent.
|
|
315
|
-
event_info="Received
|
|
316
|
-
agent_name=self._name,
|
|
336
|
+
"a2a_agent.run.client_event_received",
|
|
337
|
+
event_info="Received client event from A2A",
|
|
317
338
|
task=task,
|
|
339
|
+
update_event=update_event,
|
|
318
340
|
)
|
|
319
|
-
agent_output = self._handle_task_status(
|
|
320
|
-
agent_input=agent_input,
|
|
321
|
-
context_id=task.context_id,
|
|
322
|
-
task_id=task.id,
|
|
323
|
-
task_status=task.status,
|
|
324
|
-
)
|
|
325
|
-
return agent_output
|
|
326
341
|
|
|
327
|
-
|
|
328
|
-
# Message represents an intermediate conversational update,
|
|
329
|
-
# we need to continue waiting for task updates
|
|
330
|
-
structlogger.debug(
|
|
331
|
-
"a2a_agent.run_streaming_agent.message_received",
|
|
332
|
-
event_info="Received message from A2A",
|
|
333
|
-
agent_name=self._name,
|
|
334
|
-
message=message,
|
|
335
|
-
)
|
|
336
|
-
return None
|
|
342
|
+
return self._handle_task(agent_input=agent_input, task=task)
|
|
337
343
|
|
|
338
|
-
def
|
|
339
|
-
self, agent_input: AgentInput,
|
|
344
|
+
def _handle_message_response(
|
|
345
|
+
self, agent_input: AgentInput, message: Message
|
|
340
346
|
) -> Optional[AgentOutput]:
|
|
341
347
|
structlogger.debug(
|
|
342
|
-
"a2a_agent.
|
|
343
|
-
event_info="Received
|
|
348
|
+
"a2a_agent.run.message_received",
|
|
349
|
+
event_info="Received message from A2A",
|
|
344
350
|
agent_name=self._name,
|
|
345
|
-
|
|
346
|
-
)
|
|
347
|
-
agent_output = self._handle_task_status(
|
|
348
|
-
agent_input=agent_input,
|
|
349
|
-
context_id=event.context_id,
|
|
350
|
-
task_id=event.task_id,
|
|
351
|
-
task_status=event.status,
|
|
351
|
+
message=message,
|
|
352
352
|
)
|
|
353
|
-
|
|
353
|
+
metadata = agent_input.metadata or {}
|
|
354
|
+
metadata[A2A_AGENT_CONTEXT_ID_KEY] = message.context_id
|
|
354
355
|
|
|
355
|
-
def _handle_task_artifact_update_event(
|
|
356
|
-
self, agent_input: AgentInput, event: TaskArtifactUpdateEvent
|
|
357
|
-
) -> AgentOutput:
|
|
358
|
-
structlogger.debug(
|
|
359
|
-
"a2a_agent.run_streaming_agent.task_artifact_update_received",
|
|
360
|
-
event_info="Received task artifact update from A2A",
|
|
361
|
-
agent_name=self._name,
|
|
362
|
-
task_artifact_update_event=event,
|
|
363
|
-
)
|
|
364
356
|
return AgentOutput(
|
|
365
357
|
id=agent_input.id,
|
|
366
|
-
status=AgentStatus.
|
|
367
|
-
response_message=self._generate_response_message_from_parts(
|
|
368
|
-
|
|
369
|
-
),
|
|
370
|
-
tool_results=self._generate_tool_results_from_parts(
|
|
371
|
-
agent_input, event.artifact.parts
|
|
372
|
-
),
|
|
358
|
+
status=AgentStatus.INPUT_REQUIRED,
|
|
359
|
+
response_message=self._generate_response_message_from_parts(message.parts),
|
|
360
|
+
metadata=metadata,
|
|
373
361
|
)
|
|
374
362
|
|
|
375
363
|
def _handle_unexpected_response_type(
|
|
376
364
|
self, agent_input: AgentInput, response_result: Any
|
|
377
365
|
) -> AgentOutput:
|
|
378
366
|
structlogger.error(
|
|
379
|
-
"a2a_agent.
|
|
367
|
+
"a2a_agent.run.unexpected_response_type",
|
|
380
368
|
event_info="Received unexpected response type from A2A server "
|
|
381
369
|
"during streaming",
|
|
382
370
|
agent_name=self._name,
|
|
@@ -388,29 +376,26 @@ class A2AAgent(AgentProtocol):
|
|
|
388
376
|
error_message=f"Unexpected response type: {type(response_result)}",
|
|
389
377
|
)
|
|
390
378
|
|
|
391
|
-
def
|
|
379
|
+
def _handle_task(
|
|
392
380
|
self,
|
|
393
381
|
agent_input: AgentInput,
|
|
394
|
-
|
|
395
|
-
task_id: str,
|
|
396
|
-
task_status: TaskStatus,
|
|
397
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
382
|
+
task: Task,
|
|
398
383
|
) -> Optional[AgentOutput]:
|
|
399
384
|
"""If the task status is terminal (i.e., completed, failed, etc.),
|
|
400
385
|
return an AgentOutput.
|
|
401
386
|
If the task is still in progress (i.e., submitted, working), return None,
|
|
402
387
|
so that the streaming or pooling agent can continue to wait for updates.
|
|
403
388
|
"""
|
|
404
|
-
state =
|
|
389
|
+
state = task.status.state
|
|
405
390
|
|
|
406
|
-
metadata = metadata or {}
|
|
407
|
-
metadata[A2A_AGENT_CONTEXT_ID_KEY] = context_id
|
|
408
|
-
metadata[A2A_AGENT_TASK_ID_KEY] =
|
|
391
|
+
metadata = agent_input.metadata or {}
|
|
392
|
+
metadata[A2A_AGENT_CONTEXT_ID_KEY] = task.context_id
|
|
393
|
+
metadata[A2A_AGENT_TASK_ID_KEY] = task.id
|
|
409
394
|
|
|
410
395
|
if state == TaskState.input_required:
|
|
411
396
|
response_message = (
|
|
412
|
-
self._generate_response_message_from_parts(
|
|
413
|
-
if
|
|
397
|
+
self._generate_response_message_from_parts(task.status.message.parts)
|
|
398
|
+
if task.status.message
|
|
414
399
|
else ""
|
|
415
400
|
) # This should not happen, but as type of message property
|
|
416
401
|
# is optional, so we need to handle it
|
|
@@ -421,16 +406,19 @@ class A2AAgent(AgentProtocol):
|
|
|
421
406
|
metadata=metadata,
|
|
422
407
|
)
|
|
423
408
|
elif state == TaskState.completed:
|
|
424
|
-
response_message = (
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
409
|
+
response_message = self._generate_completed_response_message(task)
|
|
410
|
+
structured_results = (
|
|
411
|
+
self._generate_structured_results_from_artifacts(
|
|
412
|
+
agent_input, task.artifacts
|
|
413
|
+
)
|
|
414
|
+
if task.artifacts
|
|
415
|
+
else None
|
|
416
|
+
)
|
|
430
417
|
return AgentOutput(
|
|
431
418
|
id=agent_input.id,
|
|
432
419
|
status=AgentStatus.COMPLETED,
|
|
433
420
|
response_message=response_message,
|
|
421
|
+
structured_results=structured_results,
|
|
434
422
|
metadata=metadata,
|
|
435
423
|
)
|
|
436
424
|
elif (
|
|
@@ -469,7 +457,7 @@ class A2AAgent(AgentProtocol):
|
|
|
469
457
|
)
|
|
470
458
|
|
|
471
459
|
@staticmethod
|
|
472
|
-
def
|
|
460
|
+
def _prepare_message(agent_input: AgentInput) -> Message:
|
|
473
461
|
parts: List[Part] = []
|
|
474
462
|
if agent_input.metadata and A2A_AGENT_CONTEXT_ID_KEY in agent_input.metadata:
|
|
475
463
|
# Agent knows the conversation history already, send the last
|
|
@@ -497,17 +485,94 @@ class A2AAgent(AgentProtocol):
|
|
|
497
485
|
task_id=agent_input.metadata.get(A2A_AGENT_TASK_ID_KEY, None),
|
|
498
486
|
)
|
|
499
487
|
structlogger.debug(
|
|
500
|
-
"a2a_agent.
|
|
488
|
+
"a2a_agent.prepare_message",
|
|
501
489
|
event_info="Prepared message to send to A2A server",
|
|
502
490
|
agent_name=agent_input.id,
|
|
503
491
|
message=agent_message,
|
|
504
492
|
)
|
|
505
|
-
return
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
493
|
+
return agent_message
|
|
494
|
+
|
|
495
|
+
async def _pool_task_until_terminal(
|
|
496
|
+
self,
|
|
497
|
+
agent_input: AgentInput,
|
|
498
|
+
task_id: str,
|
|
499
|
+
max_wait: int,
|
|
500
|
+
initial_delay: float,
|
|
501
|
+
max_delay: int,
|
|
502
|
+
) -> AgentOutput:
|
|
503
|
+
"""Poll the task status until it reaches a terminal state or times out."""
|
|
504
|
+
if not self._client:
|
|
505
|
+
structlogger.error(
|
|
506
|
+
"a2a_agent.pool_task_until_terminal.error",
|
|
507
|
+
event_info="A2A client is not initialized. Call connect() first.",
|
|
508
|
+
)
|
|
509
|
+
return AgentOutput(
|
|
510
|
+
id=agent_input.id,
|
|
511
|
+
status=AgentStatus.FATAL_ERROR,
|
|
512
|
+
error_message="Client not initialized",
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
structlogger.debug(
|
|
516
|
+
"a2a_agent.pool_task_until_terminal.start",
|
|
517
|
+
event_info="Start polling task from A2A server",
|
|
518
|
+
agent_name=self._name,
|
|
519
|
+
task_id=task_id,
|
|
520
|
+
max_wait=max_wait,
|
|
521
|
+
initial_delay=initial_delay,
|
|
522
|
+
max_delay=max_delay,
|
|
510
523
|
)
|
|
524
|
+
start_time = time.monotonic()
|
|
525
|
+
delay = initial_delay
|
|
526
|
+
|
|
527
|
+
while True:
|
|
528
|
+
try:
|
|
529
|
+
task = await self._client.get_task(TaskQueryParams(id=task_id))
|
|
530
|
+
agent_output = self._handle_task(agent_input=agent_input, task=task)
|
|
531
|
+
if agent_output is not None:
|
|
532
|
+
# Reached a terminal state, return the output
|
|
533
|
+
return agent_output
|
|
534
|
+
|
|
535
|
+
elapsed = time.monotonic() - start_time
|
|
536
|
+
if elapsed >= max_wait:
|
|
537
|
+
structlogger.debug(
|
|
538
|
+
"a2a_agent.pool_task_until_terminal.timeout",
|
|
539
|
+
event_info="Polling task from A2A server timed out",
|
|
540
|
+
agent_name=self._name,
|
|
541
|
+
task_id=task_id,
|
|
542
|
+
elapsed=elapsed,
|
|
543
|
+
max_wait=max_wait,
|
|
544
|
+
)
|
|
545
|
+
return AgentOutput(
|
|
546
|
+
id=agent_input.id,
|
|
547
|
+
status=AgentStatus.FATAL_ERROR,
|
|
548
|
+
error_message="Polling timed out",
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
structlogger.error(
|
|
552
|
+
"a2a_agent.pool_task_until_terminal.waiting",
|
|
553
|
+
event_info="Task not in terminal state yet, waiting to poll again",
|
|
554
|
+
delay=delay,
|
|
555
|
+
agent_name=self._name,
|
|
556
|
+
task_id=task_id,
|
|
557
|
+
elapsed=elapsed,
|
|
558
|
+
max_wait=max_wait,
|
|
559
|
+
)
|
|
560
|
+
await asyncio.sleep(delay)
|
|
561
|
+
# Exponential backoff with cap
|
|
562
|
+
delay = min(delay * 2, max_delay)
|
|
563
|
+
|
|
564
|
+
except A2AClientError as exception:
|
|
565
|
+
structlogger.error(
|
|
566
|
+
"a2a_agent.pool_task_until_terminal.error",
|
|
567
|
+
event_info="Error during polling task from A2A server",
|
|
568
|
+
agent_name=self._name,
|
|
569
|
+
error=str(exception),
|
|
570
|
+
)
|
|
571
|
+
return AgentOutput(
|
|
572
|
+
id=agent_input.id,
|
|
573
|
+
status=AgentStatus.FATAL_ERROR,
|
|
574
|
+
error_message=f"Polling error: {exception!s}",
|
|
575
|
+
)
|
|
511
576
|
|
|
512
577
|
@staticmethod
|
|
513
578
|
def _generate_response_message_from_parts(parts: Optional[List[Part]]) -> str:
|
|
@@ -519,7 +584,7 @@ class A2AAgent(AgentProtocol):
|
|
|
519
584
|
if isinstance(part.root, TextPart):
|
|
520
585
|
result += part.root.text + "\n"
|
|
521
586
|
elif isinstance(part.root, DataPart):
|
|
522
|
-
# DataPart results will be returned as a
|
|
587
|
+
# DataPart results will be returned as a part of the structured results,
|
|
523
588
|
# we don't need to include it in the response message
|
|
524
589
|
continue
|
|
525
590
|
elif isinstance(part.root, FilePart) and isinstance(
|
|
@@ -536,29 +601,66 @@ class A2AAgent(AgentProtocol):
|
|
|
536
601
|
return result.strip()
|
|
537
602
|
|
|
538
603
|
@staticmethod
|
|
539
|
-
def
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
604
|
+
def _generate_completed_response_message(task: Task) -> str:
|
|
605
|
+
"""Generate a response message for a completed task.
|
|
606
|
+
In case of completed tasks, the final message might be in
|
|
607
|
+
the task status message or in the artifacts (or both).
|
|
608
|
+
"""
|
|
609
|
+
result = ""
|
|
610
|
+
if task.status.message:
|
|
611
|
+
result += (
|
|
612
|
+
A2AAgent._generate_response_message_from_parts(
|
|
613
|
+
task.status.message.parts
|
|
614
|
+
)
|
|
615
|
+
+ "\n"
|
|
616
|
+
)
|
|
617
|
+
if task.artifacts:
|
|
618
|
+
for artifact in task.artifacts:
|
|
619
|
+
result += (
|
|
620
|
+
A2AAgent._generate_response_message_from_parts(artifact.parts)
|
|
621
|
+
+ "\n"
|
|
554
622
|
)
|
|
623
|
+
return result.strip()
|
|
555
624
|
|
|
556
|
-
|
|
557
|
-
|
|
625
|
+
@staticmethod
|
|
626
|
+
def _generate_structured_results_from_artifacts(
|
|
627
|
+
agent_input: AgentInput, artifacts: List[Artifact]
|
|
628
|
+
) -> Optional[List[List[Dict[str, Any]]]]:
|
|
629
|
+
structured_results_of_current_iteration: List[Dict[str, Any]] = []
|
|
630
|
+
# There might be multiple artifacts in the response, each of them might
|
|
631
|
+
# contain multiple parts. We will treat each DataPart in each artifact
|
|
632
|
+
# as a separate tool result. The tool name will be the agent ID + index
|
|
633
|
+
# of the artifact + index of the part.
|
|
634
|
+
# E.g., foo_0_1, foo_0_2, foo_1_0, etc.
|
|
635
|
+
for artifact_index, artifact in enumerate(artifacts):
|
|
636
|
+
for part_index, part in enumerate(artifact.parts):
|
|
637
|
+
if isinstance(part.root, DataPart) and len(part.root.data) > 0:
|
|
638
|
+
structured_result = {
|
|
639
|
+
"name": f"{agent_input.id}_{artifact_index}_{part_index}",
|
|
640
|
+
"type": "data",
|
|
641
|
+
"result": part.root.data,
|
|
642
|
+
}
|
|
643
|
+
structured_results_of_current_iteration.append(structured_result)
|
|
644
|
+
elif isinstance(part.root, FilePart) and isinstance(
|
|
645
|
+
part.root.file, FileWithUri
|
|
646
|
+
):
|
|
647
|
+
structured_result = {
|
|
648
|
+
"name": f"{agent_input.id}_{artifact_index}_{part_index}",
|
|
649
|
+
"type": "file",
|
|
650
|
+
"result ": {
|
|
651
|
+
"uri": part.root.file.uri,
|
|
652
|
+
"name": part.root.file.name,
|
|
653
|
+
"mime_type": part.root.file.mime_type,
|
|
654
|
+
},
|
|
655
|
+
}
|
|
656
|
+
structured_results_of_current_iteration.append(structured_result)
|
|
657
|
+
|
|
658
|
+
previous_structured_results: List[List[Dict[str, Any]]] = (
|
|
659
|
+
agent_input.metadata.get(AGENT_METADATA_STRUCTURED_RESULTS_KEY, []) or []
|
|
558
660
|
)
|
|
559
|
-
|
|
661
|
+
previous_structured_results.append(structured_results_of_current_iteration)
|
|
560
662
|
|
|
561
|
-
return
|
|
663
|
+
return previous_structured_results
|
|
562
664
|
|
|
563
665
|
@staticmethod
|
|
564
666
|
def _load_agent_card_from_file(agent_card_path: str) -> AgentCard:
|
|
@@ -566,42 +668,24 @@ class A2AAgent(AgentProtocol):
|
|
|
566
668
|
try:
|
|
567
669
|
with open(os.path.abspath(agent_card_path), "r") as f:
|
|
568
670
|
card_data = json.load(f)
|
|
671
|
+
return AgentCard.model_validate(card_data)
|
|
569
672
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
for skill_data in card_data.get("skills", [])
|
|
579
|
-
]
|
|
580
|
-
|
|
581
|
-
return AgentCard(
|
|
582
|
-
name=card_data["name"],
|
|
583
|
-
description=card_data["description"],
|
|
584
|
-
url=card_data["url"],
|
|
585
|
-
version=card_data.get("version", "1.0.0"),
|
|
586
|
-
default_input_modes=card_data.get(
|
|
587
|
-
"defaultInputModes", ["text", "text/plain"]
|
|
588
|
-
),
|
|
589
|
-
default_output_modes=card_data.get(
|
|
590
|
-
"defaultOutputModes", ["text", "text/plain", "application/json"]
|
|
591
|
-
),
|
|
592
|
-
capabilities=AgentCapabilities(
|
|
593
|
-
streaming=card_data.get("capabilities", {}).get("streaming", True)
|
|
594
|
-
),
|
|
595
|
-
skills=skills,
|
|
596
|
-
)
|
|
597
|
-
except FileNotFoundError:
|
|
598
|
-
raise FileNotFoundError(f"Agent card file not found: {agent_card_path}")
|
|
673
|
+
except FileNotFoundError as e:
|
|
674
|
+
raise AgentInitializationException(
|
|
675
|
+
f"Agent card file not found: {agent_card_path}"
|
|
676
|
+
) from e
|
|
677
|
+
except (IOError, PermissionError) as e:
|
|
678
|
+
raise AgentInitializationException(
|
|
679
|
+
f"Error reading agent card file {agent_card_path}: {e}"
|
|
680
|
+
) from e
|
|
599
681
|
except json.JSONDecodeError as e:
|
|
600
|
-
raise
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
682
|
+
raise AgentInitializationException(
|
|
683
|
+
f"Invalid JSON in agent card file {agent_card_path}: {e}"
|
|
684
|
+
) from e
|
|
685
|
+
except ValidationError as e:
|
|
686
|
+
raise AgentInitializationException(
|
|
687
|
+
f"Failed to load agent card from {agent_card_path}: {e}"
|
|
688
|
+
) from e
|
|
605
689
|
|
|
606
690
|
@staticmethod
|
|
607
691
|
async def _resolve_agent_card_with_retry(
|
|
@@ -660,3 +744,77 @@ class A2AAgent(AgentProtocol):
|
|
|
660
744
|
f"Failed to resolve agent card from {agent_card_path} after "
|
|
661
745
|
f"{max_retries} attempts."
|
|
662
746
|
)
|
|
747
|
+
|
|
748
|
+
def _init_client(self) -> Client:
|
|
749
|
+
factory = ClientFactory(
|
|
750
|
+
config=ClientConfig(
|
|
751
|
+
httpx_client=httpx.AsyncClient(timeout=self._timeout),
|
|
752
|
+
streaming=True,
|
|
753
|
+
supported_transports=[
|
|
754
|
+
TransportProtocol.jsonrpc,
|
|
755
|
+
TransportProtocol.http_json,
|
|
756
|
+
TransportProtocol.grpc,
|
|
757
|
+
],
|
|
758
|
+
accepted_output_modes=self.__SUPPORTED_OUTPUT_MODES,
|
|
759
|
+
)
|
|
760
|
+
)
|
|
761
|
+
return factory.create(self.agent_card)
|
|
762
|
+
|
|
763
|
+
async def _perform_health_check(self) -> None:
|
|
764
|
+
if not self._client or not self.agent_card:
|
|
765
|
+
structlogger.error(
|
|
766
|
+
"a2a_agent.health_check.error",
|
|
767
|
+
event_info="A2A client is not initialized. Call connect() first.",
|
|
768
|
+
)
|
|
769
|
+
raise AgentInitializationException("Client not initialized")
|
|
770
|
+
|
|
771
|
+
try:
|
|
772
|
+
test_message = Message(
|
|
773
|
+
role=Role.user,
|
|
774
|
+
parts=[Part(root=TextPart(text="hello"))],
|
|
775
|
+
message_id=str(uuid.uuid4()),
|
|
776
|
+
)
|
|
777
|
+
async for event in self._client.send_message(test_message):
|
|
778
|
+
if (
|
|
779
|
+
isinstance(event, Message)
|
|
780
|
+
or isinstance(event, tuple)
|
|
781
|
+
and len(event) == 2
|
|
782
|
+
and isinstance(event[0], Task)
|
|
783
|
+
):
|
|
784
|
+
# We got a valid response, health check succeeded
|
|
785
|
+
return
|
|
786
|
+
|
|
787
|
+
event_info = "Unexpected response type during health check"
|
|
788
|
+
structlogger.error(
|
|
789
|
+
"a2a_agent.health_check.unexpected_response",
|
|
790
|
+
event_info=event_info,
|
|
791
|
+
agent_name=self._name,
|
|
792
|
+
response=event,
|
|
793
|
+
url=str(self.agent_card.url),
|
|
794
|
+
)
|
|
795
|
+
raise AgentInitializationException(f"{event_info}: {event}")
|
|
796
|
+
# If the loop completes with no return, no events were received
|
|
797
|
+
event_info = (
|
|
798
|
+
f"Health check failed for A2A agent '{self._name}' "
|
|
799
|
+
f"at {self.agent_card.url}: no events received"
|
|
800
|
+
)
|
|
801
|
+
structlogger.error(
|
|
802
|
+
"a2a_agent.health_check.no_events",
|
|
803
|
+
event_info=event_info,
|
|
804
|
+
agent_name=self._name,
|
|
805
|
+
url=str(self.agent_card.url),
|
|
806
|
+
)
|
|
807
|
+
raise AgentInitializationException(event_info)
|
|
808
|
+
except Exception as exception:
|
|
809
|
+
event_info = (
|
|
810
|
+
f"Health check failed for A2A agent '{self._name}' at "
|
|
811
|
+
f"{self.agent_card.url}: {exception!s}"
|
|
812
|
+
)
|
|
813
|
+
structlogger.error(
|
|
814
|
+
"a2a_agent.health_check.failed",
|
|
815
|
+
event_info=event_info,
|
|
816
|
+
agent_name=self._name,
|
|
817
|
+
error=str(exception),
|
|
818
|
+
url=str(self.agent_card.url),
|
|
819
|
+
)
|
|
820
|
+
raise AgentInitializationException(event_info) from exception
|