vellum-ai 1.3.8__py3-none-any.whl → 1.3.9__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 (33) hide show
  1. vellum/client/core/client_wrapper.py +2 -2
  2. vellum/client/reference.md +71 -0
  3. vellum/client/resources/workflows/client.py +80 -0
  4. vellum/client/resources/workflows/raw_client.py +98 -0
  5. vellum/client/types/vellum_error.py +2 -1
  6. vellum/client/types/vellum_error_request.py +2 -1
  7. vellum/workflows/utils/tests/test_vellum_variables.py +7 -1
  8. vellum/workflows/utils/vellum_variables.py +42 -3
  9. {vellum_ai-1.3.8.dist-info → vellum_ai-1.3.9.dist-info}/METADATA +1 -1
  10. {vellum_ai-1.3.8.dist-info → vellum_ai-1.3.9.dist-info}/RECORD +33 -33
  11. vellum_ee/workflows/display/editor/types.py +2 -0
  12. vellum_ee/workflows/display/nodes/base_node_display.py +42 -14
  13. vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +64 -0
  14. vellum_ee/workflows/display/nodes/vellum/final_output_node.py +1 -1
  15. vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -1
  16. vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +12 -12
  17. vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +4 -4
  18. vellum_ee/workflows/display/nodes/vellum/try_node.py +1 -1
  19. vellum_ee/workflows/display/tests/test_base_workflow_display.py +46 -0
  20. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +1 -1
  21. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +8 -8
  22. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +1 -0
  23. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +1 -0
  24. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +2 -1
  25. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +2 -1
  26. vellum_ee/workflows/display/utils/events.py +7 -1
  27. vellum_ee/workflows/display/utils/expressions.py +33 -19
  28. vellum_ee/workflows/display/utils/tests/test_events.py +4 -4
  29. vellum_ee/workflows/display/workflows/base_workflow_display.py +1 -1
  30. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +10 -10
  31. {vellum_ai-1.3.8.dist-info → vellum_ai-1.3.9.dist-info}/LICENSE +0 -0
  32. {vellum_ai-1.3.8.dist-info → vellum_ai-1.3.9.dist-info}/WHEEL +0 -0
  33. {vellum_ai-1.3.8.dist-info → vellum_ai-1.3.9.dist-info}/entry_points.txt +0 -0
@@ -2,6 +2,7 @@ from dataclasses import asdict, is_dataclass
2
2
  import inspect
3
3
  from io import StringIO
4
4
  import sys
5
+ from uuid import UUID
5
6
  from typing import TYPE_CHECKING, Any, Dict, List, cast
6
7
 
7
8
  from pydantic import BaseModel
@@ -157,7 +158,9 @@ def get_child_descriptor(value: LazyReference, display_context: "WorkflowDisplay
157
158
  return value._get()
158
159
 
159
160
 
160
- def _serialize_condition(display_context: "WorkflowDisplayContext", condition: BaseDescriptor) -> JsonObject:
161
+ def _serialize_condition(
162
+ executable_id: UUID, display_context: "WorkflowDisplayContext", condition: BaseDescriptor
163
+ ) -> JsonObject:
161
164
  if isinstance(
162
165
  condition,
163
166
  (
@@ -171,16 +174,16 @@ def _serialize_condition(display_context: "WorkflowDisplayContext", condition: B
171
174
  ParseJsonExpression,
172
175
  ),
173
176
  ):
174
- lhs = serialize_value(display_context, condition._expression)
177
+ lhs = serialize_value(executable_id, display_context, condition._expression)
175
178
  return {
176
179
  "type": "UNARY_EXPRESSION",
177
180
  "lhs": lhs,
178
181
  "operator": convert_descriptor_to_operator(condition),
179
182
  }
180
183
  elif isinstance(condition, (BetweenExpression, NotBetweenExpression)):
181
- base = serialize_value(display_context, condition._value)
182
- lhs = serialize_value(display_context, condition._start)
183
- rhs = serialize_value(display_context, condition._end)
184
+ base = serialize_value(executable_id, display_context, condition._value)
185
+ lhs = serialize_value(executable_id, display_context, condition._start)
186
+ rhs = serialize_value(executable_id, display_context, condition._end)
184
187
 
185
188
  return {
186
189
  "type": "TERNARY_EXPRESSION",
@@ -214,8 +217,8 @@ def _serialize_condition(display_context: "WorkflowDisplayContext", condition: B
214
217
  OrExpression,
215
218
  ),
216
219
  ):
217
- lhs = serialize_value(display_context, condition._lhs)
218
- rhs = serialize_value(display_context, condition._rhs)
220
+ lhs = serialize_value(executable_id, display_context, condition._lhs)
221
+ rhs = serialize_value(executable_id, display_context, condition._rhs)
219
222
 
220
223
  return {
221
224
  "type": "BINARY_EXPRESSION",
@@ -226,9 +229,9 @@ def _serialize_condition(display_context: "WorkflowDisplayContext", condition: B
226
229
  elif isinstance(condition, AccessorExpression):
227
230
  return {
228
231
  "type": "BINARY_EXPRESSION",
229
- "lhs": serialize_value(display_context, condition._base),
232
+ "lhs": serialize_value(executable_id, display_context, condition._base),
230
233
  "operator": "accessField",
231
- "rhs": serialize_value(display_context, condition._field),
234
+ "rhs": serialize_value(executable_id, display_context, condition._field),
232
235
  }
233
236
 
234
237
  raise UnsupportedSerializationException(f"Unsupported condition type: {condition.__class__.__name__}")
@@ -248,16 +251,27 @@ def serialize_key(key: Any) -> str:
248
251
  _UNDEFINED_SENTINEL: JsonObject = {"__undefined__": True}
249
252
 
250
253
 
251
- def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> JsonObject:
254
+ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContext", value: Any) -> JsonObject:
255
+ """
256
+ Serialize a value to a JSON object.
257
+
258
+ Args:
259
+ executable_id: node id or workflow id
260
+ display_context: workflow display context
261
+ value: value to serialize
262
+
263
+ Returns:
264
+ serialized value
265
+ """
252
266
  if value is undefined:
253
267
  return _UNDEFINED_SENTINEL
254
268
 
255
269
  if isinstance(value, ConstantValueReference):
256
- return serialize_value(display_context, value._value)
270
+ return serialize_value(executable_id, display_context, value._value)
257
271
 
258
272
  if isinstance(value, LazyReference):
259
273
  child_descriptor = get_child_descriptor(value, display_context)
260
- return serialize_value(display_context, child_descriptor)
274
+ return serialize_value(executable_id, display_context, child_descriptor)
261
275
 
262
276
  if isinstance(value, WorkflowInputReference):
263
277
  try:
@@ -324,7 +338,7 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
324
338
  if isinstance(value, list):
325
339
  serialized_items = []
326
340
  for item in value:
327
- serialized_item = serialize_value(display_context, item)
341
+ serialized_item = serialize_value(executable_id, display_context, item)
328
342
  if serialized_item != _UNDEFINED_SENTINEL:
329
343
  serialized_items.append(serialized_item)
330
344
 
@@ -355,16 +369,16 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
355
369
 
356
370
  if is_dataclass(value) and not isinstance(value, type):
357
371
  dict_value = asdict(value)
358
- return serialize_value(display_context, dict_value)
372
+ return serialize_value(executable_id, display_context, dict_value)
359
373
 
360
374
  if isinstance(value, dict):
361
375
  serialized_entries: List[Dict[str, Any]] = []
362
376
  for key, val in value.items():
363
- serialized_val = serialize_value(display_context, val)
377
+ serialized_val = serialize_value(executable_id, display_context, val)
364
378
  if serialized_val != _UNDEFINED_SENTINEL:
365
379
  serialized_entries.append(
366
380
  {
367
- "id": str(uuid4_from_hash(f"{key}|{val}")),
381
+ "id": str(uuid4_from_hash(f"{executable_id}|{key}")),
368
382
  "key": serialize_key(key),
369
383
  "value": serialized_val,
370
384
  }
@@ -434,7 +448,7 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
434
448
 
435
449
  if isinstance(value, BaseModel):
436
450
  dict_value = value.model_dump()
437
- return serialize_value(display_context, dict_value)
451
+ return serialize_value(executable_id, display_context, dict_value)
438
452
 
439
453
  if callable(value):
440
454
  function_definition = compile_function_definition(value)
@@ -447,7 +461,7 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
447
461
  if inputs:
448
462
  serialized_inputs = {}
449
463
  for param_name, input_ref in inputs.items():
450
- serialized_inputs[param_name] = serialize_value(display_context, input_ref)
464
+ serialized_inputs[param_name] = serialize_value(executable_id, display_context, input_ref)
451
465
 
452
466
  model_data = function_definition.model_dump()
453
467
  model_data["inputs"] = serialized_inputs
@@ -485,4 +499,4 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
485
499
 
486
500
  # If it's not any of the references we know about,
487
501
  # then try to serialize it as a nested value
488
- return _serialize_condition(display_context, value)
502
+ return _serialize_condition(executable_id, display_context, value)
@@ -47,7 +47,7 @@ from vellum_ee.workflows.display.utils.events import event_enricher
47
47
  ),
48
48
  ],
49
49
  )
50
- def test_event_enricher_static_workflow(is_dynamic: bool, expected_config: Optional[dict]):
50
+ def test_event_enricher_static_workflow(vellum_client, is_dynamic: bool, expected_config: Optional[dict]):
51
51
  """Test event_enricher with a static workflow (is_dynamic=False)."""
52
52
  # GIVEN a workflow class with the specified is_dynamic value
53
53
  _is_dynamic = is_dynamic
@@ -65,7 +65,7 @@ def test_event_enricher_static_workflow(is_dynamic: bool, expected_config: Optio
65
65
  )
66
66
 
67
67
  # WHEN the event_enricher is called with mocked dependencies
68
- event_enricher(event)
68
+ event_enricher(event, vellum_client)
69
69
 
70
70
  # THEN workflow_version_exec_config is set to the expected config
71
71
  assert event.body.workflow_version_exec_config == expected_config
@@ -76,7 +76,7 @@ def test_event_enricher_static_workflow(is_dynamic: bool, expected_config: Optio
76
76
  assert hasattr(event.body.display_context, "workflow_outputs")
77
77
 
78
78
 
79
- def test_event_enricher_marks_subworkflow_deployment_as_dynamic():
79
+ def test_event_enricher_marks_subworkflow_deployment_as_dynamic(vellum_client):
80
80
  """Test that event_enricher treats subworkflow deployments as dynamic."""
81
81
 
82
82
  class TestWorkflow(BaseWorkflow):
@@ -110,7 +110,7 @@ def test_event_enricher_marks_subworkflow_deployment_as_dynamic():
110
110
  ),
111
111
  )
112
112
 
113
- enriched_event = event_enricher(event)
113
+ enriched_event = event_enricher(event, vellum_client)
114
114
 
115
115
  assert hasattr(enriched_event.body, "workflow_version_exec_config")
116
116
  assert enriched_event.body.workflow_version_exec_config is not None
@@ -302,7 +302,7 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
302
302
  output_values.append(
303
303
  {
304
304
  "output_variable_id": str(workflow_output_display.id),
305
- "value": serialize_value(self.display_context, workflow_output.instance),
305
+ "value": serialize_value(self.workflow_id, self.display_context, workflow_output.instance),
306
306
  }
307
307
  )
308
308
 
@@ -706,12 +706,12 @@ def test_serialize_workflow__dict_reference():
706
706
  "type": "DICTIONARY_REFERENCE",
707
707
  "entries": [
708
708
  {
709
- "id": "b528ce26-68ee-42ba-828d-199441810685",
709
+ "id": "7689f0df-e0bc-4e53-a63f-dbee027f58b9",
710
710
  "key": "key1",
711
711
  "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "constant1"}},
712
712
  },
713
713
  {
714
- "id": "a7acccfe-2f80-42ee-a307-c1eb0b137c2b",
714
+ "id": "89e01555-b0b5-42d5-a0a7-bce72716cf65",
715
715
  "key": "key2",
716
716
  "value": {
717
717
  "type": "NODE_OUTPUT",
@@ -720,12 +720,12 @@ def test_serialize_workflow__dict_reference():
720
720
  },
721
721
  },
722
722
  {
723
- "id": "8f41013e-7a9f-4659-ac17-c25c6ec6fe99",
723
+ "id": "2dc84109-b85c-4732-aa60-8c10a1a377d2",
724
724
  "key": "key3",
725
725
  "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "constant2"}},
726
726
  },
727
727
  {
728
- "id": "609e84e8-573a-44ea-b3aa-82c3f3cc2c36",
728
+ "id": "d1b3ce75-1b1e-45e3-b798-beafe6c4826f",
729
729
  "key": "key4",
730
730
  "value": {
731
731
  "type": "NODE_OUTPUT",
@@ -745,18 +745,18 @@ def test_serialize_workflow__dict_reference():
745
745
  "type": "DICTIONARY_REFERENCE",
746
746
  "entries": [
747
747
  {
748
- "id": "02abe9d0-bf93-4eea-b34a-902dae7c2b90",
748
+ "id": "7689f0df-e0bc-4e53-a63f-dbee027f58b9",
749
749
  "key": "key1",
750
750
  "value": {
751
751
  "type": "DICTIONARY_REFERENCE",
752
752
  "entries": [
753
753
  {
754
- "id": "b528ce26-68ee-42ba-828d-199441810685",
754
+ "id": "7689f0df-e0bc-4e53-a63f-dbee027f58b9",
755
755
  "key": "key1",
756
756
  "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "constant1"}},
757
757
  },
758
758
  {
759
- "id": "a7acccfe-2f80-42ee-a307-c1eb0b137c2b",
759
+ "id": "89e01555-b0b5-42d5-a0a7-bce72716cf65",
760
760
  "key": "key2",
761
761
  "value": {
762
762
  "type": "NODE_OUTPUT",
@@ -768,18 +768,18 @@ def test_serialize_workflow__dict_reference():
768
768
  },
769
769
  },
770
770
  {
771
- "id": "c8640477-13cc-412e-82cc-35cbe9e78ff2",
771
+ "id": "89e01555-b0b5-42d5-a0a7-bce72716cf65",
772
772
  "key": "key2",
773
773
  "value": {
774
774
  "type": "DICTIONARY_REFERENCE",
775
775
  "entries": [
776
776
  {
777
- "id": "86709f21-a811-4351-993e-a8e9f1c7774f",
777
+ "id": "7689f0df-e0bc-4e53-a63f-dbee027f58b9",
778
778
  "key": "key1",
779
779
  "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "constant2"}},
780
780
  },
781
781
  {
782
- "id": "a7acccfe-2f80-42ee-a307-c1eb0b137c2b",
782
+ "id": "89e01555-b0b5-42d5-a0a7-bce72716cf65",
783
783
  "key": "key2",
784
784
  "value": {
785
785
  "type": "NODE_OUTPUT",