alita-sdk 0.3.175__py3-none-any.whl → 0.3.177__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.
Files changed (44) hide show
  1. alita_sdk/community/__init__.py +7 -17
  2. alita_sdk/tools/carrier/api_wrapper.py +6 -0
  3. alita_sdk/tools/carrier/backend_tests_tool.py +308 -7
  4. alita_sdk/tools/carrier/carrier_sdk.py +18 -0
  5. alita_sdk/tools/carrier/create_ui_test_tool.py +90 -109
  6. alita_sdk/tools/carrier/run_ui_test_tool.py +311 -184
  7. alita_sdk/tools/carrier/tools.py +2 -1
  8. alita_sdk/tools/confluence/api_wrapper.py +1 -0
  9. {alita_sdk-0.3.175.dist-info → alita_sdk-0.3.177.dist-info}/METADATA +2 -2
  10. {alita_sdk-0.3.175.dist-info → alita_sdk-0.3.177.dist-info}/RECORD +13 -44
  11. alita_sdk/community/browseruse/__init__.py +0 -73
  12. alita_sdk/community/browseruse/api_wrapper.py +0 -288
  13. alita_sdk/community/deep_researcher/__init__.py +0 -70
  14. alita_sdk/community/deep_researcher/agents/__init__.py +0 -1
  15. alita_sdk/community/deep_researcher/agents/baseclass.py +0 -182
  16. alita_sdk/community/deep_researcher/agents/knowledge_gap_agent.py +0 -74
  17. alita_sdk/community/deep_researcher/agents/long_writer_agent.py +0 -251
  18. alita_sdk/community/deep_researcher/agents/planner_agent.py +0 -124
  19. alita_sdk/community/deep_researcher/agents/proofreader_agent.py +0 -80
  20. alita_sdk/community/deep_researcher/agents/thinking_agent.py +0 -64
  21. alita_sdk/community/deep_researcher/agents/tool_agents/__init__.py +0 -20
  22. alita_sdk/community/deep_researcher/agents/tool_agents/crawl_agent.py +0 -87
  23. alita_sdk/community/deep_researcher/agents/tool_agents/search_agent.py +0 -96
  24. alita_sdk/community/deep_researcher/agents/tool_selector_agent.py +0 -83
  25. alita_sdk/community/deep_researcher/agents/utils/__init__.py +0 -0
  26. alita_sdk/community/deep_researcher/agents/utils/parse_output.py +0 -148
  27. alita_sdk/community/deep_researcher/agents/writer_agent.py +0 -63
  28. alita_sdk/community/deep_researcher/api_wrapper.py +0 -116
  29. alita_sdk/community/deep_researcher/deep_research.py +0 -185
  30. alita_sdk/community/deep_researcher/examples/deep_example.py +0 -30
  31. alita_sdk/community/deep_researcher/examples/iterative_example.py +0 -34
  32. alita_sdk/community/deep_researcher/examples/report_plan_example.py +0 -27
  33. alita_sdk/community/deep_researcher/iterative_research.py +0 -419
  34. alita_sdk/community/deep_researcher/llm_config.py +0 -87
  35. alita_sdk/community/deep_researcher/main.py +0 -67
  36. alita_sdk/community/deep_researcher/tools/__init__.py +0 -2
  37. alita_sdk/community/deep_researcher/tools/crawl_website.py +0 -109
  38. alita_sdk/community/deep_researcher/tools/web_search.py +0 -294
  39. alita_sdk/community/deep_researcher/utils/__init__.py +0 -0
  40. alita_sdk/community/deep_researcher/utils/md_to_pdf.py +0 -8
  41. alita_sdk/community/deep_researcher/utils/os.py +0 -21
  42. {alita_sdk-0.3.175.dist-info → alita_sdk-0.3.177.dist-info}/WHEEL +0 -0
  43. {alita_sdk-0.3.175.dist-info → alita_sdk-0.3.177.dist-info}/licenses/LICENSE +0 -0
  44. {alita_sdk-0.3.175.dist-info → alita_sdk-0.3.177.dist-info}/top_level.txt +0 -0
@@ -16,30 +16,32 @@ class RunUITestTool(BaseTool):
16
16
  name: str = "run_ui_test"
17
17
  description: str = ("Run and execute UI tests from the Carrier platform. Use this tool when user wants to run, execute, or start a UI test. "
18
18
  "Provide either test ID or test name, or leave empty to see available tests. "
19
- "Optionally provide custom parameters like loops, cpu_quota, memory_quota, cloud_settings, or custom_cmd.")
19
+ "When no custom parameters are provided, the tool will show default configuration and ask for confirmation. "
20
+ "You can override parameters like cpu_quota, memory_quota, cloud_settings, custom_cmd, or loops. "
21
+ )
20
22
  args_schema: Type[BaseModel] = create_model(
21
23
  "RunUITestInput",
22
24
  test_id=(str, Field(default="", description="Test ID to execute")),
23
25
  test_name=(str, Field(default="", description="Test name to execute")),
24
- loops=(int, Field(default=None, description="Number of loops to run the test")),
25
26
  cpu_quota=(str, Field(default=None, description="CPU quota for the test runner")),
26
27
  memory_quota=(str, Field(default=None, description="Memory quota for the test runner")),
27
28
  cloud_settings=(str, Field(default=None, description="Cloud settings name for the test runner")),
28
29
  custom_cmd=(str, Field(default=None, description="Custom command to run with the test")),
30
+ loops=(str, Field(default=None, description="Number of loops to run the test")),
31
+ proceed_with_defaults=(bool, Field(default=False, description="Proceed with default configuration. True ONLY when user directly wants to run the test with default parameters." \
32
+ " If cpu_quota, memory_quota, cloud_settings, custom_cmd, or loops are provided, proceed_with_defaults must be False")),
29
33
  )
30
34
 
31
- def _run(self, test_id: str = "", test_name: str = "", loops: int = None,
35
+ def _run(self, test_id: str = "", test_name: str = "",
32
36
  cpu_quota: str = None, memory_quota: str = None,
33
- cloud_settings: str = None, custom_cmd: str = None):
37
+ cloud_settings: str = None, custom_cmd: str = None, loops: str = None,
38
+ proceed_with_defaults: bool = False):
34
39
  try:
35
40
  # Check if neither test_id nor test_name is provided
36
41
  if (not test_id or test_id.strip() == "") and (not test_name or test_name.strip() == ""):
37
42
  return self._missing_input_response()
38
-
39
- # Check if user wants to see the list of tests (can be in test_name field)
40
- if test_name.lower() in ["show me the list of ui tests", "list ui tests", "show ui tests"]:
41
- return self._show_ui_tests_list()
42
- # Get UI tests list only when we need to search for and run a test
43
+
44
+ # Get UI tests list only when we need to search for and run a test
43
45
  ui_tests = self.api_wrapper.get_ui_tests_list()
44
46
 
45
47
  # Find the test by ID or name
@@ -91,36 +93,81 @@ class RunUITestTool(BaseTool):
91
93
  for test in ui_tests:
92
94
  available_tests.append(f"ID: {test.get('id')}, Name: {test.get('name')}")
93
95
 
96
+ available_locations = self._get_available_locations()
97
+
94
98
  search_criteria = []
95
99
  if test_id:
96
100
  search_criteria.append(f"ID: {test_id}")
97
101
  if test_name:
98
102
  search_criteria.append(f"Name: {test_name}")
99
103
 
100
- return f"Test not found for {' or '.join(search_criteria)}. Available UI tests:\n" + "\n".join(available_tests)
104
+ error_message = []
105
+ error_message.append(f"Test not found for {' or '.join(search_criteria)}.")
106
+ error_message.append("")
107
+ error_message.append("Available UI tests:")
108
+ error_message.extend(available_tests)
109
+ error_message.append("")
110
+ error_message.append("Available runners/locations:")
111
+ error_message.extend(available_locations)
112
+
113
+ return "\n".join(error_message)
101
114
 
102
- # Check if custom parameters are provided
103
- has_custom_params = any([loops is not None, cpu_quota is not None, memory_quota is not None,
104
- cloud_settings is not None, custom_cmd is not None])
115
+ # Check if custom parameters are provided (including cloud_settings)
116
+ has_custom_params = any([cpu_quota is not None, memory_quota is not None,
117
+ cloud_settings is not None, custom_cmd is not None, loops is not None])
105
118
 
106
- # If no custom parameters provided, show info message with default values and available options
107
- if not has_custom_params:
108
- return self._show_test_parameter_info(test_data, ui_test_id)
109
-
110
- # Get detailed test configuration for the POST request
111
- test_details = self._get_ui_test_details(ui_test_id)
119
+ if has_custom_params:
120
+ proceed_with_defaults = False # If any custom params are provided, do not proceed with defaults
121
+
122
+ # Get detailed test configuration from API (not from UI tests list)
123
+ test_details = self.api_wrapper.get_ui_test_details(str(ui_test_id))
112
124
 
113
125
  if not test_details:
114
126
  return f"Could not retrieve test details for test ID {ui_test_id}."
115
127
 
116
- # Prepare POST request data with custom parameters
117
- post_data = self._prepare_post_data_with_custom_params(test_details, loops, cpu_quota, memory_quota, cloud_settings, custom_cmd)
128
+ # Validate cloud_settings location if provided
129
+ if cloud_settings and not self._validate_cloud_settings_location(cloud_settings):
130
+ available_locations = self._get_available_locations()
131
+ error_message = []
132
+ error_message.append(f"❌ Invalid location/cloud_settings: '{cloud_settings}'")
133
+ error_message.append("")
134
+ error_message.append("Available runners/locations:")
135
+ error_message.extend(available_locations)
136
+ error_message.append("")
137
+ error_message.append("Please choose a valid location name from the list above.")
138
+ return "\n".join(error_message)
139
+
140
+ # If no custom parameters provided, check if user wants to proceed with defaults
141
+ if not has_custom_params:
142
+ if not proceed_with_defaults:
143
+ # Show default configuration and ask user if they want to change anything
144
+ default_message = self._show_default_configuration_message(test_details)
145
+ if isinstance(default_message, dict) and "message" in default_message:
146
+ message_str = "\n".join(default_message["message"])
147
+ else:
148
+ message_str = str(default_message)
149
+ return message_str + "\n\nTo proceed with default configuration, type `Run test with default configuration` or specify any parameters you want to override."
150
+ else:
151
+ # User confirmed to proceed with defaults
152
+ post_data = self._prepare_post_data_default(test_details)
153
+ else:
154
+ # Prepare POST request data with custom parameters or cloud settings
155
+ post_data = self._prepare_post_data_with_overrides(test_details, cpu_quota, memory_quota, cloud_settings, custom_cmd, loops)
118
156
 
119
157
  # Execute the UI test
120
158
  result_id = self.api_wrapper.run_ui_test(str(ui_test_id), post_data)
121
159
 
122
- return f"UI test started successfully. Result ID: {result_id}. " \
123
- f"Link to report: {self.api_wrapper.url.rstrip('/')}/-/performance/ui/results?result_id={result_id}"
160
+ # Show location info in success message
161
+ location_used = "default"
162
+ if cloud_settings:
163
+ location_used = cloud_settings
164
+ elif post_data.get("common_params", {}).get("location"):
165
+ location_used = post_data["common_params"]["location"]
166
+
167
+ return f"✅ UI test started successfully!\n" \
168
+ f"Result ID: {result_id}\n" \
169
+ f"Location used: {location_used}\n" \
170
+ f"Link to report: {self.api_wrapper._client.credentials.url.rstrip('/')}/-/performance/ui/results?result_id={result_id}"
124
171
 
125
172
  except Exception:
126
173
  stacktrace = traceback.format_exc()
@@ -146,122 +193,95 @@ class RunUITestTool(BaseTool):
146
193
  logger.error(f"Error fetching UI tests list: {stacktrace}")
147
194
  raise ToolException(stacktrace)
148
195
 
149
- def _get_ui_test_details(self, test_id: int):
150
- """Get detailed test configuration from the UI tests list."""
196
+ def _prepare_post_data_default(self, test_details):
197
+ """Prepare POST request data with default parameters."""
151
198
  try:
152
- ui_tests = self.api_wrapper.get_ui_tests_list()
199
+ # Extract values from the test details
200
+ test_parameters = test_details.get("test_parameters", [])
201
+ env_vars = test_details.get("env_vars", {})
202
+ integrations = test_details.get("integrations", {})
203
+ location = test_details.get("location", "")
204
+ parallel_runners = test_details.get("parallel_runners", 1)
205
+ aggregation = test_details.get("aggregation", "max")
206
+ loops = test_details.get("loops", 1)
153
207
 
154
- for test in ui_tests:
155
- if test.get("id") == test_id:
156
- return test
208
+ # Find specific test parameters by name
209
+ def find_param_by_name(params, name):
210
+ for param in params:
211
+ if param.get("name") == name:
212
+ return param
213
+ return {}
157
214
 
158
- return None
215
+ # Extract S3 integration
216
+ s3_integration = integrations.get("system", {}).get("s3_integration", {})
159
217
 
160
- except Exception:
161
- stacktrace = traceback.format_exc()
162
- logger.error(f"Error getting UI test details: {stacktrace}")
163
- return None
164
-
165
- def _show_test_parameter_info(self, test_data, test_id):
166
- """Show information about test parameters that can be changed."""
167
- try:
168
- # Get current default values from test data
169
- env_vars = test_data.get("env_vars", {})
170
-
171
- info_message = []
172
- info_message.append(f"Test '{test_data.get('name')}' (ID: {test_id}) found!")
173
- info_message.append("\nCurrent default parameters:")
174
- info_message.append(f"- loops: 1 (default override)")
175
- info_message.append(f"- cpu_quota: {env_vars.get('cpu_quota', 'Not set')}")
176
- info_message.append(f"- memory_quota: {env_vars.get('memory_quota', 'Not set')}")
177
- info_message.append(f"- cloud_settings: {env_vars.get('cloud_settings', 'Not set')}")
178
- info_message.append(f"- custom_cmd: {env_vars.get('custom_cmd', 'Not set')}")
179
- # Always try to get and display available cloud settings - this is critical information
180
- info_message.append("\n" + "="*60)
181
- info_message.append("🏃 AVAILABLE RUNNERS - CHOOSE ONE FOR cloud_settings:")
182
- info_message.append("="*60)
183
-
184
- try:
185
- locations_data = self.api_wrapper.get_locations()
186
- if not locations_data:
187
- info_message.append("⚠️ Could not fetch locations data - API returned empty response")
188
- else:
189
- cloud_regions = locations_data.get("cloud_regions", [])
190
- public_regions = locations_data.get("public_regions", [])
191
- project_regions = locations_data.get("project_regions", [])
192
- # Add public regions information (these are the most commonly used)
193
- info_message.append("\n🌐 PUBLIC REGIONS (use these names):")
194
- if public_regions:
195
- for region in public_regions:
196
- info_message.append(f" ✅ '{region}'")
197
- else:
198
- info_message.append(" ❌ No public regions available")
199
-
200
- # Add project regions information
201
- if project_regions:
202
- info_message.append("\n🏢 PROJECT REGIONS (use these names):")
203
- for region in project_regions:
204
- info_message.append(f" ✅ '{region}'")
205
-
206
- # Add cloud regions information
207
- if cloud_regions:
208
- info_message.append("\n☁️ CLOUD REGIONS (advanced - use full names):")
209
- for region in cloud_regions:
210
- region_name = region.get("name", "Unknown")
211
- info_message.append(f" ✅ '{region_name}'")
212
-
213
- except Exception as e:
214
- logger.error(f"Error fetching locations: {e}")
215
- info_message.append("❌ ERROR: Could not fetch available runners!")
216
- info_message.append(f" Reason: {str(e)}")
217
- info_message.append(" Please check your API connection and try again.")
218
-
219
- info_message.append("="*60)
220
- info_message.append("\n📋 HOW TO USE:")
221
- info_message.append("To run this test with custom parameters, specify the values you want to change.")
222
- info_message.append("\n💡 EXAMPLES:")
223
- info_message.append(" • Use default runner: cloud_settings='default'")
224
- info_message.append(" • Change loops: loops=5")
225
- info_message.append(" • Change resources: cpu_quota='2', memory_quota='4Gi'")
226
- info_message.append(" • Full example: loops=3, cloud_settings='default', cpu_quota='2'")
227
- info_message.append("\n📝 RUNNER TYPES:")
228
- info_message.append(" • Public regions: Use empty cloud_settings {}, location = runner name")
229
- info_message.append(" • Project regions: Use empty cloud_settings {}, location = runner name")
230
- info_message.append(" • Cloud regions: Use full cloud configuration object")
231
-
232
- return "\n".join(info_message)
218
+ # Get actual cloud_settings from test details (could be empty {} or have actual settings)
219
+ actual_cloud_settings = env_vars.get("cloud_settings", {})
220
+
221
+ # Prepare the POST request body with default parameters
222
+ post_data = {
223
+ "common_params": {
224
+ "name": find_param_by_name(test_parameters, "test_name"),
225
+ "test_type": find_param_by_name(test_parameters, "test_type"),
226
+ "env_type": find_param_by_name(test_parameters, "env_type"),
227
+ "env_vars": {
228
+ "cpu_quota": env_vars.get("cpu_quota"),
229
+ "memory_quota": env_vars.get("memory_quota"),
230
+ "cloud_settings": actual_cloud_settings, # Use actual cloud settings from test details
231
+ "ENV": env_vars.get("ENV", "prod"),
232
+ "custom_cmd": env_vars.get("custom_cmd", "")
233
+ },
234
+ "parallel_runners": parallel_runners,
235
+ "location": location
236
+ },
237
+ "test_parameters": test_parameters,
238
+ "integrations": {
239
+ "system": {
240
+ "s3_integration": {
241
+ "integration_id": s3_integration.get("integration_id"),
242
+ "is_local": s3_integration.get("is_local")
243
+ }
244
+ }
245
+ },
246
+ "loops": loops,
247
+ "aggregation": aggregation
248
+ }
249
+
250
+ return post_data
233
251
 
234
252
  except Exception:
235
253
  stacktrace = traceback.format_exc()
236
- logger.error(f"Error showing test parameter info: {stacktrace}")
254
+ logger.error(f"Error preparing default POST data: {stacktrace}")
237
255
  raise ToolException(stacktrace)
238
-
239
- def _prepare_post_data_with_custom_params(self, test_data, loops=None, cpu_quota=None,
240
- memory_quota=None, cloud_settings=None, custom_cmd=None):
241
- """Prepare POST request data with custom parameters."""
256
+
257
+ def _prepare_post_data_with_overrides(self, test_details, cpu_quota=None,
258
+ memory_quota=None, cloud_settings=None, custom_cmd=None, loops=None):
259
+ """Prepare POST request data with overrides or cloud settings."""
242
260
  try:
243
- # Extract values from the test data
244
- test_parameters = test_data.get("test_parameters", [])
245
- env_vars = test_data.get("env_vars", {})
246
- integrations = test_data.get("integrations", {})
247
- location = test_data.get("location", "")
248
- parallel_runners = test_data.get("parallel_runners", 1)
249
- aggregation = test_data.get("aggregation", "max")
261
+ # Extract values from the test details
262
+ test_parameters = test_details.get("test_parameters", [])
263
+ env_vars = test_details.get("env_vars", {})
264
+ integrations = test_details.get("integrations", {})
265
+ location = test_details.get("location", "")
266
+ parallel_runners = test_details.get("parallel_runners", 1)
267
+ aggregation = test_details.get("aggregation", "max")
268
+ default_loops = test_details.get("loops", 1)
269
+ # Use provided loops parameter or default
270
+ final_loops = loops if loops is not None else default_loops
250
271
 
251
- # Extract reporter email for integrations
252
- reporter_email = integrations.get("reporters", {}).get("reporter_email", {})
253
-
254
- # Extract S3 integration
255
- s3_integration = integrations.get("system", {}).get("s3_integration", {})
256
- # Find specific test parameters by name
272
+ # Find specific test parameters by name
257
273
  def find_param_by_name(params, name):
258
274
  for param in params:
259
275
  if param.get("name") == name:
260
276
  return param
261
- return {}
262
- # Handle cloud_settings parameter and location
263
- final_cloud_settings = env_vars.get("cloud_settings")
264
- final_location = location # Use original location as default
277
+ return {}
278
+
279
+ # Extract S3 integration
280
+ s3_integration = integrations.get("system", {}).get("s3_integration", {})
281
+
282
+ # Handle cloud_settings parameter and determine the scenario
283
+ final_cloud_settings = {}
284
+ final_location = location
265
285
 
266
286
  if cloud_settings:
267
287
  try:
@@ -270,65 +290,59 @@ class RunUITestTool(BaseTool):
270
290
  public_regions = locations_data.get("public_regions", [])
271
291
  project_regions = locations_data.get("project_regions", [])
272
292
 
273
- # Check if it's a public region first
274
- if cloud_settings in public_regions:
275
- # For public regions, use empty cloud_settings and set location to the runner name
276
- final_cloud_settings = {}
277
- final_location = cloud_settings
278
- # Check if it's a project region
279
- elif cloud_settings in project_regions:
280
- # For project regions, use empty cloud_settings and set location to the runner name
293
+ # Check if it's a public or project region (scenario 1)
294
+ if cloud_settings in public_regions or cloud_settings in project_regions:
295
+ # For public/project regions, use empty cloud_settings and set location
281
296
  final_cloud_settings = {}
282
297
  final_location = cloud_settings
283
298
  else:
284
- # Try to find exact match in cloud regions
285
- found_match = False
299
+ # Check if it's a cloud region (scenario 2)
300
+ found_cloud_region = None
286
301
  for region in cloud_regions:
287
302
  if region.get("name", "").lower() == cloud_settings.lower():
288
- # Get the complete cloud_settings object and add the missing fields
289
- region_cloud_settings = region.get("cloud_settings", {})
290
- # Add the additional fields that are expected in the POST request
291
- region_cloud_settings.update({
292
- "instance_type": "on-demand",
293
- "ec2_instance_type": "t2.xlarge",
294
- "cpu_cores_limit": int(cpu_quota) if cpu_quota else env_vars.get("cpu_quota", 1),
295
- "memory_limit": int(memory_quota) if memory_quota else env_vars.get("memory_quota", 8),
296
- "concurrency": 1
297
- })
298
- final_cloud_settings = region_cloud_settings
299
- final_location = location # Keep original location for cloud regions
300
- found_match = True
303
+ found_cloud_region = region
301
304
  break
302
305
 
303
- # If no exact match in cloud regions, try partial match
304
- if not found_match:
306
+ # If not exact match, try partial match
307
+ if not found_cloud_region:
305
308
  for region in cloud_regions:
306
309
  if cloud_settings.lower() in region.get("name", "").lower():
307
- region_cloud_settings = region.get("cloud_settings", {})
308
- region_cloud_settings.update({
309
- "instance_type": "on-demand",
310
- "ec2_instance_type": "t2.xlarge",
311
- "cpu_cores_limit": int(cpu_quota) if cpu_quota else env_vars.get("cpu_quota", 1),
312
- "memory_limit": int(memory_quota) if memory_quota else env_vars.get("memory_quota", 8),
313
- "concurrency": 1
314
- })
315
- final_cloud_settings = region_cloud_settings
316
- final_location = location # Keep original location for cloud regions
317
- found_match = True
310
+ found_cloud_region = region
318
311
  break
319
312
 
320
- # If still no match found, treat as public region fallback
321
- if not found_match:
313
+ if found_cloud_region:
314
+ # Extract cloud settings details for scenario 2
315
+ # cloud_name = found_cloud_region.get("name", "")
316
+ cloud_config = found_cloud_region.get("cloud_settings", {})
317
+ final_cloud_settings = {
318
+ "integration_name": cloud_config.get("integration_name"),
319
+ "id": cloud_config.get("id"),
320
+ "project_id": cloud_config.get("project_id"),
321
+ "aws_access_key": cloud_config.get("aws_access_key"),
322
+ "aws_secret_access_key": cloud_config.get("aws_secret_access_key", {}),
323
+ "region_name": cloud_config.get("region_name"),
324
+ "security_groups": cloud_config.get("security_groups"),
325
+ "image_id": cloud_config.get("image_id"),
326
+ "key_name": cloud_config.get("key_name", ""),
327
+ "instance_type": "spot",
328
+ "ec2_instance_type": "t2.xlarge"
329
+ }
330
+ final_location = found_cloud_region.get("name")
331
+ else:
332
+ # If no match found, treat as public region fallback
322
333
  final_cloud_settings = {}
323
334
  final_location = cloud_settings
324
335
 
325
336
  except Exception as e:
326
337
  logger.error(f"Error processing cloud_settings: {e}")
327
- # Use the provided value as-is if we can't process it
328
- final_cloud_settings = cloud_settings
329
- final_location = location
330
-
331
- # Prepare the POST request body with custom parameters
338
+ # Use empty cloud_settings as fallback
339
+ final_cloud_settings = {}
340
+ final_location = cloud_settings if cloud_settings else location
341
+ else:
342
+ # If no cloud_settings provided, use default from test details
343
+ final_cloud_settings = env_vars.get("cloud_settings", {})
344
+
345
+ # Prepare the POST request body with overrides
332
346
  post_data = {
333
347
  "common_params": {
334
348
  "name": find_param_by_name(test_parameters, "test_name"),
@@ -338,21 +352,14 @@ class RunUITestTool(BaseTool):
338
352
  "cpu_quota": cpu_quota if cpu_quota is not None else env_vars.get("cpu_quota"),
339
353
  "memory_quota": memory_quota if memory_quota is not None else env_vars.get("memory_quota"),
340
354
  "cloud_settings": final_cloud_settings,
341
- "ENV": "prod", # Override as per reference code
355
+ "ENV": env_vars.get("ENV", "prod"),
342
356
  "custom_cmd": custom_cmd if custom_cmd is not None else env_vars.get("custom_cmd", "")
343
- }, "parallel_runners": parallel_runners,
357
+ },
358
+ "parallel_runners": parallel_runners,
344
359
  "location": final_location
345
360
  },
346
361
  "test_parameters": test_parameters,
347
362
  "integrations": {
348
- "reporters": {
349
- "reporter_email": {
350
- "id": reporter_email.get("id"),
351
- "is_local": reporter_email.get("is_local"),
352
- "project_id": reporter_email.get("project_id"),
353
- "recipients": reporter_email.get("recipients")
354
- }
355
- },
356
363
  "system": {
357
364
  "s3_integration": {
358
365
  "integration_id": s3_integration.get("integration_id"),
@@ -360,7 +367,7 @@ class RunUITestTool(BaseTool):
360
367
  }
361
368
  }
362
369
  },
363
- "loops": loops if loops is not None else 1, # Use custom loops or default to 1
370
+ "loops": final_loops,
364
371
  "aggregation": aggregation
365
372
  }
366
373
 
@@ -368,20 +375,29 @@ class RunUITestTool(BaseTool):
368
375
 
369
376
  except Exception:
370
377
  stacktrace = traceback.format_exc()
371
- logger.error(f"Error preparing POST data with custom parameters: {stacktrace}")
378
+ logger.error(f"Error preparing POST data with overrides: {stacktrace}")
372
379
  raise ToolException(stacktrace)
373
380
 
374
381
  def _missing_input_response(self):
375
382
  """Response when required input is missing."""
376
383
  try:
377
384
  available_tests = self._show_ui_tests_list()
385
+ available_locations = self._get_available_locations()
386
+
387
+ location_info = "Available runners/locations for cloud_settings:\n" + "\n".join(available_locations)
388
+
378
389
  return {
379
- "message": "Please provide test ID or test name of your UI test.",
390
+ "message": {
391
+ "text": (
392
+ "Please provide test ID or test name of your UI test.\n\n"
393
+ "Available UI tests:\n" + available_tests + "\n\n"
394
+ "Available runners/locations for cloud_settings:\n" + location_info
395
+ ),
396
+ },
380
397
  "parameters": {
381
398
  "test_id": None,
382
399
  "test_name": None,
383
- },
384
- "available_tests": available_tests
400
+ }
385
401
  }
386
402
  except Exception:
387
403
  return {
@@ -390,5 +406,116 @@ class RunUITestTool(BaseTool):
390
406
  "test_id": None,
391
407
  "test_name": None,
392
408
  },
393
- "available_tests": "Error fetching available tests."
409
+ "available_tests": "Error fetching available tests.",
410
+ "available_locations": "Error fetching available locations."
394
411
  }
412
+
413
+ def _show_default_configuration_message(self, test_details):
414
+ """Show information about default configuration and available override parameters."""
415
+ try:
416
+ env_vars = test_details.get("env_vars", {})
417
+ test_name = test_details.get("name", "Unknown")
418
+ loops = test_details.get("loops", 1)
419
+
420
+ # Get available locations
421
+ available_locations = self._get_available_locations()
422
+
423
+ message = []
424
+ message.append("Current default parameters:")
425
+ message.append(f" • CPU Quota: {env_vars.get('cpu_quota', 'Not set')}")
426
+ message.append(f" • Memory Quota: {env_vars.get('memory_quota', 'Not set')}")
427
+ message.append(f" • Custom Command: {env_vars.get('custom_cmd', 'Not set')}")
428
+ message.append(f" • Loops: {loops}")
429
+ message.append(f" • Cloud Settings: Default location")
430
+ message.append("")
431
+ message.append("Available parameters to override:")
432
+ message.append(" • cpu_quota - Set CPU quota for the test runner")
433
+ message.append(" • memory_quota - Set memory quota for the test runner")
434
+ message.append(" • custom_cmd - Set custom command to run with the test")
435
+ message.append(" • loops - Set number of loops to run the test")
436
+ message.append(" • cloud_settings - Set cloud settings name for the test runner")
437
+ message.append("")
438
+ message.append("Available runners/locations:")
439
+ message.extend(available_locations)
440
+
441
+ return {"message": message}
442
+
443
+ except Exception:
444
+ stacktrace = traceback.format_exc()
445
+ logger.error(f"Error showing default configuration: {stacktrace}")
446
+ return "Default configuration available for this test."
447
+
448
+ def _get_available_locations(self):
449
+ """Get formatted list of available locations for user selection."""
450
+ try:
451
+ locations_data = self.api_wrapper.get_locations()
452
+ location_list = []
453
+
454
+ # Add public regions
455
+ public_regions = locations_data.get("public_regions", [])
456
+ if public_regions:
457
+ location_list.append(" Public Regions:")
458
+ for region in public_regions:
459
+ location_list.append(f" - {region}")
460
+
461
+ # Add project regions
462
+ project_regions = locations_data.get("project_regions", [])
463
+ if project_regions:
464
+ location_list.append(" Project Regions:")
465
+ for region in project_regions:
466
+ location_list.append(f" - {region}")
467
+
468
+ # Add cloud regions
469
+ cloud_regions = locations_data.get("cloud_regions", [])
470
+ if cloud_regions:
471
+ location_list.append(" Cloud Regions:")
472
+ for region in cloud_regions:
473
+ region_name = region.get("name", "Unknown")
474
+ cloud_config = region.get("cloud_settings", {})
475
+ aws_region = cloud_config.get("region_name", "")
476
+ location_list.append(f" - {region_name} ({aws_region})")
477
+
478
+ if not location_list:
479
+ location_list.append(" No locations available")
480
+
481
+ return location_list
482
+
483
+ except Exception:
484
+ stacktrace = traceback.format_exc()
485
+ logger.error(f"Error getting available locations: {stacktrace}")
486
+ return [" Error loading locations"]
487
+
488
+ def _validate_cloud_settings_location(self, cloud_settings):
489
+ """Validate if the provided cloud_settings location exists and is available."""
490
+ try:
491
+ if not cloud_settings:
492
+ return True # No cloud_settings provided, use default
493
+
494
+ locations_data = self.api_wrapper.get_locations()
495
+
496
+ # Check in public regions
497
+ public_regions = locations_data.get("public_regions", [])
498
+ if cloud_settings in public_regions:
499
+ return True
500
+
501
+ # Check in project regions
502
+ project_regions = locations_data.get("project_regions", [])
503
+ if cloud_settings in project_regions:
504
+ return True
505
+
506
+ # Check in cloud regions (by name)
507
+ cloud_regions = locations_data.get("cloud_regions", [])
508
+ for region in cloud_regions:
509
+ region_name = region.get("name", "")
510
+ if region_name.lower() == cloud_settings.lower():
511
+ return True
512
+ # Also check partial match
513
+ if cloud_settings.lower() in region_name.lower():
514
+ return True
515
+
516
+ return False
517
+
518
+ except Exception:
519
+ stacktrace = traceback.format_exc()
520
+ logger.error(f"Error validating cloud settings location: {stacktrace}")
521
+ return True # Allow execution if validation fails
@@ -1,7 +1,7 @@
1
1
  # import all available tools
2
2
  from .tickets_tool import FetchTicketsTool, CreateTicketTool
3
3
  from .backend_reports_tool import GetReportsTool, GetReportByIDTool, CreateExcelReportTool
4
- from .backend_tests_tool import GetTestsTool, GetTestByIDTool, RunTestByIDTool
4
+ from .backend_tests_tool import GetTestsTool, GetTestByIDTool, RunTestByIDTool, CreateBackendTestTool
5
5
  from .ui_reports_tool import GetUIReportsTool, GetUIReportByIDTool, GetUITestsTool
6
6
  from .run_ui_test_tool import RunUITestTool
7
7
  from .update_ui_test_schedule_tool import UpdateUITestScheduleTool
@@ -18,6 +18,7 @@ __all__ = [
18
18
  {"name": "get_tests", "tool": GetTestsTool},
19
19
  {"name": "get_test_by_id", "tool": GetTestByIDTool},
20
20
  {"name": "run_test_by_id", "tool": RunTestByIDTool},
21
+ {"name": "create_backend_test", "tool": CreateBackendTestTool},
21
22
  {"name": "get_ui_reports", "tool": GetUIReportsTool},
22
23
  {"name": "get_ui_report_by_id", "tool": GetUIReportByIDTool},
23
24
  {"name": "get_ui_tests", "tool": GetUITestsTool},