vellum-ai 0.12.17__py3-none-any.whl → 0.13.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. vellum/__init__.py +10 -22
  2. vellum/client/__init__.py +8 -0
  3. vellum/client/core/client_wrapper.py +1 -1
  4. vellum/client/core/pydantic_utilities.py +5 -0
  5. vellum/client/resources/__init__.py +4 -0
  6. vellum/client/resources/organizations/__init__.py +2 -0
  7. vellum/client/resources/organizations/client.py +116 -0
  8. vellum/client/resources/workflows/client.py +8 -0
  9. vellum/client/resources/workspaces/__init__.py +2 -0
  10. vellum/client/resources/workspaces/client.py +114 -0
  11. vellum/client/types/__init__.py +6 -22
  12. vellum/client/types/logical_operator.py +2 -0
  13. vellum/client/types/new_member_join_behavior_enum.py +8 -0
  14. vellum/client/types/{function_call_variable_value.py → organization_read.py} +6 -4
  15. vellum/client/types/workflow_execution_workflow_result_event.py +0 -2
  16. vellum/client/types/workflow_result_event.py +0 -2
  17. vellum/client/types/workflow_result_event_output_data_array.py +4 -4
  18. vellum/client/types/{string_variable_value.py → workspace_read.py} +12 -5
  19. vellum/{types/json_variable_value.py → resources/organizations/__init__.py} +1 -1
  20. vellum/resources/organizations/client.py +3 -0
  21. vellum/{types/image_variable_value.py → resources/workspaces/__init__.py} +1 -1
  22. vellum/{types/array_variable_value.py → resources/workspaces/client.py} +1 -1
  23. vellum/types/{array_variable_value_item.py → new_member_join_behavior_enum.py} +1 -1
  24. vellum/types/{audio_variable_value.py → organization_read.py} +1 -1
  25. vellum/types/{error_variable_value.py → workspace_read.py} +1 -1
  26. vellum/workflows/descriptors/base.py +1 -1
  27. vellum/workflows/descriptors/tests/test_utils.py +3 -0
  28. vellum/workflows/expressions/accessor.py +8 -2
  29. vellum/workflows/nodes/core/map_node/node.py +49 -24
  30. vellum/workflows/nodes/core/map_node/tests/test_node.py +4 -4
  31. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +1 -1
  32. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +5 -3
  33. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +3 -0
  34. vellum/workflows/nodes/displayable/bases/search_node.py +37 -2
  35. vellum/workflows/nodes/displayable/bases/tests/__init__.py +0 -0
  36. vellum/workflows/nodes/displayable/bases/tests/test_utils.py +61 -0
  37. vellum/workflows/nodes/displayable/bases/types.py +42 -0
  38. vellum/workflows/nodes/displayable/bases/utils.py +112 -0
  39. vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +0 -1
  40. vellum/workflows/nodes/displayable/search_node/tests/__init__.py +0 -0
  41. vellum/workflows/nodes/displayable/search_node/tests/test_node.py +164 -0
  42. vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py +2 -3
  43. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +0 -1
  44. vellum/workflows/runner/runner.py +37 -4
  45. vellum/workflows/types/tests/test_utils.py +5 -2
  46. vellum/workflows/types/utils.py +4 -0
  47. vellum/workflows/workflows/base.py +14 -32
  48. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/METADATA +1 -1
  49. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/RECORD +100 -97
  50. vellum_cli/__init__.py +10 -0
  51. vellum_cli/ping.py +28 -0
  52. vellum_cli/tests/test_ping.py +47 -0
  53. vellum_ee/workflows/display/nodes/base_node_display.py +17 -10
  54. vellum_ee/workflows/display/nodes/vellum/api_node.py +1 -0
  55. vellum_ee/workflows/display/nodes/vellum/base_node.py +110 -2
  56. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -0
  57. vellum_ee/workflows/display/nodes/vellum/conditional_node.py +5 -62
  58. vellum_ee/workflows/display/nodes/vellum/error_node.py +1 -0
  59. vellum_ee/workflows/display/nodes/vellum/final_output_node.py +1 -0
  60. vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +1 -0
  61. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +4 -0
  62. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +1 -0
  63. vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -1
  64. vellum_ee/workflows/display/nodes/vellum/merge_node.py +1 -0
  65. vellum_ee/workflows/display/nodes/vellum/note_node.py +1 -0
  66. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +15 -10
  67. vellum_ee/workflows/display/nodes/vellum/search_node.py +1 -0
  68. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +1 -0
  69. vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -0
  70. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +2 -2
  71. vellum_ee/workflows/display/nodes/vellum/utils.py +71 -1
  72. vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +2 -5
  73. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +18 -2
  74. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +67 -0
  75. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +66 -0
  76. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +1015 -0
  77. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +37 -22
  78. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +12 -56
  79. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +43 -93
  80. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +31 -151
  81. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +8 -26
  82. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +4 -15
  83. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +9 -44
  84. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +19 -101
  85. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +19 -73
  86. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +9 -44
  87. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +9 -44
  88. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +8 -6
  89. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +11 -58
  90. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +8 -11
  91. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +7 -30
  92. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +2 -11
  93. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +9 -44
  94. vellum_ee/workflows/display/utils/vellum.py +4 -42
  95. vellum_ee/workflows/display/vellum.py +9 -43
  96. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +7 -10
  97. vellum_ee/workflows/server/virtual_file_loader.py +3 -3
  98. vellum/client/types/array_variable_value.py +0 -27
  99. vellum/client/types/array_variable_value_item.py +0 -29
  100. vellum/client/types/audio_variable_value.py +0 -25
  101. vellum/client/types/chat_history_variable_value.py +0 -21
  102. vellum/client/types/error_variable_value.py +0 -21
  103. vellum/client/types/image_variable_value.py +0 -25
  104. vellum/client/types/json_variable_value.py +0 -20
  105. vellum/client/types/number_variable_value.py +0 -20
  106. vellum/client/types/search_results_variable_value.py +0 -21
  107. vellum/types/chat_history_variable_value.py +0 -3
  108. vellum/types/function_call_variable_value.py +0 -3
  109. vellum/types/number_variable_value.py +0 -3
  110. vellum/types/search_results_variable_value.py +0 -3
  111. vellum/types/string_variable_value.py +0 -3
  112. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/LICENSE +0 -0
  113. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/WHEEL +0 -0
  114. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/entry_points.txt +0 -0
vellum_cli/ping.py ADDED
@@ -0,0 +1,28 @@
1
+ from dotenv import load_dotenv
2
+
3
+ from vellum.workflows.vellum_client import create_vellum_client
4
+ from vellum_cli.logger import load_cli_logger
5
+
6
+
7
+ def ping_command():
8
+ load_dotenv()
9
+ logger = load_cli_logger()
10
+
11
+ client = create_vellum_client()
12
+
13
+ workspace = client.workspaces.workspace_identity()
14
+ organization = client.organizations.organization_identity()
15
+
16
+ logger.info(
17
+ f"""\
18
+ Successfully authenticated with Vellum!
19
+
20
+ Organization:
21
+ ID: {organization.id}
22
+ Name: {organization.name}
23
+
24
+ Workspace:
25
+ ID: {workspace.id}
26
+ Name: {workspace.name}
27
+ """
28
+ )
@@ -0,0 +1,47 @@
1
+ from datetime import datetime
2
+
3
+ from click.testing import CliRunner
4
+
5
+ from vellum.client.types.organization_read import OrganizationRead
6
+ from vellum.client.types.workspace_read import WorkspaceRead
7
+ from vellum_cli import main as cli_main
8
+
9
+
10
+ def test_ping__happy_path(vellum_client):
11
+ # GIVEN a cli
12
+ runner = CliRunner()
13
+
14
+ # AND a valid response from both the workflow and organization API calls
15
+ vellum_client.workspaces.workspace_identity.return_value = WorkspaceRead(
16
+ id="1234567890",
17
+ name="Test Workspace",
18
+ label="Test Workspace",
19
+ created=datetime.now(),
20
+ )
21
+ vellum_client.organizations.organization_identity.return_value = OrganizationRead(
22
+ id="1234567890",
23
+ name="Test Organization",
24
+ new_member_join_behavior="AUTO_ACCEPT_FROM_SHARED_DOMAIN",
25
+ allow_staff_access=True,
26
+ )
27
+
28
+ # WHEN calling `vellum ping`
29
+ result = runner.invoke(cli_main, ["ping"])
30
+
31
+ # THEN it should return Status information about the user's workspace
32
+ assert result.exit_code == 0
33
+ assert (
34
+ result.output
35
+ == """\x1b[38;20m\
36
+ Successfully authenticated with Vellum!
37
+
38
+ Organization:
39
+ ID: 1234567890
40
+ Name: Test Organization
41
+
42
+ Workspace:
43
+ ID: 1234567890
44
+ Name: Test Workspace
45
+ \x1b[0m
46
+ """
47
+ )
@@ -25,7 +25,7 @@ from vellum.workflows.types.utils import get_original_base
25
25
  from vellum.workflows.utils.names import pascal_to_title_case
26
26
  from vellum.workflows.utils.uuids import uuid4_from_hash
27
27
  from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay, PortDisplay, PortDisplayOverrides
28
- from vellum_ee.workflows.display.vellum import CodeResourceDefinition, NodeDefinition
28
+ from vellum_ee.workflows.display.vellum import CodeResourceDefinition
29
29
 
30
30
  if TYPE_CHECKING:
31
31
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
@@ -54,18 +54,25 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
54
54
  def serialize(self, display_context: "WorkflowDisplayContext", **kwargs: Any) -> JsonObject:
55
55
  raise NotImplementedError(f"Serialization for nodes of type {self._node.__name__} is not supported.")
56
56
 
57
- def get_definition(self) -> NodeDefinition:
57
+ def get_base(self) -> CodeResourceDefinition:
58
58
  node = self._node
59
- node_definition = NodeDefinition(
59
+
60
+ base_node_classes = [base for base in node.__bases__ if issubclass(base, BaseNode)]
61
+ if len(base_node_classes) != 1:
62
+ raise ValueError(f"Node {node.__name__} must extend from exactly one parent node class.")
63
+
64
+ base_node_class = base_node_classes[0]
65
+
66
+ return CodeResourceDefinition(
67
+ name=base_node_class.__name__,
68
+ module=base_node_class.__module__.split("."),
69
+ )
70
+
71
+ def get_definition(self) -> CodeResourceDefinition:
72
+ node = self._node
73
+ node_definition = CodeResourceDefinition(
60
74
  name=node.__name__,
61
75
  module=node.__module__.split("."),
62
- bases=[
63
- CodeResourceDefinition(
64
- name=base.__name__,
65
- module=base.__module__.split("."),
66
- )
67
- for base in node.__bases__
68
- ],
69
76
  )
70
77
  return node_definition
71
78
 
@@ -197,5 +197,6 @@ class BaseAPINodeDisplay(BaseNodeVellumDisplay[_APINodeType], Generic[_APINodeTy
197
197
  "status_code_output_id": str(status_code_output_display.id),
198
198
  },
199
199
  "display_data": self.get_display_data().dict(),
200
+ "base": self.get_base().dict(),
200
201
  "definition": self.get_definition().dict(),
201
202
  }
@@ -1,10 +1,21 @@
1
1
  from typing import Any, Generic, TypeVar
2
2
 
3
+ from vellum.workflows.descriptors.base import BaseDescriptor
4
+ from vellum.workflows.expressions.between import BetweenExpression
5
+ from vellum.workflows.expressions.is_not_null import IsNotNullExpression
6
+ from vellum.workflows.expressions.is_null import IsNullExpression
7
+ from vellum.workflows.expressions.not_between import NotBetweenExpression
3
8
  from vellum.workflows.nodes.bases.base import BaseNode
4
- from vellum.workflows.types.core import JsonObject
9
+ from vellum.workflows.references.execution_count import ExecutionCountReference
10
+ from vellum.workflows.references.output import OutputReference
11
+ from vellum.workflows.references.vellum_secret import VellumSecretReference
12
+ from vellum.workflows.references.workflow_input import WorkflowInputReference
13
+ from vellum.workflows.types.core import JsonArray, JsonObject
5
14
  from vellum.workflows.utils.uuids import uuid4_from_hash
6
15
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
16
+ from vellum_ee.workflows.display.nodes.vellum.utils import convert_descriptor_to_operator
7
17
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
18
+ from vellum_ee.workflows.display.utils.vellum import primitive_to_vellum_value
8
19
  from vellum_ee.workflows.display.vellum import GenericNodeDisplayData
9
20
 
10
21
  _BaseNodeType = TypeVar("_BaseNodeType", bound=BaseNode)
@@ -15,17 +26,40 @@ class BaseNodeDisplay(BaseNodeVellumDisplay[_BaseNodeType], Generic[_BaseNodeTyp
15
26
  node = self._node
16
27
  node_id = self.node_id
17
28
 
29
+ ports: JsonArray = []
30
+ for idx, port in enumerate(node.Ports):
31
+ id = str(uuid4_from_hash(f"{node_id}|{idx}"))
32
+
33
+ if port._condition_type:
34
+ ports.append(
35
+ {
36
+ "id": id,
37
+ "type": port._condition_type.value,
38
+ "expression": (
39
+ self.serialize_condition(display_context, port._condition) if port._condition else None
40
+ ),
41
+ }
42
+ )
43
+ else:
44
+ ports.append(
45
+ {
46
+ "id": id,
47
+ "type": "DEFAULT",
48
+ }
49
+ )
50
+
18
51
  return {
19
52
  "id": str(node_id),
20
53
  "label": node.__qualname__,
21
54
  "type": "GENERIC",
22
55
  "display_data": self.get_generic_node_display_data().dict(),
56
+ "base": self.get_base().dict(),
23
57
  "definition": self.get_definition().dict(),
24
58
  "trigger": {
25
59
  "id": str(uuid4_from_hash(f"{node_id}|trigger")),
26
60
  "merge_behavior": node.Trigger.merge_behavior.value,
27
61
  },
28
- "ports": [],
62
+ "ports": ports,
29
63
  "adornments": None,
30
64
  "attributes": [],
31
65
  }
@@ -33,3 +67,77 @@ class BaseNodeDisplay(BaseNodeVellumDisplay[_BaseNodeType], Generic[_BaseNodeTyp
33
67
  def get_generic_node_display_data(self) -> GenericNodeDisplayData:
34
68
  explicit_value = self._get_explicit_node_display_attr("display_data", GenericNodeDisplayData)
35
69
  return explicit_value if explicit_value else GenericNodeDisplayData()
70
+
71
+ def serialize_condition(self, display_context: WorkflowDisplayContext, condition: BaseDescriptor) -> JsonObject:
72
+ if isinstance(condition, (IsNullExpression, IsNotNullExpression)):
73
+ lhs = self.serialize_value(display_context, condition._expression) # type: ignore[attr-defined]
74
+ return {
75
+ "type": "UNARY_EXPRESSION",
76
+ "lhs": lhs,
77
+ "operator": convert_descriptor_to_operator(condition),
78
+ }
79
+ elif isinstance(condition, (BetweenExpression, NotBetweenExpression)):
80
+ base = self.serialize_value(display_context, condition._value) # type: ignore[attr-defined]
81
+ lhs = self.serialize_value(display_context, condition._start) # type: ignore[attr-defined]
82
+ rhs = self.serialize_value(display_context, condition._end) # type: ignore[attr-defined]
83
+
84
+ return {
85
+ "type": "TERNARY_EXPRESSION",
86
+ "base": base,
87
+ "operator": convert_descriptor_to_operator(condition),
88
+ "lhs": lhs,
89
+ "rhs": rhs,
90
+ }
91
+ else:
92
+ lhs = self.serialize_value(display_context, condition._lhs) # type: ignore[attr-defined]
93
+ rhs = self.serialize_value(display_context, condition._rhs) # type: ignore[attr-defined]
94
+
95
+ return {
96
+ "type": "BINARY_EXPRESSION",
97
+ "lhs": lhs,
98
+ "operator": convert_descriptor_to_operator(condition),
99
+ "rhs": rhs,
100
+ }
101
+
102
+ def serialize_value(self, display_context: WorkflowDisplayContext, value: BaseDescriptor) -> JsonObject:
103
+ if isinstance(value, WorkflowInputReference):
104
+ workflow_input_display = display_context.global_workflow_input_displays[value]
105
+ return {
106
+ "type": "WORKFLOW_INPUT",
107
+ "input_variable_id": str(workflow_input_display.id),
108
+ }
109
+
110
+ if isinstance(value, OutputReference):
111
+ upstream_node, output_display = display_context.global_node_output_displays[value]
112
+ upstream_node_display = display_context.global_node_displays[upstream_node]
113
+
114
+ return {
115
+ "type": "NODE_OUTPUT",
116
+ "node_id": str(upstream_node_display.node_id),
117
+ "node_output_id": str(output_display.id),
118
+ }
119
+
120
+ if isinstance(value, VellumSecretReference):
121
+ return {
122
+ "type": "VELLUM_SECRET",
123
+ "vellum_secret_name": value.name,
124
+ }
125
+
126
+ if isinstance(value, ExecutionCountReference):
127
+ node_class_display = display_context.global_node_displays[value.node_class]
128
+
129
+ return {
130
+ "type": "EXECUTION_COUNTER",
131
+ "node_id": str(node_class_display.node_id),
132
+ }
133
+
134
+ if not isinstance(value, BaseDescriptor):
135
+ vellum_value = primitive_to_vellum_value(value)
136
+ return {
137
+ "type": "CONSTANT_VALUE",
138
+ "value": vellum_value.dict(),
139
+ }
140
+
141
+ # If it's not any of the references we know about,
142
+ # then try to serialize it as a nested value
143
+ return self.serialize_condition(display_context, value)
@@ -92,5 +92,6 @@ class BaseCodeExecutionNodeDisplay(BaseNodeVellumDisplay[_CodeExecutionNodeType]
92
92
  "log_output_id": str(self.log_output_id) if self.log_output_id else str(log_output_display.id),
93
93
  },
94
94
  "display_data": self.get_display_data().dict(),
95
+ "base": self.get_base().dict(),
95
96
  "definition": self.get_definition().dict(),
96
97
  }
@@ -4,34 +4,16 @@ from typing import Any, ClassVar, Dict, Generic, List, Optional, Tuple, TypeVar,
4
4
 
5
5
  from vellum.workflows.descriptors.base import BaseDescriptor
6
6
  from vellum.workflows.expressions.and_ import AndExpression
7
- from vellum.workflows.expressions.begins_with import BeginsWithExpression
8
7
  from vellum.workflows.expressions.between import BetweenExpression
9
- from vellum.workflows.expressions.contains import ContainsExpression
10
- from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
11
- from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
12
- from vellum.workflows.expressions.does_not_end_with import DoesNotEndWithExpression
13
- from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
14
- from vellum.workflows.expressions.ends_with import EndsWithExpression
15
- from vellum.workflows.expressions.equals import EqualsExpression
16
- from vellum.workflows.expressions.greater_than import GreaterThanExpression
17
- from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
18
- from vellum.workflows.expressions.in_ import InExpression
19
- from vellum.workflows.expressions.is_nil import IsNilExpression
20
- from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
21
8
  from vellum.workflows.expressions.is_not_null import IsNotNullExpression
22
- from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
23
9
  from vellum.workflows.expressions.is_null import IsNullExpression
24
- from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
25
- from vellum.workflows.expressions.less_than import LessThanExpression
26
- from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
27
10
  from vellum.workflows.expressions.not_between import NotBetweenExpression
28
- from vellum.workflows.expressions.not_in import NotInExpression
29
11
  from vellum.workflows.expressions.or_ import OrExpression
30
12
  from vellum.workflows.nodes.displayable import ConditionalNode
31
13
  from vellum.workflows.types.core import ConditionType, JsonObject
32
14
  from vellum.workflows.utils.uuids import uuid4_from_hash
33
15
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
34
- from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
16
+ from vellum_ee.workflows.display.nodes.vellum.utils import convert_descriptor_to_operator, create_node_input
35
17
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
36
18
  from vellum_ee.workflows.display.vellum import NodeInput
37
19
 
@@ -113,7 +95,7 @@ but the defined conditions have length {len(condition_ids)}"""
113
95
  )
114
96
  node_inputs.append(expression_node_input)
115
97
  field_node_input_id = expression_node_input.id
116
- operator = self._convert_descriptor_to_operator(descriptor)
98
+ operator = convert_descriptor_to_operator(descriptor)
117
99
 
118
100
  elif isinstance(descriptor, (BetweenExpression, NotBetweenExpression)):
119
101
  field_node_input = create_node_input(
@@ -127,7 +109,7 @@ but the defined conditions have length {len(condition_ids)}"""
127
109
  value_node_input_id,
128
110
  )
129
111
  node_inputs.extend([field_node_input, value_node_input])
130
- operator = self._convert_descriptor_to_operator(descriptor)
112
+ operator = convert_descriptor_to_operator(descriptor)
131
113
  field_node_input_id = field_node_input.id
132
114
  value_node_input_id = value_node_input.id
133
115
 
@@ -147,7 +129,7 @@ but the defined conditions have length {len(condition_ids)}"""
147
129
  node_inputs.append(rhs_node_input)
148
130
  value_node_input_id = rhs_node_input.id
149
131
 
150
- operator = self._convert_descriptor_to_operator(descriptor)
132
+ operator = convert_descriptor_to_operator(descriptor)
151
133
  field_node_input_id = lhs_node_input.id
152
134
 
153
135
  return {
@@ -218,49 +200,10 @@ but the defined conditions have length {len(condition_ids)}"""
218
200
  "version": "2",
219
201
  },
220
202
  "display_data": self.get_display_data().dict(),
203
+ "base": self.get_base().dict(),
221
204
  "definition": self.get_definition().dict(),
222
205
  }
223
206
 
224
- def _convert_descriptor_to_operator(self, descriptor: BaseDescriptor) -> str:
225
- if isinstance(descriptor, EqualsExpression):
226
- return "="
227
- elif isinstance(descriptor, DoesNotEqualExpression):
228
- return "!="
229
- elif isinstance(descriptor, LessThanExpression):
230
- return "<"
231
- elif isinstance(descriptor, GreaterThanExpression):
232
- return ">"
233
- elif isinstance(descriptor, LessThanOrEqualToExpression):
234
- return "<="
235
- elif isinstance(descriptor, GreaterThanOrEqualToExpression):
236
- return ">="
237
- elif isinstance(descriptor, ContainsExpression):
238
- return "contains"
239
- elif isinstance(descriptor, BeginsWithExpression):
240
- return "beginsWith"
241
- elif isinstance(descriptor, EndsWithExpression):
242
- return "endsWith"
243
- elif isinstance(descriptor, DoesNotContainExpression):
244
- return "doesNotContain"
245
- elif isinstance(descriptor, DoesNotBeginWithExpression):
246
- return "doesNotBeginWith"
247
- elif isinstance(descriptor, DoesNotEndWithExpression):
248
- return "doesNotEndWith"
249
- elif isinstance(descriptor, (IsNullExpression, IsNilExpression, IsUndefinedExpression)):
250
- return "null"
251
- elif isinstance(descriptor, (IsNotNullExpression, IsNotNilExpression, IsNotUndefinedExpression)):
252
- return "notNull"
253
- elif isinstance(descriptor, InExpression):
254
- return "in"
255
- elif isinstance(descriptor, NotInExpression):
256
- return "notIn"
257
- elif isinstance(descriptor, BetweenExpression):
258
- return "between"
259
- elif isinstance(descriptor, NotBetweenExpression):
260
- return "notBetween"
261
- else:
262
- raise ValueError(f"Unsupported descriptor type: {descriptor}")
263
-
264
207
  def get_nested_rule_details_by_path(
265
208
  self, rule_ids: List[RuleIdMap], path: List[int]
266
209
  ) -> Union[Tuple[str, Optional[str], Optional[str]], None]:
@@ -44,5 +44,6 @@ class BaseErrorNodeDisplay(BaseNodeVellumDisplay[_ErrorNodeType], Generic[_Error
44
44
  "error_output_id": str(self.error_output_id),
45
45
  },
46
46
  "display_data": self.get_display_data().dict(),
47
+ "base": self.get_base().dict(),
47
48
  "definition": self.get_definition().dict(),
48
49
  }
@@ -45,6 +45,7 @@ class BaseFinalOutputNodeDisplay(BaseNodeVellumDisplay[_FinalOutputNodeType], Ge
45
45
  },
46
46
  "inputs": [node_input.dict()],
47
47
  "display_data": self.get_display_data().dict(),
48
+ "base": self.get_base().dict(),
48
49
  "definition": self.get_definition().dict(),
49
50
  }
50
51
 
@@ -45,5 +45,6 @@ class BaseGuardrailNodeDisplay(BaseNodeVellumDisplay[_GuardrailNodeType], Generi
45
45
  "release_tag": raise_if_descriptor(node.release_tag),
46
46
  },
47
47
  "display_data": self.get_display_data().dict(),
48
+ "base": self.get_base().dict(),
48
49
  "definition": self.get_definition().dict(),
49
50
  }
@@ -59,6 +59,7 @@ class BaseInlinePromptNodeDisplay(BaseNodeVellumDisplay[_InlinePromptNodeType],
59
59
  "ml_model_name": raise_if_descriptor(node.ml_model),
60
60
  },
61
61
  "display_data": self.get_display_data().dict(),
62
+ "base": self.get_base().dict(),
62
63
  "definition": self.get_definition().dict(),
63
64
  }
64
65
 
@@ -73,6 +74,9 @@ class BaseInlinePromptNodeDisplay(BaseNodeVellumDisplay[_InlinePromptNodeType],
73
74
  node_inputs: List[NodeInput] = []
74
75
  prompt_inputs: List[VellumVariable] = []
75
76
 
77
+ if not value:
78
+ return node_inputs, prompt_inputs
79
+
76
80
  for variable_name, variable_value in value.items():
77
81
  node_input = create_node_input(
78
82
  node_id=node_id,
@@ -52,6 +52,7 @@ class BaseInlineSubworkflowNodeDisplay(
52
52
  "output_variables": [workflow_output.dict() for workflow_output in workflow_outputs],
53
53
  },
54
54
  "display_data": self.get_display_data().dict(),
55
+ "base": self.get_base().dict(),
55
56
  "definition": self.get_definition().dict(),
56
57
  }
57
58
 
@@ -69,11 +69,12 @@ class BaseMapNodeDisplay(BaseNodeVellumDisplay[_MapNodeType], Generic[_MapNodeTy
69
69
  "workflow_raw_data": serialized_subworkflow["workflow_raw_data"],
70
70
  "input_variables": cast(JsonObject, renamed_input_variables),
71
71
  "output_variables": serialized_subworkflow["output_variables"],
72
- "concurrency": raise_if_descriptor(node.concurrency),
72
+ "concurrency": raise_if_descriptor(node.max_concurrency),
73
73
  "items_input_id": items_workflow_input_id,
74
74
  "item_input_id": item_workflow_input_id,
75
75
  "index_input_id": index_workflow_input_id,
76
76
  },
77
77
  "display_data": self.get_display_data().dict(),
78
+ "base": self.get_base().dict(),
78
79
  "definition": self.get_definition().dict(),
79
80
  }
@@ -45,6 +45,7 @@ class BaseMergeNodeDisplay(BaseNodeVellumDisplay[_MergeNodeType], Generic[_Merge
45
45
  "source_handle_id": str(self.get_source_handle_id(display_context.port_displays)),
46
46
  },
47
47
  "display_data": self.get_display_data().dict(),
48
+ "base": self.get_base().dict(),
48
49
  "definition": self.get_definition().dict(),
49
50
  }
50
51
 
@@ -26,5 +26,6 @@ class BaseNoteNodeDisplay(BaseNodeVellumDisplay[_NoteNodeType], Generic[_NoteNod
26
26
  "style": json.dumps(self.style) if self.style else None,
27
27
  },
28
28
  "display_data": self.get_display_data().dict(),
29
+ "base": self.get_base().dict(),
29
30
  "definition": self.get_definition().dict(),
30
31
  }
@@ -27,16 +27,20 @@ class BasePromptDeploymentNodeDisplay(
27
27
  node_id = self.node_id
28
28
 
29
29
  prompt_inputs = raise_if_descriptor(node.prompt_inputs)
30
- node_inputs = [
31
- create_node_input(
32
- node_id=node_id,
33
- input_name=variable_name,
34
- value=variable_value,
35
- display_context=display_context,
36
- input_id=self.prompt_input_ids_by_name.get(variable_name),
37
- )
38
- for variable_name, variable_value in prompt_inputs.items()
39
- ]
30
+ node_inputs = (
31
+ [
32
+ create_node_input(
33
+ node_id=node_id,
34
+ input_name=variable_name,
35
+ value=variable_value,
36
+ display_context=display_context,
37
+ input_id=self.prompt_input_ids_by_name.get(variable_name),
38
+ )
39
+ for variable_name, variable_value in prompt_inputs.items()
40
+ ]
41
+ if prompt_inputs
42
+ else []
43
+ )
40
44
 
41
45
  _, output_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.text)]
42
46
  _, array_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.results)]
@@ -64,5 +68,6 @@ class BasePromptDeploymentNodeDisplay(
64
68
  "release_tag": raise_if_descriptor(node.release_tag),
65
69
  },
66
70
  "display_data": self.get_display_data().dict(),
71
+ "base": self.get_base().dict(),
67
72
  "definition": self.get_definition().dict(),
68
73
  }
@@ -65,6 +65,7 @@ class BaseSearchNodeDisplay(BaseNodeVellumDisplay[_SearchNodeType], Generic[_Sea
65
65
  "metadata_filters_node_input_id": str(node_inputs["metadata_filters"].id),
66
66
  },
67
67
  "display_data": self.get_display_data().dict(),
68
+ "base": self.get_base().dict(),
68
69
  "definition": self.get_definition().dict(),
69
70
  }
70
71
 
@@ -56,5 +56,6 @@ class BaseSubworkflowDeploymentNodeDisplay(
56
56
  "release_tag": raise_if_descriptor(node.release_tag),
57
57
  },
58
58
  "display_data": self.get_display_data().dict(),
59
+ "base": self.get_base().dict(),
59
60
  "definition": self.get_definition().dict(),
60
61
  }
@@ -73,5 +73,6 @@ class BaseTemplatingNodeDisplay(BaseNodeVellumDisplay[_TemplatingNodeType], Gene
73
73
  "output_type": inferred_output_type,
74
74
  },
75
75
  "display_data": self.get_display_data().dict(),
76
+ "base": self.get_base().dict(),
76
77
  "definition": self.get_definition().dict(),
77
78
  }
@@ -2,6 +2,7 @@ import pytest
2
2
  from uuid import UUID, uuid4
3
3
  from typing import List, cast
4
4
 
5
+ from vellum.client.types.string_vellum_value import StringVellumValue
5
6
  from vellum.workflows.descriptors.base import BaseDescriptor
6
7
  from vellum.workflows.inputs import BaseInputs
7
8
  from vellum.workflows.nodes.bases import BaseNode
@@ -19,7 +20,6 @@ from vellum_ee.workflows.display.vellum import (
19
20
  NodeInputValuePointerRule,
20
21
  NodeOutputData,
21
22
  NodeOutputPointer,
22
- StringVellumValue,
23
23
  WorkflowInputsVellumDisplayOverrides,
24
24
  WorkflowMetaVellumDisplay,
25
25
  )
@@ -74,7 +74,7 @@ class MyNodeB(BaseNode):
74
74
  type="INPUT_VARIABLE",
75
75
  data=InputVariableData(input_variable_id="a154c29d-fac0-4cd0-ba88-bc52034f5470"),
76
76
  ),
77
- ConstantValuePointer(type="CONSTANT_VALUE", data=StringVellumValue(type="STRING", value="fallback")),
77
+ ConstantValuePointer(type="CONSTANT_VALUE", data=StringVellumValue(value="fallback")),
78
78
  ],
79
79
  ),
80
80
  ],
@@ -2,12 +2,37 @@ from uuid import UUID
2
2
  from typing import Any, List, Optional, Type, Union, cast
3
3
 
4
4
  from vellum.workflows.descriptors.base import BaseDescriptor
5
+ from vellum.workflows.expressions.and_ import AndExpression
6
+ from vellum.workflows.expressions.begins_with import BeginsWithExpression
7
+ from vellum.workflows.expressions.between import BetweenExpression
5
8
  from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
9
+ from vellum.workflows.expressions.contains import ContainsExpression
10
+ from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
11
+ from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
12
+ from vellum.workflows.expressions.does_not_end_with import DoesNotEndWithExpression
13
+ from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
14
+ from vellum.workflows.expressions.ends_with import EndsWithExpression
15
+ from vellum.workflows.expressions.equals import EqualsExpression
16
+ from vellum.workflows.expressions.greater_than import GreaterThanExpression
17
+ from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
18
+ from vellum.workflows.expressions.in_ import InExpression
19
+ from vellum.workflows.expressions.is_nil import IsNilExpression
20
+ from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
21
+ from vellum.workflows.expressions.is_not_null import IsNotNullExpression
22
+ from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
23
+ from vellum.workflows.expressions.is_null import IsNullExpression
24
+ from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
25
+ from vellum.workflows.expressions.less_than import LessThanExpression
26
+ from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
27
+ from vellum.workflows.expressions.not_between import NotBetweenExpression
28
+ from vellum.workflows.expressions.not_in import NotInExpression
29
+ from vellum.workflows.expressions.or_ import OrExpression
30
+ from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
6
31
  from vellum.workflows.nodes.utils import get_wrapped_node, has_wrapped_node
7
32
  from vellum.workflows.references import NodeReference, OutputReference
8
33
  from vellum.workflows.utils.uuids import uuid4_from_hash
9
34
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
10
- from vellum_ee.workflows.display.utils.vellum import create_node_input_value_pointer_rule, primitive_to_vellum_value
35
+ from vellum_ee.workflows.display.utils.vellum import create_node_input_value_pointer_rule
11
36
  from vellum_ee.workflows.display.vellum import (
12
37
  ConstantValuePointer,
13
38
  ExecutionCounterData,
@@ -109,3 +134,48 @@ def create_pointer(
109
134
  return ConstantValuePointer(type="CONSTANT_VALUE", data=vellum_variable_value)
110
135
  else:
111
136
  raise ValueError(f"Pointer type {pointer_type} not supported")
137
+
138
+
139
+ def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> str:
140
+ if isinstance(descriptor, EqualsExpression):
141
+ return "="
142
+ elif isinstance(descriptor, DoesNotEqualExpression):
143
+ return "!="
144
+ elif isinstance(descriptor, LessThanExpression):
145
+ return "<"
146
+ elif isinstance(descriptor, GreaterThanExpression):
147
+ return ">"
148
+ elif isinstance(descriptor, LessThanOrEqualToExpression):
149
+ return "<="
150
+ elif isinstance(descriptor, GreaterThanOrEqualToExpression):
151
+ return ">="
152
+ elif isinstance(descriptor, ContainsExpression):
153
+ return "contains"
154
+ elif isinstance(descriptor, BeginsWithExpression):
155
+ return "beginsWith"
156
+ elif isinstance(descriptor, EndsWithExpression):
157
+ return "endsWith"
158
+ elif isinstance(descriptor, DoesNotContainExpression):
159
+ return "doesNotContain"
160
+ elif isinstance(descriptor, DoesNotBeginWithExpression):
161
+ return "doesNotBeginWith"
162
+ elif isinstance(descriptor, DoesNotEndWithExpression):
163
+ return "doesNotEndWith"
164
+ elif isinstance(descriptor, (IsNullExpression, IsNilExpression, IsUndefinedExpression)):
165
+ return "null"
166
+ elif isinstance(descriptor, (IsNotNullExpression, IsNotNilExpression, IsNotUndefinedExpression)):
167
+ return "notNull"
168
+ elif isinstance(descriptor, InExpression):
169
+ return "in"
170
+ elif isinstance(descriptor, NotInExpression):
171
+ return "notIn"
172
+ elif isinstance(descriptor, BetweenExpression):
173
+ return "between"
174
+ elif isinstance(descriptor, NotBetweenExpression):
175
+ return "notBetween"
176
+ elif isinstance(descriptor, AndExpression):
177
+ return "and"
178
+ elif isinstance(descriptor, OrExpression):
179
+ return "or"
180
+ else:
181
+ raise ValueError(f"Unsupported descriptor type: {descriptor}")