codemie-test-harness 0.1.222__py3-none-any.whl → 0.1.224__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.
- codemie_test_harness/tests/conftest.py +13 -3
- codemie_test_harness/tests/enums/model_types.py +1 -0
- codemie_test_harness/tests/test_data/llm_test_data.py +1 -0
- codemie_test_harness/tests/test_data/vendor_workflow_test_data.py +50 -0
- codemie_test_harness/tests/utils/vendor_utils.py +8 -8
- codemie_test_harness/tests/utils/vendor_workflow_utils.py +418 -0
- codemie_test_harness/tests/vendor/assistants/test_vendor_assistants.py +5 -5
- codemie_test_harness/tests/vendor/assistants/test_vendor_assistants_endpoints.py +53 -43
- codemie_test_harness/tests/vendor/workflows/__init__.py +1 -0
- codemie_test_harness/tests/vendor/workflows/test_vendor_workflow_endpoints.py +341 -0
- codemie_test_harness/tests/vendor/workflows/test_vendor_workflows.py +63 -0
- {codemie_test_harness-0.1.222.dist-info → codemie_test_harness-0.1.224.dist-info}/METADATA +2 -2
- {codemie_test_harness-0.1.222.dist-info → codemie_test_harness-0.1.224.dist-info}/RECORD +15 -10
- {codemie_test_harness-0.1.222.dist-info → codemie_test_harness-0.1.224.dist-info}/WHEEL +0 -0
- {codemie_test_harness-0.1.222.dist-info → codemie_test_harness-0.1.224.dist-info}/entry_points.txt +0 -0
|
@@ -951,11 +951,21 @@ def integration(integration_utils):
|
|
|
951
951
|
|
|
952
952
|
|
|
953
953
|
@pytest.fixture(scope="session")
|
|
954
|
-
def
|
|
954
|
+
def vendor_assistant_utils():
|
|
955
955
|
"""Create VendorUtils instance for managing vendor assistants"""
|
|
956
|
-
from codemie_test_harness.tests.utils.vendor_utils import
|
|
956
|
+
from codemie_test_harness.tests.utils.vendor_utils import VendorAssistantUtils
|
|
957
957
|
|
|
958
|
-
return
|
|
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()
|
|
959
969
|
|
|
960
970
|
|
|
961
971
|
def pytest_sessionfinish(session):
|
|
@@ -56,6 +56,7 @@ MODEL_RESPONSES = [
|
|
|
56
56
|
LlmResponseData(ModelTypes.CLAUDE_4_1_OPUS, AWS_ENVS),
|
|
57
57
|
LlmResponseData(ModelTypes.CLAUDE_4_SONNET_1M, AWS_ENVS),
|
|
58
58
|
LlmResponseData(ModelTypes.CLAUDE_4_5_SONNET, AWS_ENVS),
|
|
59
|
+
LlmResponseData(ModelTypes.CLAUDE_4_5_HAIKU, AWS_ENVS),
|
|
59
60
|
# Other LLMs test data
|
|
60
61
|
LlmResponseData(ModelTypes.RLAB_QWQ_32B, OTHER_ENVS),
|
|
61
62
|
LlmResponseData(ModelTypes.DEEPSEEK_R1, OTHER_ENVS),
|
|
@@ -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
|
+
]
|
|
@@ -20,13 +20,13 @@ logger = setup_logger(__name__)
|
|
|
20
20
|
DRAFT_VERSION = "DRAFT"
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class
|
|
23
|
+
class VendorAssistantUtils:
|
|
24
24
|
"""Utility class for vendor assistant operations."""
|
|
25
25
|
|
|
26
26
|
def __init__(self):
|
|
27
27
|
"""Initialize VendorUtils with CodeMie client."""
|
|
28
28
|
self.client = get_client()
|
|
29
|
-
self.
|
|
29
|
+
self.vendor_assistant_service = self.client.vendor_assistants
|
|
30
30
|
|
|
31
31
|
def get_assistant_settings(
|
|
32
32
|
self,
|
|
@@ -47,7 +47,7 @@ class VendorUtils:
|
|
|
47
47
|
logger.info(
|
|
48
48
|
f"Getting assistant settings for {vendor.value} (page={page}, per_page={per_page})"
|
|
49
49
|
)
|
|
50
|
-
settings = self.
|
|
50
|
+
settings = self.vendor_assistant_service.get_assistant_settings(
|
|
51
51
|
vendor=vendor, page=page, per_page=per_page
|
|
52
52
|
)
|
|
53
53
|
logger.info(
|
|
@@ -76,7 +76,7 @@ class VendorUtils:
|
|
|
76
76
|
logger.info(
|
|
77
77
|
f"Getting assistants for {vendor.value} setting {setting_id} (per_page={per_page})"
|
|
78
78
|
)
|
|
79
|
-
assistants = self.
|
|
79
|
+
assistants = self.vendor_assistant_service.get_assistants(
|
|
80
80
|
vendor=vendor,
|
|
81
81
|
setting_id=setting_id,
|
|
82
82
|
per_page=per_page,
|
|
@@ -106,7 +106,7 @@ class VendorUtils:
|
|
|
106
106
|
logger.info(
|
|
107
107
|
f"Getting assistant {assistant_id} for {vendor.value} setting {setting_id}"
|
|
108
108
|
)
|
|
109
|
-
assistant = self.
|
|
109
|
+
assistant = self.vendor_assistant_service.get_assistant(
|
|
110
110
|
vendor=vendor, assistant_id=assistant_id, setting_id=setting_id
|
|
111
111
|
)
|
|
112
112
|
logger.info(
|
|
@@ -137,7 +137,7 @@ class VendorUtils:
|
|
|
137
137
|
logger.info(
|
|
138
138
|
f"Getting aliases for assistant {assistant_id} in {vendor.value} setting {setting_id}"
|
|
139
139
|
)
|
|
140
|
-
aliases = self.
|
|
140
|
+
aliases = self.vendor_assistant_service.get_assistant_aliases(
|
|
141
141
|
vendor=vendor,
|
|
142
142
|
assistant_id=assistant_id,
|
|
143
143
|
setting_id=setting_id,
|
|
@@ -164,7 +164,7 @@ class VendorUtils:
|
|
|
164
164
|
VendorAssistantInstallResponse containing installation summary with AI run IDs
|
|
165
165
|
"""
|
|
166
166
|
logger.info(f"Installing {len(assistants)} assistant(s) for {vendor.value}")
|
|
167
|
-
response = self.
|
|
167
|
+
response = self.vendor_assistant_service.install_assistants(
|
|
168
168
|
vendor=vendor, assistants=assistants
|
|
169
169
|
)
|
|
170
170
|
for item in response.summary:
|
|
@@ -188,7 +188,7 @@ class VendorUtils:
|
|
|
188
188
|
VendorAssistantUninstallResponse with success status
|
|
189
189
|
"""
|
|
190
190
|
logger.info(f"Uninstalling assistant with CodeMie ID: {codemie_id}")
|
|
191
|
-
response = self.
|
|
191
|
+
response = self.vendor_assistant_service.uninstall_assistant(
|
|
192
192
|
vendor=vendor, ai_run_id=codemie_id
|
|
193
193
|
)
|
|
194
194
|
if response.success:
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"""Utility class for managing vendor workflows (AWS Bedrock, Azure, GCP)."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional, List
|
|
4
|
+
from codemie_sdk.models.vendor_assistant import VendorType
|
|
5
|
+
from codemie_sdk.models.vendor_workflow import (
|
|
6
|
+
VendorWorkflowSettingsResponse,
|
|
7
|
+
VendorWorkflowsResponse,
|
|
8
|
+
VendorWorkflow,
|
|
9
|
+
VendorWorkflowAliasesResponse,
|
|
10
|
+
VendorWorkflowInstallRequest,
|
|
11
|
+
VendorWorkflowInstallResponse,
|
|
12
|
+
VendorWorkflowUninstallResponse,
|
|
13
|
+
VendorWorkflowStatus,
|
|
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 VendorWorkflowUtils:
|
|
24
|
+
"""Utility class for vendor workflow operations."""
|
|
25
|
+
|
|
26
|
+
def __init__(self):
|
|
27
|
+
"""Initialize VendorWorkflowUtils with CodeMie client."""
|
|
28
|
+
self.client = get_client()
|
|
29
|
+
self.vendor_workflow_service = self.client.vendor_workflows
|
|
30
|
+
|
|
31
|
+
def get_workflow_settings(
|
|
32
|
+
self,
|
|
33
|
+
vendor: VendorType,
|
|
34
|
+
page: int = 0,
|
|
35
|
+
per_page: int = 10,
|
|
36
|
+
) -> VendorWorkflowSettingsResponse:
|
|
37
|
+
"""Get workflow 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
|
+
VendorWorkflowSettingsResponse containing list of settings
|
|
46
|
+
"""
|
|
47
|
+
logger.info(
|
|
48
|
+
f"Getting workflow settings for {vendor.value} (page={page}, per_page={per_page})"
|
|
49
|
+
)
|
|
50
|
+
settings = self.vendor_workflow_service.get_workflow_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_workflows(
|
|
59
|
+
self,
|
|
60
|
+
vendor: VendorType,
|
|
61
|
+
setting_id: str,
|
|
62
|
+
per_page: int = 10,
|
|
63
|
+
next_token: Optional[str] = None,
|
|
64
|
+
) -> VendorWorkflowsResponse:
|
|
65
|
+
"""Get workflows 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
|
+
VendorWorkflowsResponse containing list of workflows
|
|
75
|
+
"""
|
|
76
|
+
logger.info(
|
|
77
|
+
f"Getting workflows for {vendor.value} setting {setting_id} (per_page={per_page})"
|
|
78
|
+
)
|
|
79
|
+
workflows = self.vendor_workflow_service.get_workflows(
|
|
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(workflows.data)} workflows for setting {setting_id}"
|
|
87
|
+
)
|
|
88
|
+
return workflows
|
|
89
|
+
|
|
90
|
+
def get_workflow(
|
|
91
|
+
self,
|
|
92
|
+
vendor: VendorType,
|
|
93
|
+
workflow_id: str,
|
|
94
|
+
setting_id: str,
|
|
95
|
+
) -> VendorWorkflow:
|
|
96
|
+
"""Get a specific workflow by ID.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
vendor: Cloud vendor type
|
|
100
|
+
workflow_id: ID of the workflow
|
|
101
|
+
setting_id: ID of the vendor setting
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
VendorWorkflow with workflow details
|
|
105
|
+
"""
|
|
106
|
+
logger.info(
|
|
107
|
+
f"Getting workflow {workflow_id} for {vendor.value} setting {setting_id}"
|
|
108
|
+
)
|
|
109
|
+
workflow = self.vendor_workflow_service.get_workflow(
|
|
110
|
+
vendor=vendor, workflow_id=workflow_id, setting_id=setting_id
|
|
111
|
+
)
|
|
112
|
+
logger.info(f"Retrieved workflow: {workflow.name} (status: {workflow.status})")
|
|
113
|
+
return workflow
|
|
114
|
+
|
|
115
|
+
def get_workflow_aliases(
|
|
116
|
+
self,
|
|
117
|
+
vendor: VendorType,
|
|
118
|
+
workflow_id: str,
|
|
119
|
+
setting_id: str,
|
|
120
|
+
per_page: int = 10,
|
|
121
|
+
next_token: Optional[str] = None,
|
|
122
|
+
) -> VendorWorkflowAliasesResponse:
|
|
123
|
+
"""Get aliases for a specific vendor workflow.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
vendor: Cloud vendor type
|
|
127
|
+
workflow_id: ID of the workflow
|
|
128
|
+
setting_id: ID of the vendor setting
|
|
129
|
+
per_page: Number of items per page
|
|
130
|
+
next_token: Token for pagination
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
VendorWorkflowAliasesResponse containing list of aliases
|
|
134
|
+
"""
|
|
135
|
+
logger.info(
|
|
136
|
+
f"Getting aliases for workflow {workflow_id} in {vendor.value} setting {setting_id}"
|
|
137
|
+
)
|
|
138
|
+
aliases = self.vendor_workflow_service.get_workflow_aliases(
|
|
139
|
+
vendor=vendor,
|
|
140
|
+
workflow_id=workflow_id,
|
|
141
|
+
setting_id=setting_id,
|
|
142
|
+
per_page=per_page,
|
|
143
|
+
next_token=next_token,
|
|
144
|
+
)
|
|
145
|
+
logger.info(f"Retrieved {len(aliases.data)} aliases for workflow {workflow_id}")
|
|
146
|
+
return aliases
|
|
147
|
+
|
|
148
|
+
def install_workflows(
|
|
149
|
+
self,
|
|
150
|
+
vendor: VendorType,
|
|
151
|
+
workflows: List[VendorWorkflowInstallRequest],
|
|
152
|
+
) -> VendorWorkflowInstallResponse:
|
|
153
|
+
"""Install/activate vendor workflows.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
vendor: Cloud vendor type
|
|
157
|
+
workflows: List of workflow installation requests
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
VendorWorkflowInstallResponse containing installation summary with AI run IDs
|
|
161
|
+
"""
|
|
162
|
+
logger.info(f"Installing {len(workflows)} workflow(s) for {vendor.value}")
|
|
163
|
+
response = self.vendor_workflow_service.install_workflows(
|
|
164
|
+
vendor=vendor, workflows=workflows
|
|
165
|
+
)
|
|
166
|
+
for item in response.summary:
|
|
167
|
+
logger.info(
|
|
168
|
+
f"Installed workflow {item.flowId} (alias: {item.flowAliasId}) -> CodeMie ID: {item.aiRunId}"
|
|
169
|
+
)
|
|
170
|
+
return response
|
|
171
|
+
|
|
172
|
+
def uninstall_workflow(
|
|
173
|
+
self,
|
|
174
|
+
vendor: VendorType,
|
|
175
|
+
codemie_id: str,
|
|
176
|
+
) -> VendorWorkflowUninstallResponse:
|
|
177
|
+
"""Uninstall/deactivate a vendor workflow.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
vendor: Cloud vendor type
|
|
181
|
+
codemie_id: CodeMie workflow ID from installation
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
VendorWorkflowUninstallResponse with success status
|
|
185
|
+
"""
|
|
186
|
+
logger.info(f"Uninstalling workflow with CodeMie ID: {codemie_id}")
|
|
187
|
+
response = self.vendor_workflow_service.uninstall_workflow(
|
|
188
|
+
vendor=vendor, ai_run_id=codemie_id
|
|
189
|
+
)
|
|
190
|
+
if response.success:
|
|
191
|
+
logger.info(f"Successfully uninstalled workflow {codemie_id}")
|
|
192
|
+
else:
|
|
193
|
+
logger.warning(f"Failed to uninstall workflow {codemie_id}")
|
|
194
|
+
return response
|
|
195
|
+
|
|
196
|
+
def get_prepared_workflow(
|
|
197
|
+
self,
|
|
198
|
+
workflows: List[VendorWorkflow],
|
|
199
|
+
) -> Optional[VendorWorkflow]:
|
|
200
|
+
"""Get first PREPARED workflow from the list.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
workflows: List of vendor workflows
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
First PREPARED workflow or first workflow if none are PREPARED
|
|
207
|
+
"""
|
|
208
|
+
return next(
|
|
209
|
+
(w for w in workflows if w.status == VendorWorkflowStatus.PREPARED),
|
|
210
|
+
workflows[0] if workflows else None,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
def get_non_draft_alias(
|
|
214
|
+
self,
|
|
215
|
+
aliases: List,
|
|
216
|
+
) -> Optional:
|
|
217
|
+
"""Get first non-DRAFT alias from the list.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
aliases: List of vendor workflow aliases
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
First non-DRAFT alias or first alias if all are DRAFT
|
|
224
|
+
"""
|
|
225
|
+
return next(
|
|
226
|
+
(a for a in aliases if a.version != DRAFT_VERSION),
|
|
227
|
+
aliases[0] if aliases else None,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
def find_workflow_by_name(
|
|
231
|
+
self,
|
|
232
|
+
vendor: VendorType,
|
|
233
|
+
setting_id: str,
|
|
234
|
+
workflow_name: str,
|
|
235
|
+
) -> Optional[tuple[VendorWorkflow, str]]:
|
|
236
|
+
"""Find a workflow by name and return it with an alias.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
vendor: Cloud vendor type
|
|
240
|
+
setting_id: ID of the vendor setting
|
|
241
|
+
workflow_name: Name of the workflow to find
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
Tuple of (VendorWorkflow, alias_id) or None if workflow not found
|
|
245
|
+
"""
|
|
246
|
+
logger.info(
|
|
247
|
+
f"Searching for workflow '{workflow_name}' in {vendor.value} setting {setting_id}"
|
|
248
|
+
)
|
|
249
|
+
workflows_response = self.get_workflows(vendor=vendor, setting_id=setting_id)
|
|
250
|
+
|
|
251
|
+
for workflow in workflows_response.data:
|
|
252
|
+
if (
|
|
253
|
+
workflow.name == workflow_name
|
|
254
|
+
and workflow.status == VendorWorkflowStatus.PREPARED
|
|
255
|
+
):
|
|
256
|
+
aliases_response = self.get_workflow_aliases(
|
|
257
|
+
vendor=vendor, workflow_id=workflow.id, setting_id=setting_id
|
|
258
|
+
)
|
|
259
|
+
if aliases_response.data:
|
|
260
|
+
non_draft_alias = self.get_non_draft_alias(aliases_response.data)
|
|
261
|
+
if non_draft_alias:
|
|
262
|
+
logger.info(
|
|
263
|
+
f"Found workflow: {workflow.name} (ID: {workflow.id}, Alias: {non_draft_alias.id})"
|
|
264
|
+
)
|
|
265
|
+
return workflow, non_draft_alias.id
|
|
266
|
+
|
|
267
|
+
logger.warning(
|
|
268
|
+
f"Workflow '{workflow_name}' not found for {vendor.value} setting {setting_id}"
|
|
269
|
+
)
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
def find_first_available_workflow(
|
|
273
|
+
self,
|
|
274
|
+
vendor: VendorType,
|
|
275
|
+
setting_id: str,
|
|
276
|
+
) -> Optional[tuple[VendorWorkflow, str]]:
|
|
277
|
+
"""Find the first available (PREPARED) workflow with an alias.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
vendor: Cloud vendor type
|
|
281
|
+
setting_id: ID of the vendor setting
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Tuple of (VendorWorkflow, alias_id) or None if no available workflow found
|
|
285
|
+
"""
|
|
286
|
+
logger.info(
|
|
287
|
+
f"Searching for available workflow in {vendor.value} setting {setting_id}"
|
|
288
|
+
)
|
|
289
|
+
workflows_response = self.get_workflows(vendor=vendor, setting_id=setting_id)
|
|
290
|
+
|
|
291
|
+
for workflow in workflows_response.data:
|
|
292
|
+
if workflow.status == VendorWorkflowStatus.PREPARED:
|
|
293
|
+
aliases_response = self.get_workflow_aliases(
|
|
294
|
+
vendor=vendor, workflow_id=workflow.id, setting_id=setting_id
|
|
295
|
+
)
|
|
296
|
+
if aliases_response.data:
|
|
297
|
+
first_alias = aliases_response.data[0]
|
|
298
|
+
logger.info(
|
|
299
|
+
f"Found available workflow: {workflow.name} (ID: {workflow.id}, Alias: {first_alias.id})"
|
|
300
|
+
)
|
|
301
|
+
return workflow, first_alias.id
|
|
302
|
+
|
|
303
|
+
logger.warning(
|
|
304
|
+
f"No available workflow found for {vendor.value} setting {setting_id}"
|
|
305
|
+
)
|
|
306
|
+
return None
|
|
307
|
+
|
|
308
|
+
def install_workflow_by_name(
|
|
309
|
+
self,
|
|
310
|
+
vendor: VendorType,
|
|
311
|
+
setting_id: str,
|
|
312
|
+
workflow_name: str,
|
|
313
|
+
) -> Optional[str]:
|
|
314
|
+
"""Find and install a workflow by name.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
vendor: Cloud vendor type
|
|
318
|
+
setting_id: ID of the vendor setting
|
|
319
|
+
workflow_name: Name of the workflow to install
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
CodeMie ID of the installed workflow or None if workflow not found
|
|
323
|
+
"""
|
|
324
|
+
result = self.find_workflow_by_name(
|
|
325
|
+
vendor=vendor, setting_id=setting_id, workflow_name=workflow_name
|
|
326
|
+
)
|
|
327
|
+
if not result:
|
|
328
|
+
return None
|
|
329
|
+
|
|
330
|
+
workflow, alias_id = result
|
|
331
|
+
install_request = VendorWorkflowInstallRequest(
|
|
332
|
+
id=workflow.id,
|
|
333
|
+
flowAliasId=alias_id,
|
|
334
|
+
setting_id=setting_id,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
install_response = self.install_workflows(
|
|
338
|
+
vendor=vendor, workflows=[install_request]
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
if install_response.summary:
|
|
342
|
+
return install_response.summary[0].aiRunId
|
|
343
|
+
|
|
344
|
+
return None
|
|
345
|
+
|
|
346
|
+
def install_first_available_workflow(
|
|
347
|
+
self,
|
|
348
|
+
vendor: VendorType,
|
|
349
|
+
setting_id: str,
|
|
350
|
+
) -> Optional[str]:
|
|
351
|
+
"""Find and install the first available workflow.
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
vendor: Cloud vendor type
|
|
355
|
+
setting_id: ID of the vendor setting
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
CodeMie ID of the installed workflow or None if no workflow available
|
|
359
|
+
"""
|
|
360
|
+
result = self.find_first_available_workflow(
|
|
361
|
+
vendor=vendor, setting_id=setting_id
|
|
362
|
+
)
|
|
363
|
+
if not result:
|
|
364
|
+
return None
|
|
365
|
+
|
|
366
|
+
workflow, alias_id = result
|
|
367
|
+
install_request = VendorWorkflowInstallRequest(
|
|
368
|
+
id=workflow.id,
|
|
369
|
+
flowAliasId=alias_id,
|
|
370
|
+
setting_id=setting_id,
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
install_response = self.install_workflows(
|
|
374
|
+
vendor=vendor, workflows=[install_request]
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
if install_response.summary:
|
|
378
|
+
return install_response.summary[0].aiRunId
|
|
379
|
+
|
|
380
|
+
return None
|
|
381
|
+
|
|
382
|
+
def find_setting_for_integration(
|
|
383
|
+
self,
|
|
384
|
+
vendor: VendorType,
|
|
385
|
+
integration_id: str,
|
|
386
|
+
):
|
|
387
|
+
"""Find setting for an integration by paginating through all settings.
|
|
388
|
+
|
|
389
|
+
Args:
|
|
390
|
+
vendor: Type of vendor (AWS, AZURE, GCP)
|
|
391
|
+
integration_id: ID of the integration to find (searches by setting_id)
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
VendorWorkflowSetting or None if not found
|
|
395
|
+
"""
|
|
396
|
+
page = 0
|
|
397
|
+
per_page = 50
|
|
398
|
+
|
|
399
|
+
while True:
|
|
400
|
+
settings_response = self.get_workflow_settings(
|
|
401
|
+
vendor=vendor,
|
|
402
|
+
page=page,
|
|
403
|
+
per_page=per_page,
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
# Find the setting for our integration by setting_id
|
|
407
|
+
for s in settings_response.data:
|
|
408
|
+
if s.setting_id == integration_id:
|
|
409
|
+
return s
|
|
410
|
+
|
|
411
|
+
# Check if there are more pages
|
|
412
|
+
if page >= settings_response.pagination.pages - 1:
|
|
413
|
+
break
|
|
414
|
+
|
|
415
|
+
page += 1
|
|
416
|
+
|
|
417
|
+
logger.warning(f"Setting not found for integration ID '{integration_id}'")
|
|
418
|
+
return None
|
|
@@ -12,7 +12,7 @@ from codemie_test_harness.tests.test_data.vendor_test_data import (
|
|
|
12
12
|
vendor_assistant_test_data,
|
|
13
13
|
)
|
|
14
14
|
def test_vendor_assistant_installation_and_chat(
|
|
15
|
-
|
|
15
|
+
vendor_assistant_utils,
|
|
16
16
|
integration,
|
|
17
17
|
assistant_utils,
|
|
18
18
|
similarity_check,
|
|
@@ -25,21 +25,21 @@ def test_vendor_assistant_installation_and_chat(
|
|
|
25
25
|
"""Test vendor assistant installation and chat functionality."""
|
|
26
26
|
_integration = integration(credential_type, credentials)
|
|
27
27
|
|
|
28
|
-
setting =
|
|
28
|
+
setting = vendor_assistant_utils.find_setting_for_integration(
|
|
29
29
|
vendor=vendor_type,
|
|
30
30
|
integration_id=_integration.id,
|
|
31
31
|
)
|
|
32
32
|
assert_that(setting, is_not(none()))
|
|
33
33
|
assert_that(setting.invalid or False, is_(False))
|
|
34
34
|
|
|
35
|
-
assistants_response =
|
|
35
|
+
assistants_response = vendor_assistant_utils.get_assistants(
|
|
36
36
|
vendor=vendor_type,
|
|
37
37
|
setting_id=setting.setting_id,
|
|
38
38
|
)
|
|
39
39
|
assert_that(assistants_response, is_not(none()))
|
|
40
40
|
assert_that(assistants_response.data, is_not(empty()))
|
|
41
41
|
|
|
42
|
-
codemie_id =
|
|
42
|
+
codemie_id = vendor_assistant_utils.install_first_available_assistant(
|
|
43
43
|
vendor=vendor_type,
|
|
44
44
|
setting_id=setting.setting_id,
|
|
45
45
|
)
|
|
@@ -58,7 +58,7 @@ def test_vendor_assistant_installation_and_chat(
|
|
|
58
58
|
|
|
59
59
|
similarity_check.check_similarity(response, expected_response)
|
|
60
60
|
|
|
61
|
-
uninstall_response =
|
|
61
|
+
uninstall_response = vendor_assistant_utils.uninstall_assistant(
|
|
62
62
|
vendor=vendor_type,
|
|
63
63
|
codemie_id=codemie_id,
|
|
64
64
|
)
|