vellum-ai 0.14.89__py3-none-any.whl → 1.0.1__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 (62) hide show
  1. vellum/__init__.py +7 -1
  2. vellum/client/__init__.py +2 -2
  3. vellum/client/core/client_wrapper.py +2 -2
  4. vellum/client/types/__init__.py +6 -0
  5. vellum/client/types/organization_limit_config.py +24 -0
  6. vellum/client/types/organization_read.py +2 -0
  7. vellum/client/types/quota.py +21 -0
  8. vellum/client/types/vembda_service_tier_enum.py +5 -0
  9. vellum/client/types/workflow_execution_actual.py +1 -1
  10. vellum/evaluations/resources.py +5 -5
  11. vellum/types/organization_limit_config.py +3 -0
  12. vellum/types/quota.py +3 -0
  13. vellum/types/vembda_service_tier_enum.py +3 -0
  14. vellum/workflows/events/node.py +1 -1
  15. vellum/workflows/events/types.py +1 -1
  16. vellum/workflows/events/workflow.py +1 -1
  17. vellum/workflows/nodes/bases/tests/test_base_node.py +1 -1
  18. vellum/workflows/nodes/displayable/api_node/node.py +1 -0
  19. vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +30 -0
  20. vellum/workflows/nodes/displayable/bases/api_node/node.py +27 -10
  21. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +1 -1
  22. vellum/workflows/nodes/displayable/bases/search_node.py +1 -1
  23. vellum/workflows/nodes/displayable/code_execution_node/node.py +1 -1
  24. vellum/workflows/nodes/displayable/guardrail_node/node.py +1 -1
  25. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +1 -1
  26. vellum/workflows/nodes/displayable/tool_calling_node/node.py +5 -0
  27. vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +3 -0
  28. vellum/workflows/nodes/displayable/tool_calling_node/utils.py +86 -114
  29. vellum/workflows/nodes/experimental/__init__.py +2 -2
  30. vellum/workflows/state/base.py +1 -1
  31. vellum/workflows/state/delta.py +1 -1
  32. {vellum_ai-0.14.89.dist-info → vellum_ai-1.0.1.dist-info}/METADATA +1 -1
  33. {vellum_ai-0.14.89.dist-info → vellum_ai-1.0.1.dist-info}/RECORD +59 -55
  34. vellum_cli/config.py +1 -1
  35. vellum_cli/push.py +1 -1
  36. vellum_cli/tests/test_ping.py +1 -0
  37. vellum_ee/workflows/display/base.py +0 -54
  38. vellum_ee/workflows/display/nodes/base_node_display.py +24 -0
  39. vellum_ee/workflows/display/nodes/vellum/api_node.py +20 -1
  40. vellum_ee/workflows/display/nodes/vellum/conditional_node.py +16 -2
  41. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +0 -26
  42. vellum_ee/workflows/display/nodes/vellum/tests/test_api_node.py +31 -0
  43. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +3 -3
  44. vellum_ee/workflows/display/tests/test_base_workflow_display.py +2 -4
  45. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +2 -2
  46. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +10 -0
  47. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +11 -11
  48. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +21 -0
  49. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +21 -0
  50. vellum_ee/workflows/display/vellum.py +2 -128
  51. vellum_ee/workflows/display/workflows/__init__.py +0 -1
  52. vellum_ee/workflows/display/workflows/base_workflow_display.py +15 -3
  53. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +127 -0
  54. vellum_ee/workflows/tests/local_workflow/display/nodes/final_output.py +1 -1
  55. vellum_ee/workflows/tests/local_workflow/display/nodes/templating_node.py +1 -1
  56. vellum_ee/workflows/tests/local_workflow/display/workflow.py +11 -14
  57. vellum/workflows/nodes/experimental/tool_calling_node/__init__.py +0 -3
  58. vellum/workflows/nodes/experimental/tool_calling_node/node.py +0 -3
  59. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +0 -9
  60. {vellum_ai-0.14.89.dist-info → vellum_ai-1.0.1.dist-info}/LICENSE +0 -0
  61. {vellum_ai-0.14.89.dist-info → vellum_ai-1.0.1.dist-info}/WHEEL +0 -0
  62. {vellum_ai-0.14.89.dist-info → vellum_ai-1.0.1.dist-info}/entry_points.txt +0 -0
@@ -11,7 +11,6 @@ from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
11
11
  from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
12
12
  from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
13
13
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
14
- from vellum_ee.workflows.display.utils.expressions import serialize_value
15
14
  from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
16
15
  from vellum_ee.workflows.display.vellum import NodeInput
17
16
 
@@ -173,7 +172,6 @@ class BaseInlinePromptNodeDisplay(BaseNodeDisplay[_InlinePromptNodeType], Generi
173
172
  }
174
173
 
175
174
  elif prompt_block.block_type == "CHAT_MESSAGE":
176
-
177
175
  chat_properties: JsonObject = {
178
176
  "chat_role": prompt_block.chat_role,
179
177
  "chat_source": prompt_block.chat_source,
@@ -248,30 +246,6 @@ class BaseInlinePromptNodeDisplay(BaseNodeDisplay[_InlinePromptNodeType], Generi
248
246
 
249
247
  return block
250
248
 
251
- def _serialize_attributes(self, display_context: "WorkflowDisplayContext"):
252
- attributes = []
253
- for attribute in self._node:
254
- if attribute in self.__unserializable_attributes__:
255
- continue
256
-
257
- id = (
258
- str(self.attribute_ids_by_name[attribute.name])
259
- if self.attribute_ids_by_name.get(attribute.name)
260
- else str(uuid4_from_hash(f"{self.node_id}|{attribute.name}"))
261
- )
262
- try:
263
- attributes.append(
264
- {
265
- "id": id,
266
- "name": attribute.name,
267
- "value": serialize_value(display_context, attribute.instance),
268
- }
269
- )
270
- except ValueError as e:
271
- raise ValueError(f"Failed to serialize attribute '{attribute.name}': {e}")
272
-
273
- return attributes
274
-
275
249
  def _serialize_parameters(self, parameters, display_context: "WorkflowDisplayContext") -> JsonObject:
276
250
  """Serialize parameters, returning empty object when nested descriptors are detected."""
277
251
  params = raise_if_descriptor(parameters)
@@ -0,0 +1,31 @@
1
+ from vellum.workflows.constants import APIRequestMethod
2
+ from vellum.workflows.nodes.displayable.api_node.node import APINode
3
+ from vellum.workflows.workflows.base import BaseWorkflow
4
+ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
5
+
6
+
7
+ def test_serialize_node__api_node_with_timeout():
8
+ # GIVEN an API node with timeout specified
9
+ class MyAPINode(APINode):
10
+ url = "https://api.example.com"
11
+ method = APIRequestMethod.GET
12
+ timeout = 30 # This is the key attribute we're testing
13
+
14
+ # AND a workflow with the API node
15
+ class Workflow(BaseWorkflow):
16
+ graph = MyAPINode
17
+
18
+ # WHEN the workflow is serialized
19
+ workflow_display = get_workflow_display(workflow_class=Workflow)
20
+ serialized_workflow: dict = workflow_display.serialize()
21
+
22
+ # THEN the node should properly serialize the timeout
23
+ my_api_node = next(node for node in serialized_workflow["workflow_raw_data"]["nodes"] if node["type"] == "API")
24
+
25
+ # Assert that timeout is present in the serialized attributes
26
+ timeout_attribute = next((attr for attr in my_api_node.get("attributes", []) if attr["name"] == "timeout"), None)
27
+
28
+ assert timeout_attribute is not None, "timeout attribute should be present in serialized attributes"
29
+ assert timeout_attribute["value"]["type"] == "CONSTANT_VALUE"
30
+ assert timeout_attribute["value"]["value"]["type"] == "NUMBER"
31
+ assert timeout_attribute["value"]["value"]["value"] == 30.0
@@ -8,6 +8,7 @@ from vellum.workflows.inputs import BaseInputs
8
8
  from vellum.workflows.nodes.bases import BaseNode
9
9
  from vellum.workflows.outputs import BaseOutputs
10
10
  from vellum.workflows.references import LazyReference
11
+ from vellum_ee.workflows.display.base import WorkflowInputsDisplay, WorkflowMetaDisplay
11
12
  from vellum_ee.workflows.display.editor.types import NodeDisplayData
12
13
  from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
13
14
  from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay
@@ -21,7 +22,6 @@ from vellum_ee.workflows.display.utils.vellum import (
21
22
  NodeOutputData,
22
23
  NodeOutputPointer,
23
24
  )
24
- from vellum_ee.workflows.display.vellum import WorkflowInputsVellumDisplayOverrides, WorkflowMetaVellumDisplay
25
25
  from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
26
26
 
27
27
 
@@ -110,13 +110,13 @@ def test_create_node_input_value_pointer_rules(
110
110
  descriptor,
111
111
  WorkflowDisplayContext(
112
112
  workflow_display_class=BaseWorkflowDisplay,
113
- workflow_display=WorkflowMetaVellumDisplay(
113
+ workflow_display=WorkflowMetaDisplay(
114
114
  entrypoint_node_id=uuid4(),
115
115
  entrypoint_node_source_handle_id=uuid4(),
116
116
  entrypoint_node_display=NodeDisplayData(),
117
117
  ),
118
118
  global_workflow_input_displays={
119
- Inputs.example_workflow_input: WorkflowInputsVellumDisplayOverrides(
119
+ Inputs.example_workflow_input: WorkflowInputsDisplay(
120
120
  id=UUID("a154c29d-fac0-4cd0-ba88-bc52034f5470"),
121
121
  ),
122
122
  },
@@ -7,7 +7,7 @@ from vellum.workflows.ports.port import Port
7
7
  from vellum.workflows.references.lazy import LazyReference
8
8
  from vellum.workflows.state import BaseState
9
9
  from vellum.workflows.workflows.base import BaseWorkflow
10
- from vellum_ee.workflows.display.vellum import WorkflowInputsVellumDisplayOverrides
10
+ from vellum_ee.workflows.display.base import WorkflowInputsDisplay
11
11
  from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
12
12
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
13
13
 
@@ -64,9 +64,7 @@ def test_vellum_workflow_display__serialize_input_variables_with_capitalized_var
64
64
 
65
65
  class ExampleWorkflowDisplay(BaseWorkflowDisplay[ExampleWorkflow]):
66
66
  inputs_display = {
67
- Inputs.foo: WorkflowInputsVellumDisplayOverrides(
68
- id=UUID("97b63d71-5413-417f-9cf5-49e1b4fd56e4"), name="Foo", required=True
69
- )
67
+ Inputs.foo: WorkflowInputsDisplay(id=UUID("97b63d71-5413-417f-9cf5-49e1b4fd56e4"), name="Foo")
70
68
  }
71
69
 
72
70
  display = get_workflow_display(
@@ -4,6 +4,7 @@ from typing import Type
4
4
 
5
5
  from vellum.workflows.types.core import JsonObject
6
6
  from vellum.workflows.types.generics import NodeType
7
+ from vellum_ee.workflows.display.base import WorkflowMetaDisplay
7
8
  from vellum_ee.workflows.display.editor.types import NodeDisplayData
8
9
  from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
9
10
  from vellum_ee.workflows.display.types import (
@@ -13,7 +14,6 @@ from vellum_ee.workflows.display.types import (
13
14
  WorkflowDisplayContext,
14
15
  WorkflowInputsDisplays,
15
16
  )
16
- from vellum_ee.workflows.display.vellum import WorkflowMetaVellumDisplay
17
17
  from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
18
18
 
19
19
 
@@ -31,7 +31,7 @@ def serialize_node():
31
31
 
32
32
  context: WorkflowDisplayContext = WorkflowDisplayContext(
33
33
  workflow_display_class=BaseWorkflowDisplay,
34
- workflow_display=WorkflowMetaVellumDisplay(
34
+ workflow_display=WorkflowMetaDisplay(
35
35
  entrypoint_node_id=uuid4(),
36
36
  entrypoint_node_source_handle_id=uuid4(),
37
37
  entrypoint_node_display=NodeDisplayData(),
@@ -162,6 +162,16 @@ def test_serialize_workflow(vellum_client):
162
162
  },
163
163
  },
164
164
  ],
165
+ "attributes": [
166
+ {
167
+ "id": "ad719e65-0032-4012-a0bd-9b5162194bce",
168
+ "name": "timeout",
169
+ "value": {
170
+ "type": "CONSTANT_VALUE",
171
+ "value": {"type": "JSON", "value": None},
172
+ },
173
+ },
174
+ ],
165
175
  "data": {
166
176
  "label": "Simple A P I Node",
167
177
  "error_output_id": None,
@@ -285,7 +285,7 @@ def test_serialize_workflow():
285
285
  {
286
286
  "id": "de7b0b4e-7803-4d36-a275-2e7e3f60342b",
287
287
  "type": "IF",
288
- "source_handle_id": "561b4e3a-8db3-448a-8933-1115937082ff",
288
+ "source_handle_id": "3a45b81f-95e4-4cbd-8997-bfdbe30251e8",
289
289
  "data": {
290
290
  "id": "2ccd0730-26d1-4fb4-baa9-1a2a182dd9a0",
291
291
  "rules": [
@@ -309,7 +309,7 @@ def test_serialize_workflow():
309
309
  {
310
310
  "id": "5e783d17-6808-441a-ac6c-33a4e184f4e0",
311
311
  "type": "ELIF",
312
- "source_handle_id": "0644f22e-2680-441a-9554-eedf1d3d22a9",
312
+ "source_handle_id": "7202f702-1ebc-4067-ab1e-ec67e49158ee",
313
313
  "data": {
314
314
  "id": "cc3f0d92-b603-42cc-b2e9-83e3b23b3bcb",
315
315
  "rules": [
@@ -333,7 +333,7 @@ def test_serialize_workflow():
333
333
  {
334
334
  "id": "6bd2f643-9cf5-4e7f-9113-f90e5c8057be",
335
335
  "type": "ELIF",
336
- "source_handle_id": "2a48d274-ecfc-4f40-95ac-bc697663f10c",
336
+ "source_handle_id": "cf45705d-1a47-43a6-9d24-a7fdf78baae0",
337
337
  "data": {
338
338
  "id": "a5a0f391-7052-452f-9fe1-a5781a491591",
339
339
  "rules": [
@@ -357,7 +357,7 @@ def test_serialize_workflow():
357
357
  {
358
358
  "id": "0a058485-18a4-4e20-8a30-6da8196ac46f",
359
359
  "type": "ELIF",
360
- "source_handle_id": "90fc9dc8-0a74-4a98-b6ac-55ffce4a2881",
360
+ "source_handle_id": "f04610dd-61cf-41b0-b337-2235e101cdb0",
361
361
  "data": {
362
362
  "id": "efe7a851-2a67-4189-99ec-bc193242b270",
363
363
  "rules": [
@@ -409,7 +409,7 @@ def test_serialize_workflow():
409
409
  {
410
410
  "id": "c2fa8a44-923b-462a-b0d2-fa800a152e52",
411
411
  "type": "ELSE",
412
- "source_handle_id": "493024f4-8010-4e1a-abae-b6adbc6fb208",
412
+ "source_handle_id": "f9dde637-ea90-465f-a871-caf8380ae377",
413
413
  "data": None,
414
414
  },
415
415
  ],
@@ -913,7 +913,7 @@ def test_conditional_node_serialize_all_operators_with_lhs_and_rhs(descriptor, o
913
913
  {
914
914
  "id": "a4c32611-fd58-4b98-9d08-313cfd1c214e",
915
915
  "type": "IF",
916
- "source_handle_id": "8124a6cf-4a34-4149-adc0-68696c11bd4e",
916
+ "source_handle_id": "2ff87aa6-37cf-43dd-af9d-13b9198ab70a",
917
917
  "data": {
918
918
  "id": "650e7105-3e76-43ca-858f-b290970b438b",
919
919
  "rules": [
@@ -937,7 +937,7 @@ def test_conditional_node_serialize_all_operators_with_lhs_and_rhs(descriptor, o
937
937
  {
938
938
  "id": "342e5497-ea2b-4e5c-99cf-e6492f133a3c",
939
939
  "type": "ELSE",
940
- "source_handle_id": "4df924c0-7bed-4f4a-9db4-2bfe51841755",
940
+ "source_handle_id": "9a7e8c2e-0228-4321-8f74-61cb5778f3df",
941
941
  "data": None,
942
942
  },
943
943
  ],
@@ -1024,7 +1024,7 @@ def test_conditional_node_serialize_all_operators_with_expression(descriptor, op
1024
1024
  {
1025
1025
  "id": "a4c32611-fd58-4b98-9d08-313cfd1c214e",
1026
1026
  "type": "IF",
1027
- "source_handle_id": "8124a6cf-4a34-4149-adc0-68696c11bd4e",
1027
+ "source_handle_id": "2ff87aa6-37cf-43dd-af9d-13b9198ab70a",
1028
1028
  "data": {
1029
1029
  "id": "650e7105-3e76-43ca-858f-b290970b438b",
1030
1030
  "rules": [
@@ -1048,7 +1048,7 @@ def test_conditional_node_serialize_all_operators_with_expression(descriptor, op
1048
1048
  {
1049
1049
  "id": "342e5497-ea2b-4e5c-99cf-e6492f133a3c",
1050
1050
  "type": "ELSE",
1051
- "source_handle_id": "4df924c0-7bed-4f4a-9db4-2bfe51841755",
1051
+ "source_handle_id": "9a7e8c2e-0228-4321-8f74-61cb5778f3df",
1052
1052
  "data": None,
1053
1053
  },
1054
1054
  ],
@@ -1147,7 +1147,7 @@ def test_conditional_node_serialize_all_operators_with_value_and_start_and_end(d
1147
1147
  {
1148
1148
  "id": "a4c32611-fd58-4b98-9d08-313cfd1c214e",
1149
1149
  "type": "IF",
1150
- "source_handle_id": "8124a6cf-4a34-4149-adc0-68696c11bd4e",
1150
+ "source_handle_id": "2ff87aa6-37cf-43dd-af9d-13b9198ab70a",
1151
1151
  "data": {
1152
1152
  "id": "650e7105-3e76-43ca-858f-b290970b438b",
1153
1153
  "rules": [
@@ -1171,7 +1171,7 @@ def test_conditional_node_serialize_all_operators_with_value_and_start_and_end(d
1171
1171
  {
1172
1172
  "id": "342e5497-ea2b-4e5c-99cf-e6492f133a3c",
1173
1173
  "type": "ELSE",
1174
- "source_handle_id": "4df924c0-7bed-4f4a-9db4-2bfe51841755",
1174
+ "source_handle_id": "9a7e8c2e-0228-4321-8f74-61cb5778f3df",
1175
1175
  "data": None,
1176
1176
  },
1177
1177
  ],
@@ -407,6 +407,27 @@ def test_serialize_workflow():
407
407
  ],
408
408
  },
409
409
  },
410
+ {
411
+ "id": "229cd1ca-dc2f-4586-b933-c4d4966f7bd1",
412
+ "name": "parameters",
413
+ "value": {
414
+ "type": "CONSTANT_VALUE",
415
+ "value": {
416
+ "type": "JSON",
417
+ "value": {
418
+ "stop": [],
419
+ "temperature": 0.0,
420
+ "max_tokens": 4096.0,
421
+ "top_p": 1.0,
422
+ "top_k": 0.0,
423
+ "frequency_penalty": 0.0,
424
+ "presence_penalty": 0.0,
425
+ "logit_bias": None,
426
+ "custom_parameters": None,
427
+ },
428
+ },
429
+ },
430
+ },
410
431
  {
411
432
  "id": "1668419e-a193-43a5-8a97-3394e89bf278",
412
433
  "name": "max_prompt_iterations",
@@ -169,6 +169,27 @@ def test_serialize_workflow():
169
169
  ],
170
170
  },
171
171
  },
172
+ {
173
+ "id": "229cd1ca-dc2f-4586-b933-c4d4966f7bd1",
174
+ "name": "parameters",
175
+ "value": {
176
+ "type": "CONSTANT_VALUE",
177
+ "value": {
178
+ "type": "JSON",
179
+ "value": {
180
+ "stop": [],
181
+ "temperature": 0.0,
182
+ "max_tokens": 4096.0,
183
+ "top_p": 1.0,
184
+ "top_k": 0.0,
185
+ "frequency_penalty": 0.0,
186
+ "presence_penalty": 0.0,
187
+ "logit_bias": None,
188
+ "custom_parameters": None,
189
+ },
190
+ },
191
+ },
192
+ },
172
193
  {
173
194
  "id": "1668419e-a193-43a5-8a97-3394e89bf278",
174
195
  "name": "max_prompt_iterations",
@@ -1,135 +1,9 @@
1
- from dataclasses import dataclass
2
- from uuid import UUID
3
- from typing import List, Literal, Optional
1
+ from typing import List, Literal
4
2
 
5
- from vellum.core import UniversalBaseModel
6
- from vellum_ee.workflows.display.base import (
7
- EdgeDisplayOverrides,
8
- EntrypointDisplayOverrides,
9
- StateValueDisplayOverrides,
10
- WorkflowInputsDisplay,
11
- WorkflowMetaDisplayOverrides,
12
- WorkflowOutputDisplayOverrides,
13
- )
14
- from vellum_ee.workflows.display.base import WorkflowDisplayData # noqa: F401 - Remove in 0.15.0
15
- from vellum_ee.workflows.display.base import WorkflowDisplayDataViewport # noqa: F401 - Remove in 0.15.0
16
- from vellum_ee.workflows.display.editor.types import NodeDisplayComment # noqa: F401 - Remove in 0.15.0
17
- from vellum_ee.workflows.display.editor.types import NodeDisplayData
18
- from vellum_ee.workflows.display.editor.types import NodeDisplayPosition # noqa: F401 - Remove in 0.15.0
3
+ from vellum.client.core import UniversalBaseModel
19
4
  from vellum_ee.workflows.display.utils.vellum import NodeInputValuePointerRule
20
5
 
21
6
 
22
- @dataclass
23
- class WorkflowMetaVellumDisplayOverrides(WorkflowMetaDisplayOverrides):
24
- """
25
- DEPRECATED: Use WorkflowMetaDisplay instead. Will be removed in 0.15.0
26
- """
27
-
28
- pass
29
-
30
-
31
- @dataclass
32
- class WorkflowMetaVellumDisplay(WorkflowMetaVellumDisplayOverrides):
33
- """
34
- DEPRECATED: Use WorkflowMetaDisplay instead. Will be removed in 0.15.0
35
- """
36
-
37
- pass
38
-
39
-
40
- @dataclass
41
- class WorkflowInputsVellumDisplayOverrides(WorkflowInputsDisplay):
42
- """
43
- DEPRECATED: Use WorkflowInputsDisplay instead. Will be removed in 0.15.0
44
- """
45
-
46
- required: Optional[bool] = None
47
-
48
-
49
- @dataclass
50
- class WorkflowInputsVellumDisplay(WorkflowInputsVellumDisplayOverrides):
51
- pass
52
-
53
-
54
- @dataclass
55
- class StateValueVellumDisplayOverrides(StateValueDisplayOverrides):
56
- """
57
- DEPRECATED: Use StateValueDisplay instead. Will be removed in 0.15.0
58
- """
59
-
60
- required: Optional[bool] = None
61
-
62
-
63
- @dataclass
64
- class StateValueVellumDisplay(StateValueVellumDisplayOverrides):
65
- """
66
- DEPRECATED: Use StateValueDisplay instead. Will be removed in 0.15.0
67
- """
68
-
69
- pass
70
-
71
-
72
- @dataclass
73
- class EdgeVellumDisplayOverrides(EdgeDisplayOverrides):
74
- """
75
- DEPRECATED: Use EdgeDisplay instead. Will be removed in 0.15.0
76
- """
77
-
78
- pass
79
-
80
-
81
- @dataclass
82
- class EdgeVellumDisplay(EdgeVellumDisplayOverrides):
83
- """
84
- DEPRECATED: Use EdgeDisplay instead. Will be removed in 0.15.0
85
- """
86
-
87
- source_node_id: UUID
88
- source_handle_id: UUID
89
- target_node_id: UUID
90
- target_handle_id: UUID
91
- type: Literal["DEFAULT"] = "DEFAULT"
92
-
93
-
94
- @dataclass
95
- class EntrypointVellumDisplayOverrides(EntrypointDisplayOverrides):
96
- """
97
- DEPRECATED: Use EntrypointDisplay instead. Will be removed in 0.15.0
98
- """
99
-
100
- pass
101
-
102
-
103
- @dataclass
104
- class EntrypointVellumDisplay(EntrypointVellumDisplayOverrides):
105
- """
106
- DEPRECATED: Use EntrypointDisplay instead. Will be removed in 0.15.0
107
- """
108
-
109
- pass
110
-
111
-
112
- @dataclass
113
- class WorkflowOutputVellumDisplayOverrides(WorkflowOutputDisplayOverrides):
114
- """
115
- DEPRECATED: Use WorkflowOutputDisplay instead. Will be removed in 0.15.0
116
- """
117
-
118
- label: Optional[str] = None
119
- node_id: Optional[UUID] = None
120
- display_data: Optional[NodeDisplayData] = None
121
- target_handle_id: Optional[UUID] = None
122
-
123
-
124
- @dataclass
125
- class WorkflowOutputVellumDisplay(WorkflowOutputVellumDisplayOverrides):
126
- """
127
- DEPRECATED: Use WorkflowOutputDisplay instead. Will be removed in 0.15.0
128
- """
129
-
130
- pass
131
-
132
-
133
7
  class NodeInputValuePointer(UniversalBaseModel):
134
8
  rules: List[NodeInputValuePointerRule]
135
9
  combinator: Literal["OR"] = "OR"
@@ -2,4 +2,3 @@
2
2
 
3
3
  # These must be imported to register the classes in the registry
4
4
  from .base_workflow_display import BaseWorkflowDisplay
5
- from .vellum_workflow_display import VellumWorkflowDisplay
@@ -9,7 +9,7 @@ from uuid import UUID
9
9
  from typing import Any, Dict, ForwardRef, Generic, Iterator, List, Optional, Tuple, Type, TypeVar, Union, cast, get_args
10
10
 
11
11
  from vellum.client import Vellum as VellumClient
12
- from vellum.core.pydantic_utilities import UniversalBaseModel
12
+ from vellum.client.core.pydantic_utilities import UniversalBaseModel
13
13
  from vellum.workflows import BaseWorkflow
14
14
  from vellum.workflows.constants import undefined
15
15
  from vellum.workflows.descriptors.base import BaseDescriptor
@@ -136,13 +136,19 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
136
136
  if workflow_input_reference.instance
137
137
  else None
138
138
  )
139
+
140
+ # An input is required if it has no default value AND is not optional
141
+ has_default = workflow_input_reference.instance is not undefined
142
+ is_optional = type(None) in workflow_input_reference.types
143
+ is_required = not has_default and not is_optional
144
+
139
145
  input_variables.append(
140
146
  {
141
147
  "id": str(workflow_input_display.id),
142
148
  "key": workflow_input_display.name or workflow_input_reference.name,
143
149
  "type": infer_vellum_variable_type(workflow_input_reference),
144
150
  "default": default.dict() if default else None,
145
- "required": workflow_input_reference.instance is undefined,
151
+ "required": is_required,
146
152
  "extensions": {"color": workflow_input_display.color},
147
153
  }
148
154
  )
@@ -152,13 +158,19 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
152
158
  default = (
153
159
  primitive_to_vellum_value(state_value_reference.instance) if state_value_reference.instance else None
154
160
  )
161
+
162
+ # A state variable is required if it has no default value AND is not optional
163
+ has_default = state_value_reference.instance is not undefined
164
+ is_optional = type(None) in state_value_reference.types
165
+ is_required = not has_default and not is_optional
166
+
155
167
  state_variables.append(
156
168
  {
157
169
  "id": str(state_value_display.id),
158
170
  "key": state_value_display.name or state_value_reference.name,
159
171
  "type": infer_vellum_variable_type(state_value_reference),
160
172
  "default": default.dict() if default else None,
161
- "required": state_value_reference.instance is undefined,
173
+ "required": is_required,
162
174
  "extensions": {"color": state_value_display.color},
163
175
  }
164
176
  )
@@ -1,6 +1,8 @@
1
1
  import pytest
2
2
  from uuid import uuid4
3
+ from typing import Optional
3
4
 
5
+ from vellum.workflows.inputs import BaseInputs
4
6
  from vellum.workflows.nodes.bases.base import BaseNode
5
7
  from vellum.workflows.nodes.core.inline_subworkflow_node.node import InlineSubworkflowNode
6
8
  from vellum.workflows.nodes.core.retry_node.node import RetryNode
@@ -8,6 +10,7 @@ from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
8
10
  from vellum.workflows.nodes.core.try_node.node import TryNode
9
11
  from vellum.workflows.nodes.displayable.final_output_node.node import FinalOutputNode
10
12
  from vellum.workflows.references.lazy import LazyReference
13
+ from vellum.workflows.state.base import BaseState
11
14
  from vellum.workflows.workflows.base import BaseWorkflow
12
15
  from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDisplayPosition
13
16
  from vellum_ee.workflows.display.nodes import BaseNodeDisplay
@@ -828,3 +831,127 @@ def test_serialize_workflow__empty_rules_indexerror():
828
831
  terminal_nodes = [node for node in nodes if node.get("type") == "TERMINAL"]
829
832
  assert len(terminal_nodes) == 1
830
833
  assert terminal_nodes[0]["data"]["name"] == "problematic_output"
834
+
835
+
836
+ def test_serialize_workflow__input_variables():
837
+ # GIVEN a workflow with inputs
838
+ class Inputs(BaseInputs):
839
+ input_1: str
840
+ input_2: Optional[str]
841
+ input_3: int = 1
842
+ input_4: Optional[int] = 2
843
+
844
+ class MyWorkflow(BaseWorkflow[Inputs, BaseState]):
845
+ pass
846
+
847
+ # WHEN we serialize it
848
+ workflow_display = get_workflow_display(workflow_class=MyWorkflow)
849
+ data = workflow_display.serialize()
850
+
851
+ # THEN the inputs should be serialized correctly
852
+ assert "input_variables" in data
853
+ input_variables = data["input_variables"]
854
+ assert isinstance(input_variables, list)
855
+ assert len(input_variables) == 4
856
+
857
+ input_1 = next(var for var in input_variables if isinstance(var, dict) and var["key"] == "input_1")
858
+ assert input_1 == {
859
+ "id": "13bd7980-3fbd-486c-9ebd-a29d84f7bda0",
860
+ "key": "input_1",
861
+ "type": "STRING",
862
+ "default": None,
863
+ "required": True,
864
+ "extensions": {"color": None},
865
+ }
866
+
867
+ input_2 = next(var for var in input_variables if isinstance(var, dict) and var["key"] == "input_2")
868
+ assert input_2 == {
869
+ "id": "13847952-beab-408d-945e-cfa079e6e124",
870
+ "key": "input_2",
871
+ "type": "STRING",
872
+ "default": None,
873
+ "required": False,
874
+ "extensions": {"color": None},
875
+ }
876
+
877
+ input_3 = next(var for var in input_variables if isinstance(var, dict) and var["key"] == "input_3")
878
+ assert input_3 == {
879
+ "id": "2e38e1a4-09ff-4bb8-a12e-9bf54d4f3a5e",
880
+ "key": "input_3",
881
+ "type": "NUMBER",
882
+ "default": {"type": "NUMBER", "value": 1.0},
883
+ "required": False,
884
+ "extensions": {"color": None},
885
+ }
886
+
887
+ input_4 = next(var for var in input_variables if isinstance(var, dict) and var["key"] == "input_4")
888
+ assert input_4 == {
889
+ "id": "d945b6ae-2490-4bfb-9b1c-b1e484dfd4f6",
890
+ "key": "input_4",
891
+ "type": "NUMBER",
892
+ "default": {"type": "NUMBER", "value": 2.0},
893
+ "required": False,
894
+ "extensions": {"color": None},
895
+ }
896
+
897
+
898
+ def test_serialize_workflow__state_variables():
899
+ # GIVEN a workflow with state variables
900
+ class State(BaseState):
901
+ state_1: str = "hello"
902
+ state_2: Optional[str] = None
903
+ state_3: int = 1
904
+ state_4: Optional[int] = 2
905
+
906
+ class MyWorkflow(BaseWorkflow[BaseInputs, State]):
907
+ pass
908
+
909
+ # WHEN we serialize it
910
+ workflow_display = get_workflow_display(workflow_class=MyWorkflow)
911
+ data = workflow_display.serialize()
912
+
913
+ # THEN the state variables should be serialized correctly
914
+ assert "state_variables" in data
915
+ state_variables = data["state_variables"]
916
+ assert isinstance(state_variables, list)
917
+ assert len(state_variables) == 4
918
+
919
+ state_1 = next(var for var in state_variables if isinstance(var, dict) and var["key"] == "state_1")
920
+ assert state_1 == {
921
+ "id": "83c5b71d-56eb-42a5-84df-97e3591370c2",
922
+ "key": "state_1",
923
+ "type": "STRING",
924
+ "default": {"type": "STRING", "value": "hello"},
925
+ "required": False,
926
+ "extensions": {"color": None},
927
+ }
928
+
929
+ state_2 = next(var for var in state_variables if isinstance(var, dict) and var["key"] == "state_2")
930
+ assert state_2 == {
931
+ "id": "9b0cfeec-aa66-42b3-8f31-aa7eb8ac30ea",
932
+ "key": "state_2",
933
+ "type": "STRING",
934
+ "default": None,
935
+ "required": False,
936
+ "extensions": {"color": None},
937
+ }
938
+
939
+ state_3 = next(var for var in state_variables if isinstance(var, dict) and var["key"] == "state_3")
940
+ assert state_3 == {
941
+ "id": "3e19c570-6b46-4eab-ad81-d8d97028496f",
942
+ "key": "state_3",
943
+ "type": "NUMBER",
944
+ "default": {"type": "NUMBER", "value": 1.0},
945
+ "required": False,
946
+ "extensions": {"color": None},
947
+ }
948
+
949
+ state_4 = next(var for var in state_variables if isinstance(var, dict) and var["key"] == "state_4")
950
+ assert state_4 == {
951
+ "id": "50c735de-f269-4d0a-b511-c9a1104451bb",
952
+ "key": "state_4",
953
+ "type": "NUMBER",
954
+ "default": {"type": "NUMBER", "value": 2.0},
955
+ "required": False,
956
+ "extensions": {"color": None},
957
+ }