rasa-pro 3.14.0rc3__py3-none-any.whl → 3.14.0rc4__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.

@@ -71,7 +71,7 @@ structlogger = structlog.get_logger()
71
71
 
72
72
 
73
73
  class MCPBaseAgent(AgentProtocol):
74
- """MCP protocol implementation"""
74
+ """MCP protocol implementation."""
75
75
 
76
76
  MAX_ITERATIONS = 10
77
77
 
@@ -135,6 +135,20 @@ class MCPBaseAgent(AgentProtocol):
135
135
  @classmethod
136
136
  def from_config(cls, config: AgentConfig) -> "MCPBaseAgent":
137
137
  """Initialize the MCP Open Agent with the given configuration."""
138
+ # Warn if configuration.timeout is set for MCP agents
139
+ if config.configuration and config.configuration.timeout is not None:
140
+ structlogger.warning(
141
+ "mcp_agent.configuration.timeout.not_implemented",
142
+ event_info="configuration.timeout is not implemented for MCP agents. "
143
+ "MCP agents do not establish external connections, "
144
+ "so agent-level timeout is not used. "
145
+ "To set timeout for LLM requests, "
146
+ "configure 'timeout' in the model_group "
147
+ "in endpoints.yml and reference it via configuration.llm.model_group.",
148
+ agent_name=config.agent.name,
149
+ timeout_value=config.configuration.timeout,
150
+ )
151
+
138
152
  return cls(
139
153
  name=config.agent.name,
140
154
  description=config.agent.description,
rasa/agents/validation.py CHANGED
@@ -5,6 +5,8 @@ import urllib.parse
5
5
  from collections import Counter
6
6
  from typing import Any, Dict, List, NoReturn, Set
7
7
 
8
+ import jinja2.exceptions
9
+ import structlog
8
10
  from pydantic import ValidationError as PydanticValidationError
9
11
 
10
12
  from rasa.agents.exceptions import (
@@ -23,8 +25,13 @@ from rasa.core.available_agents import (
23
25
  from rasa.core.config.available_endpoints import AvailableEndpoints
24
26
  from rasa.core.config.configuration import Configuration
25
27
  from rasa.exceptions import ValidationError
28
+ from rasa.shared.agents.auth.utils import validate_secrets_in_params
29
+ from rasa.shared.utils.llm import get_prompt_template, validate_jinja2_template
26
30
  from rasa.shared.utils.yaml import read_config_file
27
31
 
32
+ # Initialize logger
33
+ structlogger = structlog.get_logger()
34
+
28
35
  # Centralized allowed keys configuration to eliminate duplication
29
36
  ALLOWED_KEYS = {
30
37
  "agent": {"name", "protocol", "description"},
@@ -151,6 +158,41 @@ def _validate_a2a_config(agent_config: AgentConfig) -> None:
151
158
  f"exist: {agent_card}",
152
159
  )
153
160
 
161
+ # Validate right use of secrets in auth configuration
162
+ if agent_config.configuration.auth:
163
+ validate_secrets_in_params(
164
+ agent_config.configuration.auth, f"agent '{agent_name}'"
165
+ )
166
+
167
+
168
+ def _validate_prompt_template_syntax(prompt_path: str, agent_name: str) -> None:
169
+ """Validate Jinja2 syntax of a prompt template file."""
170
+ try:
171
+ # Use a simple default template, as we're assuming
172
+ # that the default templates are valid
173
+ default_template = "{{ content }}"
174
+ template_content = get_prompt_template(
175
+ prompt_path,
176
+ default_template,
177
+ log_source_component=f"agent.validation.{agent_name}",
178
+ log_source_method="init",
179
+ )
180
+ validate_jinja2_template(template_content)
181
+
182
+ except jinja2.exceptions.TemplateSyntaxError as e:
183
+ raise ValidationError(
184
+ code="agent.validation.prompt_template_syntax_error",
185
+ event_info=(
186
+ f"Agent '{agent_name}' has invalid Jinja2 template syntax at line "
187
+ f"{e.lineno}: {e.message}"
188
+ ),
189
+ ) from e
190
+ except Exception as e:
191
+ raise ValidationError(
192
+ code="agent.validation.optional.prompt_template_error",
193
+ event_info=(f"Agent '{agent_name}' has error reading prompt template: {e}"),
194
+ ) from e
195
+
154
196
 
155
197
  def _validate_optional_keys(agent_config: AgentConfig) -> None:
156
198
  """Validate optional keys in agent configuration."""
@@ -160,11 +202,22 @@ def _validate_optional_keys(agent_config: AgentConfig) -> None:
160
202
  if agent_config.configuration and agent_config.configuration.prompt_template:
161
203
  prompt_path = agent_config.configuration.prompt_template
162
204
  if not os.path.exists(prompt_path):
163
- raise ValidationError(
164
- code="agent.validation.optional.prompt_template_not_found",
165
- event_info=f"Agent '{agent_name}' has prompt template that "
166
- f"does not exist: {prompt_path}",
205
+ # If reading the custom prompt fails,
206
+ # allow fallback to default prompt template
207
+ structlogger.warning(
208
+ "agent.validation.optional.prompt_template_file_not_found",
209
+ agent_name=agent_name,
210
+ prompt_path=prompt_path,
211
+ event_info=(
212
+ f"Prompt template file not found: {prompt_path}. "
213
+ f"Agent will use default template."
214
+ ),
167
215
  )
216
+ # Don't raise ValidationError, allow fallback to default template
217
+ return
218
+
219
+ # Validate Jinja2 syntax
220
+ _validate_prompt_template_syntax(prompt_path, agent_name)
168
221
 
169
222
  # Validate module if present
170
223
  if agent_config.configuration and agent_config.configuration.module:
@@ -14,6 +14,7 @@ COPILOT_TRAINING_ERROR_HANDLER_PROMPT_FILE = (
14
14
  COPILOT_MESSAGE_TEMPLATES_DIR = "builder.copilot.templated_messages"
15
15
  RASA_INTERNAL_MESSAGES_TEMPLATES_FILE = "copilot_internal_messages_templates.yml"
16
16
  COPILOT_HANDLER_RESPONSES_FILE = "copilot_templated_responses.yml"
17
+ COPILOT_WELCOME_MESSAGES_FILE = "copilot_welcome_messages.yml"
17
18
 
18
19
  # OpenAI roles copilot utilizes - Use literal types to avoid type errors with OpenAI
19
20
  ROLE_USER: Literal["user"] = "user"
@@ -32,3 +33,6 @@ COPILOT_SEGMENT_WRITE_KEY_ENV_VAR = "COPILOT_SEGMENT_WRITE_KEY"
32
33
 
33
34
  # Copilot signing
34
35
  SIGNATURE_VERSION_V1 = "v1"
36
+
37
+ # Welcome message key for prompt-to-bot (not a template enum)
38
+ PROMPT_TO_BOT_KEY = "prompt_to_bot"
@@ -7,6 +7,7 @@ import yaml # type: ignore
7
7
  from rasa.builder.copilot.constants import (
8
8
  COPILOT_HANDLER_RESPONSES_FILE,
9
9
  COPILOT_MESSAGE_TEMPLATES_DIR,
10
+ COPILOT_WELCOME_MESSAGES_FILE,
10
11
  RASA_INTERNAL_MESSAGES_TEMPLATES_FILE,
11
12
  )
12
13
  from rasa.shared.constants import PACKAGE_NAME
@@ -56,3 +57,25 @@ def load_copilot_handler_default_responses() -> Dict[str, str]:
56
57
  error=e,
57
58
  )
58
59
  return dict()
60
+
61
+
62
+ def load_copilot_welcome_messages() -> Dict[str, str]:
63
+ """Load welcome message templates from the YAML configuration file.
64
+
65
+ Returns:
66
+ Dictionary mapping template names to welcome message text.
67
+ """
68
+ try:
69
+ config = yaml.safe_load(
70
+ importlib.resources.read_text(
71
+ f"{PACKAGE_NAME}.{COPILOT_MESSAGE_TEMPLATES_DIR}",
72
+ COPILOT_WELCOME_MESSAGES_FILE,
73
+ )
74
+ )
75
+ return config.get("welcome_messages", {})
76
+ except Exception as e:
77
+ structlogger.error(
78
+ "copilot_templated_message_provider.failed_to_load_welcome_messages",
79
+ error=e,
80
+ )
81
+ return dict()
@@ -36,3 +36,6 @@ responses:
36
36
  guardrail_blocked_project_response: |
37
37
  Your Copilot access has been temporarily blocked due to repeated policy violations.
38
38
  If you believe this is an error or would like to request a review, please reach out to support@rasa.com.
39
+
40
+ training_success_response: |
41
+ Your changes have been saved successfully.
@@ -0,0 +1,56 @@
1
+ welcome_messages:
2
+ copilot_intro: |
3
+ 👋 Welcome to Hello Rasa!
4
+
5
+ I'm your **Copilot** — here to help you explore Rasa and start customizing your agent.
6
+ You can ask me how your agent works, how to add new skills, or how to connect integrations.
7
+
8
+ finance: |
9
+ 👋 Welcome to Hello Rasa!
10
+
11
+ I'm your **Copilot** — here to help you explore Rasa and start customizing your agent.
12
+ You can ask me how your agent works, how to add new skills, or how to connect integrations.
13
+
14
+ Your **Banking Agent template** is now live.
15
+
16
+ ### ▶️ **First step: try it out**
17
+ Ask your agent (in the chat preview on the right):
18
+ - *What's my current balance?*
19
+ - *Send 100 dollars to James.*
20
+
21
+ telco: |
22
+ 👋 Welcome to Hello Rasa!
23
+
24
+ I'm your **Copilot** — here to help you explore Rasa and start customizing your agent.
25
+ You can ask me how your agent works, how to add new skills, or how to connect integrations.
26
+
27
+ Your **Telecom Support Agent template** is now live.
28
+
29
+ ### ▶️ **First step: try it out**
30
+ Ask your agent (in the chat preview on the right):
31
+ - *Why is my internet slow?*
32
+ - *How do i reboot my router?*
33
+
34
+ basic: |
35
+ 👋 Welcome to Hello Rasa!
36
+
37
+ I'm your **Copilot** — here to help you explore Rasa and start customizing your agent.
38
+ You can ask me how your agent works, how to add new skills, or how to connect integrations.
39
+
40
+ Your **Starter Agent template** is now live.
41
+
42
+ ### ▶️ **First step: try it out**
43
+ Ask your agent (in the chat preview on the right):
44
+ - *What can you do?*
45
+ - *Can I talk to a human?*
46
+
47
+ prompt_to_bot: |
48
+ 👋 Welcome to Hello Rasa!
49
+
50
+ I'm your **Copilot** — here to help you explore Rasa and start customizing your agent.
51
+ You can ask me how your agent works, how to add new skills, or how to connect integrations.
52
+
53
+ Your custom agent has been created and trained successfully.
54
+
55
+ ### ▶️ **First step: try it out**
56
+ Test your agent in the chat preview on the right to see how it responds to your users.
rasa/builder/jobs.py CHANGED
@@ -4,6 +4,13 @@ import structlog
4
4
  from sanic import Sanic
5
5
 
6
6
  from rasa.builder import config
7
+ from rasa.builder.copilot.constants import (
8
+ PROMPT_TO_BOT_KEY,
9
+ )
10
+ from rasa.builder.copilot.copilot_templated_message_provider import (
11
+ load_copilot_handler_default_responses,
12
+ load_copilot_welcome_messages,
13
+ )
7
14
  from rasa.builder.copilot.models import (
8
15
  CopilotContext,
9
16
  FileContent,
@@ -80,11 +87,20 @@ async def run_prompt_to_bot_job(
80
87
  update_agent(agent, app)
81
88
  await push_job_status_event(job, JobStatus.train_success)
82
89
 
90
+ # 3. Create copilot welcome message job
91
+ copilot_welcome_job = job_manager.create_job()
92
+ app.add_task(run_copilot_welcome_message_job(app, copilot_welcome_job))
93
+
83
94
  structlogger.info(
84
95
  "bot_builder_service.prompt_to_bot.success",
85
96
  files_generated=list(bot_files.keys()),
97
+ copilot_welcome_job_id=copilot_welcome_job.id,
98
+ )
99
+ await push_job_status_event(
100
+ job=job,
101
+ status=JobStatus.done,
102
+ payload={"copilot_welcome_job_id": copilot_welcome_job.id},
86
103
  )
87
- await push_job_status_event(job, JobStatus.done)
88
104
  job_manager.mark_done(job)
89
105
 
90
106
  except TrainingError as exc:
@@ -165,12 +181,23 @@ async def run_template_to_bot_job(
165
181
  update_agent(agent, app)
166
182
  await push_job_status_event(job, JobStatus.train_success)
167
183
 
168
- # 3) Done
184
+ # 3) Create copilot welcome message job
185
+ copilot_welcome_job = job_manager.create_job()
186
+ app.add_task(
187
+ run_copilot_welcome_message_job(app, copilot_welcome_job, template_name)
188
+ )
189
+
190
+ # 4) Done - include welcome job ID in payload
169
191
  structlogger.info(
170
192
  "bot_builder_service.template_to_bot.success",
171
193
  files_generated=list(bot_files.keys()),
194
+ copilot_welcome_job_id=copilot_welcome_job.id,
195
+ )
196
+ await push_job_status_event(
197
+ job=job,
198
+ status=JobStatus.done,
199
+ payload={"copilot_welcome_job_id": copilot_welcome_job.id},
172
200
  )
173
- await push_job_status_event(job, JobStatus.done)
174
201
  job_manager.mark_done(job)
175
202
 
176
203
  except TrainingError as exc:
@@ -256,8 +283,19 @@ async def run_replace_all_files_job(
256
283
  update_agent(agent, app)
257
284
  await push_job_status_event(job, JobStatus.train_success)
258
285
 
259
- # Send final done event
260
- await push_job_status_event(job, JobStatus.done)
286
+ # Send final done event with copilot training success response job ID
287
+ copilot_training_success_job = job_manager.create_job()
288
+ app.add_task(
289
+ run_copilot_training_success_job(app, copilot_training_success_job)
290
+ )
291
+
292
+ await push_job_status_event(
293
+ job=job,
294
+ status=JobStatus.done,
295
+ payload={
296
+ "copilot_training_success_job_id": copilot_training_success_job.id
297
+ },
298
+ )
261
299
  job_manager.mark_done(job)
262
300
 
263
301
  except ValidationError as exc:
@@ -450,3 +488,122 @@ async def run_copilot_training_error_analysis_job(
450
488
  job, JobStatus.copilot_analysis_error, message=str(exc)
451
489
  )
452
490
  job_manager.mark_done(job, error=str(exc))
491
+
492
+
493
+ async def run_copilot_welcome_message_job(
494
+ app: "Sanic",
495
+ job: JobInfo,
496
+ template_name: Optional[ProjectTemplateName] = None,
497
+ ) -> None:
498
+ """Run the welcome message job in the background.
499
+
500
+ This job sends a welcome message to the user after successful bot creation.
501
+ For template-based bots, it sends a predefined message.
502
+ For prompt-based bots, it can be extended to stream generated messages.
503
+
504
+ Args:
505
+ app: The Sanic application instance.
506
+ job: The job information instance.
507
+ template_name: The template name for template-based bots, None for prompt-based.
508
+ """
509
+ try:
510
+ # Load welcome messages from YAML
511
+ welcome_messages = load_copilot_welcome_messages()
512
+
513
+ # Get the appropriate welcome message
514
+ if template_name:
515
+ welcome_message = welcome_messages.get(
516
+ template_name.value,
517
+ welcome_messages.get(PROMPT_TO_BOT_KEY),
518
+ )
519
+ else:
520
+ welcome_message = welcome_messages.get(PROMPT_TO_BOT_KEY)
521
+
522
+ # Send the welcome message as a single event
523
+ await push_job_status_event(
524
+ job,
525
+ JobStatus.copilot_welcome_message,
526
+ payload={
527
+ "content": welcome_message,
528
+ "response_category": "copilot",
529
+ "completeness": "complete",
530
+ },
531
+ )
532
+
533
+ # Mark job as done
534
+ await push_job_status_event(job, JobStatus.done)
535
+ job_manager.mark_done(job)
536
+
537
+ structlogger.info(
538
+ "copilot_welcome_message_job.success",
539
+ job_id=job.id,
540
+ template=template_name.value if template_name else PROMPT_TO_BOT_KEY,
541
+ )
542
+
543
+ except Exception as exc:
544
+ structlogger.exception(
545
+ "welcome_message_job.error",
546
+ job_id=job.id,
547
+ error=str(exc),
548
+ )
549
+ await push_job_status_event(job, JobStatus.error, message=str(exc))
550
+ job_manager.mark_done(job, error=str(exc))
551
+
552
+
553
+ async def run_copilot_training_success_job(
554
+ app: "Sanic",
555
+ job: JobInfo,
556
+ ) -> None:
557
+ """Run the training success job in the background.
558
+
559
+ This job sends a training success message to the user after successful bot training.
560
+
561
+ Args:
562
+ app: The Sanic application instance.
563
+ job: The job information instance.
564
+ """
565
+ try:
566
+ # Load copilot default messages from YAML
567
+ internal_messages = load_copilot_handler_default_responses()
568
+
569
+ # Get the appropriate training success message
570
+ training_success_message = internal_messages.get("training_success_response")
571
+
572
+ # Send the training success message
573
+ await push_job_status_event(
574
+ job,
575
+ JobStatus.train_success_message,
576
+ payload={
577
+ "content": training_success_message,
578
+ "response_category": "copilot",
579
+ "completeness": "complete",
580
+ },
581
+ )
582
+
583
+ # Send the training success category
584
+ await push_job_status_event(
585
+ job,
586
+ JobStatus.train_success_message,
587
+ payload={
588
+ "response_category": "copilot_training_success",
589
+ "completeness": "complete",
590
+ },
591
+ )
592
+
593
+ # Mark job as done
594
+ await push_job_status_event(job, JobStatus.done)
595
+ job_manager.mark_done(job)
596
+
597
+ structlogger.info(
598
+ "copilot_training_success_job.success",
599
+ job_id=job.id,
600
+ )
601
+
602
+ except Exception as exc:
603
+ structlogger.exception(
604
+ "copilot_training_success_job.error",
605
+ job_id=job.id,
606
+ error=str(exc),
607
+ )
608
+ await push_job_status_event(job, JobStatus.error, message=str(exc))
609
+ job_manager.mark_done(job, error=str(exc))
rasa/builder/models.py CHANGED
@@ -191,6 +191,7 @@ class JobStatus(str, Enum):
191
191
 
192
192
  training = "training"
193
193
  train_success = "train_success"
194
+ train_success_message = "train_success_message"
194
195
  train_error = "train_error"
195
196
 
196
197
  validating = "validating"
@@ -202,6 +203,8 @@ class JobStatus(str, Enum):
202
203
  copilot_analysis_success = "copilot_analysis_success"
203
204
  copilot_analysis_error = "copilot_analysis_error"
204
205
 
206
+ copilot_welcome_message = "copilot_welcome_message"
207
+
205
208
 
206
209
  class JobCreateResponse(BaseModel):
207
210
  job_id: str = Field(...)
@@ -189,6 +189,7 @@ def validate_files(
189
189
  validator, max_history, fail_on_warnings
190
190
  )
191
191
  valid_flows = validator.verify_flows()
192
+ valid_prompt_templates = validator.verify_prompt_templates()
192
193
  if validator.config:
193
194
  valid_translations = validator.verify_translations(summary_mode=True)
194
195
  else:
@@ -207,6 +208,7 @@ def validate_files(
207
208
  and valid_nlu
208
209
  and valid_stories
209
210
  and valid_flows
211
+ and valid_prompt_templates
210
212
  and valid_translations
211
213
  and valid_CALM_slot_mappings
212
214
  and valid_sub_agents
@@ -7,6 +7,7 @@ from typing import Any, Dict, List, Optional, Union
7
7
  from pydantic import BaseModel, ConfigDict, Field, model_validator
8
8
 
9
9
  from rasa.core.constants import MCP_SERVERS_KEY
10
+ from rasa.shared.agents.auth.utils import validate_secrets_in_params
10
11
  from rasa.shared.core.constants import (
11
12
  GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE,
12
13
  GLOBAL_SILENCE_TIMEOUT_KEY,
@@ -77,6 +78,11 @@ class MCPServerConfig(BaseModel):
77
78
  # validate that name and url are not empty
78
79
  if not self.name or not self.url:
79
80
  raise ValueError("Name and URL cannot be empty")
81
+ # validate secrets in additional_params
82
+ if self.additional_params:
83
+ validate_secrets_in_params(
84
+ self.additional_params, f"MCP server - '{self.name}'"
85
+ )
80
86
  return self
81
87
 
82
88
  @model_validator(mode="before")
@@ -227,28 +227,30 @@ flows:
227
227
  - noop: true
228
228
  next:
229
229
  - if: context.multiple_flows_interrupted
230
+ then: collect_interrupted_flow_to_continue
231
+ - else: collect_continue_interrupted_flow_confirmation
232
+ - id: collect_interrupted_flow_to_continue
233
+ collect: interrupted_flow_to_continue
234
+ description: "Fill this slot with the name of the flow the user wants to continue. If the user does not want to continue any of the interrupted flows, fill this slot with 'none'."
235
+ next:
236
+ - if: slots.interrupted_flow_to_continue != "none"
237
+ then:
238
+ - action: action_continue_interrupted_flow
239
+ next: END
240
+ - else:
241
+ - action: action_cancel_interrupted_flows
242
+ next: END
243
+ - id: collect_continue_interrupted_flow_confirmation
244
+ collect: continue_interrupted_flow_confirmation
245
+ description: "If the user wants to continue the interrupted flow, fill this slot with true. If the user does not want to continue the interrupted flow, fill this slot with false."
246
+ next:
247
+ - if: slots.continue_interrupted_flow_confirmation
230
248
  then:
231
- - collect: interrupted_flow_to_continue
232
- description: "Fill this slot with the name of the flow the user wants to continue. If the user does not want to continue any of the interrupted flows, fill this slot with 'none'."
233
- next:
234
- - if: slots.interrupted_flow_to_continue != "none"
235
- then:
236
- - action: action_continue_interrupted_flow
237
- next: END
238
- - else:
239
- - action: action_cancel_interrupted_flows
240
- next: END
249
+ - action: action_continue_interrupted_flow
250
+ next: END
241
251
  - else:
242
- - collect: continue_interrupted_flow_confirmation
243
- description: "If the user wants to continue the interrupted flow, fill this slot with true. If the user does not want to continue the interrupted flow, fill this slot with false."
244
- next:
245
- - if: slots.continue_interrupted_flow_confirmation
246
- then:
247
- - action: action_continue_interrupted_flow
248
- next: END
249
- - else:
250
- - action: action_cancel_interrupted_flows
251
- next: END
252
+ - action: action_cancel_interrupted_flows
253
+ next: END
252
254
 
253
255
  pattern_correction:
254
256
  description: Conversation repair flow for managing user input changes or error corrections
rasa/engine/validation.py CHANGED
@@ -81,6 +81,7 @@ from rasa.shared.constants import (
81
81
  ROUTING_STRATEGIES_NOT_REQUIRING_CACHE,
82
82
  ROUTING_STRATEGIES_REQUIRING_REDIS_CACHE,
83
83
  ROUTING_STRATEGY_CONFIG_KEY,
84
+ SECRET_DATA_FORMAT_PATTERN,
84
85
  SENSITIVE_DATA,
85
86
  USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY,
86
87
  VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY,
@@ -1359,7 +1360,10 @@ def _validate_usage_of_environment_variables_in_model_group_config(
1359
1360
  for model_config in model_group[MODELS_CONFIG_KEY]:
1360
1361
  for key, value in model_config.items():
1361
1362
  if isinstance(value, str):
1362
- if re.match(r"\${(\w+)}", value) and key not in allowed_env_vars:
1363
+ if (
1364
+ re.match(SECRET_DATA_FORMAT_PATTERN, value)
1365
+ and key not in allowed_env_vars
1366
+ ):
1363
1367
  raise ValidationError(
1364
1368
  code="engine.validation.validate_model_group_configuration_setup"
1365
1369
  ".invalid_use_of_environment_variables",
@@ -1386,7 +1390,7 @@ def _validate_sensitive_keys_are_an_environment_variables_for_model_groups(
1386
1390
  for key, value in model_config.items():
1387
1391
  if key in SENSITIVE_DATA:
1388
1392
  if isinstance(value, str):
1389
- if not re.match(r"\${(\w+)}", value):
1393
+ if not re.match(SECRET_DATA_FORMAT_PATTERN, value):
1390
1394
  raise ValidationError(
1391
1395
  code="engine.validation.validate_model_group_configuration_setup"
1392
1396
  ".sensitive_key_string_value_must_be_set_as_env_var",
@@ -0,0 +1,85 @@
1
+ """Utilities for agent authentication and secret validation."""
2
+
3
+ import re
4
+ from typing import Any, Dict
5
+
6
+ from rasa.exceptions import ValidationError
7
+ from rasa.shared.agents.auth.constants import (
8
+ CONFIG_API_KEY_KEY,
9
+ CONFIG_CLIENT_SECRET_KEY,
10
+ CONFIG_OAUTH_KEY,
11
+ CONFIG_TOKEN_KEY,
12
+ )
13
+ from rasa.shared.constants import SECRET_DATA_FORMAT_PATTERN
14
+
15
+ AUTH_SECRETS = [CONFIG_API_KEY_KEY, CONFIG_TOKEN_KEY, CONFIG_CLIENT_SECRET_KEY]
16
+
17
+
18
+ def _is_valid_secret_data_format(value: str) -> bool:
19
+ """Check if a value is in the correct environment variable format.
20
+
21
+ Args:
22
+ value: The value to check
23
+
24
+ Returns:
25
+ True if the value is in format "${env_var}", False otherwise
26
+ """
27
+ if not isinstance(value, str):
28
+ return False
29
+
30
+ # Use the common regex pattern for environment variable validation
31
+ return bool(re.match(SECRET_DATA_FORMAT_PATTERN, value))
32
+
33
+
34
+ def _validate_secret_value(value: Any, key: str, context: str) -> None:
35
+ """Generic function to validate a single secret value.
36
+
37
+ Args:
38
+ value: The value to validate
39
+ key: The key name for error messages
40
+ context: Context for error messages
41
+ (e.g., "agent 'my_agent'", "MCP server 'my_server'")
42
+ """
43
+ if isinstance(value, str):
44
+ if not _is_valid_secret_data_format(value):
45
+ raise ValidationError(
46
+ code="validation.sensitive_key_string_value_must_be_set_as_env_var",
47
+ event_info=(
48
+ f"You defined the '{key}' in {context} as a string. The '{key}' "
49
+ f"must be set as an environment variable. Please update your "
50
+ f"config."
51
+ ),
52
+ key=key,
53
+ )
54
+ else:
55
+ raise ValidationError(
56
+ code="validation.sensitive_key_must_be_set_as_env_var",
57
+ event_info=(
58
+ f"You should define the '{key}' in {context} using the environment "
59
+ f"variable syntax - ${{ENV_VARIABLE_NAME}}. Please update your config."
60
+ ),
61
+ key=key,
62
+ )
63
+
64
+
65
+ def validate_secrets_in_params(
66
+ params: Dict[str, Any], context_name: str = "configuration"
67
+ ) -> None:
68
+ """Validate that secrets in params are in environment variable format.
69
+
70
+ Args:
71
+ params: The parameters dictionary to validate
72
+ context_name: Name of the context for error messages
73
+ (e.g., "agent", "MCP server")
74
+ """
75
+ for key, value in params.items():
76
+ if key in AUTH_SECRETS:
77
+ _validate_secret_value(value, key, context_name)
78
+ elif key == CONFIG_OAUTH_KEY and isinstance(value, dict):
79
+ # Handle oauth object specifically - we know it contains client_secret
80
+ if CONFIG_CLIENT_SECRET_KEY in value:
81
+ _validate_secret_value(
82
+ value[CONFIG_CLIENT_SECRET_KEY],
83
+ CONFIG_CLIENT_SECRET_KEY,
84
+ context_name,
85
+ )
rasa/shared/constants.py CHANGED
@@ -367,3 +367,6 @@ FAQ_DOCUMENT_LINE_SEPARATOR = "\n"
367
367
 
368
368
  # Constants for the MCP server
369
369
  KEY_TOOL_CALLS = "tool_calls"
370
+
371
+ # Regex pattern for secrets data validation
372
+ SECRET_DATA_FORMAT_PATTERN = r"\${(\w+)}"
rasa/shared/utils/llm.py CHANGED
@@ -23,6 +23,7 @@ from typing import (
23
23
  )
24
24
 
25
25
  import structlog
26
+ from jinja2 import Environment, select_autoescape
26
27
  from pydantic import BaseModel, Field
27
28
 
28
29
  import rasa.cli.telemetry
@@ -718,6 +719,38 @@ def embedder_client_factory(
718
719
  return client
719
720
 
720
721
 
722
+ def validate_jinja2_template(template_content: Text) -> None:
723
+ """Validate that a template string has valid Jinja2 syntax.
724
+
725
+ Args:
726
+ template_content: The template content to validate
727
+
728
+ Raises:
729
+ jinja2.exceptions.TemplateSyntaxError: If the template has invalid syntax
730
+ Exception: If there's an error during validation
731
+ """
732
+ # Create environment with custom filters
733
+ env = Environment(
734
+ autoescape=select_autoescape(
735
+ disabled_extensions=["jinja2"],
736
+ default_for_string=False,
737
+ default=True,
738
+ )
739
+ )
740
+ # Register filters - lazy import to avoid circular dependencies
741
+ from rasa.dialogue_understanding.generator._jinja_filters import (
742
+ to_json_escaped_string,
743
+ )
744
+ from rasa.dialogue_understanding.generator.constants import (
745
+ TO_JSON_ESCAPED_STRING_JINJA_FILTER,
746
+ )
747
+
748
+ env.filters[TO_JSON_ESCAPED_STRING_JINJA_FILTER] = to_json_escaped_string
749
+
750
+ # Validate Jinja2 syntax
751
+ env.from_string(template_content)
752
+
753
+
721
754
  def get_prompt_template(
722
755
  jinja_file_path: Optional[Text],
723
756
  default_prompt_template: Text,
rasa/utils/pypred.py CHANGED
@@ -10,6 +10,7 @@ https://rasahq.atlassian.net/browse/ATO-1925
10
10
  The solution is based on https://github.com/FreeCAD/FreeCAD/issues/6315
11
11
  """
12
12
 
13
+ import logging
13
14
  from typing import Any
14
15
 
15
16
  import ply.yacc
@@ -19,12 +20,18 @@ from pypred import Predicate as OriginalPredicate # noqa: TID251
19
20
  # Store the original yacc function
20
21
  _original_yacc = ply.yacc.yacc
21
22
 
23
+ # Create a logger that suppresses warnings to avoid yacc table file version warnings
24
+ _yacc_logger = logging.getLogger("ply.yacc")
25
+ _yacc_logger.setLevel(logging.ERROR)
26
+
22
27
 
23
28
  def patched_yacc(*args: Any, **kwargs: Any) -> Any:
24
29
  # Disable generation of debug ('parser.out') and table
25
30
  # cache ('parsetab.py'), as it requires a writable location.
26
31
  kwargs["write_tables"] = False
27
32
  kwargs["module"] = pypred.parser
33
+ # Suppress yacc warnings by using a logger that only shows errors
34
+ kwargs["errorlog"] = _yacc_logger
28
35
  return _original_yacc(*args, **kwargs)
29
36
 
30
37
 
rasa/validator.py CHANGED
@@ -4,14 +4,13 @@ import string
4
4
  from collections import defaultdict
5
5
  from typing import Any, Dict, List, Optional, Set, Text, Tuple
6
6
 
7
+ import jinja2.exceptions
7
8
  import structlog
8
9
  from jinja2 import Template
9
10
  from pypred.ast import CompareOperator, Literal, NegateOperator
10
11
 
11
12
  import rasa.core.training.story_conflict
12
13
  import rasa.shared.nlu.constants
13
- import rasa.shared.utils.cli
14
- import rasa.shared.utils.io
15
14
  from rasa.agents.validation import validate_agent_names_not_conflicting_with_flows
16
15
  from rasa.core.channels import UserMessage
17
16
  from rasa.core.config.configuration import Configuration
@@ -1977,6 +1976,95 @@ class Validator:
1977
1976
 
1978
1977
  return all_good
1979
1978
 
1979
+ def verify_prompt_templates(self) -> bool:
1980
+ """Verify that all prompt templates have valid Jinja2 syntax.
1981
+
1982
+ Returns:
1983
+ True if all templates are valid, False otherwise.
1984
+ """
1985
+ all_good = True
1986
+
1987
+ # Check the components in the pipeline and policies for prompt templates
1988
+ pipeline = self.config.get(CONFIG_PIPELINE_KEY, [])
1989
+ for component in pipeline:
1990
+ if isinstance(component, dict):
1991
+ component_name = component.get("name", "")
1992
+ prompt_template = component.get("prompt_template")
1993
+ if prompt_template:
1994
+ all_good = (
1995
+ self._validate_template_file(
1996
+ prompt_template, component_name, "pipeline component"
1997
+ )
1998
+ and all_good
1999
+ )
2000
+
2001
+ # Check policies for prompt templates
2002
+ policies = self.config.get("policies") or []
2003
+ for policy in policies:
2004
+ if isinstance(policy, dict):
2005
+ policy_name = policy.get("name", "")
2006
+ prompt_template = policy.get("prompt_template")
2007
+ if prompt_template:
2008
+ all_good = (
2009
+ self._validate_template_file(
2010
+ prompt_template, policy_name, "policy"
2011
+ )
2012
+ and all_good
2013
+ )
2014
+
2015
+ return all_good
2016
+
2017
+ def _validate_template_file(
2018
+ self, prompt_template: str, component_name: str, component_type: str
2019
+ ) -> bool:
2020
+ """Validate a single prompt template file.
2021
+
2022
+ Args:
2023
+ prompt_template: The template file path to validate
2024
+ component_name: Name of the component using the template
2025
+ component_type: Type of component (e.g., "policy", "pipeline component")
2026
+
2027
+ Returns:
2028
+ True if template is valid, False otherwise.
2029
+ """
2030
+ try:
2031
+ # Use a simple default template, as we're assuming
2032
+ # that the default templates are valid
2033
+ default_template = "{{ content }}"
2034
+ template_content = rasa.shared.utils.llm.get_prompt_template(
2035
+ prompt_template,
2036
+ default_template,
2037
+ log_source_component=f"validator.{component_name}",
2038
+ log_source_method="init",
2039
+ )
2040
+
2041
+ # Validate Jinja2 syntax using the shared validation function
2042
+ rasa.shared.utils.llm.validate_jinja2_template(template_content)
2043
+ return True
2044
+ except jinja2.exceptions.TemplateSyntaxError as e:
2045
+ structlogger.error(
2046
+ "validator.verify_prompt_templates.syntax_error",
2047
+ component=component_name,
2048
+ component_type=component_type,
2049
+ event_info=(
2050
+ f"Invalid Jinja2 template syntax in file {prompt_template} "
2051
+ f"at line {e.lineno}: {e.message}"
2052
+ ),
2053
+ error=str(e),
2054
+ template_line=e.lineno,
2055
+ template_file=prompt_template,
2056
+ )
2057
+ return False
2058
+ except Exception as e:
2059
+ structlogger.error(
2060
+ "validator.verify_prompt_templates.error",
2061
+ component=component_name,
2062
+ component_type=component_type,
2063
+ event_info=f"Error validating prompt template: {e}",
2064
+ error=str(e),
2065
+ )
2066
+ return False
2067
+
1980
2068
  def validate_conditional_response_variation_predicates(self) -> bool:
1981
2069
  """Validate the conditional response variation predicates."""
1982
2070
  context = {SLOTS: {slot.name: None for slot in self.domain.slots}}
rasa/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.14.0rc3"
3
+ __version__ = "3.14.0rc4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rasa-pro
3
- Version: 3.14.0rc3
3
+ Version: 3.14.0rc4
4
4
  Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
5
5
  Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
6
6
  Author: Rasa Technologies GmbH
@@ -29,19 +29,19 @@ Requires-Dist: CacheControl (>=0.14.2,<0.15.0)
29
29
  Requires-Dist: PyJWT[crypto] (>=2.8.0,<3.0.0)
30
30
  Requires-Dist: SQLAlchemy (>=2.0.42,<2.1.0)
31
31
  Requires-Dist: a2a-sdk (>=0.3.4,<0.4.0)
32
- Requires-Dist: absl-py (>=2.0,<2.1)
32
+ Requires-Dist: absl-py (>=2.3.1,<2.4)
33
33
  Requires-Dist: aio-pika (>=8.2.3,<9.4.4)
34
34
  Requires-Dist: aiogram (>=3.22.0,<3.23.0) ; extra == "full" or extra == "channels"
35
35
  Requires-Dist: aiohttp (>=3.10,<3.11)
36
36
  Requires-Dist: aioshutil (>=1.5,<1.6)
37
- Requires-Dist: apscheduler (>=3.10,<3.11)
37
+ Requires-Dist: apscheduler (>=3.11,<3.12)
38
38
  Requires-Dist: attrs (>=23.1,<25.0)
39
39
  Requires-Dist: audioop-lts (>=0.2.2,<0.3.0) ; python_version >= "3.13"
40
40
  Requires-Dist: aws-msk-iam-sasl-signer-python (>=1.0.2,<1.1.0)
41
41
  Requires-Dist: azure-identity (>=1.24.0,<1.25.0)
42
42
  Requires-Dist: azure-storage-blob (>=12.26.0,<12.27.0)
43
43
  Requires-Dist: boto3 (>=1.40.21,<1.41.0)
44
- Requires-Dist: certifi (>=2024.07.04)
44
+ Requires-Dist: certifi (>=2025.10.5,<2025.11.0)
45
45
  Requires-Dist: colorama (>=0.4.6,<0.5.0) ; sys_platform == "win32"
46
46
  Requires-Dist: colorclass (>=2.2,<2.3)
47
47
  Requires-Dist: coloredlogs (>=15,<16)
@@ -68,6 +68,7 @@ Requires-Dist: jinja2 (>=3.1.6,<3.2.0)
68
68
  Requires-Dist: jsonpatch (>=1.33,<2.0)
69
69
  Requires-Dist: jsonpickle (>=3.3.0,<3.4)
70
70
  Requires-Dist: jsonschema (>=4.22)
71
+ Requires-Dist: keras (>=3.11.0)
71
72
  Requires-Dist: langchain (>=0.3.27,<0.4.0)
72
73
  Requires-Dist: langchain-community (>=0.3.29,<0.4.0)
73
74
  Requires-Dist: langcodes (>=3.5.0,<4.0.0)
@@ -105,13 +106,13 @@ Requires-Dist: python-socketio (>=5.13,<6)
105
106
  Requires-Dist: pytz (>=2022.7.1,<2023.0)
106
107
  Requires-Dist: pyyaml (>=6.0.2,<6.1.0)
107
108
  Requires-Dist: qdrant-client (>=1.9.1,<1.10.0)
108
- Requires-Dist: questionary (>=1.10.0,<2.1.0)
109
+ Requires-Dist: questionary (>=2.1.1,<2.2.0)
109
110
  Requires-Dist: randomname (>=0.2.1,<0.3.0)
110
111
  Requires-Dist: rasa-sdk (==3.14.0rc1)
111
112
  Requires-Dist: redis (>=4.6.0,<6.0)
112
113
  Requires-Dist: regex (>=2024.7.24,<2024.8.0)
113
114
  Requires-Dist: requests (>=2.32.5,<2.33.0)
114
- Requires-Dist: rich (>=13.4.2,<14.0.0)
115
+ Requires-Dist: rich (>=14.1.0,<14.2.0)
115
116
  Requires-Dist: rocketchat_API (>=1.32.0,<1.33.0) ; extra == "full" or extra == "channels"
116
117
  Requires-Dist: ruamel.yaml (>=0.17.21,<0.17.22)
117
118
  Requires-Dist: safetensors (>=0.4.5,<0.5.0)
@@ -12,7 +12,7 @@ rasa/agents/protocol/__init__.py,sha256=rDR_QdaWuHvkHTKF1MmgzjIk7T8m__KJIK9wtjQn
12
12
  rasa/agents/protocol/a2a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  rasa/agents/protocol/a2a/a2a_agent.py,sha256=ErxmCNlZuqEEK0t0Js2LJlJC5zC2ho4-_DAD4pBWy8M,35157
14
14
  rasa/agents/protocol/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- rasa/agents/protocol/mcp/mcp_base_agent.py,sha256=GOD835Wv0ijz56zauldVMOq84i6k0Wb9jz5VrE2qnwo,28826
15
+ rasa/agents/protocol/mcp/mcp_base_agent.py,sha256=T8pBxSPFsy9p-N7TNJ4Ow9N-DxHu3nTRN33tNm8QYNg,29598
16
16
  rasa/agents/protocol/mcp/mcp_open_agent.py,sha256=2lcGoNl_Qpqot-iw22MetH4GjAts8F9LHRt9uTdQZKY,13362
17
17
  rasa/agents/protocol/mcp/mcp_task_agent.py,sha256=MewMbBUg40P9WaHB7aZQr-e9Vd2zFF1dL8NRY-j94Lw,21809
18
18
  rasa/agents/schemas/__init__.py,sha256=ubFluIAybA-uGoUMOYQOVrHfqK0Ol4SExJC0lEs4tBA,422
@@ -24,17 +24,17 @@ rasa/agents/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
24
24
  rasa/agents/templates/mcp_open_agent_prompt_template.jinja2,sha256=hXv01NsnF5P1vsoGxJZdRRCqqUx2TCbL29lgBWGaPy4,1318
25
25
  rasa/agents/templates/mcp_task_agent_prompt_template.jinja2,sha256=KBSVV-_SdirRi1xz0PXUvOb9Ahd5KSWeJkIVFaZZkHI,1056
26
26
  rasa/agents/utils.py,sha256=j3Rljc7txMJ4cyQnJ6F65in7iRVdIb3n3DPw3Yb4kqU,7667
27
- rasa/agents/validation.py,sha256=wLqDvdmt4yraYWMHXbYFpijue-iz1H9HNLfRP8cN3gc,17482
27
+ rasa/agents/validation.py,sha256=_HHFEBD7wngwsQCDw-AAplQdOBuQu7VCroif4unXlIk,19515
28
28
  rasa/api.py,sha256=q5L8HRN577Xug3AqOtfHCRqoRUDnQ2FPA-uXu2wmUAY,6749
29
29
  rasa/builder/README.md,sha256=7WYioSzBHFY25h1QCFellv7bIOW9VLH7Gf7dwQEc1k0,3715
30
30
  rasa/builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  rasa/builder/auth.py,sha256=naswg4P1o_zB1GQDybqySbhnY0OPIp7cH2Ze98Uhwgc,5436
32
32
  rasa/builder/config.py,sha256=XtaRBoT3aYlrnfuRcSmtShAwcH6mzXqFNJyY9LHvsfA,3809
33
33
  rasa/builder/copilot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- rasa/builder/copilot/constants.py,sha256=zpNNW33ojunKVK0qq62C9WvSBsxih3yoVc1dRpFumyE,1339
34
+ rasa/builder/copilot/constants.py,sha256=WLhmiFnaNMt-b4-IO0sujzDos3CdQM3Jlf03Nz88jnA,1501
35
35
  rasa/builder/copilot/copilot.py,sha256=Q8vqBYeyZcSw2LJznjZAn86qPq3poyB4iTJYmYte44A,21106
36
36
  rasa/builder/copilot/copilot_response_handler.py,sha256=teozaZFKR-XADdK2Nvkqu3wp48Bg1iqB7VT8rn5HcI4,20257
37
- rasa/builder/copilot/copilot_templated_message_provider.py,sha256=eY8S7rVad6kX1-luyGpUT_2MNnIzfL4Fd1ZdLTTqM0g,1676
37
+ rasa/builder/copilot/copilot_templated_message_provider.py,sha256=BjsyYt02cl1o4p0MdmAw2kwiHG4-LFIhp0iU8dHCzrc,2392
38
38
  rasa/builder/copilot/exceptions.py,sha256=6alRMH8pyyXyjfKjtfSdjP1LunztC_c6Xu1OtlaUC2E,663
39
39
  rasa/builder/copilot/models.py,sha256=XbmXZt0S45bJBRNK7jo4Tc4IX8esTNbSBCUGbpa3fjM,23175
40
40
  rasa/builder/copilot/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -45,7 +45,8 @@ rasa/builder/copilot/signing.py,sha256=z_eAGFMM1Mk009ambXA-mjJpM8KQRPaNHECpH2A2f
45
45
  rasa/builder/copilot/telemetry.py,sha256=hzZX6H-3a9OojTWqsDpckb37b_BvXa0JLJ1S7OVF2IE,8676
46
46
  rasa/builder/copilot/templated_messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  rasa/builder/copilot/templated_messages/copilot_internal_messages_templates.yml,sha256=dqKDO-25_srbDAVBoq0asdnPD95o8xcQ3eWIGyf0D2I,746
48
- rasa/builder/copilot/templated_messages/copilot_templated_responses.yml,sha256=i6Nja6Gv_NtymUEFoXWNq5pMIXIyLjiMvtrhyYyl2OU,1935
48
+ rasa/builder/copilot/templated_messages/copilot_templated_responses.yml,sha256=9kufWSRFx7L-Cr9-X7y1YTlcfuUpfzE3B_M0G9J3ads,2014
49
+ rasa/builder/copilot/templated_messages/copilot_welcome_messages.yml,sha256=tBWJpvmhZUrSSBC1XTm-C40jRMsTqlcIdZaTW9Sfrdc,2051
49
50
  rasa/builder/document_retrieval/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
51
  rasa/builder/document_retrieval/constants.py,sha256=bqG88KtCqxXgMFeiEFEDV5P1fe0J_hAg0FjMnXpatQk,356
51
52
  rasa/builder/document_retrieval/inkeep-rag-response-schema.json,sha256=ePVbGo6u6sm_CPS8EeECX3UayIvcfUe6yTy2gtexKlk,1498
@@ -62,11 +63,11 @@ rasa/builder/guardrails/policy_checker.py,sha256=06zIeI5z4gMlRxsp6iazk05L4r2ZSRC
62
63
  rasa/builder/guardrails/store.py,sha256=-mJdsCnHgSI08uPnPwZRObIyRV9u98zcpQ5QkeHdVK0,7660
63
64
  rasa/builder/guardrails/utils.py,sha256=3B-ybAkIYhpx7G1HSEnMKW8NW_bY4UCg3w73e7aYogw,3027
64
65
  rasa/builder/job_manager.py,sha256=eQ5HRff-U4Cj3joHKqpjDcfCMWj4nz4D_oQmoozpwPM,2507
65
- rasa/builder/jobs.py,sha256=H5kpqIJeoX-EpbCvLIhUXrI5f34dN2EDNvlahiCK-hk,15434
66
+ rasa/builder/jobs.py,sha256=R-PKwSOmAh3vV6spuMLMLg_DFHvy7V1-EBUzMQZW7HE,20626
66
67
  rasa/builder/llm_service.py,sha256=5yN4d7W1DYJIk4XLNz7Uvj2ZPp6RzdHoZ7tGh4H9ZVY,9974
67
68
  rasa/builder/logging_utils.py,sha256=E1YZs5BdHT9TrnoA2758sFMD1Xw7e5mnAtqWSAZs1gk,9296
68
69
  rasa/builder/main.py,sha256=hSDkcaV_gCYss9rfXjqM1QeBjEIhmRrACycoFDHKHEE,7597
69
- rasa/builder/models.py,sha256=E4gWb8l0h1gBAvSY3wCyhnyQg3XiKn2Mng-EtoIUthY,6508
70
+ rasa/builder/models.py,sha256=3dQP7cyXYinQ9RZEP6O1WPKtfc8YH_pgOus-jOYfSkg,6617
70
71
  rasa/builder/project_generator.py,sha256=wD9I_paxaNWwqwjcg570AuvaeKk8TfopTKGapHTKGeA,18391
71
72
  rasa/builder/project_info.py,sha256=ZBwFCigZLSo1RBMhlZDYBoVl2G-9OnhRrYxdMWHn6S4,2093
72
73
  rasa/builder/service.py,sha256=pB_PCUQTxYKvzrE__pg0AnQNmTCkl3p8OdLPQ9xtSq4,49057
@@ -343,7 +344,7 @@ rasa/cli/test.py,sha256=HOByA0RQCupaPvmoPYzUCBcJLJnakT1uRrqxZLewm1Y,9834
343
344
  rasa/cli/train.py,sha256=tJ4e3I0nJLUosnZPJmF1_msfV9usnB7b8WMsBBB3Rwk,10208
344
345
  rasa/cli/utils.py,sha256=BpMNV6Cyo0bfJ-jnMXgqVCgfa0BFvV7HkbmtA2ZjXhM,4155
345
346
  rasa/cli/validation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
346
- rasa/cli/validation/bot_config.py,sha256=bLzK1NK7f8_NzlcSxSb4kGx0mYtO8jWexBk0tjLNKwE,8380
347
+ rasa/cli/validation/bot_config.py,sha256=RVzTWokWIv36y9kJUOFGYZUUJq5nR75vVt0j6izC240,8488
347
348
  rasa/cli/validation/config_path_validation.py,sha256=ME3BQ5KwJbLl7igDTvoegIuFLybCphKkxsKHvJ3nYiQ,8424
348
349
  rasa/cli/visualize.py,sha256=YmRAATAfxHpgE8_PknGyM-oIujwICNzVftTzz6iLNNc,1256
349
350
  rasa/cli/x.py,sha256=S7MLMgpFCnURPTU-o8ReHkbUPPOGv0XkfcVpLoGHTWo,6995
@@ -562,7 +563,7 @@ rasa/core/channels/voice_stream/voice_channel.py,sha256=m7P8krfe1MNoAXXlecsciFUe
562
563
  rasa/core/channels/webexteams.py,sha256=z_o_jnc6B7hsHpd6XorImFkF43wB4yx_kiTPKAjPSuo,4805
563
564
  rasa/core/concurrent_lock_store.py,sha256=sDO7Zcl-IdZrGnOMVJa_lN7ht9uJVfaRkSbyXaTizlc,11375
564
565
  rasa/core/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
565
- rasa/core/config/available_endpoints.py,sha256=nJjPU89ezuHlYfF5k-VyrsJpSFJ26_ah9BYJICx4d6c,6861
566
+ rasa/core/config/available_endpoints.py,sha256=dTwgEl0AVnGO23K3DsB5XzAVciQK45ot3jtLpy4agnA,7137
566
567
  rasa/core/config/configuration.py,sha256=UDWPuHCxTqdSr-V0bEzXQjU40dzx0zaKW-Nh_5EGWJ0,9877
567
568
  rasa/core/config/credentials.py,sha256=2oLgHc8PV7yT-TPX-86Ykf9OQzqsYX7-13sPADDAveI,547
568
569
  rasa/core/config/message_procesing_config.py,sha256=guZ4ULqt4-G4aML1hNlrpoNFvRqr_q_fiUcQBejZ8e4,1042
@@ -724,7 +725,7 @@ rasa/dialogue_understanding/patterns/collect_information.py,sha256=8YWvhFTt8CJML
724
725
  rasa/dialogue_understanding/patterns/completed.py,sha256=7qkyUj2d__2R3mpwWVmQpfwCCbJruBrjRZbmbDr3Zbo,1278
725
726
  rasa/dialogue_understanding/patterns/continue_interrupted.py,sha256=vHGjBfXP6adzLU8caSN6I3qsn7pHMJa9vaVly22-PCM,10644
726
727
  rasa/dialogue_understanding/patterns/correction.py,sha256=7fQ02-JU1CGZiTjTi9YqmD1F4o-9Tv5WCAXnFgZlvtY,11380
727
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml,sha256=agfZIbfW1kYMVuMBZIGz8YAsl97GS2wIAOigySsW5zM,12674
728
+ rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml,sha256=pjj0T7uYB1WCzzrjkUdVJJL5_VMT7J3cPITbaJvHpR8,12726
728
729
  rasa/dialogue_understanding/patterns/domain_for_patterns.py,sha256=Zv_lCJn4nbkxeNYOPGsR0V8tmYAUsM_Ho_9to8hku-o,6493
729
730
  rasa/dialogue_understanding/patterns/human_handoff.py,sha256=1hkSdL6kui42rZc7zERZ9R7nLyvRHi_tHgNU7FyrhAQ,1132
730
731
  rasa/dialogue_understanding/patterns/internal_error.py,sha256=APCKVv16M6mSQ4upu4UwG0yIaaKTyr7uB2yV8ZtpMzo,1609
@@ -812,7 +813,7 @@ rasa/engine/training/components.py,sha256=Ymz8-JcKm5A9dqPblay11Lxo_AFShkakXlsHQ9
812
813
  rasa/engine/training/fingerprinting.py,sha256=RrJzkhTefKsj2A1S4yAJ4IIUZGganGTcKKdor-FfLjA,2008
813
814
  rasa/engine/training/graph_trainer.py,sha256=jLfJZVn-mDwIOEADnx56Ly67EPf5XMpf_gH5PwRe-7o,10636
814
815
  rasa/engine/training/hooks.py,sha256=dec5yMRNbVIJwtijhESJNlt8lbZb1KJffcBRBajuZes,5469
815
- rasa/engine/validation.py,sha256=IkesdqcN9b4zkFLFNS1cmu-VS8NpahWXPLnodjHHCPE,62172
816
+ rasa/engine/validation.py,sha256=LAq7ZR3y9sWFl_Wmo-Mo_04yBjdKiaQNQK29GDyQYFk,62304
816
817
  rasa/env.py,sha256=zLzQMkATVIZj6s4C7RsLLOLT8g6-Q96m5iBaHW_mEA8,480
817
818
  rasa/exceptions.py,sha256=rw9JV55PUWEWCBvswVdWgANiW35iT4S9atn5N7QTthM,2867
818
819
  rasa/graph_components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -944,8 +945,9 @@ rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py,sha256=PXbNb
944
945
  rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py,sha256=ETPw2OkhE2K0Lyy5L8q6lsbTzEQEmSOhxy79FelZ-xs,6331
945
946
  rasa/shared/agents/auth/constants.py,sha256=Rh81Vl9ZjpIQnQs3QOqm-pHkXZrfg-Ym_mroenmnBGo,437
946
947
  rasa/shared/agents/auth/types.py,sha256=tvcYZEwh0UpjEjgwMLuj8-h3AMSx_uQw-Hi504rHoqI,294
948
+ rasa/shared/agents/auth/utils.py,sha256=B8D0yOsYy03tXW0Z5aV5yq7j9TR4OX_Jq1f7d_vUtW8,2958
947
949
  rasa/shared/agents/utils.py,sha256=Dux_STACmYlni-c4c8EpdBX9SmcFofaJI8prwsKlNeM,1011
948
- rasa/shared/constants.py,sha256=HMHc0UKJKWpZYP98lDU7vk034gPunXoKzHXt_jxYoJA,13066
950
+ rasa/shared/constants.py,sha256=z-SrX4GzNoUX38UvcdZiNOJYCLG37_Drz7g-XpO461w,13153
949
951
  rasa/shared/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
950
952
  rasa/shared/core/command_payload_reader.py,sha256=aWmEe6NyGdGZ8qaCPxGZu1frLROv04SFbwPpZNrtj7Q,3741
951
953
  rasa/shared/core/constants.py,sha256=Dzm0Vh_8GXQ_pv-6nmjphYTodaXFhO1Qx3Q-d_gR8Pk,7048
@@ -1079,7 +1081,7 @@ rasa/shared/utils/health_check/embeddings_health_check_mixin.py,sha256=ASOzDtI3i
1079
1081
  rasa/shared/utils/health_check/health_check.py,sha256=ZuMJhHF5gXuB0oroeeg4cwCun1VCsGkXzFOwTT1drR4,9706
1080
1082
  rasa/shared/utils/health_check/llm_health_check_mixin.py,sha256=ANP5Q68TRX8p4wWkRCAISsWBV1iYYeGnqWILnR1NawE,957
1081
1083
  rasa/shared/utils/io.py,sha256=AhuECoXGO367NvWRCBu99utEtTQnyxWVJyKOOpLePpg,15917
1082
- rasa/shared/utils/llm.py,sha256=wWYy_PH4VgZM0hh4RWqAwGuH_kGKOVSKT8olDoK-zew,41616
1084
+ rasa/shared/utils/llm.py,sha256=gF_wAA3RxK6KDKTD2hjqbGu6shLAoUJ7DIXmC8gtMxc,42695
1083
1085
  rasa/shared/utils/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1084
1086
  rasa/shared/utils/mcp/server_connection.py,sha256=PnNgBfLYBxeMC3VsbxoR9EenMWCnKQ_IvzFh7_I2EuI,9399
1085
1087
  rasa/shared/utils/mcp/utils.py,sha256=Adb-rx2uXpBoh8jJkwwn4et4HVlMgkDcq7UHgtn1Oxc,590
@@ -1132,7 +1134,7 @@ rasa/utils/mapper.py,sha256=CZiD3fu7-W-OJgoB1R8JaOg-Hq13TK20D-zGVNgbF18,7726
1132
1134
  rasa/utils/ml_utils.py,sha256=5mGQFQ-m0sJVLT9Mx60nXce3Y__eLhTD8kb6SJ4UJ1k,4169
1133
1135
  rasa/utils/openapi.py,sha256=59bYTclJHieWp1evIikwWvFioDg6albxHaSGYVufPec,5646
1134
1136
  rasa/utils/plotting.py,sha256=QT30kYXQxqAL8ZECjwOOvawuWALJ_rcO3rBZY5PWF-s,12272
1135
- rasa/utils/pypred.py,sha256=nJXn3BySjUZq9U3JWjYPgNvGL-GbBPAqdSglavb18PM,1079
1137
+ rasa/utils/pypred.py,sha256=KAeBS-ifNx7SL7tlhVLCTodADjI6xtrw6jQ3TiUv04k,1370
1136
1138
  rasa/utils/sanic_error_handler.py,sha256=nDL1hyBe8DRdXyXPJFCfWOn3GzTm--UypF7OT2KCra8,1152
1137
1139
  rasa/utils/singleton.py,sha256=w1-sZeBPwe84bod-CuAf8IX8sMJ36pu2UYHHm0eF3wI,565
1138
1140
  rasa/utils/tensorflow/__init__.py,sha256=vCDc2zPhrbtlEpHgFstNSJT8dQg032yXUIgZHCrHjWU,185
@@ -1155,10 +1157,10 @@ rasa/utils/tensorflow/types.py,sha256=PLG7VI5P_3fNZaXYdGyNIRF4dOMTnLtzfvgms67_IS
1155
1157
  rasa/utils/train_utils.py,sha256=LJO7mM6ptYvLMZr4HDl3fBkPHb7-BVFXuuZseh4Pp68,22409
1156
1158
  rasa/utils/url_tools.py,sha256=dZ1HGkVdWTJB7zYEdwoDIrEuyX9HE5WsxKKFVsXBLE0,1218
1157
1159
  rasa/utils/yaml.py,sha256=KjbZq5C94ZP7Jdsw8bYYF7HASI6K4-C_kdHfrnPLpSI,2000
1158
- rasa/validator.py,sha256=nx2oNtPP1u3iOlmAROYigSdomniccNktgbyc9NzlniA,84834
1159
- rasa/version.py,sha256=_vV7weCbN4pf7BPluC_QRmFfFjeocywQmqQTj8gKK98,120
1160
- rasa_pro-3.14.0rc3.dist-info/METADATA,sha256=tC_jg06_YHjqOVCbbGbAPxnOkak_VfVhwrIzWsijH4o,12474
1161
- rasa_pro-3.14.0rc3.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
1162
- rasa_pro-3.14.0rc3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
1163
- rasa_pro-3.14.0rc3.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
1164
- rasa_pro-3.14.0rc3.dist-info/RECORD,,
1160
+ rasa/validator.py,sha256=peO1q1z73a_JCsWj0rq92MfmGh5uvl7Pb2A9xFTKsb0,88309
1161
+ rasa/version.py,sha256=f275zy0pMZIR0luXOE9LM7-86j7Fep2Ev2xIb4SVXX0,120
1162
+ rasa_pro-3.14.0rc4.dist-info/METADATA,sha256=Avwe5cOBKc9VgA5IRjhQJKZ60dxDWwx6MY-jkNYcx4U,12517
1163
+ rasa_pro-3.14.0rc4.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
1164
+ rasa_pro-3.14.0rc4.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
1165
+ rasa_pro-3.14.0rc4.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
1166
+ rasa_pro-3.14.0rc4.dist-info/RECORD,,