codemie-test-harness 0.1.221__py3-none-any.whl → 0.1.223__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 codemie-test-harness might be problematic. Click here for more details.

@@ -950,6 +950,24 @@ def integration(integration_utils):
950
950
  integration_utils.delete_integration(created_integration)
951
951
 
952
952
 
953
+ @pytest.fixture(scope="session")
954
+ def vendor_assistant_utils():
955
+ """Create VendorUtils instance for managing vendor assistants"""
956
+ from codemie_test_harness.tests.utils.vendor_utils import VendorAssistantUtils
957
+
958
+ return VendorAssistantUtils()
959
+
960
+
961
+ @pytest.fixture(scope="session")
962
+ def vendor_workflow_utils():
963
+ """Create VendorWorkflowUtils instance for managing vendor workflows"""
964
+ from codemie_test_harness.tests.utils.vendor_workflow_utils import (
965
+ VendorWorkflowUtils,
966
+ )
967
+
968
+ return VendorWorkflowUtils()
969
+
970
+
953
971
  def pytest_sessionfinish(session):
954
972
  """Run cleanup code after all tests have finished."""
955
973
  clean_up_timeout = 1 if EnvironmentResolver.is_production() else 0
@@ -0,0 +1,36 @@
1
+ """Test data for vendor service endpoint tests."""
2
+
3
+ import pytest
4
+ from codemie_sdk.models.vendor_assistant import VendorType
5
+ from codemie_sdk.models.integration import CredentialTypes
6
+
7
+ from codemie_test_harness.tests.utils.credentials_manager import CredentialsManager
8
+
9
+
10
+ # Test data for vendor endpoint tests
11
+ # Extensible for AWS Bedrock, Azure AI, and GCP Vertex AI
12
+ vendor_endpoint_test_data = [
13
+ pytest.param(
14
+ VendorType.AWS,
15
+ CredentialTypes.AWS,
16
+ CredentialsManager.aws_credentials(),
17
+ marks=[pytest.mark.aws, pytest.mark.bedrock],
18
+ id="AWS_Bedrock",
19
+ ),
20
+ # Future: Azure AI endpoints
21
+ # pytest.param(
22
+ # VendorType.AZURE,
23
+ # CredentialTypes.AZURE,
24
+ # CredentialsManager.azure_credentials(),
25
+ # marks=[pytest.mark.azure],
26
+ # id="Azure_AI",
27
+ # ),
28
+ # Future: GCP Vertex AI endpoints
29
+ # pytest.param(
30
+ # VendorType.GCP,
31
+ # CredentialTypes.GCP,
32
+ # CredentialsManager.gcp_credentials(),
33
+ # marks=[pytest.mark.gcp],
34
+ # id="GCP_Vertex_AI",
35
+ # ),
36
+ ]
@@ -0,0 +1,43 @@
1
+ """Test data for 3rd party vendor assistant tests."""
2
+
3
+ import pytest
4
+ from codemie_sdk.models.vendor_assistant import VendorType
5
+ from codemie_sdk.models.integration import CredentialTypes
6
+
7
+ from codemie_test_harness.tests.llm.assistants.test_llm import SIMPLE_GREETING_PROMPT
8
+ from codemie_test_harness.tests.utils.credentials_manager import CredentialsManager
9
+
10
+
11
+ # Test data for vendor assistant tests
12
+ # Extensible for AWS Bedrock, Azure AI, and GCP Vertex AI
13
+ vendor_assistant_test_data = [
14
+ pytest.param(
15
+ VendorType.AWS,
16
+ CredentialTypes.AWS,
17
+ CredentialsManager.aws_credentials(),
18
+ SIMPLE_GREETING_PROMPT,
19
+ "Hello",
20
+ marks=[pytest.mark.aws, pytest.mark.bedrock],
21
+ id="AWS_Bedrock",
22
+ ),
23
+ # Future: Azure AI assistants
24
+ # pytest.param(
25
+ # VendorType.AZURE,
26
+ # CredentialTypes.AZURE,
27
+ # CredentialsManager.azure_credentials(),
28
+ # "Just say one word: 'Hello'",
29
+ # "Hello",
30
+ # marks=[pytest.mark.vendor, pytest.mark.azure, pytest.mark.api],
31
+ # id="Azure_AI",
32
+ # ),
33
+ # Future: GCP Vertex AI assistants
34
+ # pytest.param(
35
+ # VendorType.GCP,
36
+ # CredentialTypes.GCP,
37
+ # CredentialsManager.gcp_credentials(),
38
+ # "Just say one word: 'Hello'",
39
+ # "Hello",
40
+ # marks=[pytest.mark.vendor, pytest.mark.gcp, pytest.mark.api],
41
+ # id="GCP_Vertex_AI",
42
+ # ),
43
+ ]
@@ -0,0 +1,50 @@
1
+ """Test data for vendor workflow e2e tests."""
2
+
3
+ import json
4
+ import pytest
5
+ from codemie_sdk.models.vendor_assistant import VendorType
6
+ from codemie_sdk.models.integration import CredentialTypes
7
+
8
+ from codemie_test_harness.tests.utils.credentials_manager import CredentialsManager
9
+
10
+
11
+ vendor_workflow_test_data = [
12
+ pytest.param(
13
+ VendorType.AWS,
14
+ CredentialTypes.AWS,
15
+ CredentialsManager.aws_credentials(),
16
+ "codemie-autotests-flow-object-input",
17
+ json.dumps({"genre": "pop", "number": 3}),
18
+ """
19
+ # Pop Playlist: Just Three Hits
20
+
21
+ 1. "As It Was" by Harry Styles
22
+ 2. "Blinding Lights" by The Weeknd
23
+ 3. "Levitating" by Dua Lipa
24
+
25
+ These three modern pop classics offer a perfect mini-playlist with upbeat tempos and catchy hooks. Enjoy!
26
+ """,
27
+ marks=[pytest.mark.aws, pytest.mark.bedrock],
28
+ id="AWS_Bedrock_Object_Input",
29
+ ),
30
+ # pytest.param(
31
+ # VendorType.AZURE,
32
+ # CredentialTypes.AZURE,
33
+ # CredentialsManager.azure_credentials(),
34
+ # "workflow-name",
35
+ # json.dumps({"genre": "rock", "number": 5}),
36
+ # "Rock Playlist",
37
+ # marks=[pytest.mark.azure],
38
+ # id="Azure_AI_Object_Input",
39
+ # ),
40
+ # pytest.param(
41
+ # VendorType.GCP,
42
+ # CredentialTypes.GCP,
43
+ # CredentialsManager.gcp_credentials(),
44
+ # "workflow-name",
45
+ # json.dumps({"genre": "jazz", "number": 4}),
46
+ # "Jazz Playlist",
47
+ # marks=[pytest.mark.gcp],
48
+ # id="GCP_Vertex_AI_Object_Input",
49
+ # ),
50
+ ]
@@ -0,0 +1,343 @@
1
+ """Utility class for managing vendor assistants (AWS Bedrock, Azure, GCP)."""
2
+
3
+ from typing import Optional, List
4
+ from codemie_sdk.models.vendor_assistant import (
5
+ VendorType,
6
+ VendorAssistantSettingsResponse,
7
+ VendorAssistantsResponse,
8
+ VendorAssistant,
9
+ VendorAssistantAliasesResponse,
10
+ VendorAssistantInstallRequest,
11
+ VendorAssistantInstallResponse,
12
+ VendorAssistantUninstallResponse,
13
+ VendorAssistantStatus,
14
+ )
15
+ from codemie_test_harness.tests.utils.client_factory import get_client
16
+ from codemie_test_harness.tests.utils.logger_util import setup_logger
17
+
18
+ logger = setup_logger(__name__)
19
+
20
+ DRAFT_VERSION = "DRAFT"
21
+
22
+
23
+ class VendorAssistantUtils:
24
+ """Utility class for vendor assistant operations."""
25
+
26
+ def __init__(self):
27
+ """Initialize VendorUtils with CodeMie client."""
28
+ self.client = get_client()
29
+ self.vendor_assistant_service = self.client.vendor_assistants
30
+
31
+ def get_assistant_settings(
32
+ self,
33
+ vendor: VendorType,
34
+ page: int = 0,
35
+ per_page: int = 10,
36
+ ) -> VendorAssistantSettingsResponse:
37
+ """Get assistant settings for a specific cloud vendor.
38
+
39
+ Args:
40
+ vendor: Cloud vendor type (AWS, AZURE, GCP)
41
+ page: Page number for pagination
42
+ per_page: Number of items per page
43
+
44
+ Returns:
45
+ VendorAssistantSettingsResponse containing list of settings
46
+ """
47
+ logger.info(
48
+ f"Getting assistant settings for {vendor.value} (page={page}, per_page={per_page})"
49
+ )
50
+ settings = self.vendor_assistant_service.get_assistant_settings(
51
+ vendor=vendor, page=page, per_page=per_page
52
+ )
53
+ logger.info(
54
+ f"Retrieved {len(settings.data)} settings for {vendor.value} (total: {settings.pagination.total})"
55
+ )
56
+ return settings
57
+
58
+ def get_assistants(
59
+ self,
60
+ vendor: VendorType,
61
+ setting_id: str,
62
+ per_page: int = 10,
63
+ next_token: Optional[str] = None,
64
+ ) -> VendorAssistantsResponse:
65
+ """Get assistants for a specific vendor setting.
66
+
67
+ Args:
68
+ vendor: Cloud vendor type
69
+ setting_id: ID of the vendor setting
70
+ per_page: Number of items per page
71
+ next_token: Token for pagination
72
+
73
+ Returns:
74
+ VendorAssistantsResponse containing list of assistants
75
+ """
76
+ logger.info(
77
+ f"Getting assistants for {vendor.value} setting {setting_id} (per_page={per_page})"
78
+ )
79
+ assistants = self.vendor_assistant_service.get_assistants(
80
+ vendor=vendor,
81
+ setting_id=setting_id,
82
+ per_page=per_page,
83
+ next_token=next_token,
84
+ )
85
+ logger.info(
86
+ f"Retrieved {len(assistants.data)} assistants for setting {setting_id}"
87
+ )
88
+ return assistants
89
+
90
+ def get_assistant(
91
+ self,
92
+ vendor: VendorType,
93
+ assistant_id: str,
94
+ setting_id: str,
95
+ ) -> VendorAssistant:
96
+ """Get a specific assistant by ID.
97
+
98
+ Args:
99
+ vendor: Cloud vendor type
100
+ assistant_id: ID of the assistant
101
+ setting_id: ID of the vendor setting
102
+
103
+ Returns:
104
+ VendorAssistant with assistant details
105
+ """
106
+ logger.info(
107
+ f"Getting assistant {assistant_id} for {vendor.value} setting {setting_id}"
108
+ )
109
+ assistant = self.vendor_assistant_service.get_assistant(
110
+ vendor=vendor, assistant_id=assistant_id, setting_id=setting_id
111
+ )
112
+ logger.info(
113
+ f"Retrieved assistant: {assistant.name} (status: {assistant.status})"
114
+ )
115
+ return assistant
116
+
117
+ def get_assistant_aliases(
118
+ self,
119
+ vendor: VendorType,
120
+ assistant_id: str,
121
+ setting_id: str,
122
+ per_page: int = 10,
123
+ next_token: Optional[str] = None,
124
+ ) -> VendorAssistantAliasesResponse:
125
+ """Get aliases for a specific vendor assistant.
126
+
127
+ Args:
128
+ vendor: Cloud vendor type
129
+ assistant_id: ID of the assistant
130
+ setting_id: ID of the vendor setting
131
+ per_page: Number of items per page
132
+ next_token: Token for pagination
133
+
134
+ Returns:
135
+ VendorAssistantAliasesResponse containing list of aliases
136
+ """
137
+ logger.info(
138
+ f"Getting aliases for assistant {assistant_id} in {vendor.value} setting {setting_id}"
139
+ )
140
+ aliases = self.vendor_assistant_service.get_assistant_aliases(
141
+ vendor=vendor,
142
+ assistant_id=assistant_id,
143
+ setting_id=setting_id,
144
+ per_page=per_page,
145
+ next_token=next_token,
146
+ )
147
+ logger.info(
148
+ f"Retrieved {len(aliases.data)} aliases for assistant {assistant_id}"
149
+ )
150
+ return aliases
151
+
152
+ def install_assistants(
153
+ self,
154
+ vendor: VendorType,
155
+ assistants: List[VendorAssistantInstallRequest],
156
+ ) -> VendorAssistantInstallResponse:
157
+ """Install/activate vendor assistants.
158
+
159
+ Args:
160
+ vendor: Cloud vendor type
161
+ assistants: List of assistant installation requests
162
+
163
+ Returns:
164
+ VendorAssistantInstallResponse containing installation summary with AI run IDs
165
+ """
166
+ logger.info(f"Installing {len(assistants)} assistant(s) for {vendor.value}")
167
+ response = self.vendor_assistant_service.install_assistants(
168
+ vendor=vendor, assistants=assistants
169
+ )
170
+ for item in response.summary:
171
+ logger.info(
172
+ f"Installed assistant {item.agentId} (alias: {item.agentAliasId}) -> CodeMie ID: {item.aiRunId}"
173
+ )
174
+ return response
175
+
176
+ def uninstall_assistant(
177
+ self,
178
+ vendor: VendorType,
179
+ codemie_id: str,
180
+ ) -> VendorAssistantUninstallResponse:
181
+ """Uninstall/deactivate a vendor assistant.
182
+
183
+ Args:
184
+ vendor: Cloud vendor type
185
+ codemie_id: CodeMie assistant ID from installation
186
+
187
+ Returns:
188
+ VendorAssistantUninstallResponse with success status
189
+ """
190
+ logger.info(f"Uninstalling assistant with CodeMie ID: {codemie_id}")
191
+ response = self.vendor_assistant_service.uninstall_assistant(
192
+ vendor=vendor, ai_run_id=codemie_id
193
+ )
194
+ if response.success:
195
+ logger.info(f"Successfully uninstalled assistant {codemie_id}")
196
+ else:
197
+ logger.warning(f"Failed to uninstall assistant {codemie_id}")
198
+ return response
199
+
200
+ def get_prepared_assistant(
201
+ self,
202
+ assistants: List[VendorAssistant],
203
+ ) -> Optional[VendorAssistant]:
204
+ """Get first PREPARED assistant from the list.
205
+
206
+ Args:
207
+ assistants: List of vendor assistants
208
+
209
+ Returns:
210
+ First PREPARED assistant or first assistant if none are PREPARED
211
+ """
212
+ return next(
213
+ (a for a in assistants if a.status == VendorAssistantStatus.PREPARED),
214
+ assistants[0] if assistants else None,
215
+ )
216
+
217
+ def get_non_draft_alias(
218
+ self,
219
+ aliases: List,
220
+ ) -> Optional:
221
+ """Get first non-DRAFT alias from the list.
222
+
223
+ Args:
224
+ aliases: List of vendor assistant aliases
225
+
226
+ Returns:
227
+ First non-DRAFT alias or first alias if all are DRAFT
228
+ """
229
+ return next(
230
+ (a for a in aliases if a.version != DRAFT_VERSION),
231
+ aliases[0] if aliases else None,
232
+ )
233
+
234
+ def find_first_available_assistant(
235
+ self,
236
+ vendor: VendorType,
237
+ setting_id: str,
238
+ ) -> Optional[tuple[VendorAssistant, str]]:
239
+ """Find the first available (PREPARED) assistant with an alias.
240
+
241
+ Args:
242
+ vendor: Cloud vendor type
243
+ setting_id: ID of the vendor setting
244
+
245
+ Returns:
246
+ Tuple of (VendorAssistant, alias_id) or None if no available assistant found
247
+ """
248
+ logger.info(
249
+ f"Searching for available assistant in {vendor.value} setting {setting_id}"
250
+ )
251
+ assistants_response = self.get_assistants(vendor=vendor, setting_id=setting_id)
252
+
253
+ for assistant in assistants_response.data:
254
+ if assistant.status.value == "PREPARED":
255
+ # Get aliases for this assistant
256
+ aliases_response = self.get_assistant_aliases(
257
+ vendor=vendor, assistant_id=assistant.id, setting_id=setting_id
258
+ )
259
+ if aliases_response.data:
260
+ first_alias = aliases_response.data[0]
261
+ logger.info(
262
+ f"Found available assistant: {assistant.name} (ID: {assistant.id}, Alias: {first_alias.id})"
263
+ )
264
+ return assistant, first_alias.id
265
+
266
+ logger.warning(
267
+ f"No available assistant found for {vendor.value} setting {setting_id}"
268
+ )
269
+ return None
270
+
271
+ def install_first_available_assistant(
272
+ self,
273
+ vendor: VendorType,
274
+ setting_id: str,
275
+ ) -> Optional[str]:
276
+ """Find and install the first available assistant.
277
+
278
+ Args:
279
+ vendor: Cloud vendor type
280
+ setting_id: ID of the vendor setting
281
+
282
+ Returns:
283
+ CodeMie ID of the installed assistant or None if no assistant available
284
+ """
285
+ result = self.find_first_available_assistant(
286
+ vendor=vendor, setting_id=setting_id
287
+ )
288
+ if not result:
289
+ return None
290
+
291
+ assistant, alias_id = result
292
+ install_request = VendorAssistantInstallRequest(
293
+ id=assistant.id,
294
+ agentAliasId=alias_id,
295
+ setting_id=setting_id,
296
+ )
297
+
298
+ install_response = self.install_assistants(
299
+ vendor=vendor, assistants=[install_request]
300
+ )
301
+
302
+ if install_response.summary:
303
+ return install_response.summary[0].aiRunId
304
+
305
+ return None
306
+
307
+ def find_setting_for_integration(
308
+ self,
309
+ vendor: VendorType,
310
+ integration_id: str,
311
+ ):
312
+ """Find setting for an integration by paginating through all settings.
313
+
314
+ Args:
315
+ vendor: Type of vendor (AWS, AZURE, GCP)
316
+ integration_id: ID of the integration to find (searches by setting_id)
317
+
318
+ Returns:
319
+ VendorAssistantSetting or None if not found
320
+ """
321
+ page = 0
322
+ per_page = 50
323
+
324
+ while True:
325
+ settings_response = self.get_assistant_settings(
326
+ vendor=vendor,
327
+ page=page,
328
+ per_page=per_page,
329
+ )
330
+
331
+ # Find the setting for our integration by setting_id
332
+ for s in settings_response.data:
333
+ if s.setting_id == integration_id:
334
+ return s
335
+
336
+ # Check if there are more pages
337
+ if page >= settings_response.pagination.pages - 1:
338
+ break
339
+
340
+ page += 1
341
+
342
+ logger.warning(f"Setting not found for integration ID '{integration_id}'")
343
+ return None