vellum-ai 0.11.0__py3-none-any.whl → 0.11.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. vellum/__init__.py +16 -0
  2. vellum/client/core/client_wrapper.py +1 -1
  3. vellum/client/types/__init__.py +28 -0
  4. vellum/client/types/test_suite_run_exec_config.py +7 -1
  5. vellum/client/types/test_suite_run_exec_config_request.py +8 -0
  6. vellum/client/types/test_suite_run_prompt_sandbox_history_item_exec_config.py +31 -0
  7. vellum/client/types/test_suite_run_prompt_sandbox_history_item_exec_config_data.py +27 -0
  8. vellum/client/types/test_suite_run_prompt_sandbox_history_item_exec_config_data_request.py +27 -0
  9. vellum/client/types/test_suite_run_prompt_sandbox_history_item_exec_config_request.py +31 -0
  10. vellum/client/types/test_suite_run_workflow_sandbox_history_item_exec_config.py +31 -0
  11. vellum/client/types/test_suite_run_workflow_sandbox_history_item_exec_config_data.py +27 -0
  12. vellum/client/types/test_suite_run_workflow_sandbox_history_item_exec_config_data_request.py +27 -0
  13. vellum/client/types/test_suite_run_workflow_sandbox_history_item_exec_config_request.py +31 -0
  14. vellum/types/test_suite_run_prompt_sandbox_history_item_exec_config.py +3 -0
  15. vellum/types/test_suite_run_prompt_sandbox_history_item_exec_config_data.py +3 -0
  16. vellum/types/test_suite_run_prompt_sandbox_history_item_exec_config_data_request.py +3 -0
  17. vellum/types/test_suite_run_prompt_sandbox_history_item_exec_config_request.py +3 -0
  18. vellum/types/test_suite_run_workflow_sandbox_history_item_exec_config.py +3 -0
  19. vellum/types/test_suite_run_workflow_sandbox_history_item_exec_config_data.py +3 -0
  20. vellum/types/test_suite_run_workflow_sandbox_history_item_exec_config_data_request.py +3 -0
  21. vellum/types/test_suite_run_workflow_sandbox_history_item_exec_config_request.py +3 -0
  22. vellum/workflows/context.py +42 -0
  23. vellum/workflows/nodes/core/inline_subworkflow_node/node.py +13 -7
  24. vellum/workflows/nodes/displayable/api_node/node.py +3 -2
  25. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +9 -0
  26. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +10 -1
  27. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +10 -1
  28. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +1 -1
  29. vellum/workflows/runner/runner.py +74 -70
  30. vellum/workflows/workflows/event_filters.py +4 -1
  31. {vellum_ai-0.11.0.dist-info → vellum_ai-0.11.1.dist-info}/METADATA +1 -1
  32. {vellum_ai-0.11.0.dist-info → vellum_ai-0.11.1.dist-info}/RECORD +43 -26
  33. vellum_cli/pull.py +3 -1
  34. vellum_cli/tests/test_pull.py +18 -0
  35. vellum_ee/workflows/display/base.py +1 -0
  36. vellum_ee/workflows/display/nodes/vellum/api_node.py +53 -54
  37. vellum_ee/workflows/display/nodes/vellum/utils.py +26 -6
  38. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +29 -1
  39. vellum_ee/workflows/display/vellum.py +1 -1
  40. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +10 -7
  41. {vellum_ai-0.11.0.dist-info → vellum_ai-0.11.1.dist-info}/LICENSE +0 -0
  42. {vellum_ai-0.11.0.dist-info → vellum_ai-0.11.1.dist-info}/WHEEL +0 -0
  43. {vellum_ai-0.11.0.dist-info → vellum_ai-0.11.1.dist-info}/entry_points.txt +0 -0
@@ -8,6 +8,7 @@ from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeV
8
8
  from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
9
9
  from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
10
10
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
11
+ from vellum_ee.workflows.display.vellum import WorkspaceSecretPointer
11
12
 
12
13
  _APINodeType = TypeVar("_APINodeType", bound=APINode)
13
14
 
@@ -79,16 +80,13 @@ class BaseAPINodeDisplay(BaseNodeVellumDisplay[_APINodeType], Generic[_APINodeTy
79
80
  if authorization_type
80
81
  else None
81
82
  )
82
- bearer_token_value_node_input = (
83
- create_node_input(
84
- node_id=node_id,
85
- input_name="bearer_token_value",
86
- value=bearer_token_value,
87
- display_context=display_context,
88
- input_id=self.bearer_token_value_input_id,
89
- )
90
- if bearer_token_value
91
- else None
83
+ bearer_token_value_node_input = create_node_input(
84
+ node_id=node_id,
85
+ input_name="bearer_token_value",
86
+ value=bearer_token_value,
87
+ display_context=display_context,
88
+ input_id=self.bearer_token_value_input_id,
89
+ pointer_type=WorkspaceSecretPointer,
92
90
  )
93
91
  api_key_header_key_node_input = (
94
92
  create_node_input(
@@ -101,52 +99,52 @@ class BaseAPINodeDisplay(BaseNodeVellumDisplay[_APINodeType], Generic[_APINodeTy
101
99
  if api_key_header_key
102
100
  else None
103
101
  )
104
- api_key_header_value_node_input = (
105
- create_node_input(
106
- node_id=node_id,
107
- input_name="api_key_header_value",
108
- value=node.api_key_header_value,
109
- display_context=display_context,
110
- input_id=self.api_key_header_value_input_id,
111
- )
112
- if headers and api_key_header_key and api_key_header_value
113
- else None
102
+ api_key_header_value_node_input = create_node_input(
103
+ node_id=node_id,
104
+ input_name="api_key_header_value",
105
+ value=api_key_header_value,
106
+ display_context=display_context,
107
+ input_id=self.api_key_header_value_input_id,
108
+ pointer_type=WorkspaceSecretPointer,
114
109
  )
115
110
 
116
- # TODO: Add stable IDs for additional headers
117
- # https://app.shortcut.com/vellum/story/5083
118
- additional_headers: JsonArray = (
119
- [
120
- {
121
- "header_key_input_id": create_node_input(
122
- node_id=node_id,
123
- input_name="additional_header_key",
124
- value=key,
125
- display_context=display_context,
126
- input_id=(
127
- self.additional_header_key_input_ids.get(key)
128
- if self.additional_header_key_input_ids
129
- else None
130
- ),
131
- ).id,
132
- "header_value_input_id": create_node_input(
133
- node_id=node_id,
134
- input_name="additional_header_value",
135
- value=value,
136
- display_context=display_context,
137
- input_id=(
138
- self.additional_header_value_input_ids.get(key)
139
- if self.additional_header_value_input_ids
140
- else None
141
- ),
142
- ).id,
143
- }
144
- for key, value in headers.items()
145
- if key not in {api_key_header_key, "Authorization"}
146
- ]
147
- if headers
148
- else []
149
- )
111
+ additional_header_inputs = []
112
+
113
+ additional_headers: JsonArray = []
114
+ if headers:
115
+ for key, value in headers.items():
116
+ if key in {api_key_header_key, "Authorization"}:
117
+ continue
118
+
119
+ header_key_input = create_node_input(
120
+ node_id=node_id,
121
+ input_name="additional_header_key",
122
+ value=key,
123
+ display_context=display_context,
124
+ input_id=(
125
+ self.additional_header_key_input_ids.get(key) if self.additional_header_key_input_ids else None
126
+ ),
127
+ )
128
+ header_value_input = create_node_input(
129
+ node_id=node_id,
130
+ input_name="additional_header_value",
131
+ value=value,
132
+ display_context=display_context,
133
+ input_id=(
134
+ self.additional_header_value_input_ids.get(key)
135
+ if self.additional_header_value_input_ids
136
+ else None
137
+ ),
138
+ )
139
+
140
+ additional_header_inputs.extend([header_key_input, header_value_input])
141
+
142
+ additional_headers.append(
143
+ {
144
+ "header_key_input_id": header_key_input.id,
145
+ "header_value_input_id": header_value_input.id,
146
+ }
147
+ )
150
148
 
151
149
  inputs = [
152
150
  input
@@ -161,6 +159,7 @@ class BaseAPINodeDisplay(BaseNodeVellumDisplay[_APINodeType], Generic[_APINodeTy
161
159
  ]
162
160
  if input is not None
163
161
  ]
162
+ inputs.extend(additional_header_inputs)
164
163
 
165
164
  _, text_output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.text)]
166
165
  _, json_output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.json)]
@@ -1,5 +1,5 @@
1
1
  from uuid import UUID
2
- from typing import Any, List, Optional, cast
2
+ from typing import Any, List, Optional, Type, cast
3
3
 
4
4
  from vellum.workflows.descriptors.base import BaseDescriptor
5
5
  from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
@@ -13,6 +13,8 @@ from vellum_ee.workflows.display.vellum import (
13
13
  NodeInput,
14
14
  NodeInputValuePointer,
15
15
  NodeInputValuePointerRule,
16
+ WorkspaceSecretData,
17
+ WorkspaceSecretPointer,
16
18
  )
17
19
 
18
20
 
@@ -22,6 +24,7 @@ def create_node_input(
22
24
  value: Any,
23
25
  display_context: WorkflowDisplayContext,
24
26
  input_id: Optional[UUID],
27
+ pointer_type: Optional[Type[NodeInputValuePointerRule]] = ConstantValuePointer,
25
28
  ) -> NodeInput:
26
29
  input_id = input_id or uuid4_from_hash(f"{node_id}|{input_name}")
27
30
  if (
@@ -33,7 +36,7 @@ def create_node_input(
33
36
  if wrapped_node._is_wrapped_node:
34
37
  value = getattr(wrapped_node.Outputs, value.name)
35
38
 
36
- rules = create_node_input_value_pointer_rules(value, display_context)
39
+ rules = create_node_input_value_pointer_rules(value, display_context, pointer_type=pointer_type)
37
40
  return NodeInput(
38
41
  id=str(input_id),
39
42
  key=input_name,
@@ -48,6 +51,7 @@ def create_node_input_value_pointer_rules(
48
51
  value: Any,
49
52
  display_context: WorkflowDisplayContext,
50
53
  existing_rules: Optional[List[NodeInputValuePointerRule]] = None,
54
+ pointer_type: Optional[Type[NodeInputValuePointerRule]] = None,
51
55
  ) -> List[NodeInputValuePointerRule]:
52
56
  node_input_value_pointer_rules: List[NodeInputValuePointerRule] = existing_rules or []
53
57
 
@@ -59,18 +63,34 @@ def create_node_input_value_pointer_rules(
59
63
 
60
64
  if isinstance(value, CoalesceExpression):
61
65
  # Recursively handle the left-hand side
62
- lhs_rules = create_node_input_value_pointer_rules(value.lhs, display_context, [])
66
+ lhs_rules = create_node_input_value_pointer_rules(value.lhs, display_context, [], pointer_type=pointer_type)
63
67
  node_input_value_pointer_rules.extend(lhs_rules)
64
68
 
65
69
  # Handle the right-hand side
66
70
  if not isinstance(value.rhs, CoalesceExpression):
67
- rhs_rules = create_node_input_value_pointer_rules(value.rhs, display_context, [])
71
+ rhs_rules = create_node_input_value_pointer_rules(
72
+ value.rhs, display_context, [], pointer_type=pointer_type
73
+ )
68
74
  node_input_value_pointer_rules.extend(rhs_rules)
69
75
  else:
70
76
  # Non-CoalesceExpression case
71
77
  node_input_value_pointer_rules.append(create_node_input_value_pointer_rule(value, display_context))
72
78
  else:
73
- vellum_variable_value = primitive_to_vellum_value(value)
74
- node_input_value_pointer_rules.append(ConstantValuePointer(type="CONSTANT_VALUE", data=vellum_variable_value))
79
+ pointer = create_pointer(value, pointer_type)
80
+ node_input_value_pointer_rules.append(pointer)
75
81
 
76
82
  return node_input_value_pointer_rules
83
+
84
+
85
+ def create_pointer(
86
+ value: Any,
87
+ pointer_type: Optional[Type[NodeInputValuePointerRule]] = None,
88
+ ) -> NodeInputValuePointerRule:
89
+ if value is None:
90
+ if pointer_type is WorkspaceSecretPointer:
91
+ return WorkspaceSecretPointer(
92
+ type="WORKSPACE_SECRET", data=WorkspaceSecretData(type="STRING", workspace_secret_id=None)
93
+ )
94
+
95
+ vellum_variable_value = primitive_to_vellum_value(value)
96
+ return ConstantValuePointer(type="CONSTANT_VALUE", data=vellum_variable_value)
@@ -119,6 +119,16 @@ def test_serialize_workflow(vellum_client):
119
119
  "combinator": "OR",
120
120
  },
121
121
  },
122
+ {
123
+ "id": "fee5e3c9-442a-4922-ba80-5ee07361cea7",
124
+ "key": "bearer_token_value",
125
+ "value": {
126
+ "rules": [
127
+ {"type": "WORKSPACE_SECRET", "data": {"type": "STRING", "workspace_secret_id": None}}
128
+ ],
129
+ "combinator": "OR",
130
+ },
131
+ },
122
132
  {
123
133
  "id": "2fcdfbc3-8095-4277-bb4a-a201fd326b54",
124
134
  "key": "api_key_header_key",
@@ -143,6 +153,24 @@ def test_serialize_workflow(vellum_client):
143
153
  "combinator": "OR",
144
154
  },
145
155
  },
156
+ {
157
+ "id": "57c31247-998a-430d-bb62-bf50eca7df35",
158
+ "key": "additional_header_key",
159
+ "value": {
160
+ "rules": [{"type": "CONSTANT_VALUE", "data": {"type": "STRING", "value": "additional_header"}}],
161
+ "combinator": "OR",
162
+ },
163
+ },
164
+ {
165
+ "id": "47b32274-f19b-4c15-b788-55c069c311c5",
166
+ "key": "additional_header_value",
167
+ "value": {
168
+ "rules": [
169
+ {"type": "CONSTANT_VALUE", "data": {"type": "STRING", "value": "additional header value"}}
170
+ ],
171
+ "combinator": "OR",
172
+ },
173
+ },
146
174
  ],
147
175
  "data": {
148
176
  "label": "Simple A P I Node",
@@ -153,7 +181,7 @@ def test_serialize_workflow(vellum_client):
153
181
  "method_input_id": "fd61b5ac-39f9-4cfe-a839-f8ce78c202df",
154
182
  "body_input_id": "c3a17ceb-e201-4025-b18a-9162aac7705e",
155
183
  "authorization_type_input_id": "3092bf23-3202-4f3e-874c-9a33ccc73459",
156
- "bearer_token_value_input_id": None,
184
+ "bearer_token_value_input_id": "fee5e3c9-442a-4922-ba80-5ee07361cea7",
157
185
  "api_key_header_key_input_id": "2fcdfbc3-8095-4277-bb4a-a201fd326b54",
158
186
  "api_key_header_value_input_id": "d794bb51-a419-4fd8-be63-dfaf4166e831",
159
187
  "additional_headers": [
@@ -202,7 +202,7 @@ class InputVariablePointer(UniversalBaseModel):
202
202
 
203
203
  class WorkspaceSecretData(UniversalBaseModel):
204
204
  type: VellumVariableType
205
- workspace_secret_id: str
205
+ workspace_secret_id: Optional[str] = None
206
206
 
207
207
 
208
208
  class WorkspaceSecretPointer(UniversalBaseModel):
@@ -14,7 +14,6 @@ from vellum.workflows.types.core import JsonArray, JsonObject
14
14
  from vellum.workflows.types.generics import WorkflowType
15
15
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
16
16
  from vellum_ee.workflows.display.nodes.types import PortDisplay
17
- from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
18
17
  from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
19
18
  from vellum_ee.workflows.display.utils.uuids import uuid4_from_hash
20
19
  from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type, primitive_to_vellum_value
@@ -57,12 +56,12 @@ class VellumWorkflowDisplay(
57
56
  def serialize(self, raise_errors: bool = True) -> JsonObject:
58
57
  input_variables: JsonArray = []
59
58
  for workflow_input, workflow_input_display in self.display_context.workflow_input_displays.items():
60
- default = (
61
- primitive_to_vellum_value(raise_if_descriptor(workflow_input.instance))
62
- if workflow_input.instance
63
- else None
59
+ default = primitive_to_vellum_value(workflow_input.instance) if workflow_input.instance else None
60
+ required = (
61
+ workflow_input_display.required
62
+ if workflow_input_display.required is not None
63
+ else type(None) not in workflow_input.types
64
64
  )
65
- required = type(None) not in workflow_input.types
66
65
 
67
66
  input_variables.append(
68
67
  {
@@ -270,12 +269,16 @@ class VellumWorkflowDisplay(
270
269
  self, workflow_input: WorkflowInputReference, overrides: Optional[WorkflowInputsVellumDisplayOverrides] = None
271
270
  ) -> WorkflowInputsVellumDisplay:
272
271
  workflow_input_id: UUID
272
+ required = None
273
+ color = None
273
274
  if overrides:
274
275
  workflow_input_id = overrides.id
276
+ required = overrides.required
277
+ color = overrides.color
275
278
  else:
276
279
  workflow_input_id = uuid4_from_hash(f"{self.workflow_id}|inputs|id|{workflow_input.name}")
277
280
 
278
- return WorkflowInputsVellumDisplay(id=workflow_input_id)
281
+ return WorkflowInputsVellumDisplay(id=workflow_input_id, required=required, color=color)
279
282
 
280
283
  def _generate_entrypoint_display(
281
284
  self,