vellum-ai 1.7.9__py3-none-any.whl → 1.7.10__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.

Potentially problematic release.


This version of vellum-ai might be problematic. Click here for more details.

@@ -27,10 +27,10 @@ class BaseClientWrapper:
27
27
 
28
28
  def get_headers(self) -> typing.Dict[str, str]:
29
29
  headers: typing.Dict[str, str] = {
30
- "User-Agent": "vellum-ai/1.7.9",
30
+ "User-Agent": "vellum-ai/1.7.10",
31
31
  "X-Fern-Language": "Python",
32
32
  "X-Fern-SDK-Name": "vellum-ai",
33
- "X-Fern-SDK-Version": "1.7.9",
33
+ "X-Fern-SDK-Version": "1.7.10",
34
34
  **(self.get_custom_headers() or {}),
35
35
  }
36
36
  if self._api_version is not None:
@@ -4,9 +4,11 @@ from typing import ClassVar, Generator, Generic, Iterator, List, Optional, Union
4
4
  from vellum import AdHocExecutePromptEvent, ExecutePromptEvent, PromptOutput
5
5
  from vellum.client.core import RequestOptions
6
6
  from vellum.client.core.api_error import ApiError
7
+ from vellum.workflows.descriptors.base import BaseDescriptor
7
8
  from vellum.workflows.errors.types import WorkflowErrorCode, vellum_error_to_workflow_error
8
9
  from vellum.workflows.events.node import NodeExecutionStreamingEvent
9
10
  from vellum.workflows.exceptions import NodeException
11
+ from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
10
12
  from vellum.workflows.nodes.bases import BaseNode
11
13
  from vellum.workflows.outputs.base import BaseOutput, BaseOutputs
12
14
  from vellum.workflows.references.output import OutputReference
@@ -14,6 +16,16 @@ from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior
14
16
  from vellum.workflows.types.generics import StateType
15
17
 
16
18
 
19
+ def _contains_reference_to_output(reference: BaseDescriptor, target_reference: OutputReference) -> bool:
20
+ if reference == target_reference:
21
+ return True
22
+ if isinstance(reference, CoalesceExpression):
23
+ return _contains_reference_to_output(reference.lhs, target_reference) or _contains_reference_to_output(
24
+ reference.rhs, target_reference
25
+ )
26
+ return False
27
+
28
+
17
29
  class BasePromptNode(BaseNode[StateType], Generic[StateType]):
18
30
  # Inputs that are passed to the Prompt
19
31
  prompt_inputs: ClassVar[Optional[EntityInputsInterface]] = None
@@ -112,10 +124,7 @@ class BasePromptNode(BaseNode[StateType], Generic[StateType]):
112
124
  if not target_node_output:
113
125
  return False
114
126
 
115
- if not isinstance(target_node_output.instance, OutputReference):
127
+ if not isinstance(target_node_output.instance, BaseDescriptor):
116
128
  return False
117
129
 
118
- if target_node_output.instance.name != "text":
119
- return False
120
-
121
- return True
130
+ return _contains_reference_to_output(target_node_output.instance, event.node_definition.Outputs.text)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 1.7.9
3
+ Version: 1.7.10
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -111,7 +111,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_ser
111
111
  vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=exT7U-axwtYgFylagScflSQLJEND51qIAx2UATju6JM,6023
112
112
  vellum_ee/workflows/display/tests/workflow_serialization/test_final_output_node_map_reference_serialization.py,sha256=vl3pxUJlrYRA8zzFJ-gRm7fe-5fviLNSIsUC7imnMqk,3502
113
113
  vellum_ee/workflows/display/tests/workflow_serialization/test_manual_trigger_serialization.py,sha256=L4bJWW94eq5cl6pjIaX7pQrDHoF67Gudfx-41dmmd10,2330
114
- vellum_ee/workflows/display/tests/workflow_serialization/test_slack_trigger_serialization.py,sha256=lBCzNJHmP_Z7_QEnzBO2FYvjJzVm8-lHxb9buivrqZk,4971
114
+ vellum_ee/workflows/display/tests/workflow_serialization/test_slack_trigger_serialization.py,sha256=HCZKF2_wOrn05s94PKWBP8cLl6Uw8j3y7Ec83xxQfLM,2258
115
115
  vellum_ee/workflows/display/tests/workflow_serialization/test_terminal_node_any_serialization.py,sha256=4WAmSEJZlDBLPhsD1f4GwY9ahB9F6qJKGnL6j7ZYlzQ,1740
116
116
  vellum_ee/workflows/display/tests/workflow_serialization/test_web_search_node_serialization.py,sha256=vbDFBrWUPeeW7cxjNA6SXrsHlYcbOAhlQ4C45Vdnr1c,3428
117
117
  vellum_ee/workflows/display/tests/workflow_serialization/test_workflow_input_parameterization_error.py,sha256=vAdmn3YTBDpo55znbydQxsgg9ASqHcvsUPwiBR_7wfo,1461
@@ -155,14 +155,14 @@ vellum_ee/workflows/tests/local_workflow/workflow.py,sha256=A4qOzOPNwePYxWbcAgIP
155
155
  vellum_ee/workflows/tests/test_display_meta.py,sha256=PkXJVnMZs9GNooDkd59n4YTBAX3XGPQWeSSVbhehVFM,5112
156
156
  vellum_ee/workflows/tests/test_registry.py,sha256=B8xRIuEyLWfSqrYoPldNQXhKPfe50PllvtAZoI8-uPs,6066
157
157
  vellum_ee/workflows/tests/test_serialize_module.py,sha256=zleQTcGZa5_nzwu4zpFoqEHhk7pb64hGrhObR4anhPQ,4471
158
- vellum_ee/workflows/tests/test_server.py,sha256=RmLE2s9Cs7NejvWf7aPRNuAeEER-hGk-9Q9fYrn5wps,26013
158
+ vellum_ee/workflows/tests/test_server.py,sha256=Ao2htC5i6drtnx1b2HHFM1O-OzVGuTi6PsJorzKF_mM,26284
159
159
  vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
160
160
  vellum/__init__.py,sha256=6dkyRHmIKuQPzL_z3QLVUrbkAF-HJKDhDSMCnf4ZsKw,49502
161
161
  vellum/client/README.md,sha256=flqu57ubZNTfpq60CdLtJC9gp4WEkyjb_n_eZ4OYf9w,6497
162
162
  vellum/client/__init__.py,sha256=rMnKRqL5-356SBc-rfm56MkO87PuAi2mtcfBszcJU1M,74316
163
163
  vellum/client/core/__init__.py,sha256=lTcqUPXcx4112yLDd70RAPeqq6tu3eFMe1pKOqkW9JQ,1562
164
164
  vellum/client/core/api_error.py,sha256=44vPoTyWN59gonCIZMdzw7M1uspygiLnr3GNFOoVL2Q,614
165
- vellum/client/core/client_wrapper.py,sha256=SDfeITPfYIuFYtFxDzo3M3ePxfx4Mu0Yw6Y3QEnkCts,2840
165
+ vellum/client/core/client_wrapper.py,sha256=9c4zn6yMqgyXRP7ix8lzAHvyY9fwno1tGUAQ2N1anrI,2842
166
166
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
167
167
  vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
168
168
  vellum/client/core/force_multipart.py,sha256=awxh5MtcRYe74ehY8U76jzv6fYM_w_D3Rur7KQQzSDk,429
@@ -1924,7 +1924,7 @@ vellum/workflows/nodes/displayable/bases/api_node/node.py,sha256=cOYaIqimzDL6TuX
1924
1924
  vellum/workflows/nodes/displayable/bases/api_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1925
1925
  vellum/workflows/nodes/displayable/bases/api_node/tests/test_node.py,sha256=5C59vn_yg4r5EWioKIr658Jr1MSGX3YF4yKJokY37Xc,4726
1926
1926
  vellum/workflows/nodes/displayable/bases/base_prompt_node/__init__.py,sha256=Org3xTvgp1pA0uUXFfnJr29D3HzCey2lEdYF4zbIUgo,70
1927
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py,sha256=w02vgydiwNoKru324QLSkH3BiGUvHTgKbf05BEx945s,4657
1927
+ vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py,sha256=ZIAXMreHcs3OR-djlkXgqF6tw7-Qfl8KUvjmJ7qRU3U,5204
1928
1928
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/__init__.py,sha256=Hl35IAoepRpE-j4cALaXVJIYTYOF3qszyVbxTj4kS1s,82
1929
1929
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=ITxAa1HWF6OPdcKg0DdTK7YP94ezzzWVyZzCRMiybIg,18638
1930
1930
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -2079,8 +2079,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
2079
2079
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2080
2080
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=Boa-_m9ii2Qsa1RvVM-VYniF7zCpzGgEGy-OnPZkrHg,23941
2081
2081
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
2082
- vellum_ai-1.7.9.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
2083
- vellum_ai-1.7.9.dist-info/METADATA,sha256=W9uh0R7Qv8FtGnts5F2-3PAMz4ki8JwFXCa43kinV8U,5547
2084
- vellum_ai-1.7.9.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
2085
- vellum_ai-1.7.9.dist-info/entry_points.txt,sha256=xVavzAKN4iF_NbmhWOlOkHluka0YLkbN_pFQ9pW3gLI,117
2086
- vellum_ai-1.7.9.dist-info/RECORD,,
2082
+ vellum_ai-1.7.10.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
2083
+ vellum_ai-1.7.10.dist-info/METADATA,sha256=vdfRtdqtbtZRBcpr0kWHkp5NLGNlT28vVlfm4GtK6cQ,5548
2084
+ vellum_ai-1.7.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
2085
+ vellum_ai-1.7.10.dist-info/entry_points.txt,sha256=xVavzAKN4iF_NbmhWOlOkHluka0YLkbN_pFQ9pW3gLI,117
2086
+ vellum_ai-1.7.10.dist-info/RECORD,,
@@ -1,148 +1,13 @@
1
- """Tests for serialization of workflows with SlackTrigger."""
2
-
3
- from vellum.workflows import BaseWorkflow
4
- from vellum.workflows.inputs.base import BaseInputs
5
- from vellum.workflows.nodes.bases.base import BaseNode
6
- from vellum.workflows.state.base import BaseState
7
- from vellum.workflows.triggers.slack import SlackTrigger
8
1
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
9
2
 
3
+ from tests.workflows.basic_trigger_slack.workflow import SlackTriggerWorkflow
10
4
 
11
- class Inputs(BaseInputs):
12
- input: str
13
-
14
-
15
- class SimpleNode(BaseNode):
16
- class Outputs(BaseNode.Outputs):
17
- output = Inputs.input
18
-
19
-
20
- def test_slack_trigger_serialization() -> None:
21
- """Workflow with SlackTrigger serializes with triggers field."""
22
-
23
- class TestWorkflow(BaseWorkflow[Inputs, BaseState]):
24
- graph = SlackTrigger >> SimpleNode
25
-
26
- class Outputs(BaseWorkflow.Outputs):
27
- output = SimpleNode.Outputs.output
28
-
29
- result = get_workflow_display(workflow_class=TestWorkflow).serialize()
30
-
31
- # Validate triggers structure
32
- assert "triggers" in result
33
- triggers = result["triggers"]
34
- assert isinstance(triggers, list)
35
- assert len(triggers) == 1
36
-
37
- trigger = triggers[0]
38
- assert isinstance(trigger, dict)
39
- assert trigger["type"] == "SLACK_MESSAGE"
40
- assert "id" in trigger
41
-
42
- # Validate attributes
43
- assert "attributes" in trigger
44
- attributes = trigger["attributes"]
45
- assert isinstance(attributes, list)
46
- assert len(attributes) == 6
47
-
48
- attribute_names = set()
49
- for attribute in attributes:
50
- assert isinstance(attribute, dict)
51
- assert "name" in attribute
52
- assert isinstance(attribute["name"], str)
53
- attribute_names.add(attribute["name"])
54
- assert attribute_names == {
55
- "message",
56
- "channel",
57
- "user",
58
- "timestamp",
59
- "thread_ts",
60
- "event_type",
61
- }
62
-
63
- for attribute in attributes:
64
- assert isinstance(attribute, dict)
65
- assert attribute["value"] is None
66
- assert isinstance(attribute["id"], str)
67
- assert attribute["id"]
68
-
69
-
70
- def test_slack_trigger_multiple_entrypoints() -> None:
71
- """SlackTrigger with multiple entrypoints."""
72
-
73
- class NodeA(BaseNode):
74
- class Outputs(BaseNode.Outputs):
75
- output = Inputs.input
76
5
 
77
- class NodeB(BaseNode):
78
- class Outputs(BaseNode.Outputs):
79
- output = Inputs.input
6
+ def test_serialize_slack_trigger_workflow():
7
+ workflow_display = get_workflow_display(workflow_class=SlackTriggerWorkflow)
8
+ serialized_workflow: dict = workflow_display.serialize()
80
9
 
81
- class MultiWorkflow(BaseWorkflow[Inputs, BaseState]):
82
- graph = SlackTrigger >> {NodeA, NodeB}
83
-
84
- class Outputs(BaseWorkflow.Outputs):
85
- output_a = NodeA.Outputs.output
86
- output_b = NodeB.Outputs.output
87
-
88
- result = get_workflow_display(workflow_class=MultiWorkflow).serialize()
89
-
90
- # Validate triggers
91
- assert "triggers" in result
92
- triggers = result["triggers"]
93
- assert isinstance(triggers, list)
94
- assert len(triggers) == 1
95
-
96
- trigger = triggers[0]
97
- assert isinstance(trigger, dict)
98
- assert trigger["type"] == "SLACK_MESSAGE"
99
-
100
- # Validate attributes
101
- assert "attributes" in trigger
102
- attributes = trigger["attributes"]
103
- assert isinstance(attributes, list)
104
- attribute_names = set()
105
- for attribute in attributes:
106
- assert isinstance(attribute, dict)
107
- assert "name" in attribute
108
- assert isinstance(attribute["name"], str)
109
- attribute_names.add(attribute["name"])
110
-
111
- assert attribute_names == {
112
- "message",
113
- "channel",
114
- "user",
115
- "timestamp",
116
- "thread_ts",
117
- "event_type",
118
- }
119
-
120
- # Validate nodes
121
- assert "workflow_raw_data" in result
122
- workflow_data = result["workflow_raw_data"]
123
- assert isinstance(workflow_data, dict)
124
- assert "nodes" in workflow_data
125
- nodes = workflow_data["nodes"]
126
- assert isinstance(nodes, list)
127
-
128
- generic_nodes = [node for node in nodes if isinstance(node, dict) and node.get("type") == "GENERIC"]
129
- assert len(generic_nodes) >= 2
130
-
131
-
132
- def test_serialized_slack_workflow_structure() -> None:
133
- """Verify complete structure of serialized workflow with SlackTrigger."""
134
-
135
- class TestWorkflow(BaseWorkflow[Inputs, BaseState]):
136
- graph = SlackTrigger >> SimpleNode
137
-
138
- class Outputs(BaseWorkflow.Outputs):
139
- output = SimpleNode.Outputs.output
140
-
141
- result = get_workflow_display(workflow_class=TestWorkflow).serialize()
142
-
143
- # Validate top-level structure
144
- assert isinstance(result, dict)
145
- assert set(result.keys()) == {
10
+ assert serialized_workflow.keys() == {
146
11
  "workflow_raw_data",
147
12
  "input_variables",
148
13
  "state_variables",
@@ -150,18 +15,38 @@ def test_serialized_slack_workflow_structure() -> None:
150
15
  "triggers",
151
16
  }
152
17
 
153
- # Validate workflow_raw_data structure
154
- workflow_raw_data = result["workflow_raw_data"]
155
- assert isinstance(workflow_raw_data, dict)
156
- assert set(workflow_raw_data.keys()) == {
157
- "nodes",
158
- "edges",
159
- "display_data",
160
- "definition",
161
- "output_values",
162
- }
163
-
164
- # Validate definition
165
- definition = workflow_raw_data["definition"]
166
- assert isinstance(definition, dict)
167
- assert definition["name"] == "TestWorkflow"
18
+ triggers = serialized_workflow["triggers"]
19
+ assert triggers == [
20
+ {
21
+ "id": "45855aa4-27a0-426b-b399-a8ff2932a684",
22
+ "type": "SLACK_MESSAGE",
23
+ "attributes": [
24
+ {"id": "9d4bd7d7-314d-48b8-a483-f964ac3ca28a", "name": "channel", "type": "STRING", "value": None},
25
+ {"id": "af4aac3c-74f2-4250-801b-f2dbd7745277", "name": "event_type", "type": "STRING", "value": None},
26
+ {"id": "bdf8965f-b2f1-4f83-9a5a-e1532d73c795", "name": "message", "type": "STRING", "value": None},
27
+ {"id": "5a910518-f875-497c-ab5f-680eecce2d1d", "name": "thread_ts", "type": "STRING", "value": None},
28
+ {"id": "4aadb9ec-aabf-4a58-a9bb-41e89e8a20cb", "name": "timestamp", "type": "STRING", "value": None},
29
+ {"id": "c16971a0-73a3-4b81-93dc-2bcaafa3585a", "name": "user", "type": "STRING", "value": None},
30
+ ],
31
+ }
32
+ ]
33
+
34
+ workflow_raw_data = serialized_workflow["workflow_raw_data"]
35
+ nodes = workflow_raw_data["nodes"]
36
+
37
+ process_node = next(node for node in nodes if node["type"] == "GENERIC" and node["label"] == "Process Message Node")
38
+ assert "outputs" in process_node
39
+ assert process_node["outputs"] == [
40
+ {
41
+ "id": "a1208db6-2daf-48a4-acee-71c8b1f42656",
42
+ "name": "processed_message",
43
+ "type": "STRING",
44
+ "value": {
45
+ "type": "TRIGGER_ATTRIBUTE",
46
+ "trigger_id": "45855aa4-27a0-426b-b399-a8ff2932a684",
47
+ "attribute_id": "bdf8965f-b2f1-4f83-9a5a-e1532d73c795",
48
+ },
49
+ }
50
+ ]
51
+
52
+ assert triggers[0]["id"] == process_node["outputs"][0]["value"]["trigger_id"]
@@ -145,6 +145,11 @@ class CodeExecutionNode(BaseCodeExecutionNode[BaseState, int]):
145
145
  # AND we get the code execution result
146
146
  assert event.body.outputs == {"final_output": 5.0}
147
147
 
148
+ # AND the workflow definition module is correctly serialized as a list
149
+ serialized_event = event.model_dump(mode="json")
150
+ workflow_definition = serialized_event["body"]["workflow_definition"]
151
+ assert workflow_definition["module"] == [namespace, "workflow"]
152
+
148
153
 
149
154
  def test_load_from_module__simple_code_execution_node_with_try(
150
155
  vellum_client,