rasa-pro 3.14.0a15__py3-none-any.whl → 3.14.0a16__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 (93) hide show
  1. rasa/builder/config.py +1 -0
  2. rasa/builder/copilot/constants.py +3 -0
  3. rasa/builder/copilot/copilot.py +127 -31
  4. rasa/builder/copilot/models.py +34 -0
  5. rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +28 -84
  6. rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +61 -0
  7. rasa/builder/copilot/telemetry.py +16 -6
  8. rasa/builder/document_retrieval/models.py +3 -3
  9. rasa/builder/main.py +14 -5
  10. rasa/builder/project_generator.py +1 -3
  11. rasa/builder/service.py +8 -9
  12. rasa/builder/template_cache.py +183 -9
  13. rasa/cli/project_templates/telco/data/general/human_handoff.yml +1 -1
  14. rasa/cli/project_templates/telco/domain/general/human_handoff.yml +3 -6
  15. rasa/cli/project_templates/telco/tests/e2e_test_cases/billing/understand_bill.yml +67 -0
  16. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
  17. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +46 -0
  18. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/goodbye.yml +9 -0
  19. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +8 -0
  20. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +35 -0
  21. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +23 -0
  22. rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +57 -0
  23. rasa/core/channels/development_inspector.py +1 -21
  24. rasa/core/channels/hangouts.py +2 -2
  25. rasa/core/channels/inspector/dist/assets/{arc-c24d8d79.js → arc-460861ce.js} +1 -1
  26. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-1b6b9f26.js → blockDiagram-38ab4fdb-16c993e0.js} +1 -1
  27. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-da91d0f9.js → c4Diagram-3d4e48cf-488337d7.js} +1 -1
  28. rasa/core/channels/inspector/dist/assets/channel-b560a3d4.js +1 -0
  29. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-6067f302.js → classDiagram-70f12bd4-b08e53a8.js} +1 -1
  30. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-705d024a.js → classDiagram-v2-f2320105-b73f5a83.js} +1 -1
  31. rasa/core/channels/inspector/dist/assets/clone-67015557.js +1 -0
  32. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-3751dffe.js → createText-2e5e7dd3-0210a219.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-7b25b4af.js → edges-e0da2a9e-28df7099.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-eb7deea8.js → erDiagram-9861fffd-9fbf4a58.js} +1 -1
  35. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-67235ff6.js → flowDb-956e92f1-fa691f62.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-34c3a16a.js → flowDiagram-66a62f08-ca907b67.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-4a070961.js +1 -0
  38. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-f1a93631.js → flowchart-elk-definition-4a651766-c10945f2.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-a68cbad1.js → ganttDiagram-c361ad54-9d49a75a.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-0b1e4a1d.js → gitGraphDiagram-72cf32ee-9aa698ac.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{graph-f3c1d212.js → graph-3ab38d50.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/{index-3862675e-34cbca30.js → index-3862675e-6edac98f.js} +1 -1
  43. rasa/core/channels/inspector/dist/assets/{index-051c5a6e.js → index-61128091.js} +41 -40
  44. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-e69960a1.js → infoDiagram-f8f76790-21baff85.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-8dd3296a.js → journeyDiagram-49397b02-4a6c7e98.js} +1 -1
  46. rasa/core/channels/inspector/dist/assets/{layout-e93126bc.js → layout-4beae36e.js} +1 -1
  47. rasa/core/channels/inspector/dist/assets/{line-15eb1e26.js → line-633b638e.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/{linear-fec95d33.js → linear-22d77d65.js} +1 -1
  49. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-2557813e.js → mindmap-definition-fc14e90a-f219ef43.js} +1 -1
  50. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-40d756b1.js → pieDiagram-8a3498a8-c7e1cafb.js} +1 -1
  51. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-a48cbdcd.js → quadrantDiagram-120e2f19-045e49b4.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dc778150.js → requirementDiagram-deff3bca-22485cb9.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-10026b94.js → sankeyDiagram-04a897e0-281c3da2.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3b2ed10a.js → sequenceDiagram-704730f1-a3dd10e0.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-c5f3b3fb.js → stateDiagram-587899a1-61bd6eb2.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e503656b.js → stateDiagram-v2-d93cdb3a-deead491.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-a683ce56.js → styles-6aaf32cf-1b10e104.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-02bcdcee.js → styles-9a916d00-b1e18e58.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-8e90dbb9.js → styles-c10674c1-956c3492.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-7c23fc1e.js → svgDrawCommon-08f97a94-e13f753d.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-c42faec8.js → timeline-definition-85554ec2-e568acd2.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5e3bb0ea.js → xychartDiagram-e933f94c-8b7e27fc.js} +1 -1
  63. rasa/core/channels/inspector/dist/index.html +1 -1
  64. rasa/core/channels/inspector/src/App.tsx +0 -7
  65. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +9 -1
  66. rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +63 -35
  67. rasa/core/channels/inspector/src/types.ts +32 -7
  68. rasa/core/channels/studio_chat.py +14 -40
  69. rasa/core/constants.py +6 -0
  70. rasa/core/iam_credentials_providers/__init__.py +0 -0
  71. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +66 -0
  72. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +89 -0
  73. rasa/core/processor.py +32 -0
  74. rasa/core/redis_connection_factory.py +411 -0
  75. rasa/core/tracker_stores/redis_tracker_store.py +32 -14
  76. rasa/core/tracker_stores/sql_tracker_store.py +57 -1
  77. rasa/model_manager/socket_bridge.py +1 -2
  78. rasa/shared/core/constants.py +1 -0
  79. rasa/shared/core/events.py +2 -0
  80. rasa/version.py +1 -1
  81. {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/METADATA +11 -12
  82. {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/RECORD +90 -77
  83. rasa/core/channels/inspector/dist/assets/channel-d2444dfd.js +0 -1
  84. rasa/core/channels/inspector/dist/assets/clone-281a0990.js +0 -1
  85. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-aa4cca3b.js +0 -1
  86. /rasa/cli/project_templates/telco/domain/billing/{domain_undertand_bill.yml → understand_bill.yml} +0 -0
  87. /rasa/cli/project_templates/telco/domain/network/{domain_reboot_router.yml → reboot_router.yml} +0 -0
  88. /rasa/cli/project_templates/telco/domain/network/{domain_reset_router.yml → reset_router.yml} +0 -0
  89. /rasa/cli/project_templates/telco/domain/network/{domain_run_speed_test.yml → run_speed_test.yml} +0 -0
  90. /rasa/cli/project_templates/telco/domain/network/{domain_solve_internet_issue.yml → solve_internet_issue.yml} +0 -0
  91. {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/NOTICE +0 -0
  92. {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/WHEEL +0 -0
  93. {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/entry_points.txt +0 -0
rasa/builder/service.py CHANGED
@@ -1122,11 +1122,9 @@ async def copilot(request: Request) -> None:
1122
1122
  # copilot response handler
1123
1123
  start_timestamp = time.perf_counter()
1124
1124
  copilot_client = llm_service.instantiate_copilot()
1125
- (
1126
- original_stream,
1127
- used_documents,
1128
- system_prompt,
1129
- ) = await copilot_client.generate_response(context)
1125
+ (original_stream, generation_context) = await copilot_client.generate_response(
1126
+ context
1127
+ )
1130
1128
 
1131
1129
  copilot_response_handler = llm_service.instantiate_handler(
1132
1130
  COPILOT_HANDLER_ROLLING_BUFFER_SIZE
@@ -1142,18 +1140,19 @@ async def copilot(request: Request) -> None:
1142
1140
  asyncio.to_thread(
1143
1141
  telemetry.log_copilot_from_handler,
1144
1142
  handler=copilot_response_handler,
1145
- used_documents=used_documents,
1143
+ used_documents=generation_context.relevant_documents,
1146
1144
  latency_ms=int((time.perf_counter() - start_timestamp) * 1000),
1147
- system_prompt=system_prompt,
1145
+ system_message=generation_context.system_message,
1146
+ chat_history=generation_context.chat_history,
1148
1147
  **copilot_client.usage_statistics.model_dump(),
1149
1148
  )
1150
1149
  )
1151
1150
 
1152
1151
  # 9. Once the stream is over, extract and send references
1153
1152
  # if any documents were used
1154
- if used_documents:
1153
+ if generation_context.relevant_documents:
1155
1154
  reference_section = copilot_response_handler.extract_references(
1156
- used_documents
1155
+ generation_context.relevant_documents
1157
1156
  )
1158
1157
  await sse.send(reference_section.to_sse_event().format())
1159
1158
 
@@ -1,11 +1,18 @@
1
+ import asyncio
1
2
  import os
3
+ import shutil
4
+ import tarfile
5
+ import tempfile
2
6
  from pathlib import Path
7
+ from typing import Generator
3
8
 
4
9
  import aiofiles
5
- import aiofiles.os
6
- import aioshutil
10
+ import aiohttp
7
11
  import structlog
12
+ from sanic import Sanic
8
13
 
14
+ import rasa.version
15
+ from rasa.builder.logging_utils import capture_exception_with_context
9
16
  from rasa.cli.scaffold import ProjectTemplateName
10
17
 
11
18
  structlogger = structlog.get_logger()
@@ -13,15 +20,64 @@ structlogger = structlog.get_logger()
13
20
  CACHE_BUCKET_URL = "https://trained-templates.s3.us-east-1.amazonaws.com"
14
21
 
15
22
  # Root directory for storing downloaded template caches on disk.
16
- _CACHE_ROOT_DIR = Path(os.getenv("RASA_TEMPLATE_CACHE_DIR", "/templates"))
23
+ _CACHE_ROOT_DIR = Path(
24
+ os.getenv(
25
+ "RASA_TEMPLATE_CACHE_DIR",
26
+ Path.home().joinpath(".rasa", "template-cache").as_posix(),
27
+ )
28
+ )
17
29
 
18
30
 
19
31
  def _template_cache_dir(template: ProjectTemplateName) -> Path:
20
32
  """Return the local cache directory for a given template and version."""
21
- return _CACHE_ROOT_DIR / template.value
33
+ return _CACHE_ROOT_DIR / rasa.version.__version__ / template.value
22
34
 
23
35
 
24
- async def _copytree(src: Path, dst: Path) -> None:
36
+ def _cache_root_dir() -> Path:
37
+ return Path(
38
+ os.getenv(
39
+ "RASA_TEMPLATE_CACHE_DIR",
40
+ Path.home().joinpath(".rasa", "template-cache").as_posix(),
41
+ )
42
+ )
43
+
44
+
45
+ def _safe_tar_members(
46
+ tar: tarfile.TarFile, destination_directory: Path
47
+ ) -> Generator[tarfile.TarInfo, None, None]:
48
+ """Yield safe members for extraction to prevent path traversal and links.
49
+
50
+ Args:
51
+ tar: Open tar file handle
52
+ destination_directory: Directory to which files will be extracted
53
+
54
+ Yields:
55
+ Members that are safe to extract within destination_directory
56
+ """
57
+ base_path = destination_directory.resolve()
58
+
59
+ for member in tar.getmembers():
60
+ name = member.name
61
+ # Skip empty names and absolute paths
62
+ if not name or name.startswith("/") or name.startswith("\\"):
63
+ continue
64
+
65
+ # Disallow symlinks and hardlinks
66
+ if member.issym() or member.islnk():
67
+ continue
68
+
69
+ # Compute the final path and ensure it's within base_path
70
+ target_path = (base_path / name).resolve()
71
+ try:
72
+ target_path.relative_to(base_path)
73
+ except ValueError:
74
+ # Member would escape the destination directory
75
+ continue
76
+
77
+ yield member
78
+
79
+
80
+ def _copytree(src: Path, dst: Path) -> None:
25
81
  """Copy directory tree from src to dst, merging into dst.
26
82
 
27
83
  Existing files are overwritten. Hidden files and directories are included, as
@@ -31,14 +87,132 @@ async def _copytree(src: Path, dst: Path) -> None:
31
87
  for root, dirs, files in os.walk(src):
32
88
  rel_path = Path(root).relative_to(src)
33
89
  target_dir = dst / rel_path
34
- await aiofiles.os.makedirs(target_dir, exist_ok=True)
90
+ target_dir.mkdir(parents=True, exist_ok=True)
35
91
  for filename in files:
36
92
  src_file = Path(root) / filename
37
93
  dst_file = target_dir / filename
38
- await aioshutil.copy2(src_file, dst_file)
94
+ shutil.copy2(src_file, dst_file)
95
+
96
+
97
+ async def download_cache_for_template(
98
+ template: ProjectTemplateName, target_dir: str
99
+ ) -> None:
100
+ # get a temp path for the cache file download
101
+ temporary_cache_file = tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False)
102
+
103
+ try:
104
+ url = f"{CACHE_BUCKET_URL}/{rasa.version.__version__}-{template.value}.tar.gz"
105
+ async with aiohttp.ClientSession() as session:
106
+ async with session.get(url) as response:
107
+ response.raise_for_status()
108
+ async with aiofiles.open(temporary_cache_file.name, "wb") as f:
109
+ async for chunk in response.content.iter_chunked(1024 * 1024):
110
+ await f.write(chunk)
111
+
112
+ # extract the cache to the project folder using safe member filtering
113
+ with tarfile.open(temporary_cache_file.name, "r:gz") as tar:
114
+ destination = Path(target_dir)
115
+ destination.mkdir(parents=True, exist_ok=True)
116
+ tar.extractall(
117
+ path=destination,
118
+ members=_safe_tar_members(tar, destination),
119
+ )
120
+
121
+ structlogger.info(
122
+ "project_generator.download_cache_for_template.success",
123
+ template=template,
124
+ event_info=(
125
+ "Downloaded cache for template, extracted to target directory."
126
+ ),
127
+ target_dir=target_dir,
128
+ )
129
+ except aiohttp.ClientResponseError as e:
130
+ if e.status == 403:
131
+ structlogger.debug(
132
+ "project_generator.download_cache_for_template.no_cache_found",
133
+ template=template,
134
+ event_info=("No cache found for template, continuing without it."),
135
+ target_dir=target_dir,
136
+ )
137
+ else:
138
+ capture_exception_with_context(
139
+ e,
140
+ "project_generator.download_cache_for_template.response_error",
141
+ extra={
142
+ "template": template.value,
143
+ "status": str(e.status),
144
+ "target_dir": target_dir,
145
+ },
146
+ )
147
+ except Exception as exc:
148
+ capture_exception_with_context(
149
+ exc,
150
+ "project_generator.download_cache_for_template.unexpected_error",
151
+ extra={"template": template.value, "target_dir": target_dir},
152
+ )
153
+ finally:
154
+ # Clean up the temporary file
155
+ try:
156
+ Path(temporary_cache_file.name).unlink(missing_ok=True)
157
+ except Exception as exc:
158
+ structlogger.debug(
159
+ "project_generator.download_cache_for_template.cleanup_error",
160
+ error=str(exc),
161
+ template=template,
162
+ event_info=("Failed to cleanup cache for template, ignoring."),
163
+ )
164
+
165
+
166
+ async def background_download_template_caches(
167
+ app: Sanic, loop: asyncio.AbstractEventLoop
168
+ ) -> None:
169
+ """Kick off background downloads of template caches if enabled."""
170
+ try:
171
+ structlogger.info(
172
+ "builder.main.background_cache_download.start",
173
+ event_info=(
174
+ "Starting background download of template caches for this " "version"
175
+ ),
176
+ )
177
+
178
+ # Ensure cache root exists
179
+ _cache_root_dir().mkdir(parents=True, exist_ok=True)
180
+
181
+ async def _download(template: ProjectTemplateName) -> None:
182
+ try:
183
+ target_dir = _template_cache_dir(template)
184
+ if target_dir.exists() and any(target_dir.iterdir()):
185
+ structlogger.debug(
186
+ "builder.main.background_cache_download.skipped",
187
+ template=template,
188
+ event_info=(
189
+ "Skipping download of template cache because it "
190
+ "already exists."
191
+ ),
192
+ target_dir=target_dir,
193
+ )
194
+ return
195
+
196
+ target_dir.mkdir(parents=True, exist_ok=True)
197
+ await download_cache_for_template(template, target_dir.as_posix())
198
+ except Exception as exc:
199
+ structlogger.debug(
200
+ "builder.main.background_cache_download.error",
201
+ template=template,
202
+ error=str(exc),
203
+ )
204
+
205
+ # schedule downloads concurrently without blocking startup
206
+ for template in ProjectTemplateName:
207
+ loop.create_task(_download(template))
208
+ except Exception as exc:
209
+ structlogger.debug(
210
+ "builder.main.background_cache_download.unexpected_error",
211
+ error=str(exc),
212
+ )
39
213
 
40
214
 
41
- async def copy_cache_for_template_if_available(
215
+ def copy_cache_for_template_if_available(
42
216
  template: ProjectTemplateName, project_folder: Path
43
217
  ) -> None:
44
218
  """Copy a previously downloaded cache for `template` into `project_folder`.
@@ -48,7 +222,7 @@ async def copy_cache_for_template_if_available(
48
222
  try:
49
223
  cache_dir = _template_cache_dir(template)
50
224
  if cache_dir.exists() and any(cache_dir.iterdir()):
51
- await _copytree(cache_dir, project_folder)
225
+ _copytree(cache_dir, project_folder)
52
226
  structlogger.info(
53
227
  "project_generator.copy_cache_for_template.success",
54
228
  template=template,
@@ -6,7 +6,7 @@ flows:
6
6
  - collect: confirm_human_handoff
7
7
  ask_before_filling: True
8
8
  next:
9
- - if: slots.confirm_human_handoff is "Yes"
9
+ - if: slots.confirm_human_handoff
10
10
  then:
11
11
  - action: utter_transferring_to_human
12
12
  - action: action_human_handoff
@@ -4,20 +4,17 @@ actions:
4
4
 
5
5
  slots:
6
6
  confirm_human_handoff:
7
- type: "categorical"
7
+ type: bool
8
8
  mappings:
9
9
  - type: "from_llm"
10
- values:
11
- - "Yes"
12
- - "No"
13
10
 
14
11
  responses:
15
12
  utter_ask_confirm_human_handoff:
16
13
  - text: "Do you want to be connected to a human agent?"
17
14
  buttons:
18
- - payload: "/SetSlots(confirm_human_handoff=Yes)"
15
+ - payload: "/SetSlots(confirm_human_handoff=True)"
19
16
  title: "Yes"
20
- - payload: "/SetSlots(confirm_human_handoff=No)"
17
+ - payload: "/SetSlots(confirm_human_handoff=False)"
21
18
  title: "No"
22
19
 
23
20
  utter_transferring_to_human:
@@ -0,0 +1,67 @@
1
+ fixtures:
2
+ - customer_information: # name of the fixture must be provided and be unique
3
+ - customer_id: "123" # every fixture can contain multiple slot key-value pairs
4
+
5
+ test_cases:
6
+ - test_case: billing happy path
7
+ fixtures:
8
+ - customer_information
9
+ steps:
10
+ - user: "I would like to check my bill"
11
+ assertions:
12
+ - flow_started: "understand_bill"
13
+ - bot_uttered:
14
+ utter_name: utter_ask_bill_month
15
+ - user: "April"
16
+ assertions:
17
+ - slot_was_set:
18
+ - name: "bill_month"
19
+ value: "April"
20
+ - action_executed: action_verify_bill_by_date
21
+ - bot_uttered:
22
+ utter_name: utter_ask_breakdown_cost
23
+ text_matches: Would you like to see the breakdown of the costs?
24
+ buttons:
25
+ - title: "Yes, please"
26
+ payload: "/SetSlots(breakdown_cost=True)"
27
+ - title: "No, all good"
28
+ payload: "/SetSlots(breakdown_cost=False)"
29
+ - user: "/SetSlots(breakdown_cost=True)"
30
+ assertions:
31
+ - action_executed: action_recap_bill
32
+ - bot_uttered:
33
+ utter_name: utter_ask_more_bill_details
34
+ - user: "/SetSlots(more_bill_details=True)"
35
+ assertions:
36
+ - bot_uttered:
37
+ utter_name: utter_provide_bill_sources
38
+ # ====================================================>
39
+ - test_case: billing unhappy path
40
+ steps:
41
+ - user: "I would like to check my bill"
42
+ assertions:
43
+ - flow_started: "understand_bill"
44
+ - bot_uttered:
45
+ utter_name: utter_ask_bill_month
46
+ - user: "February"
47
+ assertions:
48
+ - slot_was_set:
49
+ - name: "bill_month"
50
+ value: "February"
51
+ - action_executed: action_verify_bill_by_date
52
+ - bot_uttered:
53
+ utter_name: utter_ask_breakdown_cost
54
+ text_matches: Would you like to see the breakdown of the costs?
55
+ buttons:
56
+ - title: "Yes, please"
57
+ payload: "/SetSlots(breakdown_cost=True)"
58
+ - title: "No, all good"
59
+ payload: "/SetSlots(breakdown_cost=False)"
60
+ - user: "/SetSlots(breakdown_cost=False)"
61
+ assertions:
62
+ - bot_uttered:
63
+ utter_name: utter_ask_issue_solved
64
+ - user: "/SetSlots(issue_solved=True)"
65
+ assertions:
66
+ - bot_uttered:
67
+ utter_name: utter_end_conversation
@@ -0,0 +1,8 @@
1
+ test_cases:
2
+ - test_case: bot challenge
3
+ steps:
4
+ - user: "are you a bot?"
5
+ assertions:
6
+ - flow_started: "bot_challenge"
7
+ - bot_uttered:
8
+ utter_name: "utter_bot_challenge"
@@ -0,0 +1,46 @@
1
+ test_cases:
2
+ - test_case: positive feedback
3
+ steps:
4
+ - user: "goodbye"
5
+ assertions:
6
+ - flow_started: "goodbye"
7
+ - bot_uttered:
8
+ utter_name: "utter_goodbye"
9
+ - flow_started: "leave_feedback"
10
+ - bot_uttered:
11
+ utter_name: "utter_ask_feedback_rating"
12
+ buttons:
13
+ - title: "👍 Great"
14
+ payload: "/SetSlots(feedback_rating=thumbs_up)"
15
+ - title: "👎 Could be better"
16
+ payload: "/SetSlots(feedback_rating=thumbs_down)"
17
+ - user: "/SetSlots(feedback_rating=thumbs_up)"
18
+ assertions:
19
+ - slot_was_set:
20
+ - name: "feedback_rating"
21
+ value: "thumbs_up"
22
+ - bot_uttered:
23
+ utter_name: "utter_thankyou_positive"
24
+ #
25
+ - test_case: negative feedback
26
+ steps:
27
+ - user: "goodbye"
28
+ assertions:
29
+ - flow_started: "goodbye"
30
+ - bot_uttered:
31
+ utter_name: "utter_goodbye"
32
+ - flow_started: "leave_feedback"
33
+ - bot_uttered:
34
+ utter_name: "utter_ask_feedback_rating"
35
+ buttons:
36
+ - title: "👍 Great"
37
+ payload: "/SetSlots(feedback_rating=thumbs_up)"
38
+ - title: "👎 Could be better"
39
+ payload: "/SetSlots(feedback_rating=thumbs_down)"
40
+ - user: "/SetSlots(feedback_rating=thumbs_down)"
41
+ assertions:
42
+ - slot_was_set:
43
+ - name: "feedback_rating"
44
+ value: "thumbs_down"
45
+ - bot_uttered:
46
+ utter_name: "utter_thankyou_negative"
@@ -0,0 +1,9 @@
1
+ test_cases:
2
+ - test_case: goodbye
3
+ steps:
4
+ - user: "goodbye"
5
+ assertions:
6
+ - flow_started: "goodbye"
7
+ - bot_uttered:
8
+ utter_name: "utter_goodbye"
9
+ - flow_started: "leave_feedback"
@@ -0,0 +1,8 @@
1
+ test_cases:
2
+ - test_case: hello
3
+ steps:
4
+ - user: "hello"
5
+ assertions:
6
+ - flow_started: "hello"
7
+ - bot_uttered:
8
+ utter_name: "utter_hello"
@@ -0,0 +1,35 @@
1
+ test_cases:
2
+ - test_case: human handoff happy path
3
+ steps:
4
+ - user: "I would like to speak with a human"
5
+ assertions:
6
+ - flow_started: "human_handoff"
7
+ - bot_uttered:
8
+ utter_name: "utter_ask_confirm_human_handoff"
9
+ buttons:
10
+ - payload: "/SetSlots(confirm_human_handoff=True)"
11
+ title: "Yes"
12
+ - payload: "/SetSlots(confirm_human_handoff=False)"
13
+ title: "No"
14
+ - user: "Yes"
15
+ assertions:
16
+ - bot_uttered:
17
+ utter_name: "utter_transferring_to_human"
18
+ - action_executed: action_human_handoff
19
+ # ====================================================>
20
+ - test_case: human handoff unhappy path
21
+ steps:
22
+ - user: "I would like to speak with a human"
23
+ assertions:
24
+ - flow_started: "human_handoff"
25
+ - bot_uttered:
26
+ utter_name: "utter_ask_confirm_human_handoff"
27
+ buttons:
28
+ - payload: "/SetSlots(confirm_human_handoff=True)"
29
+ title: "Yes"
30
+ - payload: "/SetSlots(confirm_human_handoff=False)"
31
+ title: "No"
32
+ - user: "No"
33
+ assertions:
34
+ - bot_uttered:
35
+ utter_name: "utter_human_handoff_cancelled"
@@ -0,0 +1,23 @@
1
+ test_cases:
2
+ - test_case: test pattern search
3
+ steps:
4
+ - user: "how do you run a network speed test?"
5
+ assertions:
6
+ - generative_response_is_grounded:
7
+ threshold: 0.90
8
+ ground_truth: "You can run a network speed test using special software such as \"Fast.com\", \"Speedtest.net\", or Google's \"Internet speed test\". Alternatively, if you have our app, you can go to the Home menu, select WLAN speed test and run it. These tests measure your internet connection's performance by evaluating download and upload speeds, ping, and jitter."
9
+ - user: "what is the difference between restart and reset a router"
10
+ assertions:
11
+ - flow_completed:
12
+ flow_id: "pattern_search"
13
+ - generative_response_is_grounded:
14
+ threshold: 0.90
15
+ ground_truth: "Restarting or rebooting a router involves turning it off and back on without changing any settings, which can help resolve temporary issues like slow speeds or dropped connections. Resetting a router, however, restores it to factory settings, erasing all custom configurations such as the Wi-Fi name, password, and advanced settings. Resetting should only be done as a last resort when troubleshooting persistent problems."
16
+ #
17
+ - test_case: test pattern session start
18
+ steps:
19
+ - user: "/session_start"
20
+ assertions:
21
+ - flow_started: "pattern_session_start"
22
+ - bot_uttered:
23
+ utter_name: "utter_greeting"
@@ -0,0 +1,57 @@
1
+ test_cases:
2
+ # one of these test cases will fail since the speed test will be randomly selected
3
+ - test_case: Solving Internet slow issue
4
+ steps:
5
+ - user: "Hey, my internet is very slow. What's going on?"
6
+ assertions:
7
+ - flow_started: "fix_internet_slow"
8
+ - bot_uttered:
9
+ utter_name: "utter_acknowledge_issue"
10
+ - action_executed: action_sleep_few_sec
11
+ - flow_started: "run_diagnostics"
12
+ - bot_uttered:
13
+ utter_name: "utter_communicate_run_diagnosticss"
14
+ - action_executed: "actions_run_speed_test"
15
+ - bot_uttered:
16
+ utter_name: "utter_acknowledge_speed_test_not_good"
17
+ - action_executed: "action_sleep_few_sec"
18
+ - bot_uttered:
19
+ utter_name: "utter_propose_reboot_router_solution"
20
+ - action_executed: "action_sleep_few_sec"
21
+ - flow_started: "reboot_router"
22
+ - bot_uttered:
23
+ utter_name: "utter_explain_reboot_router"
24
+ - bot_uttered:
25
+ utter_name: "utter_ask_reboot_router"
26
+ buttons:
27
+ - title: "Done"
28
+ payload: "/SetSlots(reboot_router=True)"
29
+ - title: "Facing a problem"
30
+ payload: "/SetSlots(reboot_router=False)"
31
+ - user: "/SetSlots(reboot_router=False)"
32
+ assertions:
33
+ - slot_was_set:
34
+ - name: "reboot_router"
35
+ value: False
36
+ - flow_started: "human_handoff"
37
+ #
38
+ - test_case: Solving Internet issue not slow
39
+ steps:
40
+ - user: "Hey, my internet is very slow. What's going on?"
41
+ assertions:
42
+ - flow_started: "fix_internet_slow"
43
+ - bot_uttered:
44
+ utter_name: "utter_acknowledge_issue"
45
+ - action_executed: action_sleep_few_sec
46
+ - flow_started: "run_diagnostics"
47
+ - bot_uttered:
48
+ utter_name: "utter_speed_network_not_issue"
49
+ - action_executed: "actions_run_speed_test"
50
+ - bot_uttered:
51
+ utter_name: "utter_propose_other_solutions"
52
+ - action_executed: "action_sleep_few_sec"
53
+ - bot_uttered:
54
+ utter_name: "utter_ask_more_help_needed"
55
+ - user: "/SetSlots(more_help_needed=True)"
56
+ assertions:
57
+ - flow_started: "human_handoff"
@@ -145,15 +145,10 @@ class DevelopmentInspectProxy(InputChannel):
145
145
  state = tracker.current_state(EventVerbosity.AFTER_RESTART)
146
146
  return orjson.dumps(state, option=orjson.OPT_SERIALIZE_NUMPY).decode("utf-8")
147
147
 
148
- async def on_tracker_updated(
149
- self, tracker: DialogueStateTracker, latency: Optional[float] = None
150
- ) -> None:
148
+ async def on_tracker_updated(self, tracker: DialogueStateTracker) -> None:
151
149
  """Notifies all clients about tracker updates in real-time."""
152
150
  if self.tracker_stream and tracker.sender_id:
153
151
  state = tracker.current_state(EventVerbosity.AFTER_RESTART)
154
- if latency is not None:
155
- state["latency"] = {"rasa_processing_latency_ms": latency}
156
-
157
152
  tracker_dump = orjson.dumps(
158
153
  state, option=orjson.OPT_SERIALIZE_NUMPY
159
154
  ).decode("utf-8")
@@ -163,28 +158,13 @@ class DevelopmentInspectProxy(InputChannel):
163
158
  """Records the start time of a new turn."""
164
159
  self._turn_start_times[sender_id] = time.time()
165
160
 
166
- async def _broadcast_latency(self, sender_id: Text) -> None:
167
- """Broadcasts the tracker with latency of the current turn to all clients."""
168
- if sender_id not in self._turn_start_times:
169
- return None
170
-
171
- latency = (time.time() - self._turn_start_times[sender_id]) * 1000
172
- # The turn is over, so we can remove the start time
173
- del self._turn_start_times[sender_id]
174
-
175
- # broadcast tracker update with latency
176
- tracker = await self._get_tracker(sender_id)
177
- await self.on_tracker_updated(tracker, latency)
178
-
179
161
  async def on_message_proxy(
180
162
  self,
181
163
  on_new_message: Callable[["UserMessage"], Awaitable[Any]],
182
164
  message: "UserMessage",
183
165
  ) -> None:
184
166
  """Proxies the on_new_message call to the underlying channel."""
185
- self._record_turn_start_time(message.sender_id)
186
167
  await on_new_message(message)
187
- await self._broadcast_latency(message.sender_id)
188
168
 
189
169
  @classmethod
190
170
  async def serve_inspect_html(cls) -> HTTPResponse:
@@ -213,7 +213,7 @@ class HangoutsInput(InputChannel):
213
213
  # every message. Actual caching depends on response headers.
214
214
  # see: https://github.com/googleapis/google-auth-library-python/blob/main/google/oauth2/id_token.py#L15 # noqa: E501
215
215
  cached_session = cachecontrol.CacheControl(requests.session())
216
- self.google_request = google.auth.transport.requests.Request(
216
+ self.google_request = google.auth.transport.requests.Request( # type: ignore[no-untyped-call]
217
217
  session=cached_session
218
218
  )
219
219
 
@@ -267,7 +267,7 @@ class HangoutsInput(InputChannel):
267
267
  # see https://developers.google.com/chat/how-tos/bots-develop#verifying_bot_authenticity # noqa: E501
268
268
  # and https://google-auth.readthedocs.io/en/latest/user-guide.html#identity-tokens # noqa: E501
269
269
  try:
270
- decoded_token = id_token.verify_token(
270
+ decoded_token = id_token.verify_token( # type: ignore[no-untyped-call]
271
271
  bot_token,
272
272
  self.google_request,
273
273
  audience=self.project_id,
@@ -1 +1 @@
1
- import{w as ln,c as H}from"./path-53f90ab3.js";import{aw as an,ax as V,ay as D,az as rn,aA as y,V as on,aB as K,aC as _,aD as un,aE as t,aF as sn,aG as tn,aH as fn}from"./index-051c5a6e.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function mn(l){return l.endAngle}function pn(l){return l&&l.padAngle}function xn(l,h,z,E,v,A,I,a){var B=z-l,i=E-h,n=I-v,m=a-A,r=m*B-n*i;if(!(r*r<y))return r=(n*(h-A)-m*(l-v))/r,[l+r*B,h+r*i]}function W(l,h,z,E,v,A,I){var a=l-z,B=h-E,i=(I?A:-A)/K(a*a+B*B),n=i*B,m=-i*a,r=l+n,s=h+m,f=z+n,c=E+m,O=(r+f)/2,o=(s+c)/2,p=f-r,g=c-s,R=p*p+g*g,T=v-A,w=r*c-f*s,C=(g<0?-1:1)*K(fn(0,T*T*R-w*w)),F=(w*g-p*C)/R,G=(-w*p-g*C)/R,P=(w*g+p*C)/R,x=(-w*p+g*C)/R,d=F-O,e=G-o,u=P-O,S=x-o;return d*d+e*e>u*u+S*S&&(F=P,G=x),{cx:F,cy:G,x01:-n,y01:-m,x11:F*(v/T-1),y11:G*(v/T-1)}}function vn(){var l=cn,h=yn,z=H(0),E=null,v=gn,A=mn,I=pn,a=null,B=ln(i);function i(){var n,m,r=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-rn,c=A.apply(this,arguments)-rn,O=un(c-f),o=c>f;if(a||(a=n=B()),s<r&&(m=s,s=r,r=m),!(s>y))a.moveTo(0,0);else if(O>on-y)a.moveTo(s*V(f),s*D(f)),a.arc(0,0,s,f,c,!o),r>y&&(a.moveTo(r*V(c),r*D(c)),a.arc(0,0,r,c,f,o));else{var p=f,g=c,R=f,T=c,w=O,C=O,F=I.apply(this,arguments)/2,G=F>y&&(E?+E.apply(this,arguments):K(r*r+s*s)),P=_(un(s-r)/2,+z.apply(this,arguments)),x=P,d=P,e,u;if(G>y){var S=sn(G/r*D(F)),L=sn(G/s*D(F));(w-=S*2)>y?(S*=o?1:-1,R+=S,T-=S):(w=0,R=T=(f+c)/2),(C-=L*2)>y?(L*=o?1:-1,p+=L,g-=L):(C=0,p=g=(f+c)/2)}var j=s*V(p),J=s*D(p),M=r*V(T),N=r*D(T);if(P>y){var Q=s*V(g),U=s*D(g),X=r*V(R),Y=r*D(R),q;if(O<an)if(q=xn(j,J,X,Y,Q,U,M,N)){var Z=j-q[0],$=J-q[1],k=Q-q[0],b=U-q[1],nn=1/D(tn((Z*k+$*b)/(K(Z*Z+$*$)*K(k*k+b*b)))/2),en=K(q[0]*q[0]+q[1]*q[1]);x=_(P,(r-en)/(nn-1)),d=_(P,(s-en)/(nn+1))}else x=d=0}C>y?d>y?(e=W(X,Y,j,J,s,d,o),u=W(Q,U,M,N,s,d,o),a.moveTo(e.cx+e.x01,e.cy+e.y01),d<P?a.arc(e.cx,e.cy,d,t(e.y01,e.x01),t(u.y01,u.x01),!o):(a.arc(e.cx,e.cy,d,t(e.y01,e.x01),t(e.y11,e.x11),!o),a.arc(0,0,s,t(e.cy+e.y11,e.cx+e.x11),t(u.cy+u.y11,u.cx+u.x11),!o),a.arc(u.cx,u.cy,d,t(u.y11,u.x11),t(u.y01,u.x01),!o))):(a.moveTo(j,J),a.arc(0,0,s,p,g,!o)):a.moveTo(j,J),!(r>y)||!(w>y)?a.lineTo(M,N):x>y?(e=W(M,N,Q,U,r,-x,o),u=W(j,J,X,Y,r,-x,o),a.lineTo(e.cx+e.x01,e.cy+e.y01),x<P?a.arc(e.cx,e.cy,x,t(e.y01,e.x01),t(u.y01,u.x01),!o):(a.arc(e.cx,e.cy,x,t(e.y01,e.x01),t(e.y11,e.x11),!o),a.arc(0,0,r,t(e.cy+e.y11,e.cx+e.x11),t(u.cy+u.y11,u.cx+u.x11),o),a.arc(u.cx,u.cy,x,t(u.y11,u.x11),t(u.y01,u.x01),!o))):a.arc(0,0,r,T,R,o)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,m=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[V(m)*n,D(m)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:H(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:H(+n),i):h},i.cornerRadius=function(n){return arguments.length?(z=typeof n=="function"?n:H(+n),i):z},i.padRadius=function(n){return arguments.length?(E=n==null?null:typeof n=="function"?n:H(+n),i):E},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:H(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:H(+n),i):A},i.padAngle=function(n){return arguments.length?(I=typeof n=="function"?n:H(+n),i):I},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{vn as a};
1
+ import{w as ln,c as H}from"./path-53f90ab3.js";import{aw as an,ax as V,ay as D,az as rn,aA as y,V as on,aB as K,aC as _,aD as un,aE as t,aF as sn,aG as tn,aH as fn}from"./index-61128091.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function mn(l){return l.endAngle}function pn(l){return l&&l.padAngle}function xn(l,h,z,E,v,A,I,a){var B=z-l,i=E-h,n=I-v,m=a-A,r=m*B-n*i;if(!(r*r<y))return r=(n*(h-A)-m*(l-v))/r,[l+r*B,h+r*i]}function W(l,h,z,E,v,A,I){var a=l-z,B=h-E,i=(I?A:-A)/K(a*a+B*B),n=i*B,m=-i*a,r=l+n,s=h+m,f=z+n,c=E+m,O=(r+f)/2,o=(s+c)/2,p=f-r,g=c-s,R=p*p+g*g,T=v-A,w=r*c-f*s,C=(g<0?-1:1)*K(fn(0,T*T*R-w*w)),F=(w*g-p*C)/R,G=(-w*p-g*C)/R,P=(w*g+p*C)/R,x=(-w*p+g*C)/R,d=F-O,e=G-o,u=P-O,S=x-o;return d*d+e*e>u*u+S*S&&(F=P,G=x),{cx:F,cy:G,x01:-n,y01:-m,x11:F*(v/T-1),y11:G*(v/T-1)}}function vn(){var l=cn,h=yn,z=H(0),E=null,v=gn,A=mn,I=pn,a=null,B=ln(i);function i(){var n,m,r=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-rn,c=A.apply(this,arguments)-rn,O=un(c-f),o=c>f;if(a||(a=n=B()),s<r&&(m=s,s=r,r=m),!(s>y))a.moveTo(0,0);else if(O>on-y)a.moveTo(s*V(f),s*D(f)),a.arc(0,0,s,f,c,!o),r>y&&(a.moveTo(r*V(c),r*D(c)),a.arc(0,0,r,c,f,o));else{var p=f,g=c,R=f,T=c,w=O,C=O,F=I.apply(this,arguments)/2,G=F>y&&(E?+E.apply(this,arguments):K(r*r+s*s)),P=_(un(s-r)/2,+z.apply(this,arguments)),x=P,d=P,e,u;if(G>y){var S=sn(G/r*D(F)),L=sn(G/s*D(F));(w-=S*2)>y?(S*=o?1:-1,R+=S,T-=S):(w=0,R=T=(f+c)/2),(C-=L*2)>y?(L*=o?1:-1,p+=L,g-=L):(C=0,p=g=(f+c)/2)}var j=s*V(p),J=s*D(p),M=r*V(T),N=r*D(T);if(P>y){var Q=s*V(g),U=s*D(g),X=r*V(R),Y=r*D(R),q;if(O<an)if(q=xn(j,J,X,Y,Q,U,M,N)){var Z=j-q[0],$=J-q[1],k=Q-q[0],b=U-q[1],nn=1/D(tn((Z*k+$*b)/(K(Z*Z+$*$)*K(k*k+b*b)))/2),en=K(q[0]*q[0]+q[1]*q[1]);x=_(P,(r-en)/(nn-1)),d=_(P,(s-en)/(nn+1))}else x=d=0}C>y?d>y?(e=W(X,Y,j,J,s,d,o),u=W(Q,U,M,N,s,d,o),a.moveTo(e.cx+e.x01,e.cy+e.y01),d<P?a.arc(e.cx,e.cy,d,t(e.y01,e.x01),t(u.y01,u.x01),!o):(a.arc(e.cx,e.cy,d,t(e.y01,e.x01),t(e.y11,e.x11),!o),a.arc(0,0,s,t(e.cy+e.y11,e.cx+e.x11),t(u.cy+u.y11,u.cx+u.x11),!o),a.arc(u.cx,u.cy,d,t(u.y11,u.x11),t(u.y01,u.x01),!o))):(a.moveTo(j,J),a.arc(0,0,s,p,g,!o)):a.moveTo(j,J),!(r>y)||!(w>y)?a.lineTo(M,N):x>y?(e=W(M,N,Q,U,r,-x,o),u=W(j,J,X,Y,r,-x,o),a.lineTo(e.cx+e.x01,e.cy+e.y01),x<P?a.arc(e.cx,e.cy,x,t(e.y01,e.x01),t(u.y01,u.x01),!o):(a.arc(e.cx,e.cy,x,t(e.y01,e.x01),t(e.y11,e.x11),!o),a.arc(0,0,r,t(e.cy+e.y11,e.cx+e.x11),t(u.cy+u.y11,u.cx+u.x11),o),a.arc(u.cx,u.cy,x,t(u.y11,u.x11),t(u.y01,u.x01),!o))):a.arc(0,0,r,T,R,o)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,m=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[V(m)*n,D(m)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:H(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:H(+n),i):h},i.cornerRadius=function(n){return arguments.length?(z=typeof n=="function"?n:H(+n),i):z},i.padRadius=function(n){return arguments.length?(E=n==null?null:typeof n=="function"?n:H(+n),i):E},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:H(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:H(+n),i):A},i.padAngle=function(n){return arguments.length?(I=typeof n=="function"?n:H(+n),i):I},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{vn as a};