vellum-ai 0.11.7__py3-none-any.whl → 0.11.9__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,7 +17,7 @@ class BaseClientWrapper:
17
17
  headers: typing.Dict[str, str] = {
18
18
  "X-Fern-Language": "Python",
19
19
  "X-Fern-SDK-Name": "vellum-ai",
20
- "X-Fern-SDK-Version": "0.11.7",
20
+ "X-Fern-SDK-Version": "0.11.9",
21
21
  }
22
22
  headers["X_API_KEY"] = self.api_key
23
23
  return headers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.11.7
3
+ Version: 0.11.9
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -1,17 +1,17 @@
1
1
  vellum_cli/CONTRIBUTING.md,sha256=FtDC7BGxSeMnwCXAUssFsAIElXtmJE-O5Z7BpolcgvI,2935
2
2
  vellum_cli/README.md,sha256=2NudRoLzWxNKqnuVy1JuQ7DerIaxWGYkrH8kMd-asIE,90
3
- vellum_cli/__init__.py,sha256=pftUQ6FiyfebNEB8xcfwzLjpfFDCAiH15xHBU6xr_wY,6733
3
+ vellum_cli/__init__.py,sha256=XG6aC1NSPfBjNFzqiy9Lbk4DnELCKO8lpIZ3jeJR0r0,6990
4
4
  vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
5
5
  vellum_cli/config.py,sha256=wJQnv3tCgu1BOugg0AOP94yQ-x1yAg8juX_QoFN9Y7w,5223
6
6
  vellum_cli/image_push.py,sha256=SJwhwWJsLjwGNezNVd_oCVpFMfPsAB3dfLWmriZZUtw,4419
7
7
  vellum_cli/logger.py,sha256=PuRFa0WCh4sAGFS5aqWB0QIYpS6nBWwPJrIXpWxugV4,1022
8
- vellum_cli/pull.py,sha256=6wIiorqSx2rmR6atZJHHBuLSviocxK_n0DQxEDGmCzo,4008
8
+ vellum_cli/pull.py,sha256=EkQirsTe0KCpJ8oHTE3S9_M2XHSrb2wrXNq4hTkMZng,5770
9
9
  vellum_cli/push.py,sha256=kbvlzZ9KnkS5DxxKHQP5ZvHHk1-CbCDg9LqnIRAWyt4,5258
10
10
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  vellum_cli/tests/conftest.py,sha256=eFGwBxib3Nki830lIFintB0b6r4x8T_KMnmzhlTY5x0,1337
12
12
  vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
13
13
  vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
14
- vellum_cli/tests/test_pull.py,sha256=N6ZphvHYGokclbpbTpgOmpu_m2GtocDEesbdeHFjO5Y,13194
14
+ vellum_cli/tests/test_pull.py,sha256=pGqpBkahC360UITDE8BlcJ7LPd9DyRPn4NrCNdkQmAQ,15907
15
15
  vellum_cli/tests/test_push.py,sha256=V2iGcskh2X3OHj2uV5Vx_BhmtyfmUkyx0lrp8DDOExc,5824
16
16
  vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -39,7 +39,7 @@ vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=AqUlItgSZij12qRKguKV
39
39
  vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=BM3nfL0-D8x91xW0MGhnJFo45ZgGLXDqdbiSGoSuXN0,3244
40
40
  vellum_ee/workflows/display/nodes/vellum/note_node.py,sha256=9VpC3h0RYOxJuRbjDwidBYlLKakkmlEnDMBh2C7lHcY,1107
41
41
  vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=gLRkizwyw21-Z12IyDbdOJpXayiZZd4HWd6qgZQg8sc,3106
42
- vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=YkHGcjcoI3LqBkT5dmRZjHZt7mOIllwwvP6zaDKUjGU,8682
42
+ vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=yH_xeb03kLsfTbhrZL7HPjNLGP9SepFcBjDHY7CggOo,8692
43
43
  vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=zOp4voBSgB3MR1R93wTOrsiiara_hxEAYFupLl_SvTA,2657
44
44
  vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=UNYxoE-89agE8ugK0aWg_uN61jPqlC2VSxWHk568sN4,3324
45
45
  vellum_ee/workflows/display/nodes/vellum/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -58,6 +58,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subwo
58
58
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=H1bVDG_mFPokJ7OYrnl9rM9M3gEa5bctGmhUuKccB4U,15950
59
59
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=vm-dRH_Y-qU9whkwBUNnhVPYL_Ua6cqpaDsDSEgRkxo,9998
60
60
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py,sha256=NkpgaTbu6nLr3iwgsSNtiHyiNDCUaFakd1JaoW6CC6Y,9489
61
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py,sha256=9R6ELHBn9tsp3cy15q1qp1OByyCxFOVdrM67EwCYY50,12984
61
62
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py,sha256=8bz0vm_EyQKSjnwS5vqqgnjE9ygvm-CaPKcwCfeOrlo,12704
62
63
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=xG8nKA1iKXxUe1fnD2X6qm7cUGW14iq2P-L16zhcKC8,4271
63
64
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=1_02RbghUwhKMr8VtRaPjHOXAX59hgWw1rJ2EDyKs-E,2880
@@ -78,7 +79,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
78
79
  vellum/client/__init__.py,sha256=o4m7iRZWEV8rP3GkdaztHAjNmjxjWERlarviFoHzuKI,110927
79
80
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
80
81
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
81
- vellum/client/core/client_wrapper.py,sha256=eghuX9VDHvuYYt-Wqvz8ty2UvE1SVCNJ9e3eEKHptZA,1890
82
+ vellum/client/core/client_wrapper.py,sha256=7ETrjiHmBNoSjt9dOpoOQoV1KfdagFOllIIAwyOIi8U,1890
82
83
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
83
84
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
84
85
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -1377,8 +1378,8 @@ vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528
1377
1378
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1378
1379
  vellum/workflows/workflows/base.py,sha256=mnI-kZ78yt7u6NFSTUo-tYjDnarP-RJ7uZjwjCn6PCQ,16795
1379
1380
  vellum/workflows/workflows/event_filters.py,sha256=-uQcMB7IpPd-idMku8f2QNVhPXPFWo6FZLlGjRf8rCo,1996
1380
- vellum_ai-0.11.7.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1381
- vellum_ai-0.11.7.dist-info/METADATA,sha256=Ctay-bB1zitkr2zkIvFyJ5Rp9ocF0Vy0_2WpFR9Qd1U,5128
1382
- vellum_ai-0.11.7.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
1383
- vellum_ai-0.11.7.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1384
- vellum_ai-0.11.7.dist-info/RECORD,,
1381
+ vellum_ai-0.11.9.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1382
+ vellum_ai-0.11.9.dist-info/METADATA,sha256=mbIOikcPuEIU344kVitGc9qdEQCbVQn5_-GrKT7XgdI,5128
1383
+ vellum_ai-0.11.9.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
1384
+ vellum_ai-0.11.9.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1385
+ vellum_ai-0.11.9.dist-info/RECORD,,
vellum_cli/__init__.py CHANGED
@@ -148,6 +148,11 @@ def pull(
148
148
  Should only be used for debugging purposes.""",
149
149
  )
150
150
  @click.option("--workflow-sandbox-id", type=str, help="Pull the Workflow from a specific Sandbox ID")
151
+ @click.option(
152
+ "--workflow-deployment",
153
+ type=str,
154
+ help="""Pull the Workflow from a specific Deployment. Can use the name or the ID of the Deployment.""",
155
+ )
151
156
  @click.option(
152
157
  "--exclude-code",
153
158
  is_flag=True,
@@ -158,6 +163,7 @@ def workflows_pull(
158
163
  module: Optional[str],
159
164
  include_json: Optional[bool],
160
165
  workflow_sandbox_id: Optional[str],
166
+ workflow_deployment: Optional[str],
161
167
  exclude_code: Optional[bool],
162
168
  ) -> None:
163
169
  """
@@ -169,6 +175,7 @@ def workflows_pull(
169
175
  module=module,
170
176
  include_json=include_json,
171
177
  workflow_sandbox_id=workflow_sandbox_id,
178
+ workflow_deployment=workflow_deployment,
172
179
  exclude_code=exclude_code,
173
180
  )
174
181
 
vellum_cli/pull.py CHANGED
@@ -1,39 +1,84 @@
1
1
  import io
2
2
  import os
3
3
  from pathlib import Path
4
+ from uuid import UUID
4
5
  import zipfile
5
- from typing import Optional
6
+ from typing import Optional, Union
6
7
 
7
8
  from dotenv import load_dotenv
9
+ from pydash import snake_case
8
10
 
11
+ from vellum.client.core.pydantic_utilities import UniversalBaseModel
9
12
  from vellum.workflows.vellum_client import create_vellum_client
10
13
  from vellum_cli.config import VellumCliConfig, WorkflowConfig, load_vellum_cli_config
11
14
  from vellum_cli.logger import load_cli_logger
12
15
 
13
16
 
14
- def resolve_workflow_config(
17
+ def _is_valid_uuid(val: Union[str, UUID, None]) -> bool:
18
+ try:
19
+ UUID(str(val))
20
+ return True
21
+ except (ValueError, TypeError):
22
+ return False
23
+
24
+
25
+ class WorkflowConfigResolutionResult(UniversalBaseModel):
26
+ workflow_config: Optional[WorkflowConfig] = None
27
+ pk: Optional[str] = None
28
+
29
+
30
+ def _resolve_workflow_config(
15
31
  config: VellumCliConfig,
16
32
  module: Optional[str] = None,
17
33
  workflow_sandbox_id: Optional[str] = None,
18
- ) -> Optional[WorkflowConfig]:
34
+ workflow_deployment: Optional[str] = None,
35
+ ) -> WorkflowConfigResolutionResult:
36
+ if workflow_sandbox_id and workflow_deployment:
37
+ raise ValueError("Cannot specify both workflow_sandbox_id and workflow_deployment")
38
+
19
39
  if module:
20
- return next((w for w in config.workflows if w.module == module), None)
40
+ workflow_config = next((w for w in config.workflows if w.module == module), None)
41
+ return WorkflowConfigResolutionResult(
42
+ workflow_config=workflow_config,
43
+ pk=workflow_config.workflow_sandbox_id if workflow_config else None,
44
+ )
21
45
  elif workflow_sandbox_id:
22
46
  workflow_config = WorkflowConfig(
23
47
  workflow_sandbox_id=workflow_sandbox_id,
24
48
  module=f"workflow_{workflow_sandbox_id.split('-')[0]}",
25
49
  )
26
50
  config.workflows.append(workflow_config)
27
- return workflow_config
51
+ return WorkflowConfigResolutionResult(
52
+ workflow_config=workflow_config,
53
+ pk=workflow_config.workflow_sandbox_id,
54
+ )
55
+ elif workflow_deployment:
56
+ module = (
57
+ f"workflow_{workflow_deployment.split('-')[0]}"
58
+ if _is_valid_uuid(workflow_deployment)
59
+ else snake_case(workflow_deployment)
60
+ )
61
+ workflow_config = WorkflowConfig(
62
+ module=module,
63
+ )
64
+ config.workflows.append(workflow_config)
65
+ return WorkflowConfigResolutionResult(
66
+ workflow_config=workflow_config,
67
+ pk=workflow_deployment,
68
+ )
28
69
  elif config.workflows:
29
- return config.workflows[0]
70
+ return WorkflowConfigResolutionResult(
71
+ workflow_config=config.workflows[0],
72
+ pk=config.workflows[0].workflow_sandbox_id,
73
+ )
30
74
 
31
- return None
75
+ return WorkflowConfigResolutionResult()
32
76
 
33
77
 
34
78
  def pull_command(
35
79
  module: Optional[str] = None,
36
80
  workflow_sandbox_id: Optional[str] = None,
81
+ workflow_deployment: Optional[str] = None,
37
82
  include_json: Optional[bool] = None,
38
83
  exclude_code: Optional[bool] = None,
39
84
  ) -> None:
@@ -41,17 +86,20 @@ def pull_command(
41
86
  logger = load_cli_logger()
42
87
  config = load_vellum_cli_config()
43
88
 
44
- workflow_config = resolve_workflow_config(
45
- config,
46
- module,
47
- workflow_sandbox_id,
89
+ workflow_config_result = _resolve_workflow_config(
90
+ config=config,
91
+ module=module,
92
+ workflow_sandbox_id=workflow_sandbox_id,
93
+ workflow_deployment=workflow_deployment,
48
94
  )
49
95
  save_lock_file = not module
50
96
 
97
+ workflow_config = workflow_config_result.workflow_config
51
98
  if not workflow_config:
52
99
  raise ValueError("No workflow config found in project to pull from.")
53
100
 
54
- if not workflow_config.workflow_sandbox_id:
101
+ pk = workflow_config_result.pk
102
+ if not pk:
55
103
  raise ValueError("No workflow sandbox ID found in project to pull from.")
56
104
 
57
105
  logger.info(f"Pulling workflow into {workflow_config.module}")
@@ -63,7 +111,7 @@ def pull_command(
63
111
  query_parameters["exclude_code"] = exclude_code
64
112
 
65
113
  response = client.workflows.pull(
66
- workflow_config.workflow_sandbox_id,
114
+ pk,
67
115
  request_options={"additional_query_parameters": query_parameters},
68
116
  )
69
117
 
@@ -164,6 +164,86 @@ def test_pull__sandbox_id_with_other_workflow_configured(vellum_client, mock_mod
164
164
  assert f.read() == "print('hello')"
165
165
 
166
166
 
167
+ def test_pull__workflow_deployment_with_no_config(vellum_client):
168
+ # GIVEN a workflow deployment
169
+ workflow_deployment = "my-deployment"
170
+
171
+ # AND the workflow pull API call returns a zip file
172
+ vellum_client.workflows.pull.return_value = iter([_zip_file_map({"workflow.py": "print('hello')"})])
173
+
174
+ # AND we are currently in a new directory
175
+ current_dir = os.getcwd()
176
+ temp_dir = tempfile.mkdtemp()
177
+ os.chdir(temp_dir)
178
+
179
+ # WHEN the user runs the pull command with the workflow deployment
180
+ runner = CliRunner()
181
+ result = runner.invoke(cli_main, ["workflows", "pull", "--workflow-deployment", workflow_deployment])
182
+ os.chdir(current_dir)
183
+
184
+ # THEN the command returns successfully
185
+ assert result.exit_code == 0
186
+
187
+ # AND the pull api is called with the workflow deployment
188
+ vellum_client.workflows.pull.assert_called_once()
189
+ workflow_py = os.path.join(temp_dir, "my_deployment", "workflow.py")
190
+ assert os.path.exists(workflow_py)
191
+ with open(workflow_py) as f:
192
+ assert f.read() == "print('hello')"
193
+
194
+ # AND the vellum.lock.json file is created
195
+ vellum_lock_json = os.path.join(temp_dir, "vellum.lock.json")
196
+ assert os.path.exists(vellum_lock_json)
197
+ with open(vellum_lock_json) as f:
198
+ lock_data = json.loads(f.read())
199
+ assert lock_data == {
200
+ "version": "1.0",
201
+ "workflows": [
202
+ {
203
+ "module": "my_deployment",
204
+ "workflow_sandbox_id": None,
205
+ "ignore": None,
206
+ "deployments": [],
207
+ }
208
+ ],
209
+ }
210
+
211
+
212
+ def test_pull__both_workflow_sandbox_id_and_deployment(vellum_client):
213
+ # GIVEN a workflow sandbox id
214
+ workflow_sandbox_id = "87654321-0000-0000-0000-000000000000"
215
+
216
+ # AND a workflow deployment
217
+ workflow_deployment = "my-deployment"
218
+
219
+ # AND the workflow pull API call returns a zip file
220
+ vellum_client.workflows.pull.return_value = iter([_zip_file_map({"workflow.py": "print('hello')"})])
221
+
222
+ # AND we are currently in a new directory
223
+ current_dir = os.getcwd()
224
+ temp_dir = tempfile.mkdtemp()
225
+ os.chdir(temp_dir)
226
+
227
+ # WHEN the user runs the pull command with the workflow deployment
228
+ runner = CliRunner()
229
+ result = runner.invoke(
230
+ cli_main,
231
+ [
232
+ "workflows",
233
+ "pull",
234
+ "--workflow-sandbox-id",
235
+ workflow_sandbox_id,
236
+ "--workflow-deployment",
237
+ workflow_deployment,
238
+ ],
239
+ )
240
+ os.chdir(current_dir)
241
+
242
+ # THEN the command returns successfully
243
+ assert result.exit_code == 1
244
+ assert "Cannot specify both workflow_sandbox_id and workflow_deployment" == str(result.exception)
245
+
246
+
167
247
  def test_pull__remove_missing_files(vellum_client, mock_module):
168
248
  # GIVEN a module on the user's filesystem
169
249
  temp_dir = mock_module.temp_dir
@@ -154,12 +154,12 @@ class BaseSearchNodeDisplay(BaseNodeVellumDisplay[_SearchNodeType], Generic[_Sea
154
154
  lhs_query_input_id = (
155
155
  self.input_variable_ids_by_logical_id[lhs_variable_id]
156
156
  if self.input_variable_ids_by_logical_id
157
- else uuid4_from_hash(f"{self.node_id}|{hash(tuple(path))}")
157
+ else str(uuid4_from_hash(f"{self.node_id}|{hash(tuple(path))}"))
158
158
  )
159
159
  rhs_query_input_id = (
160
160
  self.input_variable_ids_by_logical_id[rhs_variable_id]
161
161
  if self.input_variable_ids_by_logical_id
162
- else uuid4_from_hash(f"{self.node_id}|{hash(tuple(path))}")
162
+ else str(uuid4_from_hash(f"{self.node_id}|{hash(tuple(path))}"))
163
163
  )
164
164
 
165
165
  return (
@@ -0,0 +1,308 @@
1
+ from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
2
+ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
3
+
4
+ from tests.workflows.basic_search_node.workflow import BasicSearchWorkflow
5
+
6
+
7
+ def test_serialize_workflow():
8
+ # GIVEN a Workflow with a search node
9
+ # WHEN we serialize it
10
+
11
+ workflow_display = get_workflow_display(
12
+ base_display_class=VellumWorkflowDisplay, workflow_class=BasicSearchWorkflow
13
+ )
14
+
15
+ serialized_workflow: dict = workflow_display.serialize()
16
+
17
+ # THEN we should get a serialized representation of the workflow
18
+ assert serialized_workflow.keys() == {"workflow_raw_data", "input_variables", "output_variables"}
19
+
20
+ # AND its input variables should be what we expect
21
+ input_variables = serialized_workflow["input_variables"]
22
+ assert len(input_variables) == 1
23
+ assert input_variables == [
24
+ {
25
+ "id": "6e405c6c-36eb-4c06-9d54-ae06cccce585",
26
+ "key": "query",
27
+ "type": "STRING",
28
+ "default": None,
29
+ "required": True,
30
+ "extensions": {"color": None},
31
+ }
32
+ ]
33
+
34
+ # AND its output variables should be what we expect
35
+ output_variables = serialized_workflow["output_variables"]
36
+ assert len(output_variables) == 1
37
+ assert output_variables == [{"id": "27424f7d-9767-4059-bdcf-c2be8b798fd7", "key": "text", "type": "STRING"}]
38
+
39
+ # AND its raw data is what we expect
40
+ workflow_raw_data = serialized_workflow["workflow_raw_data"]
41
+ assert workflow_raw_data.keys() == {"nodes", "edges", "display_data", "definition"}
42
+ assert len(workflow_raw_data["nodes"]) == 3
43
+ assert len(workflow_raw_data["edges"]) == 2
44
+
45
+ # AND each node should be serialized correctly
46
+ entrypoint_node = workflow_raw_data["nodes"][0]
47
+ assert entrypoint_node == {
48
+ "id": "06671b25-5c6b-4675-8c74-6c396a608728",
49
+ "type": "ENTRYPOINT",
50
+ "inputs": [],
51
+ "data": {"label": "Entrypoint Node", "source_handle_id": "df80b4aa-2ba1-49a2-8375-fb1f78eee31f"},
52
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
53
+ "definition": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"], "bases": []},
54
+ }
55
+
56
+ search_node = workflow_raw_data["nodes"][1]
57
+ assert search_node == {
58
+ "id": "ab3a1413-c7b5-4cb0-a2d4-f5ab7d1d65b4",
59
+ "type": "SEARCH",
60
+ "inputs": [
61
+ {
62
+ "id": "49d21956-6e62-472b-b62a-7ec65faea1fd",
63
+ "key": "query",
64
+ "value": {
65
+ "rules": [
66
+ {
67
+ "type": "INPUT_VARIABLE",
68
+ "data": {"input_variable_id": "6e405c6c-36eb-4c06-9d54-ae06cccce585"},
69
+ }
70
+ ],
71
+ "combinator": "OR",
72
+ },
73
+ },
74
+ {
75
+ "id": "8cb28a69-088d-410d-bd0d-886d57ce7b64",
76
+ "key": "document_index_id",
77
+ "value": {
78
+ "rules": [{"type": "CONSTANT_VALUE", "data": {"type": "STRING", "value": "name"}}],
79
+ "combinator": "OR",
80
+ },
81
+ },
82
+ {
83
+ "id": "983f2b7f-ad86-45cf-b04b-08724af27236",
84
+ "key": "weights",
85
+ "value": {
86
+ "rules": [{"type": "CONSTANT_VALUE", "data": {"type": "JSON", "value": None}}],
87
+ "combinator": "OR",
88
+ },
89
+ },
90
+ {
91
+ "id": "8072ec05-5fe4-47db-bc48-4c20ce49e123",
92
+ "key": "limit",
93
+ "value": {
94
+ "rules": [{"type": "CONSTANT_VALUE", "data": {"type": "JSON", "value": None}}],
95
+ "combinator": "OR",
96
+ },
97
+ },
98
+ {
99
+ "id": "051c5d2e-4667-4ae2-9202-1076b21adf7b",
100
+ "key": "separator",
101
+ "value": {
102
+ "rules": [{"type": "CONSTANT_VALUE", "data": {"type": "STRING", "value": "\n\n#####\n\n"}}],
103
+ "combinator": "OR",
104
+ },
105
+ },
106
+ {
107
+ "id": "8aac5dac-209e-48f3-97e1-0a39e4cd98d5",
108
+ "key": "result_merging_enabled",
109
+ "value": {
110
+ "rules": [{"type": "CONSTANT_VALUE", "data": {"type": "STRING", "value": "False"}}],
111
+ "combinator": "OR",
112
+ },
113
+ },
114
+ {
115
+ "id": "036dee8f-194a-4b92-9739-69c98a4aa1b9",
116
+ "key": "external_id_filters",
117
+ "value": {
118
+ "rules": [{"type": "CONSTANT_VALUE", "data": {"type": "JSON", "value": None}}],
119
+ "combinator": "OR",
120
+ },
121
+ },
122
+ {
123
+ "id": "855d3f57-e633-467e-a348-a394360247df",
124
+ "key": "metadata_filters",
125
+ "value": {
126
+ "rules": [
127
+ {
128
+ "type": "CONSTANT_VALUE",
129
+ "data": {
130
+ "type": "JSON",
131
+ "value": {
132
+ "type": "LOGICAL_CONDITION_GROUP",
133
+ "combinator": "AND",
134
+ "conditions": [
135
+ {
136
+ "type": "LOGICAL_CONDITION",
137
+ "lhs_variable_id": "a6322ca2-8b65-4d26-b3a1-f926dcada0fa",
138
+ "operator": "=",
139
+ "rhs_variable_id": "c539a2e2-0873-43b0-ae21-81790bb1c4cb",
140
+ },
141
+ {
142
+ "type": "LOGICAL_CONDITION",
143
+ "lhs_variable_id": "a89483b6-6850-4105-8c4e-ec0fd197cd43",
144
+ "operator": "=",
145
+ "rhs_variable_id": "847b8ee0-2c37-4e41-9dea-b4ba3579e2c1",
146
+ },
147
+ ],
148
+ "negated": False,
149
+ },
150
+ },
151
+ }
152
+ ],
153
+ "combinator": "OR",
154
+ },
155
+ },
156
+ {
157
+ "id": "a6322ca2-8b65-4d26-b3a1-f926dcada0fa",
158
+ "key": "vellum-query-builder-variable-a6322ca2-8b65-4d26-b3a1-f926dcada0fa",
159
+ "value": {
160
+ "rules": [
161
+ {
162
+ "type": "INPUT_VARIABLE",
163
+ "data": {"input_variable_id": "8ffffeb2-79b3-4105-acc7-78b0267da955"},
164
+ }
165
+ ],
166
+ "combinator": "OR",
167
+ },
168
+ },
169
+ {
170
+ "id": "c539a2e2-0873-43b0-ae21-81790bb1c4cb",
171
+ "key": "vellum-query-builder-variable-c539a2e2-0873-43b0-ae21-81790bb1c4cb",
172
+ "value": {
173
+ "rules": [
174
+ {
175
+ "type": "INPUT_VARIABLE",
176
+ "data": {"input_variable_id": "8ffffeb2-79b3-4105-acc7-78b0267da955"},
177
+ }
178
+ ],
179
+ "combinator": "OR",
180
+ },
181
+ },
182
+ {
183
+ "id": "a89483b6-6850-4105-8c4e-ec0fd197cd43",
184
+ "key": "vellum-query-builder-variable-a89483b6-6850-4105-8c4e-ec0fd197cd43",
185
+ "value": {
186
+ "rules": [
187
+ {
188
+ "type": "INPUT_VARIABLE",
189
+ "data": {"input_variable_id": "f5eee974-b0c3-4775-bc8a-679a9e99d7ba"},
190
+ }
191
+ ],
192
+ "combinator": "OR",
193
+ },
194
+ },
195
+ {
196
+ "id": "847b8ee0-2c37-4e41-9dea-b4ba3579e2c1",
197
+ "key": "vellum-query-builder-variable-847b8ee0-2c37-4e41-9dea-b4ba3579e2c1",
198
+ "value": {
199
+ "rules": [
200
+ {
201
+ "type": "INPUT_VARIABLE",
202
+ "data": {"input_variable_id": "f5eee974-b0c3-4775-bc8a-679a9e99d7ba"},
203
+ }
204
+ ],
205
+ "combinator": "OR",
206
+ },
207
+ },
208
+ ],
209
+ "data": {
210
+ "label": "Simple Search Node",
211
+ "results_output_id": "e27fa934-589a-48f7-92a9-dcc90710ec7b",
212
+ "text_output_id": "3f3bd066-ce73-46ee-84f1-d8ece69ecd8c",
213
+ "error_output_id": None,
214
+ "source_handle_id": "00ae06b3-f8d9-4ae6-9fbf-e4ff4d520e9b",
215
+ "target_handle_id": "6d50305f-588b-469f-a042-b0767d3f99b1",
216
+ "query_node_input_id": "49d21956-6e62-472b-b62a-7ec65faea1fd",
217
+ "document_index_node_input_id": "8cb28a69-088d-410d-bd0d-886d57ce7b64",
218
+ "weights_node_input_id": "983f2b7f-ad86-45cf-b04b-08724af27236",
219
+ "limit_node_input_id": "8072ec05-5fe4-47db-bc48-4c20ce49e123",
220
+ "separator_node_input_id": "051c5d2e-4667-4ae2-9202-1076b21adf7b",
221
+ "result_merging_enabled_node_input_id": "8aac5dac-209e-48f3-97e1-0a39e4cd98d5",
222
+ "external_id_filters_node_input_id": "036dee8f-194a-4b92-9739-69c98a4aa1b9",
223
+ "metadata_filters_node_input_id": "855d3f57-e633-467e-a348-a394360247df",
224
+ },
225
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
226
+ "definition": {
227
+ "name": "SimpleSearchNode",
228
+ "module": ["tests", "workflows", "basic_search_node", "workflow"],
229
+ "bases": [
230
+ {"name": "SearchNode", "module": ["vellum", "workflows", "nodes", "displayable", "search_node", "node"]}
231
+ ],
232
+ },
233
+ }
234
+
235
+ final_output_node = workflow_raw_data["nodes"][2]
236
+ assert final_output_node == {
237
+ "id": "4e466510-6756-403f-a182-56e5a2b85d94",
238
+ "type": "TERMINAL",
239
+ "data": {
240
+ "label": "Final Output",
241
+ "name": "text",
242
+ "target_handle_id": "cd8c736f-1b77-493d-b857-d8feb5c03b15",
243
+ "output_id": "27424f7d-9767-4059-bdcf-c2be8b798fd7",
244
+ "output_type": "STRING",
245
+ "node_input_id": "008eaf1d-98c0-4098-8839-5b94121394d7",
246
+ },
247
+ "inputs": [
248
+ {
249
+ "id": "008eaf1d-98c0-4098-8839-5b94121394d7",
250
+ "key": "node_input",
251
+ "value": {
252
+ "rules": [
253
+ {
254
+ "type": "NODE_OUTPUT",
255
+ "data": {
256
+ "node_id": "ab3a1413-c7b5-4cb0-a2d4-f5ab7d1d65b4",
257
+ "output_id": "3f3bd066-ce73-46ee-84f1-d8ece69ecd8c",
258
+ },
259
+ }
260
+ ],
261
+ "combinator": "OR",
262
+ },
263
+ }
264
+ ],
265
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
266
+ "definition": {
267
+ "name": "FinalOutputNode",
268
+ "module": ["vellum", "workflows", "nodes", "displayable", "final_output_node", "node"],
269
+ "bases": [{"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"], "bases": []}],
270
+ },
271
+ }
272
+
273
+ # AND each edge should be serialized correctly
274
+ serialized_edges = workflow_raw_data["edges"]
275
+ assert serialized_edges == [
276
+ {
277
+ "id": "06533904-4897-4a7a-aa8d-50419b3d33ae",
278
+ "source_node_id": "06671b25-5c6b-4675-8c74-6c396a608728",
279
+ "source_handle_id": "df80b4aa-2ba1-49a2-8375-fb1f78eee31f",
280
+ "target_node_id": "ab3a1413-c7b5-4cb0-a2d4-f5ab7d1d65b4",
281
+ "target_handle_id": "6d50305f-588b-469f-a042-b0767d3f99b1",
282
+ "type": "DEFAULT",
283
+ },
284
+ {
285
+ "id": "cb918deb-f546-47b5-8b6b-db0d22a29fd1",
286
+ "source_node_id": "ab3a1413-c7b5-4cb0-a2d4-f5ab7d1d65b4",
287
+ "source_handle_id": "00ae06b3-f8d9-4ae6-9fbf-e4ff4d520e9b",
288
+ "target_node_id": "4e466510-6756-403f-a182-56e5a2b85d94",
289
+ "target_handle_id": "cd8c736f-1b77-493d-b857-d8feb5c03b15",
290
+ "type": "DEFAULT",
291
+ },
292
+ ]
293
+
294
+ # AND the display data is what we expect
295
+ display_data = workflow_raw_data["display_data"]
296
+ assert display_data == {"viewport": {"x": 0.0, "y": 0.0, "zoom": 1.0}}
297
+
298
+ # AND the definition is what we expect
299
+ definition = workflow_raw_data["definition"]
300
+ assert definition == {
301
+ "name": "BasicSearchWorkflow",
302
+ "module": [
303
+ "tests",
304
+ "workflows",
305
+ "basic_search_node",
306
+ "workflow",
307
+ ],
308
+ }