rasa-pro 3.14.0rc1__py3-none-any.whl → 3.14.0rc3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rasa-pro might be problematic. Click here for more details.

Files changed (84) hide show
  1. rasa/agents/protocol/a2a/a2a_agent.py +50 -42
  2. rasa/agents/utils.py +27 -5
  3. rasa/agents/validation.py +7 -9
  4. rasa/api.py +1 -2
  5. rasa/builder/copilot/constants.py +4 -1
  6. rasa/builder/copilot/copilot.py +191 -79
  7. rasa/builder/copilot/models.py +306 -116
  8. rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +33 -12
  9. rasa/builder/copilot/prompts/copilot_training_error_handler_prompt.jinja2 +53 -0
  10. rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +59 -29
  11. rasa/builder/copilot/telemetry.py +8 -0
  12. rasa/builder/guardrails/policy_checker.py +1 -1
  13. rasa/builder/jobs.py +182 -12
  14. rasa/builder/models.py +12 -3
  15. rasa/builder/service.py +16 -2
  16. rasa/cli/dialogue_understanding_test.py +1 -0
  17. rasa/cli/e2e_test.py +1 -0
  18. rasa/cli/inspect.py +1 -0
  19. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
  20. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
  21. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/help.yml +8 -0
  22. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/human_handoff.yml +41 -0
  23. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/patterns.yml +32 -0
  24. rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/show_faqs.yml +8 -0
  25. rasa/cli/project_templates/finance/domain/general/help.yml +0 -0
  26. rasa/cli/project_templates/telco/data/network/flow_solve_internet_issue.yml +2 -2
  27. rasa/cli/project_templates/telco/domain/network/solve_internet_issue.yml +1 -2
  28. rasa/cli/project_templates/telco/tests/e2e_test_cases/with_stub/network/solve_internet_not_slow.yml +33 -0
  29. rasa/cli/project_templates/telco/tests/e2e_test_cases/with_stub/network/solve_internet_slow.yml +47 -0
  30. rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
  31. rasa/cli/run.py +1 -5
  32. rasa/cli/shell.py +1 -0
  33. rasa/cli/train.py +1 -0
  34. rasa/cli/validation/bot_config.py +7 -2
  35. rasa/core/available_agents.py +65 -55
  36. rasa/core/brokers/kafka.py +5 -1
  37. rasa/core/concurrent_lock_store.py +38 -21
  38. rasa/core/config/available_endpoints.py +0 -3
  39. rasa/core/config/configuration.py +36 -1
  40. rasa/core/constants.py +6 -0
  41. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +69 -4
  42. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +2 -1
  43. rasa/core/lock_store.py +4 -0
  44. rasa/core/policies/flows/agent_executor.py +16 -8
  45. rasa/core/redis_connection_factory.py +7 -2
  46. rasa/core/tracker_stores/redis_tracker_store.py +4 -0
  47. rasa/core/tracker_stores/sql_tracker_store.py +3 -1
  48. rasa/dialogue_understanding/commands/start_flow_command.py +10 -3
  49. rasa/dialogue_understanding/commands/utils.py +15 -4
  50. rasa/dialogue_understanding/generator/llm_based_command_generator.py +4 -2
  51. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +4 -4
  52. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +4 -4
  53. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +2 -2
  54. rasa/dialogue_understanding_test/du_test_runner.py +2 -2
  55. rasa/e2e_test/e2e_test_runner.py +2 -2
  56. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +10 -4
  57. rasa/shared/agents/auth/constants.py +1 -0
  58. rasa/shared/core/flows/steps/call.py +2 -2
  59. rasa/telemetry.py +3 -3
  60. rasa/validator.py +37 -0
  61. rasa/version.py +1 -1
  62. {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/METADATA +14 -2
  63. {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/RECORD +83 -73
  64. rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +0 -57
  65. /rasa/cli/project_templates/{finance/tests/e2e_test_cases → basic/tests/e2e_test_cases/without_stub}/general/hello.yml +0 -0
  66. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{accounts → without_stub/accounts}/check_balance.yml +0 -0
  67. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{accounts → without_stub/accounts}/download_statements.yml +0 -0
  68. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{cards → without_stub/cards}/block_card.yml +0 -0
  69. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/bot_challenge.yml +0 -0
  70. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/feedback.yml +0 -0
  71. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/goodbye.yml +0 -0
  72. /rasa/cli/project_templates/{telco/tests/e2e_test_cases → finance/tests/e2e_test_cases/without_stub}/general/hello.yml +0 -0
  73. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/human_handoff.yml +0 -0
  74. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{general → without_stub/general}/patterns.yml +0 -0
  75. /rasa/cli/project_templates/finance/tests/e2e_test_cases/{transfers → without_stub/transfers}/transfer_money.yml +0 -0
  76. /rasa/cli/project_templates/telco/tests/e2e_test_cases/{billing → without_stub/billing}/understand_bill.yml +0 -0
  77. /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/bot_challenge.yml +0 -0
  78. /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/feedback.yml +0 -0
  79. /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/goodbye.yml +0 -0
  80. /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/human_handoff.yml +0 -0
  81. /rasa/cli/project_templates/telco/tests/e2e_test_cases/{general → without_stub/general}/patterns.yml +0 -0
  82. {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/NOTICE +0 -0
  83. {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/WHEEL +0 -0
  84. {rasa_pro-3.14.0rc1.dist-info → rasa_pro-3.14.0rc3.dist-info}/entry_points.txt +0 -0
@@ -7,6 +7,7 @@ from typing import Literal, Optional
7
7
  import structlog
8
8
 
9
9
  from rasa.cli.validation.config_path_validation import get_validated_path
10
+ from rasa.core.available_agents import DEFAULT_AGENTS_CONFIG_FOLDER, AvailableAgents
10
11
  from rasa.core.config.available_endpoints import AvailableEndpoints
11
12
  from rasa.core.config.credentials import CredentialsConfig
12
13
  from rasa.core.config.message_procesing_config import MessageProcessingConfig
@@ -146,10 +147,12 @@ class Configuration:
146
147
  def __init__(
147
148
  self,
148
149
  endpoints: AvailableEndpoints,
150
+ available_agents: AvailableAgents,
149
151
  credentials: Optional[CredentialsConfig] = None,
150
152
  message_processing_config: Optional[MessageProcessingConfig] = None,
151
153
  ):
152
154
  self.credentials = credentials
155
+ self.available_agents = available_agents
153
156
  self.endpoints = endpoints
154
157
  self.message_processing_config = message_processing_config
155
158
 
@@ -159,6 +162,7 @@ class Configuration:
159
162
  cls._instance = Configuration(
160
163
  credentials=None,
161
164
  endpoints=AvailableEndpoints(),
165
+ available_agents=AvailableAgents(),
162
166
  message_processing_config=None,
163
167
  )
164
168
  return cls._instance
@@ -177,7 +181,10 @@ class Configuration:
177
181
  )
178
182
  if cls._instance is None:
179
183
  cls._instance = Configuration(
180
- endpoints=endpoints, credentials=None, message_processing_config=None
184
+ endpoints=endpoints,
185
+ available_agents=AvailableAgents(),
186
+ credentials=None,
187
+ message_processing_config=None,
181
188
  )
182
189
  else:
183
190
  cls._instance.endpoints = endpoints
@@ -189,6 +196,7 @@ class Configuration:
189
196
  if cls._instance is None:
190
197
  cls._instance = Configuration(
191
198
  endpoints=AvailableEndpoints(),
199
+ available_agents=AvailableAgents(),
192
200
  credentials=None,
193
201
  message_processing_config=None,
194
202
  )
@@ -217,6 +225,7 @@ class Configuration:
217
225
  message_processing_config=message_processing_config,
218
226
  credentials=None,
219
227
  endpoints=AvailableEndpoints(),
228
+ available_agents=AvailableAgents(),
220
229
  )
221
230
  else:
222
231
  cls._instance.message_processing_config = message_processing_config
@@ -240,12 +249,37 @@ class Configuration:
240
249
  cls._instance = Configuration(
241
250
  credentials=credentials,
242
251
  endpoints=AvailableEndpoints(),
252
+ available_agents=AvailableAgents(),
243
253
  message_processing_config=None,
244
254
  )
245
255
  else:
246
256
  cls._instance.credentials = credentials
247
257
  return cls._instance
248
258
 
259
+ @classmethod
260
+ def initialise_sub_agents(cls, sub_agents_path: Optional[Path]) -> Configuration:
261
+ sub_agents_folder = (
262
+ str(sub_agents_path)
263
+ if sub_agents_path is not None
264
+ else DEFAULT_AGENTS_CONFIG_FOLDER
265
+ )
266
+ logger.debug(
267
+ "configuration.initialise_sub_agents.start",
268
+ sub_agents_folder=sub_agents_folder,
269
+ )
270
+ available_agents = AvailableAgents.read_from_folder(sub_agents_folder)
271
+
272
+ if cls._instance is None:
273
+ cls._instance = Configuration(
274
+ endpoints=AvailableEndpoints(),
275
+ available_agents=available_agents,
276
+ credentials=None,
277
+ message_processing_config=None,
278
+ )
279
+ else:
280
+ cls._instance.available_agents = available_agents
281
+ return cls._instance
282
+
249
283
  @classmethod
250
284
  def get_instance(cls) -> Configuration:
251
285
  if cls._instance is None:
@@ -254,6 +288,7 @@ class Configuration:
254
288
  "Call appropriate 'initialise' methods to "
255
289
  "load the config when Rasa Pro starts: "
256
290
  "initialise_endpoints(), "
291
+ "initialise_sub_agents(), "
257
292
  "initialise_credentials(), "
258
293
  "initialise_message_processing()"
259
294
  )
rasa/core/constants.py CHANGED
@@ -123,3 +123,9 @@ SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE_ENV_VAR_NAME = (
123
123
  "SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE"
124
124
  )
125
125
  AWS_ELASTICACHE_CLUSTER_NAME_ENV_VAR_NAME = "AWS_ELASTICACHE_CLUSTER_NAME"
126
+ RDS_SQL_DB_AWS_IAM_ENABLED_ENV_VAR_NAME = "RDS_SQL_DB_AWS_IAM_ENABLED"
127
+ ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME = "ELASTICACHE_REDIS_AWS_IAM_ENABLED"
128
+ KAFKA_MSK_AWS_IAM_ENABLED_ENV_VAR_NAME = "KAFKA_MSK_AWS_IAM_ENABLED"
129
+ SQL_SERVICE_NAME = "sql"
130
+ REDIS_SERVICE_NAME = "redis"
131
+ KAFKA_SERVICE_NAME = "kafka"
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import threading
3
3
  import time
4
- from typing import Optional, Tuple
4
+ from typing import Dict, Optional, Tuple
5
5
  from urllib.parse import ParseResult, urlencode, urlunparse
6
6
 
7
7
  import boto3
@@ -14,6 +14,14 @@ from botocore.session import get_session
14
14
  from botocore.signers import RequestSigner
15
15
  from cachetools import TTLCache, cached
16
16
 
17
+ from rasa.core.constants import (
18
+ ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME,
19
+ KAFKA_MSK_AWS_IAM_ENABLED_ENV_VAR_NAME,
20
+ KAFKA_SERVICE_NAME,
21
+ RDS_SQL_DB_AWS_IAM_ENABLED_ENV_VAR_NAME,
22
+ REDIS_SERVICE_NAME,
23
+ SQL_SERVICE_NAME,
24
+ )
17
25
  from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
18
26
  IAMCredentialsProvider,
19
27
  IAMCredentialsProviderInput,
@@ -24,6 +32,25 @@ from rasa.shared.exceptions import ConnectionException
24
32
 
25
33
  structlogger = structlog.get_logger(__name__)
26
34
 
35
+ SERVICE_CONFIG: Dict[Tuple[SupportedServiceType, str], str] = {
36
+ (
37
+ SupportedServiceType.TRACKER_STORE,
38
+ SQL_SERVICE_NAME,
39
+ ): RDS_SQL_DB_AWS_IAM_ENABLED_ENV_VAR_NAME,
40
+ (
41
+ SupportedServiceType.TRACKER_STORE,
42
+ REDIS_SERVICE_NAME,
43
+ ): ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME,
44
+ (
45
+ SupportedServiceType.EVENT_BROKER,
46
+ KAFKA_SERVICE_NAME,
47
+ ): KAFKA_MSK_AWS_IAM_ENABLED_ENV_VAR_NAME,
48
+ (
49
+ SupportedServiceType.LOCK_STORE,
50
+ REDIS_SERVICE_NAME,
51
+ ): ELASTICACHE_REDIS_AWS_IAM_ENABLED_ENV_VAR_NAME,
52
+ }
53
+
27
54
 
28
55
  class AWSRDSIAMCredentialsProvider(IAMCredentialsProvider):
29
56
  """Generates temporary credentials for AWS RDS using IAM roles."""
@@ -203,21 +230,59 @@ class AWSElasticacheRedisIAMCredentialsProvider(redis.CredentialProvider):
203
230
  return TemporaryCredentials()
204
231
 
205
232
 
233
+ def is_iam_enabled(provider_input: "IAMCredentialsProviderInput") -> bool:
234
+ """Checks if IAM authentication is enabled for the given service."""
235
+ service_type = provider_input.service_type
236
+ service_name = provider_input.service_name
237
+ iam_enabled_env_var_name = SERVICE_CONFIG.get((service_type, service_name))
238
+
239
+ if not iam_enabled_env_var_name:
240
+ structlogger.warning(
241
+ "rasa.core.aws_iam_credentials_providers.is_iam_enabled.unsupported_service",
242
+ event_info=f"IAM authentication check requested for unsupported service: "
243
+ f"{service_name}",
244
+ )
245
+ return False
246
+
247
+ return os.getenv(iam_enabled_env_var_name, "false").lower() == "true"
248
+
249
+
206
250
  def create_aws_iam_credentials_provider(
207
251
  provider_input: "IAMCredentialsProviderInput",
208
252
  ) -> Optional["IAMCredentialsProvider"]:
209
253
  """Factory function to create an AWS IAM credentials provider."""
210
- if provider_input.service_name == SupportedServiceType.TRACKER_STORE:
254
+ iam_enabled = is_iam_enabled(provider_input)
255
+ if not iam_enabled:
256
+ structlogger.debug(
257
+ "rasa.core.aws_iam_credentials_providers.create_provider.iam_not_enabled",
258
+ event_info=f"IAM authentication not enabled for service: "
259
+ f"{provider_input.service_type}",
260
+ )
261
+ return None
262
+
263
+ if (
264
+ provider_input.service_type == SupportedServiceType.TRACKER_STORE
265
+ and provider_input.service_name == SQL_SERVICE_NAME
266
+ ):
211
267
  return AWSRDSIAMCredentialsProvider(
212
268
  username=provider_input.username,
213
269
  host=provider_input.host,
214
270
  port=provider_input.port,
215
271
  )
216
272
 
217
- if provider_input.service_name == SupportedServiceType.EVENT_BROKER:
273
+ if (
274
+ provider_input.service_type == SupportedServiceType.TRACKER_STORE
275
+ and provider_input.service_name == REDIS_SERVICE_NAME
276
+ ):
277
+ return AWSElasticacheRedisIAMCredentialsProvider(
278
+ username=provider_input.username,
279
+ cluster_name=provider_input.cluster_name,
280
+ )
281
+
282
+ if provider_input.service_type == SupportedServiceType.EVENT_BROKER:
218
283
  return AWSMSKafkaIAMCredentialsProvider()
219
284
 
220
- if provider_input.service_name == SupportedServiceType.LOCK_STORE:
285
+ if provider_input.service_type == SupportedServiceType.LOCK_STORE:
221
286
  return AWSElasticacheRedisIAMCredentialsProvider(
222
287
  username=provider_input.username,
223
288
  cluster_name=provider_input.cluster_name,
@@ -47,7 +47,8 @@ class SupportedServiceType(Enum):
47
47
  class IAMCredentialsProviderInput(BaseModel):
48
48
  """Input data for creating an IAM credentials provider."""
49
49
 
50
- service_name: SupportedServiceType
50
+ service_type: SupportedServiceType
51
+ service_name: str
51
52
  username: Optional[str] = None
52
53
  host: Optional[str] = None
53
54
  port: Optional[int] = None
rasa/core/lock_store.py CHANGED
@@ -18,6 +18,9 @@ from pydantic import (
18
18
 
19
19
  import rasa.shared.utils.common
20
20
  from rasa.core.constants import DEFAULT_LOCK_LIFETIME, IAM_CLOUD_PROVIDER_ENV_VAR_NAME
21
+ from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
22
+ SupportedServiceType,
23
+ )
21
24
  from rasa.core.lock import TicketLock
22
25
  from rasa.core.redis_connection_factory import (
23
26
  DeploymentMode,
@@ -336,6 +339,7 @@ class RedisLockStore(LockStore):
336
339
  redis_config = RedisConfig(
337
340
  host=str(self.config.host),
338
341
  port=self.config.port,
342
+ service_type=SupportedServiceType.LOCK_STORE,
339
343
  db=self.config.db,
340
344
  username=self.config.username,
341
345
  password=self.config.password,
@@ -16,7 +16,7 @@ from rasa.agents.constants import (
16
16
  from rasa.agents.core.types import AgentStatus, ProtocolType
17
17
  from rasa.agents.schemas import AgentInput, AgentOutput
18
18
  from rasa.agents.schemas.agent_input import AgentInputSlot
19
- from rasa.core.available_agents import AvailableAgents
19
+ from rasa.core.config.configuration import Configuration
20
20
  from rasa.core.policies.flows.flow_step_result import (
21
21
  ContinueFlowWithNextStep,
22
22
  FlowActionPrediction,
@@ -47,12 +47,13 @@ from rasa.shared.core.events import (
47
47
  AgentStarted,
48
48
  Event,
49
49
  SlotSet,
50
+ deserialise_events,
50
51
  )
51
52
  from rasa.shared.core.flows.steps import (
52
53
  CallFlowStep,
53
54
  )
54
55
  from rasa.shared.core.slots import CategoricalSlot, Slot
55
- from rasa.shared.core.trackers import DialogueStateTracker
56
+ from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
56
57
  from rasa.shared.utils.llm import tracker_as_readable_transcript
57
58
 
58
59
  structlogger = structlog.get_logger()
@@ -61,8 +62,9 @@ MAX_AGENT_RETRIES = 3
61
62
 
62
63
 
63
64
  def remove_agent_stack_frame(stack: DialogueStack, agent_id: str) -> None:
64
- """Finishes the agentic loop by popping the agent stack frame from the
65
- provided `stack`. The `tracker.stack` is NOT modified.
65
+ """Finishes the agentic loop by popping the agent stack frame from provided `stack`.
66
+
67
+ The `tracker.stack` is NOT modified.
66
68
  """
67
69
  agent_stack_frame = stack.find_agent_stack_frame_by_agent(agent_id)
68
70
  if not agent_stack_frame:
@@ -136,7 +138,9 @@ async def run_agent(
136
138
  final_events.append(AgentStarted(step.call, step.flow_id))
137
139
 
138
140
  # send the input to the agent and wait for a response
139
- protocol_type = get_protocol_type(step, AvailableAgents.get_agent_config(step.call))
141
+ protocol_type = get_protocol_type(
142
+ step, Configuration.get_instance().available_agents.get_agent_config(step.call)
143
+ )
140
144
  output: AgentOutput = await _call_agent_with_retry(
141
145
  agent_name=step.call,
142
146
  protocol_type=protocol_type,
@@ -471,8 +475,9 @@ def _create_action_prediction(
471
475
  def _create_agent_request_user_input_prediction(
472
476
  message: Optional[str], events: Optional[List[Event]]
473
477
  ) -> FlowActionPrediction:
474
- """Create a prediction for requesting user input from the agent
475
- and waiting for it.
478
+ """Create a prediction for requesting user input from the agent and waiting for it.
479
+
480
+ This function creates a prediction that will pause the flow and wait for user input.
476
481
  """
477
482
  return _create_action_prediction(
478
483
  ACTION_AGENT_REQUEST_USER_INPUT_NAME, message, events
@@ -529,7 +534,9 @@ def _prepare_agent_input(
529
534
  tracker.current_slot_values(), slots, step.exit_if
530
535
  ),
531
536
  conversation_history=tracker_as_readable_transcript(tracker),
532
- events=tracker.current_state().get("events") or [],
537
+ events=deserialise_events(
538
+ tracker.current_state(EventVerbosity.ALL).get("events") or []
539
+ ),
533
540
  metadata=agent_input_metadata,
534
541
  )
535
542
 
@@ -550,6 +557,7 @@ def _prepare_slots_for_agent(
550
557
  Args:
551
558
  slot_values: The full slot dictionary from the tracker.
552
559
  slot_definitions: The slot definitions from the domain.
560
+ exit_if: Optional list of exit conditions that determine which slots to keep.
553
561
 
554
562
  Returns:
555
563
  A list of slots containing the name, current value, type, and allowed values.
@@ -6,7 +6,10 @@ import redis
6
6
  import structlog
7
7
  from pydantic import BaseModel, ConfigDict
8
8
 
9
- from rasa.core.constants import AWS_ELASTICACHE_CLUSTER_NAME_ENV_VAR_NAME
9
+ from rasa.core.constants import (
10
+ AWS_ELASTICACHE_CLUSTER_NAME_ENV_VAR_NAME,
11
+ REDIS_SERVICE_NAME,
12
+ )
10
13
  from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
11
14
  IAMCredentialsProvider,
12
15
  IAMCredentialsProviderInput,
@@ -65,6 +68,7 @@ class RedisConfig(BaseModel):
65
68
 
66
69
  host: Text = "localhost"
67
70
  port: int = 6379
71
+ service_type: SupportedServiceType
68
72
  username: Optional[Text] = None
69
73
  password: Optional[Text] = None
70
74
  use_ssl: bool = False
@@ -117,7 +121,8 @@ class RedisConnectionFactory:
117
121
 
118
122
  iam_credentials_provider = create_iam_credentials_provider(
119
123
  IAMCredentialsProviderInput(
120
- service_name=SupportedServiceType.LOCK_STORE,
124
+ service_type=config.service_type,
125
+ service_name=REDIS_SERVICE_NAME,
121
126
  username=config.username,
122
127
  cluster_name=os.getenv(AWS_ELASTICACHE_CLUSTER_NAME_ENV_VAR_NAME),
123
128
  )
@@ -8,6 +8,9 @@ from pydantic import ValidationError
8
8
 
9
9
  import rasa.shared
10
10
  from rasa.core.brokers.broker import EventBroker
11
+ from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
12
+ SupportedServiceType,
13
+ )
11
14
  from rasa.core.redis_connection_factory import (
12
15
  DeploymentMode,
13
16
  RedisConfig,
@@ -54,6 +57,7 @@ class RedisTrackerStore(TrackerStore, SerializedTrackerAsText):
54
57
  config = RedisConfig(
55
58
  host=host,
56
59
  port=port,
60
+ service_type=SupportedServiceType.TRACKER_STORE,
57
61
  db=db,
58
62
  username=username,
59
63
  password=password,
@@ -27,6 +27,7 @@ from rasa.core.constants import (
27
27
  POSTGRESQL_MAX_OVERFLOW,
28
28
  POSTGRESQL_POOL_SIZE,
29
29
  POSTGRESQL_SCHEMA,
30
+ SQL_SERVICE_NAME,
30
31
  SQL_TRACKER_STORE_SSL_MODE_ENV_VAR_NAME,
31
32
  SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE_ENV_VAR_NAME,
32
33
  )
@@ -229,7 +230,8 @@ class SQLTrackerStore(TrackerStore, SerializedTrackerAsText):
229
230
 
230
231
  iam_credentials_provider = create_iam_credentials_provider(
231
232
  IAMCredentialsProviderInput(
232
- service_name=SupportedServiceType.TRACKER_STORE,
233
+ service_type=SupportedServiceType.TRACKER_STORE,
234
+ service_name=SQL_SERVICE_NAME,
233
235
  username=username,
234
236
  host=host,
235
237
  port=port,
@@ -104,7 +104,10 @@ class StartFlowCommand(Command):
104
104
  # predicted a start flow command for the flow which is on top of the stack,
105
105
  # we just need to remove the pattern_continue_interrupted frame(s) from the
106
106
  # stack
107
- stack = remove_pattern_continue_interrupted_frames(stack)
107
+ stack, flow_completed_events = remove_pattern_continue_interrupted_frames(
108
+ stack
109
+ )
110
+ applied_events.extend(flow_completed_events)
108
111
  return applied_events + tracker.create_stack_updated_events(stack)
109
112
 
110
113
  # if the flow is already on the stack, resume it
@@ -114,7 +117,10 @@ class StartFlowCommand(Command):
114
117
  ):
115
118
  # if pattern_continue_interrupted is active, we need to remove it
116
119
  # from the stack before resuming the flow
117
- stack = remove_pattern_continue_interrupted_frames(stack)
120
+ stack, flow_completed_events = remove_pattern_continue_interrupted_frames(
121
+ stack
122
+ )
123
+ applied_events.extend(flow_completed_events)
118
124
  applied_events.extend(resume_flow(self.flow, tracker, stack))
119
125
  # the current active flow is interrupted
120
126
  applied_events.append(
@@ -128,7 +134,8 @@ class StartFlowCommand(Command):
128
134
 
129
135
  # remove the pattern_continue_interrupted frames from the stack
130
136
  # if it is currently active but the user digressed from the pattern
131
- stack = remove_pattern_continue_interrupted_frames(stack)
137
+ stack, flow_completed_events = remove_pattern_continue_interrupted_frames(stack)
138
+ applied_events.extend(flow_completed_events)
132
139
 
133
140
  if original_top_flow:
134
141
  # if the original top flow is not the same as the flow to start,
@@ -19,6 +19,7 @@ from rasa.shared.constants import ACTION_ASK_PREFIX, UTTER_ASK_PREFIX
19
19
  from rasa.shared.core.events import (
20
20
  AgentResumed,
21
21
  Event,
22
+ FlowCompleted,
22
23
  FlowResumed,
23
24
  SlotSet,
24
25
  )
@@ -250,18 +251,28 @@ def collect_frames_to_resume(
250
251
  return list(frames_to_resume), frame_to_resume
251
252
 
252
253
 
253
- def remove_pattern_continue_interrupted_frames(stack: DialogueStack) -> DialogueStack:
254
- """Remove pattern_continue_interrupted frames from the stack."""
254
+ def remove_pattern_continue_interrupted_frames(
255
+ stack: DialogueStack,
256
+ ) -> Tuple[DialogueStack, List[FlowCompleted]]:
257
+ """Remove pattern_continue_interrupted frames from the stack and return events.
258
+
259
+ Returns:
260
+ A tuple containing (updated_stack, flow_completed_events)
261
+ """
255
262
  from rasa.dialogue_understanding.stack.utils import (
256
263
  is_continue_interrupted_flow_active,
257
264
  )
258
265
 
259
266
  if not is_continue_interrupted_flow_active(stack):
260
- return stack
267
+ return stack, []
261
268
 
269
+ events = []
262
270
  # remove pattern_continue_interrupted from the stack
263
271
  top_frame = stack.top()
264
272
  while isinstance(top_frame, PatternFlowStackFrame):
273
+ # Create FlowCompleted event for the pattern frame being removed
274
+ events.append(FlowCompleted(top_frame.flow_id, top_frame.step_id))
275
+
265
276
  # If the top frame is a pattern frame, we need to remove it
266
277
  # before continuing with the active user flow frame.
267
278
  # This prevents the pattern frame
@@ -271,4 +282,4 @@ def remove_pattern_continue_interrupted_frames(stack: DialogueStack) -> Dialogue
271
282
  stack.pop()
272
283
  top_frame = stack.top()
273
284
 
274
- return stack
285
+ return stack, events
@@ -7,7 +7,7 @@ from jinja2 import Environment, Template, select_autoescape
7
7
 
8
8
  import rasa.dialogue_understanding.generator.utils
9
9
  import rasa.shared.utils.io
10
- from rasa.core.available_agents import AvailableAgents
10
+ from rasa.core.config.configuration import Configuration
11
11
  from rasa.dialogue_understanding.commands import (
12
12
  Command,
13
13
  SetSlotCommand,
@@ -398,7 +398,9 @@ class LLMBasedCommandGenerator(
398
398
  if isinstance(event, AgentStarted) and event.flow_id == flow.id
399
399
  ]
400
400
  available_agents = [
401
- AvailableAgents.get_agent_config(event.agent_id)
401
+ Configuration.get_instance().available_agents.get_agent_config(
402
+ event.agent_id
403
+ )
402
404
  for event in agent_events
403
405
  ]
404
406
  if available_agents:
@@ -2,7 +2,7 @@ from typing import Any, Dict, Literal, Optional, Text
2
2
 
3
3
  import structlog
4
4
 
5
- from rasa.core.available_agents import AvailableAgents
5
+ from rasa.core.config.configuration import Configuration
6
6
  from rasa.dialogue_understanding.commands.command_syntax_manager import (
7
7
  CommandSyntaxVersion,
8
8
  )
@@ -125,7 +125,7 @@ class CompactLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
125
125
  """Get the default prompt template file name for the command generator."""
126
126
  return (
127
127
  AGENT_DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
128
- if AvailableAgents.has_agents()
128
+ if Configuration.get_instance().available_agents.has_agents()
129
129
  else DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
130
130
  )
131
131
 
@@ -134,7 +134,7 @@ class CompactLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
134
134
  """Get the fallback prompt template file name for the command generator."""
135
135
  return (
136
136
  AGENT_FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
137
- if AvailableAgents.has_agents()
137
+ if Configuration.get_instance().available_agents.has_agents()
138
138
  else FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
139
139
  )
140
140
 
@@ -143,7 +143,7 @@ class CompactLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
143
143
  """Get the model prompt mapper for the command generator."""
144
144
  return (
145
145
  AGENT_MODEL_PROMPT_MAPPER
146
- if AvailableAgents.has_agents()
146
+ if Configuration.get_instance().available_agents.has_agents()
147
147
  else MODEL_PROMPT_MAPPER
148
148
  )
149
149
 
@@ -2,7 +2,7 @@ from typing import Any, Dict, Literal, Optional, Text
2
2
 
3
3
  import structlog
4
4
 
5
- from rasa.core.available_agents import AvailableAgents
5
+ from rasa.core.config.configuration import Configuration
6
6
  from rasa.dialogue_understanding.commands.command_syntax_manager import (
7
7
  CommandSyntaxVersion,
8
8
  )
@@ -127,7 +127,7 @@ class SearchReadyLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
127
127
  """Get the default prompt template file name for the command generator."""
128
128
  return (
129
129
  AGENT_DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
130
- if AvailableAgents.has_agents()
130
+ if Configuration.get_instance().available_agents.has_agents()
131
131
  else DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME
132
132
  )
133
133
 
@@ -136,7 +136,7 @@ class SearchReadyLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
136
136
  """Get the fallback prompt template file name for the command generator."""
137
137
  return (
138
138
  AGENT_FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
139
- if AvailableAgents.has_agents()
139
+ if Configuration.get_instance().available_agents.has_agents()
140
140
  else FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME
141
141
  )
142
142
 
@@ -145,7 +145,7 @@ class SearchReadyLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
145
145
  """Get the model prompt mapper for the command generator."""
146
146
  return (
147
147
  AGENT_MODEL_PROMPT_MAPPER
148
- if AvailableAgents.has_agents()
148
+ if Configuration.get_instance().available_agents.has_agents()
149
149
  else MODEL_PROMPT_MAPPER
150
150
  )
151
151
 
@@ -9,7 +9,7 @@ from rasa.agents.utils import (
9
9
  get_active_agent_info,
10
10
  get_completed_agents_info,
11
11
  )
12
- from rasa.core.available_agents import AvailableAgents
12
+ from rasa.core.config.configuration import Configuration
13
13
  from rasa.dialogue_understanding.commands import (
14
14
  CannotHandleCommand,
15
15
  Command,
@@ -403,7 +403,7 @@ class SingleStepBasedLLMCommandGenerator(LLMBasedCommandGenerator, ABC):
403
403
  current_slot_allowed_values = allowed_values_for_slot(
404
404
  tracker.slots.get(current_slot)
405
405
  )
406
- has_agents = AvailableAgents.has_agents()
406
+ has_agents = Configuration.get_instance().available_agents.has_agents()
407
407
  current_conversation = tracker_as_readable_transcript(
408
408
  tracker, highlight_agent_turns=has_agents
409
409
  )
@@ -6,9 +6,9 @@ from typing import Any, Dict, List, Optional, Union
6
6
  import structlog
7
7
  from tqdm import tqdm
8
8
 
9
- from rasa.core.available_agents import AvailableAgents
10
9
  from rasa.core.channels import CollectingOutputChannel, UserMessage
11
10
  from rasa.core.config.available_endpoints import AvailableEndpoints
11
+ from rasa.core.config.configuration import Configuration
12
12
  from rasa.core.exceptions import AgentNotReady
13
13
  from rasa.core.persistor import StorageType
14
14
  from rasa.dialogue_understanding.commands import Command
@@ -71,7 +71,7 @@ class DialogueUnderstandingTestRunner:
71
71
  import rasa.core.agent
72
72
 
73
73
  self._check_action_server(endpoints)
74
- sub_agents = AvailableAgents.get_instance(sub_agents_path)
74
+ sub_agents = Configuration.get_instance().available_agents
75
75
 
76
76
  self.agent = asyncio.run(
77
77
  rasa.core.agent.load_agent(
@@ -13,9 +13,9 @@ import structlog
13
13
  from tqdm import tqdm
14
14
 
15
15
  import rasa.shared.utils.io
16
- from rasa.core.available_agents import AvailableAgents
17
16
  from rasa.core.channels import CollectingOutputChannel, UserMessage
18
17
  from rasa.core.config.available_endpoints import AvailableEndpoints
18
+ from rasa.core.config.configuration import Configuration
19
19
  from rasa.core.constants import ACTIVE_FLOW_METADATA_KEY, STEP_ID_METADATA_KEY
20
20
  from rasa.core.exceptions import AgentNotReady
21
21
  from rasa.core.persistor import StorageType
@@ -96,7 +96,7 @@ class E2ETestRunner:
96
96
  if endpoints and not are_custom_actions_stubbed:
97
97
  self._action_server_is_reachable(endpoints)
98
98
 
99
- sub_agents = AvailableAgents.get_instance(sub_agents_path)
99
+ sub_agents = Configuration.get_instance().available_agents
100
100
 
101
101
  self.agent = asyncio.run(
102
102
  rasa.core.agent.load_agent(