rasa-pro 3.13.1a6__py3-none-any.whl → 3.13.1a8__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 (32) hide show
  1. rasa/builder/project_generator.py +20 -8
  2. rasa/builder/service.py +32 -19
  3. rasa/cli/project_templates/finance/actions/database.py +108 -65
  4. rasa/cli/project_templates/finance/tests/conversation_repair/cancellations.yml +12 -0
  5. rasa/cli/project_templates/finance/tests/conversation_repair/cannot_handle.yml +7 -0
  6. rasa/cli/project_templates/finance/tests/conversation_repair/chitchat.yml +7 -0
  7. rasa/cli/project_templates/finance/tests/conversation_repair/clarification.yml +9 -0
  8. rasa/cli/project_templates/finance/tests/conversation_repair/completion.yml +18 -0
  9. rasa/cli/project_templates/finance/tests/conversation_repair/corrections.yml +17 -0
  10. rasa/cli/project_templates/finance/tests/conversation_repair/digressions.yml +32 -0
  11. rasa/cli/project_templates/finance/tests/conversation_repair/human_handoff.yml +21 -0
  12. rasa/cli/project_templates/finance/tests/conversation_repair/skipping_collect_steps.yml +16 -0
  13. rasa/cli/project_templates/finance/tests/demo_scripts/main.yml +16 -0
  14. rasa/cli/project_templates/finance/tests/happy_paths/balance_verification.yml +15 -0
  15. rasa/cli/project_templates/finance/tests/happy_paths/banking_questions.yml +12 -0
  16. rasa/cli/project_templates/finance/tests/happy_paths/card_blocking.yml +52 -0
  17. rasa/cli/project_templates/finance/tests/happy_paths/money_transfer.yml +136 -0
  18. rasa/cli/project_templates/finance/tests/happy_paths/payee_management.yml +27 -0
  19. rasa/cli/project_templates/finance/tests/happy_paths/user_greeted.yml +5 -0
  20. rasa/cli/project_templates/plain/domain.yml +1 -1
  21. rasa/cli/project_templates/telco/actions/actions_billing.py +115 -70
  22. rasa/cli/project_templates/telco/actions/actions_get_data_from_db.py +26 -11
  23. rasa/core/channels/studio_chat.py +4 -2
  24. rasa/core/policies/enterprise_search_policy.py +1 -1
  25. rasa/dialogue_understanding/generator/flow_retrieval.py +10 -9
  26. rasa/version.py +1 -1
  27. {rasa_pro-3.13.1a6.dist-info → rasa_pro-3.13.1a8.dist-info}/METADATA +1 -1
  28. {rasa_pro-3.13.1a6.dist-info → rasa_pro-3.13.1a8.dist-info}/RECORD +31 -16
  29. rasa/cli/project_templates/finance/requirements.txt +0 -1
  30. {rasa_pro-3.13.1a6.dist-info → rasa_pro-3.13.1a8.dist-info}/NOTICE +0 -0
  31. {rasa_pro-3.13.1a6.dist-info → rasa_pro-3.13.1a8.dist-info}/WHEEL +0 -0
  32. {rasa_pro-3.13.1a6.dist-info → rasa_pro-3.13.1a8.dist-info}/entry_points.txt +0 -0
@@ -44,7 +44,7 @@ class ProjectGenerator:
44
44
  skill_description: str,
45
45
  template: ProjectTemplateName,
46
46
  max_retries: Optional[int] = None,
47
- ) -> Dict[str, str]:
47
+ ) -> Dict[str, Optional[str]]:
48
48
  """Generate a Rasa project with retry logic for validation failures.
49
49
 
50
50
  Args:
@@ -72,7 +72,7 @@ class ProjectGenerator:
72
72
 
73
73
  async def _generate_with_retry(
74
74
  messages: List[Dict[str, Any]], attempts_left: int
75
- ):
75
+ ) -> Dict[str, Optional[str]]:
76
76
  try:
77
77
  # Generate project data using LLM
78
78
  project_data = await llm_service.generate_rasa_project(messages)
@@ -178,7 +178,7 @@ class ProjectGenerator:
178
178
  except Exception as e:
179
179
  raise ValidationError(f"Failed to create importer: {e}")
180
180
 
181
- def get_bot_files(self) -> Dict[str, str]:
181
+ def get_bot_files(self) -> Dict[str, Optional[str]]:
182
182
  """Get the current bot files by reading from disk."""
183
183
  bot_files = {}
184
184
 
@@ -190,15 +190,27 @@ class ProjectGenerator:
190
190
  relative_path = file.relative_to(self.project_folder)
191
191
 
192
192
  # Skip hidden files and directories (any path component starting with '.')
193
+ # as well as `__pycache__` folders
193
194
  if any(part.startswith(".") for part in relative_path.parts):
194
195
  continue
195
196
 
197
+ if "__pycache__" in relative_path.parts:
198
+ continue
199
+
196
200
  # exclude the project_folder / models folder
197
201
  if relative_path.parts[0] == "models":
198
202
  continue
199
203
 
200
204
  # Read file content and store with relative path as key
201
- bot_files[relative_path.as_posix()] = file.read_text(encoding="utf-8")
205
+ try:
206
+ bot_files[relative_path.as_posix()] = file.read_text(encoding="utf-8")
207
+ except Exception as e:
208
+ structlogger.debug(
209
+ "project_generator.get_bot_files.error",
210
+ error=str(e),
211
+ file_path=file.as_posix(),
212
+ )
213
+ bot_files[relative_path.as_posix()] = None
202
214
 
203
215
  return bot_files
204
216
 
@@ -223,7 +235,7 @@ class ProjectGenerator:
223
235
  else:
224
236
  return f"data/flows/{flow_id}.yml"
225
237
 
226
- def _update_bot_files_from_llm_response(self, project_data: Dict[str, Any]):
238
+ def _update_bot_files_from_llm_response(self, project_data: Dict[str, Any]) -> None:
227
239
  """Update the bot files with generated data by writing to disk."""
228
240
  files = {"domain.yml": dump_obj_as_yaml_to_string(project_data["domain"])}
229
241
  # split up flows into one file per flow in the /flows folder
@@ -236,21 +248,21 @@ class ProjectGenerator:
236
248
  self._cleanup_flows()
237
249
  self.update_bot_files(files)
238
250
 
239
- def _cleanup_flows(self):
251
+ def _cleanup_flows(self) -> None:
240
252
  """Cleanup the flows folder."""
241
253
  flows_folder = self.project_folder / "data" / "flows"
242
254
  if flows_folder.exists():
243
255
  shutil.rmtree(flows_folder)
244
256
  flows_folder.mkdir(parents=True, exist_ok=True)
245
257
 
246
- def update_bot_files(self, files: Dict[str, str]):
258
+ def update_bot_files(self, files: Dict[str, str]) -> None:
247
259
  """Update bot files with new content by writing to disk."""
248
260
  for filename, content in files.items():
249
261
  file_path = Path(subpath(self.project_folder, filename))
250
262
  file_path.parent.mkdir(parents=True, exist_ok=True)
251
263
  file_path.write_text(content, encoding="utf-8")
252
264
 
253
- def cleanup(self):
265
+ def cleanup(self) -> None:
254
266
  """Cleanup the project folder."""
255
267
  # remove all the files and folders in the project folder resulting
256
268
  # in an empty folder
rasa/builder/service.py CHANGED
@@ -3,7 +3,7 @@
3
3
  from typing import Optional
4
4
 
5
5
  import structlog
6
- from sanic import Sanic, response
6
+ from sanic import HTTPResponse, Sanic, response
7
7
  from sanic.request import Request
8
8
 
9
9
  from rasa.builder import config
@@ -72,7 +72,7 @@ class PromptToBotService:
72
72
  )
73
73
  return StudioChatInput.from_credentials(credentials=studio_chat_credentials)
74
74
 
75
- def setup_routes(self):
75
+ def setup_routes(self) -> None:
76
76
  """Setup all API routes."""
77
77
  # Core endpoints
78
78
  self.app.add_route(
@@ -93,11 +93,11 @@ class PromptToBotService:
93
93
 
94
94
  channels.channel.register([self.input_channel], self.app, route="/webhooks/")
95
95
 
96
- def setup_middleware(self):
96
+ def setup_middleware(self) -> None:
97
97
  """Setup middleware for request/response processing."""
98
98
 
99
- @self.app.middleware("request")
100
- async def log_request(request):
99
+ @self.app.middleware("request") # type: ignore[no-untyped-call]
100
+ async def log_request(request: Request) -> None:
101
101
  structlogger.info(
102
102
  "request.received",
103
103
  method=request.method,
@@ -105,8 +105,8 @@ class PromptToBotService:
105
105
  remote_addr=request.remote_addr or "unknown",
106
106
  )
107
107
 
108
- @self.app.middleware("response")
109
- async def log_response(request, response):
108
+ @self.app.middleware("response") # type: ignore[no-untyped-call]
109
+ async def log_response(request: Request, response: HTTPResponse) -> None:
110
110
  structlogger.info(
111
111
  "request.completed",
112
112
  method=request.method,
@@ -114,11 +114,11 @@ class PromptToBotService:
114
114
  status=response.status,
115
115
  )
116
116
 
117
- async def health(self, request: Request):
117
+ async def health(self, request: Request) -> HTTPResponse:
118
118
  """Health check endpoint."""
119
119
  return response.json({"status": "ok", "service": "prompt-to-bot"})
120
120
 
121
- async def handle_prompt_to_bot(self, request: Request):
121
+ async def handle_prompt_to_bot(self, request: Request) -> HTTPResponse:
122
122
  """Handle prompt-to-bot generation requests."""
123
123
  try:
124
124
  # Validate request
@@ -191,11 +191,13 @@ class PromptToBotService:
191
191
  except Exception as e:
192
192
  structlogger.error("prompt_to_bot.unexpected_error", error=str(e))
193
193
  return response.json(
194
- ApiErrorResponse(error="Unexpected error occurred").model_dump(),
194
+ ApiErrorResponse(
195
+ error="Unexpected error occurred", details=None
196
+ ).model_dump(),
195
197
  status=500,
196
198
  )
197
199
 
198
- async def handle_template_to_bot(self, request: Request):
200
+ async def handle_template_to_bot(self, request: Request) -> HTTPResponse:
199
201
  """Handle template-to-bot generation requests."""
200
202
  try:
201
203
  # Validate request
@@ -268,18 +270,24 @@ class PromptToBotService:
268
270
  except Exception as e:
269
271
  structlogger.error("template_to_bot.unexpected_error", error=str(e))
270
272
  return response.json(
271
- ApiErrorResponse(error="Unexpected error occurred").model_dump(),
273
+ ApiErrorResponse(
274
+ error="Unexpected error occurred", details=None
275
+ ).model_dump(),
272
276
  status=500,
273
277
  )
274
278
 
275
- async def get_bot_data(self, request: Request):
279
+ async def get_bot_data(self, request: Request) -> HTTPResponse:
276
280
  """Get current bot data."""
277
281
  bot_files = self.project_generator.get_bot_files()
278
282
  return response.json(
279
- ApiResponse(status="success", data={"bot_data": bot_files}).model_dump()
283
+ ApiResponse(
284
+ status="success",
285
+ message="Bot data fetched successfully",
286
+ data={"bot_data": bot_files},
287
+ ).model_dump()
280
288
  )
281
289
 
282
- async def update_bot_data(self, request: Request):
290
+ async def update_bot_data(self, request: Request) -> None:
283
291
  """Update bot data with server-sent events for progress tracking."""
284
292
  sse_response = await request.respond(content_type="text/event-stream")
285
293
 
@@ -376,7 +384,7 @@ class PromptToBotService:
376
384
  finally:
377
385
  await sse_response.eof()
378
386
 
379
- async def llm_builder(self, request: Request):
387
+ async def llm_builder(self, request: Request) -> HTTPResponse:
380
388
  """Handle LLM builder requests."""
381
389
  try:
382
390
  # Validate request
@@ -413,7 +421,10 @@ class PromptToBotService:
413
421
  except Exception as e:
414
422
  structlogger.error("llm_builder.unexpected_error", error=str(e))
415
423
  return response.json(
416
- ApiErrorResponse(error="Unexpected error in LLM builder").model_dump(),
424
+ ApiErrorResponse(
425
+ error="Unexpected error in LLM builder",
426
+ details=None,
427
+ ).model_dump(),
417
428
  status=500,
418
429
  )
419
430
 
@@ -429,11 +440,13 @@ class PromptToBotService:
429
440
  return None
430
441
 
431
442
  @staticmethod
432
- async def _send_sse_event(sse_response, event: ServerSentEvent):
443
+ async def _send_sse_event(
444
+ sse_response: HTTPResponse, event: ServerSentEvent
445
+ ) -> None:
433
446
  """Send a server-sent event."""
434
447
  await sse_response.send(event.format())
435
448
 
436
- def run(self):
449
+ def run(self) -> None:
437
450
  """Run the service."""
438
451
  structlogger.info(
439
452
  "service.starting",
@@ -1,9 +1,9 @@
1
+ import csv
1
2
  import logging
3
+ from datetime import datetime
2
4
  from pathlib import Path
3
5
  from typing import Any, Dict, List, Optional
4
6
 
5
- import pandas as pd
6
-
7
7
 
8
8
  class Database:
9
9
  def __init__(self, csv_path: Optional[Path] = None) -> None:
@@ -28,14 +28,39 @@ class Database:
28
28
 
29
29
  return logger
30
30
 
31
+ def _read_csv(self, filename: str) -> List[Dict[str, Any]]:
32
+ """Read CSV file and return list of dictionaries."""
33
+ try:
34
+ with open(self.csv_path / filename, "r", newline="") as csvfile:
35
+ reader = csv.DictReader(csvfile)
36
+ return list(reader)
37
+ except Exception as e:
38
+ self.logger.error(f"Error reading CSV file {filename}: {e}")
39
+ return []
40
+
41
+ def _write_csv(self, filename: str, data: List[Dict[str, Any]]) -> bool:
42
+ """Write list of dictionaries to CSV file."""
43
+ try:
44
+ if not data:
45
+ return True
46
+
47
+ with open(self.csv_path / filename, "w", newline="") as csvfile:
48
+ writer = csv.DictWriter(csvfile, fieldnames=data[0].keys())
49
+ writer.writeheader()
50
+ writer.writerows(data)
51
+ return True
52
+ except Exception as e:
53
+ self.logger.error(f"Error writing CSV file {filename}: {e}")
54
+ return False
55
+
31
56
  def get_user_by_name(self, username: str) -> Optional[Dict[str, Any]]:
32
57
  """Get user information by username."""
33
58
  try:
34
- df = pd.read_csv(self.csv_path / "users.csv")
35
- user_data = df[df["name"] == username]
36
- if user_data.empty:
37
- return None
38
- return user_data.iloc[0].to_dict()
59
+ users = self._read_csv("users.csv")
60
+ for user in users:
61
+ if user["name"] == username:
62
+ return user
63
+ return None
39
64
  except Exception as e:
40
65
  self.logger.error(f"Error getting user by name: {e}")
41
66
  return None
@@ -43,11 +68,11 @@ class Database:
43
68
  def get_user_by_id(self, user_id: int) -> Optional[Dict[str, Any]]:
44
69
  """Get user information by user_id."""
45
70
  try:
46
- df = pd.read_csv(self.csv_path / "users.csv")
47
- user_data = df[df["id"] == user_id]
48
- if user_data.empty:
49
- return None
50
- return user_data.iloc[0].to_dict()
71
+ users = self._read_csv("users.csv")
72
+ for user in users:
73
+ if int(user["id"]) == user_id:
74
+ return user
75
+ return None
51
76
  except Exception as e:
52
77
  self.logger.error(f"Error getting user by id: {e}")
53
78
  return None
@@ -57,13 +82,14 @@ class Database:
57
82
  ) -> Optional[Dict[str, Any]]:
58
83
  """Get account information by user_id and account number."""
59
84
  try:
60
- df = pd.read_csv(self.csv_path / "accounts.csv")
61
- account_data = df[
62
- (df["user_id"] == user_id) & (df["number"] == account_number)
63
- ]
64
- if account_data.empty:
65
- return None
66
- return account_data.iloc[0].to_dict()
85
+ accounts = self._read_csv("accounts.csv")
86
+ for account in accounts:
87
+ if (
88
+ int(account["user_id"]) == user_id
89
+ and account["number"] == account_number
90
+ ):
91
+ return account
92
+ return None
67
93
  except Exception as e:
68
94
  self.logger.error(f"Error getting account: {e}")
69
95
  return None
@@ -71,9 +97,10 @@ class Database:
71
97
  def get_accounts_by_user(self, user_id: int) -> List[Dict[str, Any]]:
72
98
  """Get all accounts for a user."""
73
99
  try:
74
- df = pd.read_csv(self.csv_path / "accounts.csv")
75
- accounts_data = df[df["user_id"] == user_id]
76
- return accounts_data.to_dict("records")
100
+ accounts = self._read_csv("accounts.csv")
101
+ return [
102
+ account for account in accounts if int(account["user_id"]) == user_id
103
+ ]
77
104
  except Exception as e:
78
105
  self.logger.error(f"Error getting accounts by user: {e}")
79
106
  return []
@@ -81,9 +108,8 @@ class Database:
81
108
  def get_payees_by_user(self, user_id: int) -> List[Dict[str, Any]]:
82
109
  """Get all payees for a user."""
83
110
  try:
84
- df = pd.read_csv(self.csv_path / "payees.csv")
85
- payees_data = df[df["user_id"] == user_id]
86
- return payees_data.to_dict("records")
111
+ payees = self._read_csv("payees.csv")
112
+ return [payee for payee in payees if int(payee["user_id"]) == user_id]
87
113
  except Exception as e:
88
114
  self.logger.error(f"Error getting payees by user: {e}")
89
115
  return []
@@ -93,11 +119,11 @@ class Database:
93
119
  ) -> Optional[Dict[str, Any]]:
94
120
  """Get payee information by name and user_id."""
95
121
  try:
96
- df = pd.read_csv(self.csv_path / "payees.csv")
97
- payee_data = df[(df["name"] == payee_name) & (df["user_id"] == user_id)]
98
- if payee_data.empty:
99
- return None
100
- return payee_data.iloc[0].to_dict()
122
+ payees = self._read_csv("payees.csv")
123
+ for payee in payees:
124
+ if payee["name"] == payee_name and int(payee["user_id"]) == user_id:
125
+ return payee
126
+ return None
101
127
  except Exception as e:
102
128
  self.logger.error(f"Error getting payee by name and user: {e}")
103
129
  return None
@@ -105,9 +131,8 @@ class Database:
105
131
  def get_cards_by_user(self, user_id: int) -> List[Dict[str, Any]]:
106
132
  """Get all cards for a user."""
107
133
  try:
108
- df = pd.read_csv(self.csv_path / "cards.csv")
109
- cards_data = df[df["user_id"] == user_id]
110
- return cards_data.to_dict("records")
134
+ cards = self._read_csv("cards.csv")
135
+ return [card for card in cards if int(card["user_id"]) == user_id]
111
136
  except Exception as e:
112
137
  self.logger.error(f"Error getting cards by user: {e}")
113
138
  return []
@@ -115,11 +140,11 @@ class Database:
115
140
  def get_card_by_number(self, card_number: str) -> Optional[Dict[str, Any]]:
116
141
  """Get card information by card number."""
117
142
  try:
118
- df = pd.read_csv(self.csv_path / "cards.csv")
119
- card_data = df[df["number"] == card_number]
120
- if card_data.empty:
121
- return None
122
- return card_data.iloc[0].to_dict()
143
+ cards = self._read_csv("cards.csv")
144
+ for card in cards:
145
+ if card["number"] == card_number:
146
+ return card
147
+ return None
123
148
  except Exception as e:
124
149
  self.logger.error(f"Error getting card by number: {e}")
125
150
  return None
@@ -127,10 +152,12 @@ class Database:
127
152
  def update_card_status(self, card_number: str, status: str) -> bool:
128
153
  """Update card status."""
129
154
  try:
130
- df = pd.read_csv(self.csv_path / "cards.csv")
131
- df.loc[df["number"] == card_number, "status"] = status
132
- df.to_csv(self.csv_path / "cards.csv", index=False)
133
- return True
155
+ cards = self._read_csv("cards.csv")
156
+ for card in cards:
157
+ if card["number"] == card_number:
158
+ card["status"] = status
159
+ break
160
+ return self._write_csv("cards.csv", cards)
134
161
  except Exception as e:
135
162
  self.logger.error(f"Error updating card status: {e}")
136
163
  return False
@@ -146,27 +173,28 @@ class Database:
146
173
  ) -> bool:
147
174
  """Add a new payee."""
148
175
  try:
149
- df = pd.read_csv(self.csv_path / "payees.csv")
176
+ payees = self._read_csv("payees.csv")
150
177
 
151
178
  # Get the next ID
152
- next_id = df["id"].max() + 1 if not df.empty else 1
179
+ next_id = 1
180
+ if payees:
181
+ next_id = max(int(payee["id"]) for payee in payees) + 1
153
182
 
154
183
  # Create new payee record
155
184
  new_payee = {
156
- "id": next_id,
157
- "user_id": user_id,
185
+ "id": str(next_id),
186
+ "user_id": str(user_id),
158
187
  "name": name,
159
188
  "sort_code": sort_code,
160
189
  "account_number": account_number,
161
190
  "type": payee_type,
162
191
  "reference": reference,
163
- "added_at": pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S"),
192
+ "added_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
164
193
  }
165
194
 
166
- # Add to dataframe and save
167
- df = pd.concat([df, pd.DataFrame([new_payee])], ignore_index=True)
168
- df.to_csv(self.csv_path / "payees.csv", index=False)
169
- return True
195
+ # Add to list and save
196
+ payees.append(new_payee)
197
+ return self._write_csv("payees.csv", payees)
170
198
  except Exception as e:
171
199
  self.logger.error(f"Error adding payee: {e}")
172
200
  return False
@@ -174,10 +202,15 @@ class Database:
174
202
  def remove_payee(self, payee_name: str, user_id: int) -> bool:
175
203
  """Remove a payee."""
176
204
  try:
177
- df = pd.read_csv(self.csv_path / "payees.csv")
178
- df = df[~((df["name"] == payee_name) & (df["user_id"] == user_id))]
179
- df.to_csv(self.csv_path / "payees.csv", index=False)
180
- return True
205
+ payees = self._read_csv("payees.csv")
206
+ payees = [
207
+ payee
208
+ for payee in payees
209
+ if not (
210
+ payee["name"] == payee_name and int(payee["user_id"]) == user_id
211
+ )
212
+ ]
213
+ return self._write_csv("payees.csv", payees)
181
214
  except Exception as e:
182
215
  self.logger.error(f"Error removing payee: {e}")
183
216
  return False
@@ -198,8 +231,7 @@ class Database:
198
231
  def get_branches(self) -> List[Dict[str, Any]]:
199
232
  """Get all branches."""
200
233
  try:
201
- df = pd.read_csv(self.csv_path / "branches.csv")
202
- return df.to_dict("records")
234
+ return self._read_csv("branches.csv")
203
235
  except Exception as e:
204
236
  self.logger.error(f"Error getting branches: {e}")
205
237
  return []
@@ -207,9 +239,12 @@ class Database:
207
239
  def get_advisors_by_branch(self, branch_id: int) -> List[Dict[str, Any]]:
208
240
  """Get all advisors for a branch."""
209
241
  try:
210
- df = pd.read_csv(self.csv_path / "advisors.csv")
211
- advisors_data = df[df["branch_id"] == branch_id]
212
- return advisors_data.to_dict("records")
242
+ advisors = self._read_csv("advisors.csv")
243
+ return [
244
+ advisor
245
+ for advisor in advisors
246
+ if int(advisor["branch_id"]) == branch_id
247
+ ]
213
248
  except Exception as e:
214
249
  self.logger.error(f"Error getting advisors by branch: {e}")
215
250
  return []
@@ -217,17 +252,25 @@ class Database:
217
252
  def get_appointments_by_advisor(self, advisor_id: int) -> List[Dict[str, Any]]:
218
253
  """Get all appointments for an advisor."""
219
254
  try:
220
- df = pd.read_csv(self.csv_path / "appointments.csv")
221
- appointments_data = df[df["advisor_id"] == advisor_id]
222
- return appointments_data.to_dict("records")
255
+ appointments = self._read_csv("appointments.csv")
256
+ return [
257
+ appointment
258
+ for appointment in appointments
259
+ if int(appointment["advisor_id"]) == advisor_id
260
+ ]
223
261
  except Exception as e:
224
262
  self.logger.error(f"Error getting appointments by advisor: {e}")
225
263
  return []
226
264
 
227
- def __enter__(self):
265
+ def __enter__(self) -> "Database":
228
266
  """Enter the runtime context related to this object."""
229
267
  return self
230
268
 
231
- def __exit__(self, exc_type, exc_value, traceback):
269
+ def __exit__(
270
+ self,
271
+ exc_type: Optional[type],
272
+ exc_value: Optional[BaseException],
273
+ traceback: Optional[Any],
274
+ ) -> None:
232
275
  """Exit the runtime context related to this object."""
233
276
  self.logger.info("Database connection closed")
@@ -0,0 +1,12 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_simple_cancellation
3
+ steps:
4
+ - user: "hello"
5
+ - utter: utter_chitchat
6
+ - user: "who are my payees"
7
+ - bot: "You are authorised to transfer money to: Amy, Fitness Gym and William"
8
+ - user: "I want to transfer 55 to Amy"
9
+ - utter: utter_transfer_money_understand
10
+ - bot: "Which account would you like to transfer money from?"
11
+ - user: "sorry, I want to cancel that"
12
+ - utter: utter_flow_cancelled_rasa
@@ -0,0 +1,7 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_cannot_handle
3
+ steps:
4
+ - user: "hello"
5
+ - utter: utter_chitchat
6
+ - user: "I want to apply for a mortgage"
7
+ - utter: utter_ask_rephrase
@@ -0,0 +1,7 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_chitchat
3
+ steps:
4
+ - user: "hello,"
5
+ - utter: utter_chitchat
6
+ - user: "How can we solve world hunger?"
7
+ - bot: "Based on the provided documents and the context of the recent conversation, the question about solving world hunger is not directly addressed. If you have any specific questions related to the documents or conversation context, feel free to ask for more information."
@@ -0,0 +1,9 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_clarification
3
+ steps:
4
+ - user: "hello"
5
+ - utter: utter_chitchat
6
+ - user: "payee"
7
+ - utter: utter_clarification_options_rasa
8
+ - user: "view a list"
9
+ - bot: "You are authorised to transfer money to: Robert, James and Food Market"
@@ -0,0 +1,18 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_completion
3
+ steps:
4
+ - user: "hello"
5
+ - utter: utter_chitchat
6
+ - user: "Who are my payees"
7
+ - bot: "You are authorised to transfer money to: Amy, Fitness Gym and William"
8
+ - user: "I want to transfer money to William"
9
+ - utter: utter_transfer_money_understand
10
+ - bot: "Which account would you like to transfer money from?"
11
+ - user: "78901234"
12
+ - utter: utter_ask_amount
13
+ - user: "120"
14
+ - utter: utter_ask_timing
15
+ - user: "/SetSlots(timing=now)"
16
+ - utter: utter_ask_confirm_immediate_payment
17
+ - user: "yes"
18
+ - utter: utter_transfer_successful
@@ -0,0 +1,17 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_corrections
3
+ steps:
4
+ - user: "who are my payees"
5
+ - bot: "You are authorised to transfer money to: Amy, Fitness Gym and William"
6
+ - user: "I want to transfer 55 to Amy"
7
+ - utter: utter_transfer_money_understand
8
+ - bot: "Which account would you like to transfer money from?"
9
+ - user: "67890123"
10
+ - utter: utter_ask_timing
11
+ - user: "/SetSlots(timing=now)"
12
+ - utter: utter_ask_confirm_immediate_payment
13
+ - user: "Sorry, I meant 65 and from Current"
14
+ - utter: utter_corrected_previous_input
15
+ - utter: utter_ask_confirm_immediate_payment
16
+ - user: "yes"
17
+ - utter: utter_transfer_successful
@@ -0,0 +1,32 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_digressions
3
+ steps:
4
+ - user: "I want to transfer money"
5
+ - utter: utter_transfer_money_understand
6
+ - bot: "Which account would you like to transfer money from?"
7
+ - user: "who are my payees"
8
+ - bot: "You are authorised to transfer money to: Richard, Susan and Electric Company"
9
+ - utter: utter_flow_continue_interrupted
10
+ - bot: "Which account would you like to transfer money from?"
11
+ - user: "I would like to add Brad as a payee"
12
+ - utter: utter_ask_account_number
13
+ - user: "123456"
14
+ - utter: utter_ask_payee_type
15
+ - user: "/SetSlots(payee_type=person)"
16
+ - utter: utter_ask_reference
17
+ - user: "Facebook Marketplace"
18
+ - utter: utter_ask_confirm_payee_details
19
+ - user: "/SetSlots(confirm_payee_details=True)"
20
+ - utter: utter_payee_added_success
21
+ - utter: utter_flow_continue_interrupted
22
+ - bot: "Which account would you like to transfer money from?"
23
+ - user: "12345678"
24
+ - utter: utter_ask_payee_name
25
+ - user: "Brad"
26
+ - utter: utter_ask_amount
27
+ - user: "55.23"
28
+ - utter: utter_ask_timing
29
+ - user: "immediate"
30
+ - utter: utter_ask_confirm_immediate_payment
31
+ - user: "yup"
32
+ - utter: utter_transfer_successful
@@ -0,0 +1,21 @@
1
+ test_cases:
2
+ - test_case: conversation_repair_human_handoff
3
+ steps:
4
+ - user: "hello"
5
+ - utter: utter_chitchat
6
+ - user: "i want to transfer 999 from savings"
7
+ - utter: utter_transfer_money_understand
8
+ - utter: utter_ask_payee_name
9
+ - user: "who are my payees"
10
+ - bot: "You are authorised to transfer money to: Amy, Fitness Gym and William"
11
+ - utter: utter_flow_continue_interrupted
12
+ - utter: utter_ask_payee_name
13
+ - user: "Amy"
14
+ - utter: utter_ask_timing
15
+ - user: "/SetSlots(timing=now)"
16
+ - utter: utter_ask_confirm_immediate_payment
17
+ - user: "I want to talk to a human"
18
+ - utter: utter_human_handoff_not_available
19
+ - utter: utter_ask_confirm_immediate_payment
20
+ - user: "no"
21
+ - utter: utter_cancel_transfer