vellum-ai 0.13.11__py3-none-any.whl → 0.13.13__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.
@@ -18,7 +18,7 @@ class BaseClientWrapper:
18
18
  headers: typing.Dict[str, str] = {
19
19
  "X-Fern-Language": "Python",
20
20
  "X-Fern-SDK-Name": "vellum-ai",
21
- "X-Fern-SDK-Version": "0.13.11",
21
+ "X-Fern-SDK-Version": "0.13.13",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -1,7 +1,9 @@
1
+ from typing import Optional
2
+
1
3
  from vellum.workflows.references import EnvironmentVariableReference
2
4
 
3
5
 
4
6
  class Environment:
5
7
  @staticmethod
6
- def get(name: str) -> EnvironmentVariableReference:
7
- return EnvironmentVariableReference(name=name)
8
+ def get(name: str, default: Optional[str] = None) -> EnvironmentVariableReference:
9
+ return EnvironmentVariableReference(name=name, default=default)
@@ -27,7 +27,9 @@ from vellum.workflows.events.workflow import (
27
27
  from vellum.workflows.inputs.base import BaseInputs
28
28
  from vellum.workflows.nodes.bases.base import BaseNode
29
29
  from vellum.workflows.outputs.base import BaseOutput
30
+ from vellum.workflows.references.vellum_secret import VellumSecretReference
30
31
  from vellum.workflows.state.base import BaseState
32
+ from vellum.workflows.types.core import VellumSecret
31
33
  from vellum.workflows.utils.uuids import uuid4_from_hash
32
34
  from vellum.workflows.workflows.base import BaseWorkflow
33
35
 
@@ -38,6 +40,7 @@ class MockInputs(BaseInputs):
38
40
 
39
41
  class MockNode(BaseNode):
40
42
  node_foo = MockInputs.foo
43
+ node_secret = VellumSecretReference("secret")
41
44
 
42
45
  class Outputs(BaseNode.Outputs):
43
46
  example: str
@@ -97,6 +100,7 @@ mock_node_uuid = str(uuid4_from_hash(MockNode.__qualname__))
97
100
  node_definition=MockNode,
98
101
  inputs={
99
102
  MockNode.node_foo: "bar",
103
+ MockNode.node_secret: VellumSecret(name="secret"),
100
104
  },
101
105
  ),
102
106
  parent=NodeParentContext(
@@ -123,6 +127,9 @@ mock_node_uuid = str(uuid4_from_hash(MockNode.__qualname__))
123
127
  },
124
128
  "inputs": {
125
129
  "node_foo": "bar",
130
+ "node_secret": {
131
+ "name": "secret",
132
+ },
126
133
  },
127
134
  },
128
135
  "parent": {
@@ -250,11 +250,10 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
250
250
  Determines whether a Node's execution should be initiated. Override this method to define custom
251
251
  trigger criteria.
252
252
  """
253
+ if state.meta.node_execution_cache.is_node_execution_initiated(cls.node_class, node_span_id):
254
+ return False
253
255
 
254
256
  if cls.merge_behavior == MergeBehavior.AWAIT_ATTRIBUTES:
255
- if state.meta.node_execution_cache.is_node_execution_initiated(cls.node_class, node_span_id):
256
- return False
257
-
258
257
  is_ready = True
259
258
  for descriptor in cls.node_class:
260
259
  if not descriptor.instance:
@@ -268,15 +267,9 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
268
267
  return is_ready
269
268
 
270
269
  if cls.merge_behavior == MergeBehavior.AWAIT_ANY:
271
- if state.meta.node_execution_cache.is_node_execution_initiated(cls.node_class, node_span_id):
272
- return False
273
-
274
270
  return True
275
271
 
276
272
  if cls.merge_behavior == MergeBehavior.AWAIT_ALL:
277
- if state.meta.node_execution_cache.is_node_execution_initiated(cls.node_class, node_span_id):
278
- return False
279
-
280
273
  """
281
274
  A node utilizing an AWAIT_ALL merge strategy will only be considered ready for the Nth time
282
275
  when all of its dependencies have been executed N times.
@@ -1,5 +1,5 @@
1
1
  import os
2
- from typing import TYPE_CHECKING
2
+ from typing import TYPE_CHECKING, Optional
3
3
 
4
4
  from vellum.workflows.descriptors.base import BaseDescriptor
5
5
 
@@ -8,13 +8,17 @@ if TYPE_CHECKING:
8
8
 
9
9
 
10
10
  class EnvironmentVariableReference(BaseDescriptor[str]):
11
- def __init__(self, *, name: str) -> None:
11
+ def __init__(self, *, name: str, default: Optional[str]):
12
12
  super().__init__(name=name, types=(str,))
13
+ self._default = default
13
14
 
14
15
  def resolve(self, state: "BaseState") -> str:
15
16
  env_value = os.environ.get(self.name)
16
17
  if env_value is not None:
17
18
  return env_value
18
19
 
20
+ if self._default is not None:
21
+ return self._default
22
+
19
23
  # Fetch Vellum Environment Variable named `self.name` once that project is done
20
24
  raise ValueError(f"No environment variable named '{self.name}' found")
@@ -9,6 +9,8 @@ from typing import ( # type: ignore[attr-defined]
9
9
  _UnionGenericAlias,
10
10
  )
11
11
 
12
+ from vellum.client.core.pydantic_utilities import UniversalBaseModel
13
+
12
14
  JsonArray = List["Json"]
13
15
  JsonObject = Dict[str, "Json"]
14
16
  Json = Union[None, bool, int, float, str, JsonArray, JsonObject]
@@ -20,12 +22,9 @@ SpecialGenericAlias = _SpecialGenericAlias
20
22
  UnionGenericAlias = _UnionGenericAlias
21
23
 
22
24
 
23
- class VellumSecret:
25
+ class VellumSecret(UniversalBaseModel):
24
26
  name: str
25
27
 
26
- def __init__(self, name: str):
27
- self.name = name
28
-
29
28
 
30
29
  EntityInputsInterface = Dict[str, Any]
31
30
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.13.11
3
+ Version: 0.13.13
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -21,7 +21,7 @@ vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
21
21
  vellum_ee/workflows/display/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  vellum_ee/workflows/display/base.py,sha256=3ZFUYRNKL24fBqXhKpa_Dq2W1a-a86J20dmJYA3H2eY,1755
23
23
  vellum_ee/workflows/display/nodes/__init__.py,sha256=5XOcZJXYUgaLS55QgRJzyQ_W1tpeprjnYAeYVezqoGw,160
24
- vellum_ee/workflows/display/nodes/base_node_display.py,sha256=AnACr-QfL4Hwc3JEN9tUDmr0c8DE9uAjP8w7NyXAfj4,15413
24
+ vellum_ee/workflows/display/nodes/base_node_display.py,sha256=YBXHPwf453j-xaJoeJsoGhnW039WPSmhbQO-G5UGtcY,15787
25
25
  vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=pLO0dORfRu--Ne9NgoyFT_CNjfpr5fGCsgbsMkUF5GM,2845
26
26
  vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=VpGL-tnMM9wEOkuHNxX74RHAFhz5jcVXvmBkKciOBg0,1367
27
27
  vellum_ee/workflows/display/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -56,7 +56,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DE
56
56
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=EenmEdBtHUFQ0OS-kE7Vboax3JnDdj-K4Qixt5oR0Po,2253
58
58
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=pYBubuTzwNczAGFTYhaMCwvMLAcoJfCLkn5PMPbrlMI,7187
59
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=9CV44pY33cL_RF9cKmNVwn5hDGEZbPIETavOrvIL3oY,10229
59
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=yPXhdZxEDunNl5LL5Obb0jeO34djt7F-GiaTJhp_fmo,16742
60
60
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=-12ZkZb3f5gyoNASV2yeQtMo5HmNsVEo8nXwL6IC-I8,6261
61
61
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=6th6kCwzql6lddjkTQx4Jbvvs4ChqtJwctW-B4QuBhI,37352
62
62
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=EbVgg_3_ipTt3MOop4RARX0fmNjwqZtkhIXzx9nGw7Y,4487
@@ -78,7 +78,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_ser
78
78
  vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=wQ97k-y9rZwKYlZSA6Z9XGUnGRaJ5BvCFu5QnhuEp4A,7404
79
79
  vellum_ee/workflows/display/types.py,sha256=jWTpfQv3baEWjbP12duc3MBz3TK03Ja1UI5458PVQVY,4211
80
80
  vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
- vellum_ee/workflows/display/utils/vellum.py,sha256=0H-c3OaQYZ_sGdI4YmyxEcZ77oWn_Rfts-MLs_QWqls,7289
81
+ vellum_ee/workflows/display/utils/vellum.py,sha256=kETI__jHR1lvO0SoFJgnpAOCK6eWmrSi4SbfZpRUmCA,7448
82
82
  vellum_ee/workflows/display/vellum.py,sha256=8xXRI8b8Tt661H-iZreTQTvLNEKUr4lf-XaKhE7_yUY,8147
83
83
  vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
84
84
  vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=x4C621UTH_SZLJYmVBiC1q-D-wadJlTiSGlKAI6CUbA,14082
@@ -112,7 +112,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
112
112
  vellum/client/__init__.py,sha256=8nZt88C9SVwWanjLbIQMU3rzb32h5UZfFMBx3VPHB50,111887
113
113
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
114
114
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
115
- vellum/client/core/client_wrapper.py,sha256=WdGHbGL6B-WAReI6C1XsH60HY57mtWSg-jZ-2xz4eiQ,1869
115
+ vellum/client/core/client_wrapper.py,sha256=WBZxe9jwGagoDy-B3qFt1xxFJYUu4kED2-27248SBsQ,1869
116
116
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
117
117
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
118
118
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -1258,13 +1258,13 @@ vellum/workflows/edges/edge.py,sha256=N0SnY3gKVuxImPAdCbPMPlHJIXbkQ3fwq_LbJRvVMF
1258
1258
  vellum/workflows/emitters/__init__.py,sha256=YyOgaoLtVW8eFNEWODzCYb0HzL0PoSeNRf4diJ1Y0dk,80
1259
1259
  vellum/workflows/emitters/base.py,sha256=D5SADKIvnbgKwIBgYm77jaqvpo1o0rz4MmuX_muRqQU,359
1260
1260
  vellum/workflows/environment/__init__.py,sha256=wGHslgSEZ7Octe4C-hNtl84EFelNimgmWQoi7px4-uw,71
1261
- vellum/workflows/environment/environment.py,sha256=IwcVSwA51jW1JTN_MAN22UbeAtZhiAVa_JRV4rmpAAs,219
1261
+ vellum/workflows/environment/environment.py,sha256=0XhJPBs8YASWmvPx8bkSdCvcbDmzpe9stfs2kgtNDRU,296
1262
1262
  vellum/workflows/errors/__init__.py,sha256=tWGPu5xyAU8gRb8_bl0fL7OfU3wxQ9UH6qVwy4X4P_Q,113
1263
1263
  vellum/workflows/errors/types.py,sha256=-Ls41oM4HN28b78Ou13FoZnaWRuaxBgTarKgSoBlCKc,3413
1264
1264
  vellum/workflows/events/__init__.py,sha256=6pxxceJo2dcaRkWtkDAYlUQZ-PHBQSZytIoyuUK48Qw,759
1265
1265
  vellum/workflows/events/node.py,sha256=uHT6If0esgZ3nLjrjmUPTKf3qbjGhoV_x5YKpjDBDcU,5280
1266
1266
  vellum/workflows/events/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1267
- vellum/workflows/events/tests/test_event.py,sha256=izB6Y9U5ROgmHBBpLNUY2navK4-qFp6hdJqJNz6Beek,13350
1267
+ vellum/workflows/events/tests/test_event.py,sha256=9rbp92dQXpGFad-LjE2nYU17neKkiHxQz9X8RsoCWs4,13718
1268
1268
  vellum/workflows/events/types.py,sha256=cjRE8WL8tYCFradd9NOGl_H0mN3LiWWnA1uHmyT2Q0Q,3412
1269
1269
  vellum/workflows/events/workflow.py,sha256=l5tXes0sg7iWaA1ZUE5dtAqNnGQ8iy6trVbOU9meu7U,5240
1270
1270
  vellum/workflows/exceptions.py,sha256=l-FLGvXywxg6ivolCts71b8pcsYAWoB1cmUR4Jx7N8g,614
@@ -1306,7 +1306,7 @@ vellum/workflows/inputs/base.py,sha256=1kMgr0WqCYdWUqgFvgSoAMw2067FAlgwhGXLgbIOr
1306
1306
  vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
1307
1307
  vellum/workflows/nodes/__init__.py,sha256=aVdQVv7Y3Ro3JlqXGpxwaU2zrI06plDHD2aumH5WUIs,1157
1308
1308
  vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
1309
- vellum/workflows/nodes/bases/base.py,sha256=iYn8XmKZKj43vCx_xs5AbnnLgBydmjlElwjb-0xe63I,14459
1309
+ vellum/workflows/nodes/bases/base.py,sha256=qzuf8InU_DZtat-ZsROEHLwmd08pVsYxeoweU5PWQ74,14162
1310
1310
  vellum/workflows/nodes/bases/base_adornment_node.py,sha256=eFTgsPCYb3eyGS0-kw7C6crFnwFx437R5wh9-8bWYts,2905
1311
1311
  vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1312
1312
  vellum/workflows/nodes/bases/tests/test_base_node.py,sha256=51CueFVty9XYASC0rKr1cXWejho5WElmhfhp6cCONy0,3811
@@ -1395,7 +1395,7 @@ vellum/workflows/ports/port.py,sha256=rc3GB7dDQCUs0IbY08a92-31YzJHQgBeww13brSJ2J
1395
1395
  vellum/workflows/ports/utils.py,sha256=pEjVNJKw9LhD_cFN-o0MWBOW2ejno7jv26qqzjLxwS4,1662
1396
1396
  vellum/workflows/references/__init__.py,sha256=glHFC1VfXmcbNvH5VzFbkT03d8_D7MMcvEcsUBrzLIs,591
1397
1397
  vellum/workflows/references/constant.py,sha256=6yUT4q1sMj1hkI_tzzQ9AYcmeeDYFUNCqUq_W2DN0S8,540
1398
- vellum/workflows/references/environment_variable.py,sha256=7FFtiKfc4eyVkkfUbhc666OBNDqvFlMoNQEYmGpEVVE,661
1398
+ vellum/workflows/references/environment_variable.py,sha256=-gfOcdYwVp9ztSUYz6h2WI2Cg95zqxq5hhFf3Yr7aQg,791
1399
1399
  vellum/workflows/references/execution_count.py,sha256=JILHqt8ELdc9ct-WsVCA5X-rKiP1rmJODw-XTf4kpHI,722
1400
1400
  vellum/workflows/references/external_input.py,sha256=XHugauKYvAmsGoFnjgJh00FcXjSMIqBvRun_CZuJD64,1662
1401
1401
  vellum/workflows/references/input.py,sha256=3INu-TLTi4dziWmva6LO3WvgDlPzsjayUx61cVvqLJA,325
@@ -1420,7 +1420,7 @@ vellum/workflows/state/tests/test_state.py,sha256=7ap_Z9GJqyonZ1eVXwNyyuhV0AL5Xi
1420
1420
  vellum/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1421
1421
  vellum/workflows/tests/test_sandbox.py,sha256=JKwaluI-lODQo7Ek9sjDstjL_WTdSqUlVik6ZVTfVOA,1826
1422
1422
  vellum/workflows/types/__init__.py,sha256=KxUTMBGzuRCfiMqzzsykOeVvrrkaZmTTo1a7SLu8gRM,68
1423
- vellum/workflows/types/core.py,sha256=D2NcSBwGgWj_mtXZqe3KnEQcb5qd5HzqAwnxwmlCfCw,899
1423
+ vellum/workflows/types/core.py,sha256=kMQremh_I8egXpiKmtMQbB6e3OczAWiRnnTq5V6xlD0,928
1424
1424
  vellum/workflows/types/cycle_map.py,sha256=-ZMQsKzZBpCi0bchJrkuN_dtCFuz9uFABy7Fq2PI58E,928
1425
1425
  vellum/workflows/types/generics.py,sha256=ZkfoRhWs042i5IjA99v2wIhmh1u-Wieo3LzosgGWJVk,600
1426
1426
  vellum/workflows/types/stack.py,sha256=RDSGLkcV612ge8UuAH9TZiEGXxJt0Av2-H5rfzrTVVI,1014
@@ -1441,8 +1441,8 @@ vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528
1441
1441
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1442
1442
  vellum/workflows/workflows/base.py,sha256=k0kUWWko4fHyCqLSU_1cBK_pXZpl9MXekWiG-bdOAo0,18353
1443
1443
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1444
- vellum_ai-0.13.11.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1445
- vellum_ai-0.13.11.dist-info/METADATA,sha256=NHPCibqYzo79FZeV0pFNsUB0dbOubh76GZRnzEJAc74,5335
1446
- vellum_ai-0.13.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1447
- vellum_ai-0.13.11.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1448
- vellum_ai-0.13.11.dist-info/RECORD,,
1444
+ vellum_ai-0.13.13.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1445
+ vellum_ai-0.13.13.dist-info/METADATA,sha256=2lRg2bzgnlj6JyWn6sy9HkzAtf11YL4dYlyitfEwO74,5335
1446
+ vellum_ai-0.13.13.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1447
+ vellum_ai-0.13.13.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1448
+ vellum_ai-0.13.13.dist-info/RECORD,,
@@ -31,7 +31,9 @@ from vellum.workflows.nodes.bases.base import BaseNode
31
31
  from vellum.workflows.nodes.utils import get_wrapped_node
32
32
  from vellum.workflows.ports import Port
33
33
  from vellum.workflows.references import OutputReference
34
+ from vellum.workflows.references.constant import ConstantValueReference
34
35
  from vellum.workflows.references.execution_count import ExecutionCountReference
36
+ from vellum.workflows.references.lazy import LazyReference
35
37
  from vellum.workflows.references.vellum_secret import VellumSecretReference
36
38
  from vellum.workflows.references.workflow_input import WorkflowInputReference
37
39
  from vellum.workflows.types.core import JsonArray, JsonObject
@@ -337,6 +339,12 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
337
339
  }
338
340
 
339
341
  def serialize_value(self, display_context: "WorkflowDisplayContext", value: BaseDescriptor) -> JsonObject:
342
+ if isinstance(value, ConstantValueReference):
343
+ return self.serialize_value(display_context, value._value)
344
+
345
+ if isinstance(value, LazyReference):
346
+ return self.serialize_value(display_context, value._get())
347
+
340
348
  if isinstance(value, WorkflowInputReference):
341
349
  workflow_input_display = display_context.global_workflow_input_displays[value]
342
350
  return {
@@ -4,6 +4,8 @@ from deepdiff import DeepDiff
4
4
 
5
5
  from vellum.workflows.inputs.base import BaseInputs
6
6
  from vellum.workflows.nodes.bases.base import BaseNode
7
+ from vellum.workflows.references.constant import ConstantValueReference
8
+ from vellum.workflows.references.lazy import LazyReference
7
9
  from vellum.workflows.references.vellum_secret import VellumSecretReference
8
10
  from vellum_ee.workflows.display.base import WorkflowInputsDisplay
9
11
  from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
@@ -19,11 +21,7 @@ class ConstantValueGenericNode(BaseNode):
19
21
 
20
22
 
21
23
  def test_serialize_node__constant_value(serialize_node):
22
- input_id = uuid4()
23
- serialized_node = serialize_node(
24
- node_class=ConstantValueGenericNode,
25
- global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
26
- )
24
+ serialized_node = serialize_node(ConstantValueGenericNode)
27
25
 
28
26
  assert not DeepDiff(
29
27
  {
@@ -67,6 +65,92 @@ def test_serialize_node__constant_value(serialize_node):
67
65
  )
68
66
 
69
67
 
68
+ class ConstantValueReferenceGenericNode(BaseNode):
69
+ attr: str = ConstantValueReference("hello")
70
+
71
+
72
+ def test_serialize_node__constant_value_reference(serialize_node):
73
+ serialized_node = serialize_node(ConstantValueReferenceGenericNode)
74
+
75
+ assert not DeepDiff(
76
+ {
77
+ "id": "9271e2b1-f47e-47a4-95ae-51299dedb62f",
78
+ "label": "ConstantValueReferenceGenericNode",
79
+ "type": "GENERIC",
80
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
81
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
82
+ "definition": {
83
+ "name": "ConstantValueReferenceGenericNode",
84
+ "module": [
85
+ "vellum_ee",
86
+ "workflows",
87
+ "display",
88
+ "tests",
89
+ "workflow_serialization",
90
+ "generic_nodes",
91
+ "test_attributes_serialization",
92
+ ],
93
+ },
94
+ "trigger": {"id": "8cc0b4c4-4ae4-4248-8fd5-bfb2e658eb51", "merge_behavior": "AWAIT_ATTRIBUTES"},
95
+ "ports": [{"id": "fe696d84-47c2-4325-8020-34a1c586a759", "name": "default", "type": "DEFAULT"}],
96
+ "adornments": None,
97
+ "attributes": [
98
+ {
99
+ "id": "460aeb68-7369-43d2-9d3d-37caa425611f",
100
+ "name": "attr",
101
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "hello"}},
102
+ }
103
+ ],
104
+ "outputs": [],
105
+ },
106
+ serialized_node,
107
+ ignore_order=True,
108
+ )
109
+
110
+
111
+ class LazyReferenceGenericNode(BaseNode):
112
+ attr: str = LazyReference(lambda: ConstantValueReference("hello"))
113
+
114
+
115
+ def test_serialize_node__lazy_reference(serialize_node):
116
+ serialized_node = serialize_node(LazyReferenceGenericNode)
117
+
118
+ assert not DeepDiff(
119
+ {
120
+ "id": "29563b11-bd4d-47b0-b017-372f78aeaef5",
121
+ "label": "LazyReferenceGenericNode",
122
+ "type": "GENERIC",
123
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
124
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
125
+ "definition": {
126
+ "name": "LazyReferenceGenericNode",
127
+ "module": [
128
+ "vellum_ee",
129
+ "workflows",
130
+ "display",
131
+ "tests",
132
+ "workflow_serialization",
133
+ "generic_nodes",
134
+ "test_attributes_serialization",
135
+ ],
136
+ },
137
+ "trigger": {"id": "56e9791a-078a-4bb7-90bc-a26c3991c70f", "merge_behavior": "AWAIT_ATTRIBUTES"},
138
+ "ports": [{"id": "acb761a0-fcc2-4d21-bc8c-d0d560912c04", "name": "default", "type": "DEFAULT"}],
139
+ "adornments": None,
140
+ "attributes": [
141
+ {
142
+ "id": "4370b381-9165-4fb4-881e-480507abe069",
143
+ "name": "attr",
144
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "hello"}},
145
+ }
146
+ ],
147
+ "outputs": [],
148
+ },
149
+ serialized_node,
150
+ ignore_order=True,
151
+ )
152
+
153
+
70
154
  class WorkflowInputGenericNode(BaseNode):
71
155
  attr: str = Inputs.input
72
156
 
@@ -284,3 +368,100 @@ def test_serialize_node__node_execution(serialize_node):
284
368
  serialized_node,
285
369
  ignore_order=True,
286
370
  )
371
+
372
+
373
+ class CoalesceNodeA(BaseNode):
374
+ class Outputs(BaseNode.Outputs):
375
+ output: str
376
+
377
+
378
+ class CoalesceNodeADisplay(BaseNodeDisplay[CoalesceNodeA]):
379
+ pass
380
+
381
+
382
+ class CoalesceNodeB(BaseNode):
383
+ class Outputs(BaseNode.Outputs):
384
+ output: str
385
+
386
+
387
+ class CoalesceNodeBDisplay(BaseNodeDisplay[CoalesceNodeB]):
388
+ pass
389
+
390
+
391
+ class CoalesceNodeFinal(BaseNode):
392
+ attr = CoalesceNodeA.Outputs.output.coalesce(CoalesceNodeB.Outputs.output)
393
+
394
+
395
+ class CoalesceNodeFinalDisplay(BaseNodeDisplay[CoalesceNodeFinal]):
396
+ pass
397
+
398
+
399
+ def test_serialize_node__coalesce(serialize_node):
400
+ coalesce_node_a_output_id = uuid4()
401
+ coalesce_node_b_output_id = uuid4()
402
+ serialized_node = serialize_node(
403
+ node_class=CoalesceNodeFinal,
404
+ global_node_displays={
405
+ CoalesceNodeA: CoalesceNodeADisplay(),
406
+ CoalesceNodeB: CoalesceNodeBDisplay(),
407
+ CoalesceNodeFinal: CoalesceNodeFinalDisplay(),
408
+ },
409
+ global_node_output_displays={
410
+ CoalesceNodeA.Outputs.output: (
411
+ CoalesceNodeA,
412
+ NodeOutputDisplay(id=coalesce_node_a_output_id, name="output"),
413
+ ),
414
+ CoalesceNodeB.Outputs.output: (
415
+ CoalesceNodeB,
416
+ NodeOutputDisplay(id=coalesce_node_b_output_id, name="output"),
417
+ ),
418
+ },
419
+ )
420
+
421
+ assert not DeepDiff(
422
+ {
423
+ "id": "84d0ce62-afd1-4186-b0e3-5dd8e5ca8b65",
424
+ "label": "CoalesceNodeFinal",
425
+ "type": "GENERIC",
426
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
427
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
428
+ "definition": {
429
+ "name": "CoalesceNodeFinal",
430
+ "module": [
431
+ "vellum_ee",
432
+ "workflows",
433
+ "display",
434
+ "tests",
435
+ "workflow_serialization",
436
+ "generic_nodes",
437
+ "test_attributes_serialization",
438
+ ],
439
+ },
440
+ "trigger": {"id": "5165f887-153b-4ecd-9219-1beb3cf4f906", "merge_behavior": "AWAIT_ATTRIBUTES"},
441
+ "ports": [{"id": "08ab456d-f541-4400-8305-e97f30cbe745", "name": "default", "type": "DEFAULT"}],
442
+ "adornments": None,
443
+ "attributes": [
444
+ {
445
+ "id": "5a22dd48-9ef3-456b-85b8-7662cf7823eb",
446
+ "name": "attr",
447
+ "value": {
448
+ "type": "BINARY_EXPRESSION",
449
+ "lhs": {
450
+ "type": "NODE_OUTPUT",
451
+ "node_id": "20c340f2-409c-4d31-b44b-eeffd76938d5",
452
+ "node_output_id": str(coalesce_node_a_output_id),
453
+ },
454
+ "operator": "coalesce",
455
+ "rhs": {
456
+ "type": "NODE_OUTPUT",
457
+ "node_id": "9fac3c54-4e75-46ca-a1f2-a80fc6d8ad3f",
458
+ "node_output_id": str(coalesce_node_b_output_id),
459
+ },
460
+ },
461
+ }
462
+ ],
463
+ "outputs": [],
464
+ },
465
+ serialized_node,
466
+ ignore_order=True,
467
+ )
@@ -6,6 +6,7 @@ from vellum.workflows.descriptors.base import BaseDescriptor
6
6
  from vellum.workflows.expressions.and_ import AndExpression
7
7
  from vellum.workflows.expressions.begins_with import BeginsWithExpression
8
8
  from vellum.workflows.expressions.between import BetweenExpression
9
+ from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
9
10
  from vellum.workflows.expressions.contains import ContainsExpression
10
11
  from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
11
12
  from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
@@ -150,5 +151,7 @@ def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> LogicalOperato
150
151
  return "and"
151
152
  elif isinstance(descriptor, OrExpression):
152
153
  return "or"
154
+ elif isinstance(descriptor, CoalesceExpression):
155
+ return "coalesce"
153
156
  else:
154
157
  raise ValueError(f"Unsupported descriptor type: {descriptor}")