rasa-pro 3.14.0a20__py3-none-any.whl → 3.14.0a23__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 +6 -2
- 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/llm_service.py +32 -5
- rasa/builder/models.py +1 -0
- rasa/builder/project_generator.py +6 -1
- rasa/builder/service.py +16 -13
- rasa/builder/training_service.py +18 -24
- 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/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/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/human_handoff.yml +1 -1
- rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +1 -1
- rasa/cli/project_templates/finance/domain/general/_shared.yml +0 -14
- rasa/cli/project_templates/finance/domain/general/bot_challenge.yml +4 -0
- rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/finance/domain/general/human_handoff.yml +3 -6
- rasa/cli/project_templates/finance/domain/general/welcome.yml +29 -1
- 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/tests/e2e_test_cases/general/feedback.yml +1 -1
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +1 -1
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +1 -1
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +1 -1
- 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/kafka.py +1 -1
- rasa/core/channels/__init__.py +82 -35
- rasa/core/channels/development_inspector.py +3 -3
- rasa/core/channels/inspector/README.md +25 -13
- rasa/core/channels/inspector/dist/assets/{arc-35222594.js → arc-6177260a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-a0efbfd3.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0584c0f2.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-39f40dbe.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-1ad755f3.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-b0f4f0fe.js → createText-2e5e7dd3-088372e2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-9039bff9.js → edges-e0da2a9e-58676240.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-65c9b127.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4f08b38e.js → flowDb-956e92f1-ea63f85c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-e95c362a.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-703c3015.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-699328ea.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-04cf4b05.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-ee94449e.js → graph-0a6f8466.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-940162b4.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-c79c2866.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-84489d30.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-a9aa9858.js → layout-e7fbc2bf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-eb73cf26.js → line-a8aa457c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-b3399f9a.js → linear-3351e0d2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-b095bf1a.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-07644b66.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-573a3f9c.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d457e1e1.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-9d26e1a2.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3a9cde10.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-4f3e8cec.js → stateDiagram-587899a1-0e770395.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e617e5bf.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-eab30d2f.js → styles-6aaf32cf-36a9e70d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-09994be2.js → styles-9a916d00-884a8b5b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-b7110364.js → styles-c10674c1-dc097813.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-3ebc92ad.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-7d13d2f2.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-488385e1.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 +29 -4
- 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/helpers/audio/audiostream.ts +7 -4
- 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 +21 -0
- rasa/core/channels/inspector/yarn.lock +336 -189
- rasa/core/channels/studio_chat.py +6 -6
- rasa/core/channels/telegram.py +4 -9
- rasa/core/channels/voice_stream/browser_audio.py +2 -0
- rasa/core/channels/voice_stream/genesys.py +1 -1
- rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +5 -1
- rasa/core/channels/voice_stream/voice_channel.py +3 -0
- 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 +5 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +88 -3
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +2 -1
- rasa/core/lock_store.py +6 -4
- 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 +68 -44
- rasa/core/redis_connection_factory.py +78 -20
- rasa/core/run.py +37 -8
- rasa/core/test.py +4 -0
- rasa/core/tracker_stores/sql_tracker_store.py +1 -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/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/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_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 +16 -1
- rasa/shared/core/domain.py +0 -7
- rasa/shared/core/events.py +327 -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/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.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/METADATA +48 -42
- {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/RECORD +323 -251
- rasa/builder/scrape_rasa_docs.py +0 -97
- rasa/cli/project_templates/finance/data/general/agent_details.yml +0 -6
- rasa/cli/project_templates/finance/domain/_system/patterns/pattern_session_start.yml +0 -11
- rasa/cli/project_templates/finance/domain/general/agent_details.yml +0 -31
- rasa/core/channels/inspector/dist/assets/channel-8e08bed9.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-78c82dea.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b08f601.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-c941dcb3.js +0 -1336
- {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""MCP server connection utilities."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import warnings
|
|
5
|
+
from contextlib import AsyncExitStack, asynccontextmanager
|
|
6
|
+
from typing import Any, AsyncIterator, ClassVar, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
import structlog
|
|
9
|
+
from httpx import HTTPStatusError
|
|
10
|
+
from mcp import ClientSession
|
|
11
|
+
from mcp.client.streamable_http import streamablehttp_client
|
|
12
|
+
|
|
13
|
+
from rasa.shared.agents.auth.agent_auth_manager import AgentAuthManager
|
|
14
|
+
from rasa.shared.agents.auth.auth_strategy import AgentAuthStrategy
|
|
15
|
+
from rasa.shared.exceptions import AuthenticationError
|
|
16
|
+
|
|
17
|
+
structlogger = structlog.get_logger()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Suppress RuntimeWarning about unawaited coroutines when MCP server is not reachable.
|
|
21
|
+
warnings.filterwarnings(
|
|
22
|
+
"ignore",
|
|
23
|
+
message=".*BaseEventLoop.create_server.*was never awaited.*",
|
|
24
|
+
category=RuntimeWarning,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class MCPServerConnection:
|
|
29
|
+
"""
|
|
30
|
+
Manages connection to an MCP server, with optional authentication.
|
|
31
|
+
|
|
32
|
+
This class handles:
|
|
33
|
+
- Connection establishment and cleanup
|
|
34
|
+
- Session lifecycle management
|
|
35
|
+
- Authentication via AgentAuthManager (API Key, OAuth2, mTLS, etc.)
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
# Timeout for ping operations in seconds
|
|
39
|
+
PING_TIMEOUT_SECONDS = 3.0
|
|
40
|
+
|
|
41
|
+
_SUPPORTED_SERVER_TYPES: ClassVar[List[str]] = ["http", "https"]
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
server_name: str,
|
|
46
|
+
server_url: str,
|
|
47
|
+
server_type: str,
|
|
48
|
+
auth_manager: Optional[AgentAuthManager] = None,
|
|
49
|
+
):
|
|
50
|
+
"""
|
|
51
|
+
Initialize the MCP server connection.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
server_name: Server name to identify the server
|
|
55
|
+
server_url: Server URL
|
|
56
|
+
server_type: Server type (currently only 'http' is supported)
|
|
57
|
+
auth_manager: Optional AgentAuthManager instance for this connection
|
|
58
|
+
"""
|
|
59
|
+
self.server_name = server_name
|
|
60
|
+
self.server_url = server_url
|
|
61
|
+
self.server_type = server_type
|
|
62
|
+
self._auth_manager = auth_manager
|
|
63
|
+
self.session: Optional[ClientSession] = None
|
|
64
|
+
self.exit_stack: Optional[AsyncExitStack] = None
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def from_config(cls, server_config: Dict[str, Any]) -> "MCPServerConnection":
|
|
68
|
+
"""Initialize the MCP server connection from a configuration dictionary."""
|
|
69
|
+
auth_config = server_config.get("additional_params")
|
|
70
|
+
_auth_manager = AgentAuthManager.load_auth(auth_config)
|
|
71
|
+
return cls(
|
|
72
|
+
server_config["name"],
|
|
73
|
+
server_config["url"],
|
|
74
|
+
server_config.get("type", "http"),
|
|
75
|
+
_auth_manager,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
@asynccontextmanager
|
|
80
|
+
async def open_mcp_session(
|
|
81
|
+
url: str, auth_strategy: Optional[AgentAuthStrategy] = None
|
|
82
|
+
) -> AsyncIterator[ClientSession]:
|
|
83
|
+
"""
|
|
84
|
+
Open a streamable MCP session, ensuring that initialization
|
|
85
|
+
completes before yielding.
|
|
86
|
+
"""
|
|
87
|
+
async with streamablehttp_client(url, auth=auth_strategy) as (
|
|
88
|
+
read_stream,
|
|
89
|
+
write_stream,
|
|
90
|
+
_,
|
|
91
|
+
):
|
|
92
|
+
async with ClientSession(read_stream, write_stream) as session:
|
|
93
|
+
await session.initialize() # handshake done here
|
|
94
|
+
yield session
|
|
95
|
+
|
|
96
|
+
async def connect(self) -> None:
|
|
97
|
+
"""Establish connection to the MCP server.
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
ValueError: If the server type is not supported.
|
|
101
|
+
ConnectionError: If connection fails.
|
|
102
|
+
AuthenticationError: If authentication fails.
|
|
103
|
+
"""
|
|
104
|
+
if self.server_type not in self._SUPPORTED_SERVER_TYPES:
|
|
105
|
+
raise ValueError(f"Unsupported server type: {self.server_type}")
|
|
106
|
+
|
|
107
|
+
# Create a new exit stack for this connection to avoid task boundary issues
|
|
108
|
+
self.exit_stack = AsyncExitStack()
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
# Get authentication strategy that adheres to httpx.Auth.
|
|
112
|
+
auth_strategy = (
|
|
113
|
+
self._auth_manager.get_auth() if self._auth_manager else None
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Register the wrapped context manager in the stack
|
|
117
|
+
self.session = await self.exit_stack.enter_async_context(
|
|
118
|
+
self.open_mcp_session(self.server_url, auth_strategy)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
except Exception as eg:
|
|
122
|
+
for exc in getattr(eg, "exceptions", [eg]):
|
|
123
|
+
event_info = (
|
|
124
|
+
f"Failed to connect to MCP server `{self.server_name}`: {exc!s}"
|
|
125
|
+
)
|
|
126
|
+
if isinstance(exc, HTTPStatusError):
|
|
127
|
+
status_code = exc.response.status_code
|
|
128
|
+
structlogger.error(
|
|
129
|
+
"mcp_server_connection.connect.http_status_error",
|
|
130
|
+
event_info=event_info,
|
|
131
|
+
server_name=self.server_name,
|
|
132
|
+
server_url=self.server_url,
|
|
133
|
+
status_code=status_code,
|
|
134
|
+
response_text=exc.response.reason_phrase,
|
|
135
|
+
)
|
|
136
|
+
await self._cleanup()
|
|
137
|
+
if status_code in [400, 401, 403]:
|
|
138
|
+
raise AuthenticationError(eg) from eg
|
|
139
|
+
else:
|
|
140
|
+
raise ConnectionError(eg) from eg
|
|
141
|
+
else:
|
|
142
|
+
structlogger.error(
|
|
143
|
+
"mcp_server_connection.connect.other_exception",
|
|
144
|
+
event_info=event_info,
|
|
145
|
+
server_name=self.server_name,
|
|
146
|
+
server_url=self.server_url,
|
|
147
|
+
error=str(exc),
|
|
148
|
+
)
|
|
149
|
+
await self._cleanup()
|
|
150
|
+
raise ConnectionError(eg) from eg
|
|
151
|
+
|
|
152
|
+
except asyncio.CancelledError as e:
|
|
153
|
+
event_info = f"Connection to MCP server `{self.server_name}` was cancelled."
|
|
154
|
+
structlogger.error(
|
|
155
|
+
"mcp_server_connection.connect.connection_cancelled",
|
|
156
|
+
event_info=event_info,
|
|
157
|
+
server_name=self.server_name,
|
|
158
|
+
server_url=self.server_url,
|
|
159
|
+
)
|
|
160
|
+
# Clean up on cancellation
|
|
161
|
+
await self._cleanup()
|
|
162
|
+
raise ConnectionError(e) from e
|
|
163
|
+
|
|
164
|
+
async def ensure_active_session(self) -> ClientSession:
|
|
165
|
+
"""
|
|
166
|
+
Ensure an active session is available.
|
|
167
|
+
|
|
168
|
+
If no session exists or the current session is inactive,
|
|
169
|
+
a new connection will be established.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Active ClientSession instance.
|
|
173
|
+
"""
|
|
174
|
+
if self.session is None:
|
|
175
|
+
await self.connect()
|
|
176
|
+
structlogger.info(
|
|
177
|
+
"mcp_server_connection.ensure_active_session.no_session",
|
|
178
|
+
server_name=self.server_name,
|
|
179
|
+
server_url=self.server_url,
|
|
180
|
+
event_info=(
|
|
181
|
+
"No session found, connecting to the server "
|
|
182
|
+
f"`{self.server_name}` @ `{self.server_url}`"
|
|
183
|
+
),
|
|
184
|
+
)
|
|
185
|
+
if self.session:
|
|
186
|
+
try:
|
|
187
|
+
# Add timeout to prevent hanging when MCP server is down
|
|
188
|
+
await asyncio.wait_for(
|
|
189
|
+
self.session.send_ping(), timeout=self.PING_TIMEOUT_SECONDS
|
|
190
|
+
)
|
|
191
|
+
except asyncio.TimeoutError as e:
|
|
192
|
+
structlogger.error(
|
|
193
|
+
"mcp_server_connection.ensure_active_session.ping_timeout",
|
|
194
|
+
server_name=self.server_name,
|
|
195
|
+
server_url=self.server_url,
|
|
196
|
+
event_info=(
|
|
197
|
+
"Ping timed out, Server not reachable - "
|
|
198
|
+
f"`{self.server_name}` @ `{self.server_url}`"
|
|
199
|
+
),
|
|
200
|
+
)
|
|
201
|
+
raise e
|
|
202
|
+
except Exception as e:
|
|
203
|
+
structlogger.warning(
|
|
204
|
+
"mcp_server_connection.ensure_active_session.ping_failed",
|
|
205
|
+
error=str(e),
|
|
206
|
+
server_name=self.server_name,
|
|
207
|
+
server_url=self.server_url,
|
|
208
|
+
event_info=(
|
|
209
|
+
"Ping failed, trying to reconnect to the server "
|
|
210
|
+
f"`{self.server_name}` @ `{self.server_url}`"
|
|
211
|
+
),
|
|
212
|
+
)
|
|
213
|
+
# Cleanup existing session
|
|
214
|
+
await self.close()
|
|
215
|
+
# Attempt to reconnect now
|
|
216
|
+
await self.connect()
|
|
217
|
+
structlogger.info(
|
|
218
|
+
"mcp_server_connection.ensure_active_session.reconnected",
|
|
219
|
+
server_name=self.server_name,
|
|
220
|
+
server_url=self.server_url,
|
|
221
|
+
event_info=(
|
|
222
|
+
"Reconnected to the server "
|
|
223
|
+
f"`{self.server_name}` @ `{self.server_url}`"
|
|
224
|
+
),
|
|
225
|
+
)
|
|
226
|
+
assert self.session is not None # Ensures type for mypy
|
|
227
|
+
return self.session
|
|
228
|
+
|
|
229
|
+
async def close(self) -> None:
|
|
230
|
+
"""Close the connection and clean up resources."""
|
|
231
|
+
await self._cleanup()
|
|
232
|
+
|
|
233
|
+
async def _cleanup(self) -> None:
|
|
234
|
+
"""Internal cleanup method to safely close resources."""
|
|
235
|
+
if self.exit_stack:
|
|
236
|
+
try:
|
|
237
|
+
await self.exit_stack.aclose()
|
|
238
|
+
except Exception as e:
|
|
239
|
+
# Log cleanup errors but don't raise them
|
|
240
|
+
structlogger.warning(
|
|
241
|
+
"mcp_server_connection.cleanup.failed",
|
|
242
|
+
server_name=self.server_name,
|
|
243
|
+
error=str(e),
|
|
244
|
+
)
|
|
245
|
+
finally:
|
|
246
|
+
self.exit_stack = None
|
|
247
|
+
self.session = None
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""MCP utilities."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def mcp_server_exists(mcp_server: str) -> bool:
|
|
5
|
+
"""Check if an MCP server exists in the configured endpoints.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
mcp_server: The name of the MCP server to check.
|
|
9
|
+
|
|
10
|
+
Returns:
|
|
11
|
+
True if the MCP server exists, False otherwise.
|
|
12
|
+
"""
|
|
13
|
+
from rasa.core.config.configuration import Configuration
|
|
14
|
+
|
|
15
|
+
endpoints = Configuration.get_instance().endpoints
|
|
16
|
+
if (mcp_server_list := endpoints.mcp_servers) is None:
|
|
17
|
+
return False
|
|
18
|
+
|
|
19
|
+
mcp_server_names = [server.name for server in mcp_server_list]
|
|
20
|
+
return mcp_server in mcp_server_names
|
|
@@ -160,6 +160,43 @@ FLOW_CANCELLED = {
|
|
|
160
160
|
"step_id": {"type": "string"},
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
+
AGENT_STARTED = {
|
|
164
|
+
"properties": {
|
|
165
|
+
"event": {"const": "agent_started"},
|
|
166
|
+
"agent_id": {"type": "string"},
|
|
167
|
+
"flow_id": {"type": "string"},
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
AGENT_COMPLETED = {
|
|
171
|
+
"properties": {
|
|
172
|
+
"event": {"const": "agent_completed"},
|
|
173
|
+
"agent_id": {"type": "string"},
|
|
174
|
+
"flow_id": {"type": "string"},
|
|
175
|
+
"status": {"type": "string"},
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
AGENT_INTERRUPTED = {
|
|
179
|
+
"properties": {
|
|
180
|
+
"event": {"const": "agent_interrupted"},
|
|
181
|
+
"agent_id": {"type": "string"},
|
|
182
|
+
"flow_id": {"type": "string"},
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
AGENT_RESUMED = {
|
|
186
|
+
"properties": {
|
|
187
|
+
"event": {"const": "agent_resumed"},
|
|
188
|
+
"agent_id": {"type": "string"},
|
|
189
|
+
"flow_id": {"type": "string"},
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
AGENT_CANCELLED = {
|
|
193
|
+
"properties": {
|
|
194
|
+
"event": {"const": "agent_cancelled"},
|
|
195
|
+
"agent_id": {"type": "string"},
|
|
196
|
+
"flow_id": {"type": "string"},
|
|
197
|
+
"reason": {"type": "string"},
|
|
198
|
+
}
|
|
199
|
+
}
|
|
163
200
|
DIALOGUE_STACK_UPDATED = {
|
|
164
201
|
"properties": {"event": {"const": "stack"}, "update": {"type": "string"}}
|
|
165
202
|
}
|
|
@@ -204,6 +241,11 @@ EVENT_SCHEMA = {
|
|
|
204
241
|
FLOW_RESUMED,
|
|
205
242
|
FLOW_COMPLETED,
|
|
206
243
|
FLOW_CANCELLED,
|
|
244
|
+
AGENT_STARTED,
|
|
245
|
+
AGENT_COMPLETED,
|
|
246
|
+
AGENT_INTERRUPTED,
|
|
247
|
+
AGENT_RESUMED,
|
|
248
|
+
AGENT_CANCELLED,
|
|
207
249
|
DIALOGUE_STACK_UPDATED,
|
|
208
250
|
ROUTING_SESSION_ENDED,
|
|
209
251
|
SESSION_ENDED,
|
rasa/shared/utils/yaml.py
CHANGED
|
@@ -335,7 +335,9 @@ class YamlValidationException(YamlException, ValueError):
|
|
|
335
335
|
)
|
|
336
336
|
if found_lc:
|
|
337
337
|
return line_offset
|
|
338
|
-
|
|
338
|
+
if this_line is not None:
|
|
339
|
+
return this_line + line_offset
|
|
340
|
+
return line_offset
|
|
339
341
|
return line
|
|
340
342
|
elif isinstance(current, list) and head.isdigit():
|
|
341
343
|
return (
|
rasa/studio/pull/pull.py
CHANGED
|
@@ -8,6 +8,7 @@ import structlog
|
|
|
8
8
|
|
|
9
9
|
import rasa.cli.utils
|
|
10
10
|
import rasa.shared.utils.cli
|
|
11
|
+
from rasa.cli.validation.config_path_validation import get_validated_path
|
|
11
12
|
from rasa.shared.constants import (
|
|
12
13
|
DEFAULT_CONFIG_PATH,
|
|
13
14
|
DEFAULT_DATA_PATH,
|
|
@@ -140,7 +141,7 @@ def _prepare_data_and_domain_paths(args: argparse.Namespace) -> Tuple[Path, Path
|
|
|
140
141
|
A tuple containing the domain path and a data path.
|
|
141
142
|
"""
|
|
142
143
|
# Prepare domain path.
|
|
143
|
-
domain_path =
|
|
144
|
+
domain_path = get_validated_path(
|
|
144
145
|
args.domain, "domain", DEFAULT_DOMAIN_PATHS, none_is_valid=True
|
|
145
146
|
)
|
|
146
147
|
domain_or_default_path = args.domain or DEFAULT_DOMAIN_PATH
|
|
@@ -152,7 +153,7 @@ def _prepare_data_and_domain_paths(args: argparse.Namespace) -> Tuple[Path, Path
|
|
|
152
153
|
if isinstance(domain_path, str):
|
|
153
154
|
domain_path = Path(domain_path)
|
|
154
155
|
|
|
155
|
-
data_path =
|
|
156
|
+
data_path = get_validated_path(
|
|
156
157
|
args.data, "data", DEFAULT_DATA_PATH, none_is_valid=True
|
|
157
158
|
)
|
|
158
159
|
|
rasa/studio/train.py
CHANGED
|
@@ -4,13 +4,15 @@ import sys
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Any, List, Optional
|
|
6
6
|
|
|
7
|
-
import rasa.cli.utils
|
|
8
|
-
import rasa.shared.utils.cli
|
|
9
7
|
from rasa.cli.train import (
|
|
10
8
|
_model_for_finetuning,
|
|
11
9
|
extract_core_additional_arguments,
|
|
12
10
|
extract_nlu_additional_arguments,
|
|
13
11
|
)
|
|
12
|
+
from rasa.cli.validation.config_path_validation import (
|
|
13
|
+
get_validated_config,
|
|
14
|
+
get_validated_path,
|
|
15
|
+
)
|
|
14
16
|
from rasa.shared.constants import (
|
|
15
17
|
CONFIG_MANDATORY_KEYS,
|
|
16
18
|
DEFAULT_DATA_PATH,
|
|
@@ -41,10 +43,10 @@ def handle_train(args: argparse.Namespace) -> Optional[str]:
|
|
|
41
43
|
else:
|
|
42
44
|
handler.request_all_data()
|
|
43
45
|
|
|
44
|
-
domain =
|
|
46
|
+
domain = get_validated_path(
|
|
45
47
|
args.domain, "domain", DEFAULT_DOMAIN_PATH, none_is_valid=True
|
|
46
48
|
)
|
|
47
|
-
config =
|
|
49
|
+
config = get_validated_config(args.config, CONFIG_MANDATORY_KEYS)
|
|
48
50
|
data_form_studio, data_original = import_data_from_studio(
|
|
49
51
|
handler, domain, args.data
|
|
50
52
|
)
|
|
@@ -58,9 +60,7 @@ def handle_train(args: argparse.Namespace) -> Optional[str]:
|
|
|
58
60
|
)
|
|
59
61
|
|
|
60
62
|
training_files = [
|
|
61
|
-
|
|
62
|
-
f, "data", DEFAULT_DATA_PATH, none_is_valid=True
|
|
63
|
-
)
|
|
63
|
+
get_validated_path(f, "data", DEFAULT_DATA_PATH, none_is_valid=True)
|
|
64
64
|
for f in args.data
|
|
65
65
|
]
|
|
66
66
|
training_files.extend(studio_training_files)
|
|
@@ -68,6 +68,7 @@ def handle_train(args: argparse.Namespace) -> Optional[str]:
|
|
|
68
68
|
training_result = train_all(
|
|
69
69
|
domain=str(domain_file),
|
|
70
70
|
config=config,
|
|
71
|
+
endpoints=args.endpoints,
|
|
71
72
|
training_files=args.data,
|
|
72
73
|
output=args.out,
|
|
73
74
|
dry_run=args.dry_run,
|
rasa/studio/upload.py
CHANGED
|
@@ -12,6 +12,7 @@ import rasa.cli.telemetry
|
|
|
12
12
|
import rasa.cli.utils
|
|
13
13
|
import rasa.shared.utils.cli
|
|
14
14
|
import rasa.shared.utils.io
|
|
15
|
+
from rasa.cli.validation.config_path_validation import get_validated_path
|
|
15
16
|
from rasa.shared.constants import (
|
|
16
17
|
CONFIG_LANGUAGE_KEY,
|
|
17
18
|
CONFIG_LLM_KEY,
|
|
@@ -155,13 +156,9 @@ def handle_upload(args: argparse.Namespace) -> None:
|
|
|
155
156
|
|
|
156
157
|
structlogger.info("rasa.studio.upload.loading_data", event_info="Loading data...")
|
|
157
158
|
|
|
158
|
-
args.domain =
|
|
159
|
-
args.domain, "domain", DEFAULT_DOMAIN_PATHS
|
|
160
|
-
)
|
|
159
|
+
args.domain = get_validated_path(args.domain, "domain", DEFAULT_DOMAIN_PATHS)
|
|
161
160
|
|
|
162
|
-
args.config =
|
|
163
|
-
args.config, "config", DEFAULT_CONFIG_PATH
|
|
164
|
-
)
|
|
161
|
+
args.config = get_validated_path(args.config, "config", DEFAULT_CONFIG_PATH)
|
|
165
162
|
|
|
166
163
|
config = read_yaml_file(args.config, expand_env_vars=False)
|
|
167
164
|
assistant_name = args.assistant_name or _get_assistant_name(config)
|
rasa/telemetry.py
CHANGED
|
@@ -31,7 +31,6 @@ from rasa.constants import (
|
|
|
31
31
|
CONFIG_TELEMETRY_ENABLED,
|
|
32
32
|
CONFIG_TELEMETRY_ID,
|
|
33
33
|
)
|
|
34
|
-
from rasa.engine.storage.local_model_storage import LocalModelStorage
|
|
35
34
|
from rasa.privacy.privacy_config import AnonymizationType, PrivacyConfig
|
|
36
35
|
from rasa.shared.constants import (
|
|
37
36
|
ASSISTANT_ID_KEY,
|
|
@@ -50,6 +49,7 @@ from rasa.shared.constants import (
|
|
|
50
49
|
UTTER_ASK_PREFIX,
|
|
51
50
|
)
|
|
52
51
|
from rasa.shared.core.flows import Flow
|
|
52
|
+
from rasa.shared.core.flows.flows_list import FlowsList
|
|
53
53
|
from rasa.shared.core.flows.steps import (
|
|
54
54
|
CallFlowStep,
|
|
55
55
|
CollectInformationFlowStep,
|
|
@@ -61,9 +61,9 @@ from rasa.utils import common as rasa_utils
|
|
|
61
61
|
|
|
62
62
|
if typing.TYPE_CHECKING:
|
|
63
63
|
from rasa.core.agent import Agent
|
|
64
|
-
from rasa.core.available_endpoints import AvailableEndpoints
|
|
65
64
|
from rasa.core.brokers.broker import EventBroker
|
|
66
65
|
from rasa.core.channels.channel import InputChannel
|
|
66
|
+
from rasa.core.config.available_endpoints import AvailableEndpoints
|
|
67
67
|
from rasa.core.tracker_stores.tracker_store import TrackerStore
|
|
68
68
|
from rasa.e2e_test.e2e_test_case import Fixture, Metadata, TestCase
|
|
69
69
|
from rasa.shared.importers.importer import TrainingDataImporter
|
|
@@ -1056,7 +1056,7 @@ def track_model_training(
|
|
|
1056
1056
|
"policies": config.get(CONFIG_POLICIES_KEY),
|
|
1057
1057
|
"train_schema": config.get(CONFIG_TRAIN_SCHEMA),
|
|
1058
1058
|
"predict_schema": config.get(CONFIG_PREDICT_SCHEMA),
|
|
1059
|
-
"model_groups": rasa.core.
|
|
1059
|
+
"model_groups": rasa.core.config.configuration.Configuration.get_instance().endpoints.model_groups, # noqa: E501
|
|
1060
1060
|
"api_health_check_enabled": (
|
|
1061
1061
|
os.getenv(
|
|
1062
1062
|
LLM_API_HEALTH_CHECK_ENV_VAR, LLM_API_HEALTH_CHECK_DEFAULT_VALUE
|
|
@@ -1083,6 +1083,7 @@ def track_model_training(
|
|
|
1083
1083
|
"num_regexes": len(nlu_data.regex_features),
|
|
1084
1084
|
"is_finetuning": is_finetuning,
|
|
1085
1085
|
"recipe": config.get(CONFIG_RECIPE_KEY),
|
|
1086
|
+
"agents": _collect_agent_configuration(flows),
|
|
1086
1087
|
}
|
|
1087
1088
|
|
|
1088
1089
|
flow_statistics = _collect_flow_statistics(flows.underlying_flows)
|
|
@@ -1125,6 +1126,67 @@ def track_model_training(
|
|
|
1125
1126
|
)
|
|
1126
1127
|
|
|
1127
1128
|
|
|
1129
|
+
def _collect_agent_configuration(flows: FlowsList) -> Dict[str, Any]:
|
|
1130
|
+
agent_data: Dict[str, Any] = {}
|
|
1131
|
+
|
|
1132
|
+
from rasa.core.available_agents import AvailableAgents
|
|
1133
|
+
from rasa.core.config.configuration import Configuration
|
|
1134
|
+
|
|
1135
|
+
agents = AvailableAgents.get_instance().agents
|
|
1136
|
+
mcp_servers = Configuration.get_instance().endpoints.mcp_servers
|
|
1137
|
+
|
|
1138
|
+
if not agents and not mcp_servers:
|
|
1139
|
+
return agent_data
|
|
1140
|
+
|
|
1141
|
+
agent_data["usage"] = []
|
|
1142
|
+
|
|
1143
|
+
for flow in flows.underlying_flows:
|
|
1144
|
+
for step in flow.steps:
|
|
1145
|
+
if isinstance(step, CallFlowStep):
|
|
1146
|
+
if flows.flow_by_id(step.call) is not None:
|
|
1147
|
+
continue
|
|
1148
|
+
|
|
1149
|
+
if step.is_calling_mcp_tool():
|
|
1150
|
+
agent_data["usage"].append(
|
|
1151
|
+
{
|
|
1152
|
+
"flow": flow.id,
|
|
1153
|
+
"mcp_tool": step.call,
|
|
1154
|
+
"mcp_server": step.mcp_server,
|
|
1155
|
+
"mapping": step.mapping,
|
|
1156
|
+
}
|
|
1157
|
+
)
|
|
1158
|
+
|
|
1159
|
+
if step.is_calling_agent():
|
|
1160
|
+
if step.exit_if:
|
|
1161
|
+
agent_data["usage"].append(
|
|
1162
|
+
{
|
|
1163
|
+
"flow": flow.id,
|
|
1164
|
+
"agent": step.call,
|
|
1165
|
+
"exit_if": step.exit_if,
|
|
1166
|
+
}
|
|
1167
|
+
)
|
|
1168
|
+
else:
|
|
1169
|
+
agent_data["usage"].append(
|
|
1170
|
+
{
|
|
1171
|
+
"flow": flow.id,
|
|
1172
|
+
"agent": step.call,
|
|
1173
|
+
}
|
|
1174
|
+
)
|
|
1175
|
+
|
|
1176
|
+
# dump mcp_servers and agents as json and exclude any values that are None
|
|
1177
|
+
if mcp_servers:
|
|
1178
|
+
agent_data["mcp_servers"] = [
|
|
1179
|
+
mcp_server.model_dump(exclude_none=True) for mcp_server in mcp_servers
|
|
1180
|
+
]
|
|
1181
|
+
if agents:
|
|
1182
|
+
agent_data["agents"] = [
|
|
1183
|
+
{agent_name: agent_info.model_dump(exclude_none=True)}
|
|
1184
|
+
for agent_name, agent_info in agents.items()
|
|
1185
|
+
]
|
|
1186
|
+
|
|
1187
|
+
return agent_data
|
|
1188
|
+
|
|
1189
|
+
|
|
1128
1190
|
def _collect_flow_statistics(flows: List[Flow]) -> Dict[str, Any]:
|
|
1129
1191
|
"""Collects some statistics about the flows, such as number of specific steps."""
|
|
1130
1192
|
data = {
|
|
@@ -1430,7 +1492,7 @@ def track_server_start(
|
|
|
1430
1492
|
number_of_workers: number of used Sanic workers
|
|
1431
1493
|
is_api_enabled: whether the rasa API server is enabled
|
|
1432
1494
|
"""
|
|
1433
|
-
from rasa.core.available_endpoints import AvailableEndpoints
|
|
1495
|
+
from rasa.core.config.available_endpoints import AvailableEndpoints
|
|
1434
1496
|
|
|
1435
1497
|
def project_fingerprint_and_assistant_id_from_model(
|
|
1436
1498
|
_model_directory: Optional[Text],
|
|
@@ -1441,7 +1503,9 @@ def track_server_start(
|
|
|
1441
1503
|
|
|
1442
1504
|
try:
|
|
1443
1505
|
model_archive = model.get_local_model(_model_directory)
|
|
1444
|
-
metadata = LocalModelStorage.metadata_from_archive(
|
|
1506
|
+
metadata = rasa.engine.storage.local_model_storage.LocalModelStorage.metadata_from_archive( # noqa: E501
|
|
1507
|
+
model_archive
|
|
1508
|
+
)
|
|
1445
1509
|
|
|
1446
1510
|
return metadata.project_fingerprint, metadata.assistant_id
|
|
1447
1511
|
except Exception:
|
rasa/tracing/config.py
CHANGED
|
@@ -6,7 +6,6 @@ import os
|
|
|
6
6
|
from typing import Any, Dict, Optional, Text
|
|
7
7
|
|
|
8
8
|
import grpc
|
|
9
|
-
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
|
|
10
9
|
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
|
|
11
10
|
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
|
12
11
|
from opentelemetry.metrics import set_meter_provider
|
|
@@ -16,6 +15,9 @@ from opentelemetry.sdk.resources import SERVICE_NAME, Resource
|
|
|
16
15
|
from opentelemetry.sdk.trace import TracerProvider
|
|
17
16
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
18
17
|
|
|
18
|
+
from rasa.agents.protocol.a2a.a2a_agent import A2AAgent
|
|
19
|
+
from rasa.agents.protocol.mcp.mcp_open_agent import MCPOpenAgent
|
|
20
|
+
from rasa.agents.protocol.mcp.mcp_task_agent import MCPTaskAgent
|
|
19
21
|
from rasa.core.actions.custom_action_executor import (
|
|
20
22
|
CustomActionExecutor,
|
|
21
23
|
RetryCustomActionExecutor,
|
|
@@ -93,6 +95,9 @@ def configure_tracing(tracer_provider: Optional[TracerProvider]) -> None:
|
|
|
93
95
|
if custom_action_executor_class != RetryCustomActionExecutor:
|
|
94
96
|
custom_action_executor_subclasses.append(custom_action_executor_class)
|
|
95
97
|
|
|
98
|
+
# All agent classes to instrument (protocol agent classes)
|
|
99
|
+
agent_classes = [MCPOpenAgent, MCPTaskAgent, A2AAgent]
|
|
100
|
+
|
|
96
101
|
instrumentation.instrument(
|
|
97
102
|
tracer_provider=tracer_provider,
|
|
98
103
|
agent_class=Agent,
|
|
@@ -114,6 +119,7 @@ def configure_tracing(tracer_provider: Optional[TracerProvider]) -> None:
|
|
|
114
119
|
multi_step_llm_command_generator_class=MultiStepLLMCommandGenerator,
|
|
115
120
|
custom_action_executor_subclasses=custom_action_executor_subclasses,
|
|
116
121
|
flow_retrieval_class=FlowRetrieval,
|
|
122
|
+
subagent_classes=agent_classes,
|
|
117
123
|
)
|
|
118
124
|
|
|
119
125
|
|
|
@@ -172,19 +178,35 @@ class TracerConfigurer(abc.ABC):
|
|
|
172
178
|
|
|
173
179
|
|
|
174
180
|
class JaegerTracerConfigurer(TracerConfigurer):
|
|
175
|
-
"""The `TracerConfigurer` for a Jaeger backend.
|
|
181
|
+
"""The `TracerConfigurer` for a Jaeger backend.
|
|
182
|
+
|
|
183
|
+
This class maintains backward compatibility with the old Jaeger configuration format
|
|
184
|
+
while internally using OTLP to avoid protobuf compatibility issues.
|
|
185
|
+
"""
|
|
176
186
|
|
|
177
187
|
@classmethod
|
|
178
188
|
def configure_from_endpoint_config(cls, cfg: EndpointConfig) -> TracerProvider:
|
|
179
|
-
"""Configure tracing for Jaeger.
|
|
189
|
+
"""Configure tracing for Jaeger using OTLP under the hood.
|
|
180
190
|
|
|
181
|
-
This
|
|
182
|
-
|
|
183
|
-
backend.
|
|
191
|
+
This maintains backward compatibility with the old Jaeger configuration format
|
|
192
|
+
while using OTLP internally to avoid protobuf compatibility issues.
|
|
184
193
|
|
|
185
194
|
:param cfg: The configuration to be read for configuring tracing.
|
|
186
195
|
:return: The configured `TracerProvider`.
|
|
187
196
|
"""
|
|
197
|
+
# Extract Jaeger-specific configuration
|
|
198
|
+
jaeger_config = cls._extract_config(cfg)
|
|
199
|
+
|
|
200
|
+
# Map Jaeger configuration to OTLP endpoint
|
|
201
|
+
otlp_endpoint = f"http://{jaeger_config['agent_host_name']}:{jaeger_config.get('agent_port', 4317)}" # noqa: E501
|
|
202
|
+
|
|
203
|
+
# Create OTLP exporter with Jaeger-compatible configuration
|
|
204
|
+
otlp_exporter = OTLPSpanExporter(
|
|
205
|
+
endpoint=otlp_endpoint,
|
|
206
|
+
insecure=True, # Jaeger typically runs without TLS in development
|
|
207
|
+
headers=cls._build_headers(jaeger_config),
|
|
208
|
+
)
|
|
209
|
+
|
|
188
210
|
provider = TracerProvider(
|
|
189
211
|
resource=Resource.create(
|
|
190
212
|
{
|
|
@@ -195,19 +217,17 @@ class JaegerTracerConfigurer(TracerConfigurer):
|
|
|
195
217
|
)
|
|
196
218
|
)
|
|
197
219
|
|
|
198
|
-
jaeger_exporter = JaegerExporter(
|
|
199
|
-
**cls._extract_config(cfg), udp_split_oversized_batches=True
|
|
200
|
-
)
|
|
201
220
|
logger.info(
|
|
202
|
-
f"Registered {cfg.type} endpoint for tracing
|
|
203
|
-
f" {
|
|
221
|
+
f"Registered {cfg.type} endpoint for tracing using OTLP. "
|
|
222
|
+
f"Traces will be exported to {otlp_endpoint}."
|
|
204
223
|
)
|
|
205
|
-
provider.add_span_processor(BatchSpanProcessor(
|
|
224
|
+
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
|
|
206
225
|
|
|
207
226
|
return provider
|
|
208
227
|
|
|
209
228
|
@classmethod
|
|
210
229
|
def _extract_config(cls, cfg: EndpointConfig) -> Dict[str, Any]:
|
|
230
|
+
"""Extract Jaeger configuration parameters."""
|
|
211
231
|
return {
|
|
212
232
|
"agent_host_name": (cfg.kwargs.get("host", "localhost")),
|
|
213
233
|
"agent_port": (cfg.kwargs.get("port", 6831)),
|
|
@@ -215,6 +235,19 @@ class JaegerTracerConfigurer(TracerConfigurer):
|
|
|
215
235
|
"password": cfg.kwargs.get("password"),
|
|
216
236
|
}
|
|
217
237
|
|
|
238
|
+
@classmethod
|
|
239
|
+
def _build_headers(cls, jaeger_config: Dict[str, Any]) -> Optional[Dict[str, str]]:
|
|
240
|
+
"""Build OTLP headers from Jaeger authentication config."""
|
|
241
|
+
headers = {}
|
|
242
|
+
if jaeger_config.get("username") and jaeger_config.get("password"):
|
|
243
|
+
import base64
|
|
244
|
+
|
|
245
|
+
credentials = base64.b64encode(
|
|
246
|
+
f"{jaeger_config['username']}:{jaeger_config['password']}".encode()
|
|
247
|
+
).decode()
|
|
248
|
+
headers["Authorization"] = f"Basic {credentials}"
|
|
249
|
+
return headers if headers else None
|
|
250
|
+
|
|
218
251
|
|
|
219
252
|
class OTLPCollectorConfigurer(TracerConfigurer):
|
|
220
253
|
"""The `TracerConfigurer` for an OTLP collector backend."""
|