vellum-ai 0.14.8__py3-none-any.whl → 0.14.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.
- vellum/client/core/client_wrapper.py +1 -1
- vellum/utils/templating/render.py +4 -1
- vellum/workflows/descriptors/base.py +6 -0
- vellum/workflows/descriptors/tests/test_utils.py +14 -0
- vellum/workflows/events/tests/test_event.py +40 -0
- vellum/workflows/events/workflow.py +21 -1
- vellum/workflows/expressions/greater_than.py +15 -8
- vellum/workflows/expressions/greater_than_or_equal_to.py +14 -8
- vellum/workflows/expressions/less_than.py +14 -8
- vellum/workflows/expressions/less_than_or_equal_to.py +14 -8
- vellum/workflows/expressions/parse_json.py +30 -0
- vellum/workflows/expressions/tests/__init__.py +0 -0
- vellum/workflows/expressions/tests/test_expressions.py +310 -0
- vellum/workflows/expressions/tests/test_parse_json.py +31 -0
- vellum/workflows/nodes/bases/base.py +5 -2
- vellum/workflows/nodes/core/templating_node/node.py +0 -1
- vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +49 -0
- vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +6 -7
- vellum/workflows/nodes/displayable/code_execution_node/node.py +18 -8
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +53 -0
- vellum/workflows/nodes/utils.py +14 -3
- vellum/workflows/runner/runner.py +34 -9
- vellum/workflows/state/encoder.py +2 -1
- {vellum_ai-0.14.8.dist-info → vellum_ai-0.14.10.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.8.dist-info → vellum_ai-0.14.10.dist-info}/RECORD +35 -31
- vellum_ee/workflows/display/nodes/base_node_display.py +4 -0
- vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +31 -0
- vellum_ee/workflows/display/types.py +1 -14
- vellum_ee/workflows/display/workflows/base_workflow_display.py +38 -18
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +27 -0
- vellum_ee/workflows/tests/test_display_meta.py +2 -0
- vellum_ee/workflows/tests/test_server.py +1 -0
- {vellum_ai-0.14.8.dist-info → vellum_ai-0.14.10.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.8.dist-info → vellum_ai-0.14.10.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.8.dist-info → vellum_ai-0.14.10.dist-info}/entry_points.txt +0 -0
| @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            from collections import defaultdict
         | 
| 2 2 | 
             
            from copy import deepcopy
         | 
| 3 | 
            +
            from dataclasses import dataclass
         | 
| 3 4 | 
             
            import logging
         | 
| 4 5 | 
             
            from queue import Empty, Queue
         | 
| 5 6 | 
             
            from threading import Event as ThreadingEvent, Thread
         | 
| @@ -63,6 +64,12 @@ ExternalInputsArg = Dict[ExternalInputReference, Any] | |
| 63 64 | 
             
            BackgroundThreadItem = Union[BaseState, WorkflowEvent, None]
         | 
| 64 65 |  | 
| 65 66 |  | 
| 67 | 
            +
            @dataclass
         | 
| 68 | 
            +
            class ActiveNode(Generic[StateType]):
         | 
| 69 | 
            +
                node: BaseNode[StateType]
         | 
| 70 | 
            +
                was_outputs_streamed: bool = False
         | 
| 71 | 
            +
             | 
| 72 | 
            +
             | 
| 66 73 | 
             
            class WorkflowRunner(Generic[StateType]):
         | 
| 67 74 | 
             
                _entrypoints: Iterable[Type[BaseNode]]
         | 
| 68 75 |  | 
| @@ -136,7 +143,7 @@ class WorkflowRunner(Generic[StateType]): | |
| 136 143 | 
             
                    self._dependencies: Dict[Type[BaseNode], Set[Type[BaseNode]]] = defaultdict(set)
         | 
| 137 144 | 
             
                    self._state_forks: Set[StateType] = {self._initial_state}
         | 
| 138 145 |  | 
| 139 | 
            -
                    self._active_nodes_by_execution_id: Dict[UUID,  | 
| 146 | 
            +
                    self._active_nodes_by_execution_id: Dict[UUID, ActiveNode[StateType]] = {}
         | 
| 140 147 | 
             
                    self._cancel_signal = cancel_signal
         | 
| 141 148 | 
             
                    self._execution_context = init_execution_context or get_execution_context()
         | 
| 142 149 | 
             
                    self._parent_context = self._execution_context.parent_context
         | 
| @@ -321,11 +328,7 @@ class WorkflowRunner(Generic[StateType]): | |
| 321 328 | 
             
                                    node_definition=node.__class__,
         | 
| 322 329 | 
             
                                    error=e.error,
         | 
| 323 330 | 
             
                                ),
         | 
| 324 | 
            -
                                parent= | 
| 325 | 
            -
                                    span_id=span_id,
         | 
| 326 | 
            -
                                    workflow_definition=self.workflow.__class__,
         | 
| 327 | 
            -
                                    parent=self._parent_context,
         | 
| 328 | 
            -
                                ),
         | 
| 331 | 
            +
                                parent=parent_context,
         | 
| 329 332 | 
             
                            )
         | 
| 330 333 | 
             
                        )
         | 
| 331 334 | 
             
                    except Exception as e:
         | 
| @@ -404,7 +407,7 @@ class WorkflowRunner(Generic[StateType]): | |
| 404 407 | 
             
                        current_parent = get_parent_context()
         | 
| 405 408 | 
             
                        node = node_class(state=state, context=self.workflow.context)
         | 
| 406 409 | 
             
                        state.meta.node_execution_cache.initiate_node_execution(node_class, node_span_id)
         | 
| 407 | 
            -
                        self._active_nodes_by_execution_id[node_span_id] = node
         | 
| 410 | 
            +
                        self._active_nodes_by_execution_id[node_span_id] = ActiveNode(node=node)
         | 
| 408 411 |  | 
| 409 412 | 
             
                        worker_thread = Thread(
         | 
| 410 413 | 
             
                            target=self._context_run_work_item,
         | 
| @@ -413,10 +416,11 @@ class WorkflowRunner(Generic[StateType]): | |
| 413 416 | 
             
                        worker_thread.start()
         | 
| 414 417 |  | 
| 415 418 | 
             
                def _handle_work_item_event(self, event: WorkflowEvent) -> Optional[WorkflowError]:
         | 
| 416 | 
            -
                     | 
| 417 | 
            -
                    if not  | 
| 419 | 
            +
                    active_node = self._active_nodes_by_execution_id.get(event.span_id)
         | 
| 420 | 
            +
                    if not active_node:
         | 
| 418 421 | 
             
                        return None
         | 
| 419 422 |  | 
| 423 | 
            +
                    node = active_node.node
         | 
| 420 424 | 
             
                    if event.name == "node.execution.rejected":
         | 
| 421 425 | 
             
                        self._active_nodes_by_execution_id.pop(event.span_id)
         | 
| 422 426 | 
             
                        return event.error
         | 
| @@ -431,6 +435,7 @@ class WorkflowRunner(Generic[StateType]): | |
| 431 435 | 
             
                            if node_output_descriptor.name != event.output.name:
         | 
| 432 436 | 
             
                                continue
         | 
| 433 437 |  | 
| 438 | 
            +
                            active_node.was_outputs_streamed = True
         | 
| 434 439 | 
             
                            self._workflow_event_outer_queue.put(
         | 
| 435 440 | 
             
                                self._stream_workflow_event(
         | 
| 436 441 | 
             
                                    BaseOutput(
         | 
| @@ -447,6 +452,26 @@ class WorkflowRunner(Generic[StateType]): | |
| 447 452 |  | 
| 448 453 | 
             
                    if event.name == "node.execution.fulfilled":
         | 
| 449 454 | 
             
                        self._active_nodes_by_execution_id.pop(event.span_id)
         | 
| 455 | 
            +
                        if not active_node.was_outputs_streamed:
         | 
| 456 | 
            +
                            for event_node_output_descriptor, node_output_value in event.outputs:
         | 
| 457 | 
            +
                                for workflow_output_descriptor in self.workflow.Outputs:
         | 
| 458 | 
            +
                                    node_output_descriptor = workflow_output_descriptor.instance
         | 
| 459 | 
            +
                                    if not isinstance(node_output_descriptor, OutputReference):
         | 
| 460 | 
            +
                                        continue
         | 
| 461 | 
            +
                                    if node_output_descriptor.outputs_class != event.node_definition.Outputs:
         | 
| 462 | 
            +
                                        continue
         | 
| 463 | 
            +
                                    if node_output_descriptor.name != event_node_output_descriptor.name:
         | 
| 464 | 
            +
                                        continue
         | 
| 465 | 
            +
             | 
| 466 | 
            +
                                    self._workflow_event_outer_queue.put(
         | 
| 467 | 
            +
                                        self._stream_workflow_event(
         | 
| 468 | 
            +
                                            BaseOutput(
         | 
| 469 | 
            +
                                                name=workflow_output_descriptor.name,
         | 
| 470 | 
            +
                                                value=node_output_value,
         | 
| 471 | 
            +
                                            )
         | 
| 472 | 
            +
                                        )
         | 
| 473 | 
            +
                                    )
         | 
| 474 | 
            +
             | 
| 450 475 | 
             
                        self._handle_invoked_ports(node.state, event.invoked_ports)
         | 
| 451 476 |  | 
| 452 477 | 
             
                        return None
         | 
| @@ -8,6 +8,7 @@ from typing import Any, Callable, Dict, Type | |
| 8 8 |  | 
| 9 9 | 
             
            from pydantic import BaseModel
         | 
| 10 10 |  | 
| 11 | 
            +
            from vellum.workflows.constants import undefined
         | 
| 11 12 | 
             
            from vellum.workflows.inputs.base import BaseInputs
         | 
| 12 13 | 
             
            from vellum.workflows.outputs.base import BaseOutput, BaseOutputs
         | 
| 13 14 | 
             
            from vellum.workflows.ports.port import Port
         | 
| @@ -22,7 +23,7 @@ class DefaultStateEncoder(JSONEncoder): | |
| 22 23 | 
             
                        return dict(obj)
         | 
| 23 24 |  | 
| 24 25 | 
             
                    if isinstance(obj, (BaseInputs, BaseOutputs)):
         | 
| 25 | 
            -
                        return {descriptor.name: value for descriptor, value in obj}
         | 
| 26 | 
            +
                        return {descriptor.name: value for descriptor, value in obj if value is not undefined}
         | 
| 26 27 |  | 
| 27 28 | 
             
                    if isinstance(obj, (BaseOutput, Port)):
         | 
| 28 29 | 
             
                        return obj.serialize()
         | 
| @@ -23,7 +23,7 @@ vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu | |
| 23 23 | 
             
            vellum_ee/workflows/display/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 24 24 | 
             
            vellum_ee/workflows/display/base.py,sha256=ak29FIsawhaFa9_paZUHThlZRFJ1xB486JWKuSt1PYY,1965
         | 
| 25 25 | 
             
            vellum_ee/workflows/display/nodes/__init__.py,sha256=436iSAh_Ex5tC68oEYvNgPu05ZVIAVXnS4PKGrQeZ0Y,321
         | 
| 26 | 
            -
            vellum_ee/workflows/display/nodes/base_node_display.py,sha256= | 
| 26 | 
            +
            vellum_ee/workflows/display/nodes/base_node_display.py,sha256=h4_JqwH_AsT92OK14S3kqssZDjL-uyXnJfo0XcLijK0,16492
         | 
| 27 27 | 
             
            vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=pLO0dORfRu--Ne9NgoyFT_CNjfpr5fGCsgbsMkUF5GM,2845
         | 
| 28 28 | 
             
            vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=0S6ksPp53WXWh1RQVH71nj2bkCWBj4ZaFYhTxW3N2F4,1230
         | 
| 29 29 | 
             
            vellum_ee/workflows/display/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| @@ -56,7 +56,7 @@ vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=4YUaTeD_OWF- | |
| 56 56 | 
             
            vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=HBfGz4yt9GlmMW9JxzaCacPnHBDNIeXE8Jhqr9DqLLw,6191
         | 
| 57 57 | 
             
            vellum_ee/workflows/display/nodes/vellum/utils.py,sha256=F_0BrlSszllK_BhryPbojIleLq2dGXOfQD1rVp3fNFg,4733
         | 
| 58 58 | 
             
            vellum_ee/workflows/display/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 59 | 
            -
            vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256= | 
| 59 | 
            +
            vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=cdpUoDNli8ULlNTrU6rnT4TZAIR8mzsG9ZbLrikPybU,8518
         | 
| 60 60 | 
             
            vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 61 61 | 
             
            vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 62 62 | 
             
            vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=A1-tIpC5KIKG9JA_rkd1nLS8zUG3Kb4QiVdvb3boFxE,2509
         | 
| @@ -83,15 +83,15 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_n | |
| 83 83 | 
             
            vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=NdhE3lm7RMQ8DqkraPSq24IbOxNla9unbs4tsMWRzm4,3781
         | 
| 84 84 | 
             
            vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=eD5686C9nWC5s6t08vbAnm9qf9t53gYQM-E1FwAa75c,3035
         | 
| 85 85 | 
             
            vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=huKAOeMJ2MKmp6XtbvMJTUadqynoV40Ypoz9jsBEBEQ,7431
         | 
| 86 | 
            -
            vellum_ee/workflows/display/types.py,sha256= | 
| 86 | 
            +
            vellum_ee/workflows/display/types.py,sha256=ixfmcQn51Rhsm4_0hWfG0_WpzLE89ZrDZpeYBklsP1Q,2592
         | 
| 87 87 | 
             
            vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 88 88 | 
             
            vellum_ee/workflows/display/utils/expressions.py,sha256=9FpOslDI-RCR5m4TgAu9KCHh4aTVnh7CHR2ykyMUDw0,1151
         | 
| 89 89 | 
             
            vellum_ee/workflows/display/utils/vellum.py,sha256=UjK_RxnSEmlIu9klGCPWU5RAQBmgZ7cRbRdgxaTbubE,8081
         | 
| 90 90 | 
             
            vellum_ee/workflows/display/vellum.py,sha256=7mqQaKZPPrLMcXSAQkPIxCy5x8HkKs5PbCu3GRaC2o8,8507
         | 
| 91 91 | 
             
            vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
         | 
| 92 | 
            -
            vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256= | 
| 92 | 
            +
            vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=Z9s_rtqAH5IfBtXOw40gbiT0GZeN6JRdFwGgPT-DIYM,20143
         | 
| 93 93 | 
             
            vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=kp0u8LN_2IwshLrhMImhpZx1hRyAcD5gXY-kDuuaGMQ,1269
         | 
| 94 | 
            -
            vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256= | 
| 94 | 
            +
            vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=STVSG0eL97mdnwBA5nOOgW8AuK8k-b8kWDyHKatNXIA,4259
         | 
| 95 95 | 
             
            vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=mbAzCpswOek34ITeTkesbVreCXpulj4NFjIg3RcdVZ8,18243
         | 
| 96 96 | 
             
            vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 97 97 | 
             
            vellum_ee/workflows/server/virtual_file_loader.py,sha256=X_DdNK7MfyOjKWekk6YQpOSCT6klKcdjT6nVJcBH1sM,1481
         | 
| @@ -114,15 +114,15 @@ vellum_ee/workflows/tests/local_workflow/nodes/__init__.py,sha256=1F6jxUpSKfPXPj | |
| 114 114 | 
             
            vellum_ee/workflows/tests/local_workflow/nodes/final_output.py,sha256=ZX7zBv87zirg0w9VKUW3QVDSdBLDqcqAMZjCL_oWbpU,297
         | 
| 115 115 | 
             
            vellum_ee/workflows/tests/local_workflow/nodes/templating_node.py,sha256=NQwFN61QkHfI3Vssz-B0NKGfupK8PU0FDSAIAhYBLi0,325
         | 
| 116 116 | 
             
            vellum_ee/workflows/tests/local_workflow/workflow.py,sha256=A4qOzOPNwePYxWbcAgIPLsmrVS_aVEZEc-wULSv787Q,393
         | 
| 117 | 
            -
            vellum_ee/workflows/tests/test_display_meta.py,sha256= | 
| 118 | 
            -
            vellum_ee/workflows/tests/test_server.py,sha256= | 
| 117 | 
            +
            vellum_ee/workflows/tests/test_display_meta.py,sha256=xLQ7QtIXIiIm61pm2lyl588Ohzc3pjyq1nDp-qVu2Fs,2295
         | 
| 118 | 
            +
            vellum_ee/workflows/tests/test_server.py,sha256=M6vvQ2hjIpDWtQdDM9EPbMvUrZ93niAuYnxMNJWOjPA,511
         | 
| 119 119 | 
             
            vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
         | 
| 120 120 | 
             
            vellum/__init__.py,sha256=a_aM1_A04XGma4MAIDNeBF9BKzWbiQaVVMRzImHuxjA,36438
         | 
| 121 121 | 
             
            vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
         | 
| 122 122 | 
             
            vellum/client/__init__.py,sha256=tKtdM1_GqmGq1gpi9ydWD_T-MM7fPn8QdHh8ww19cNI,117564
         | 
| 123 123 | 
             
            vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
         | 
| 124 124 | 
             
            vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
         | 
| 125 | 
            -
            vellum/client/core/client_wrapper.py,sha256= | 
| 125 | 
            +
            vellum/client/core/client_wrapper.py,sha256=6EXwOd5Ka1mFWVlZmNuffO99dtW8DTAiRFes4vDlQFY,1869
         | 
| 126 126 | 
             
            vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
         | 
| 127 127 | 
             
            vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
         | 
| 128 128 | 
             
            vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
         | 
| @@ -1287,7 +1287,7 @@ vellum/utils/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG | |
| 1287 1287 | 
             
            vellum/utils/templating/constants.py,sha256=8OHMO6WFAEimbIaiHc5gy6s91D7_KvW-vTlEMWwvl_M,711
         | 
| 1288 1288 | 
             
            vellum/utils/templating/custom_filters.py,sha256=XVHriwazejRZmxB_eg4xHgCxl7AiQQ2sx-hRLMmylfU,885
         | 
| 1289 1289 | 
             
            vellum/utils/templating/exceptions.py,sha256=cDp140PP4OnInW4qAvg3KqiSiF70C71UyEAKRBR1Abo,46
         | 
| 1290 | 
            -
            vellum/utils/templating/render.py,sha256= | 
| 1290 | 
            +
            vellum/utils/templating/render.py,sha256=P2t9qU4w_WdXAVLM5Nj3bc1-XlIKOkwK-czQ80pHBag,2172
         | 
| 1291 1291 | 
             
            vellum/utils/templating/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1292 1292 | 
             
            vellum/utils/templating/tests/test_custom_filters.py,sha256=mkJwc7t1gE13SKgPxhF-lN_m2XGCkphCB9Te81dGekI,532
         | 
| 1293 1293 | 
             
            vellum/utils/typing.py,sha256=wx_daFqD69cYkuJTVnvNrpjhqC3uuhbnyJ9_bIwC9OU,327
         | 
| @@ -1298,9 +1298,9 @@ vellum/workflows/__init__.py,sha256=CssPsbNvN6rDhoLuqpEv7MMKGa51vE6dvAh6U31Pcio, | |
| 1298 1298 | 
             
            vellum/workflows/constants.py,sha256=2yg4_uo5gpqViy3ZLSwfC8qTybleYCtOnhA4Rj6bacM,1310
         | 
| 1299 1299 | 
             
            vellum/workflows/context.py,sha256=DwSf8lO9NHABiqOoD3exgrjUoRuNsKtutaL5TgRbD-A,1441
         | 
| 1300 1300 | 
             
            vellum/workflows/descriptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1301 | 
            -
            vellum/workflows/descriptors/base.py,sha256= | 
| 1301 | 
            +
            vellum/workflows/descriptors/base.py,sha256=jtT11I5oB-CPWlJBZmc1RcVe4_xOKjimBthiHQHQuT0,14597
         | 
| 1302 1302 | 
             
            vellum/workflows/descriptors/exceptions.py,sha256=gUy4UD9JFUKSeQnQpeuDSLiRqWjWiIsxLahB7p_q3JY,54
         | 
| 1303 | 
            -
            vellum/workflows/descriptors/tests/test_utils.py,sha256= | 
| 1303 | 
            +
            vellum/workflows/descriptors/tests/test_utils.py,sha256=xoojJMyG5WLG9xGtmUjirz3lDFCcDsAcxjrtbdG8dNE,6060
         | 
| 1304 1304 | 
             
            vellum/workflows/descriptors/utils.py,sha256=gmVXJjf2yWmvlYey41J2FZHeSou0JuCHKb3826K_Jok,3838
         | 
| 1305 1305 | 
             
            vellum/workflows/edges/__init__.py,sha256=wSkmAnz9xyi4vZwtDbKxwlplt2skD7n3NsxkvR_pUus,50
         | 
| 1306 1306 | 
             
            vellum/workflows/edges/edge.py,sha256=N0SnY3gKVuxImPAdCbPMPlHJIXbkQ3fwq_LbJRvVMFc,677
         | 
| @@ -1313,9 +1313,9 @@ vellum/workflows/errors/types.py,sha256=tVW7Il9zalnwWzdoDLqYPIvRTOhXIv6FPORZAbU7 | |
| 1313 1313 | 
             
            vellum/workflows/events/__init__.py,sha256=6pxxceJo2dcaRkWtkDAYlUQZ-PHBQSZytIoyuUK48Qw,759
         | 
| 1314 1314 | 
             
            vellum/workflows/events/node.py,sha256=uHT6If0esgZ3nLjrjmUPTKf3qbjGhoV_x5YKpjDBDcU,5280
         | 
| 1315 1315 | 
             
            vellum/workflows/events/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1316 | 
            -
            vellum/workflows/events/tests/test_event.py,sha256= | 
| 1316 | 
            +
            vellum/workflows/events/tests/test_event.py,sha256=uRfMwSOqU-ROeZKCEngGvvJYlOZuxBhnC3qH5AGi3fM,15399
         | 
| 1317 1317 | 
             
            vellum/workflows/events/types.py,sha256=cjRE8WL8tYCFradd9NOGl_H0mN3LiWWnA1uHmyT2Q0Q,3412
         | 
| 1318 | 
            -
            vellum/workflows/events/workflow.py,sha256= | 
| 1318 | 
            +
            vellum/workflows/events/workflow.py,sha256=sLO29djAeHGVd4hLhaNtOQ48uwUjfl-DotZQt06PxQA,6033
         | 
| 1319 1319 | 
             
            vellum/workflows/exceptions.py,sha256=NiBiR3ggfmPxBVqD-H1SqmjI-7mIn0EStSN1BqApvCM,1213
         | 
| 1320 1320 | 
             
            vellum/workflows/expressions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1321 1321 | 
             
            vellum/workflows/expressions/accessor.py,sha256=ItZF7fMLzVTqsdAiaXb5SiDupXmX0X9xbIus1W6hRds,1870
         | 
| @@ -1330,8 +1330,8 @@ vellum/workflows/expressions/does_not_end_with.py,sha256=idw2OSuIk02XwBM5CXYOESf | |
| 1330 1330 | 
             
            vellum/workflows/expressions/does_not_equal.py,sha256=LNiCibRZZIxaIrwotjW3SIsKYHWR7BpOItFI-x5KuKU,764
         | 
| 1331 1331 | 
             
            vellum/workflows/expressions/ends_with.py,sha256=FkWZjAudc_DFM-fK-A3_tr6WXavfs_Qi7F6JtVgMglw,1117
         | 
| 1332 1332 | 
             
            vellum/workflows/expressions/equals.py,sha256=gbI6BKQR7cLQih226-ge_BFSLprgEjqbdiIxo7WFg_E,758
         | 
| 1333 | 
            -
            vellum/workflows/expressions/greater_than.py,sha256= | 
| 1334 | 
            -
            vellum/workflows/expressions/greater_than_or_equal_to.py,sha256= | 
| 1333 | 
            +
            vellum/workflows/expressions/greater_than.py,sha256=1sbUH6Obf-VoBgs7ilIncwYBHYfXliKmShppTuLMtCI,1247
         | 
| 1334 | 
            +
            vellum/workflows/expressions/greater_than_or_equal_to.py,sha256=tsD5ZalB4SlryvEsvVtDkSr5Z13B2pABmHB8oHD8ojs,1276
         | 
| 1335 1335 | 
             
            vellum/workflows/expressions/in_.py,sha256=RgiAIFntXGN4eWoOVBj1gqLymnBxSiw5hYD3TngF3dk,1123
         | 
| 1336 1336 | 
             
            vellum/workflows/expressions/is_blank.py,sha256=vOOmK5poXmiNRVH7MR0feIFnL4rwKn7vmmTkJ9TcfVU,904
         | 
| 1337 1337 | 
             
            vellum/workflows/expressions/is_nil.py,sha256=xCHwhKlm2UnfC-bVedmGgENCrzNtcn4ZeCYwNflVWbU,748
         | 
| @@ -1341,11 +1341,15 @@ vellum/workflows/expressions/is_not_null.py,sha256=EoHXFgZScKP_BM2a5Z7YFQN6l7RME | |
| 1341 1341 | 
             
            vellum/workflows/expressions/is_not_undefined.py,sha256=9s-RUQBqM17-_nIRvwsHuarLdHVtrxVuwnqBNJEtmh0,735
         | 
| 1342 1342 | 
             
            vellum/workflows/expressions/is_null.py,sha256=C75ALGlG_sTGcxI46tm9HtgPVfJ7DwTIyKzX8qtEiDU,660
         | 
| 1343 1343 | 
             
            vellum/workflows/expressions/is_undefined.py,sha256=uUBK3rxYbwoeRq36AGFc7d61hXzTp8UacQAi-1JbaW0,724
         | 
| 1344 | 
            -
            vellum/workflows/expressions/less_than.py,sha256= | 
| 1345 | 
            -
            vellum/workflows/expressions/less_than_or_equal_to.py,sha256= | 
| 1344 | 
            +
            vellum/workflows/expressions/less_than.py,sha256=chY9puJ6jDB2EinjfyGNrSplJ1NJC-BB-GGSSB33bqI,1237
         | 
| 1345 | 
            +
            vellum/workflows/expressions/less_than_or_equal_to.py,sha256=JtTDBa8yFKy3fGaCOA1tb_5s1JkY8FFnH6kpoeXGnT4,1267
         | 
| 1346 1346 | 
             
            vellum/workflows/expressions/not_between.py,sha256=ZtRJeJDSSlOvajL8YoBoh5o_khjIn9xSSeQCnXYbHFE,1506
         | 
| 1347 1347 | 
             
            vellum/workflows/expressions/not_in.py,sha256=pFvwkFPsn3WJw61ssFgM2U1dqWEeglfz4FVT4xwm5Mc,1144
         | 
| 1348 1348 | 
             
            vellum/workflows/expressions/or_.py,sha256=s-8YdMSSCDS2yijR38kguwok3iqmDMMgDYKV93b4O4s,914
         | 
| 1349 | 
            +
            vellum/workflows/expressions/parse_json.py,sha256=xsk6j3HF7bU1yF6fwt5P9Ugcyd5D9ZXrdng11FRilUI,1088
         | 
| 1350 | 
            +
            vellum/workflows/expressions/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1351 | 
            +
            vellum/workflows/expressions/tests/test_expressions.py,sha256=3b6k8xs-CItBBw95NygFLUNoNPKxI4VA1GyWbkMtqyI,11623
         | 
| 1352 | 
            +
            vellum/workflows/expressions/tests/test_parse_json.py,sha256=zpB_qE5_EwWQL7ULQUJm0o1PRSfWZdAqZNW6Ah13oJE,1059
         | 
| 1349 1353 | 
             
            vellum/workflows/graph/__init__.py,sha256=3sHlay5d_-uD7j3QJXiGl0WHFZZ_QScRvgyDhN2GhHY,74
         | 
| 1350 1354 | 
             
            vellum/workflows/graph/graph.py,sha256=GGR8cGpSuNWPIiTWNWsj6l70upb5nIxAyFcn7VdaJIs,5506
         | 
| 1351 1355 | 
             
            vellum/workflows/graph/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| @@ -1357,7 +1361,7 @@ vellum/workflows/inputs/tests/test_inputs.py,sha256=Haa0Px0obef7rgIddO6wwHF_bzmv | |
| 1357 1361 | 
             
            vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
         | 
| 1358 1362 | 
             
            vellum/workflows/nodes/__init__.py,sha256=aVdQVv7Y3Ro3JlqXGpxwaU2zrI06plDHD2aumH5WUIs,1157
         | 
| 1359 1363 | 
             
            vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
         | 
| 1360 | 
            -
            vellum/workflows/nodes/bases/base.py,sha256= | 
| 1364 | 
            +
            vellum/workflows/nodes/bases/base.py,sha256=lVHODc1mjUFCorhZfK01zHohOWz9CYz7dnUzA-KENJ4,15036
         | 
| 1361 1365 | 
             
            vellum/workflows/nodes/bases/base_adornment_node.py,sha256=eFTgsPCYb3eyGS0-kw7C6crFnwFx437R5wh9-8bWYts,2905
         | 
| 1362 1366 | 
             
            vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1363 1367 | 
             
            vellum/workflows/nodes/bases/tests/test_base_node.py,sha256=4SOdZzvugVtN8CIuo5RrapAxSYGXnxUwQ77dXJ64oTU,6295
         | 
| @@ -1377,8 +1381,8 @@ vellum/workflows/nodes/core/retry_node/node.py,sha256=Vt3fx4G-DRIb9a-IHIUfaAclgf | |
| 1377 1381 | 
             
            vellum/workflows/nodes/core/retry_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1378 1382 | 
             
            vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=RM_OHwxrHwyxvlQQBJPqVBxpedFuWQ9h2-Xa3kP75sc,4399
         | 
| 1379 1383 | 
             
            vellum/workflows/nodes/core/templating_node/__init__.py,sha256=GmyuYo81_A1_Bz6id69ozVFS6FKiuDsZTiA3I6MaL2U,70
         | 
| 1380 | 
            -
            vellum/workflows/nodes/core/templating_node/node.py,sha256 | 
| 1381 | 
            -
            vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256= | 
| 1384 | 
            +
            vellum/workflows/nodes/core/templating_node/node.py,sha256=-JIqLUv6Xpx_LTVZt7whQ2X2VatgHDdTxjMrz64luEs,3721
         | 
| 1385 | 
            +
            vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=ldnmSASx0TfAnT3ZvU0AXtN0diZGrfySiXipuJIIzWU,9055
         | 
| 1382 1386 | 
             
            vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWCCc0YCAc7Fzol5ZWIWeM,56
         | 
| 1383 1387 | 
             
            vellum/workflows/nodes/core/try_node/node.py,sha256=_0df2_6kim8pW4hB7IXUJOYS4fLduaeGDH4rRhYYvcg,4212
         | 
| 1384 1388 | 
             
            vellum/workflows/nodes/core/try_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| @@ -1387,7 +1391,7 @@ vellum/workflows/nodes/displayable/__init__.py,sha256=6F_4DlSwvHuilWnIalp8iDjjDX | |
| 1387 1391 | 
             
            vellum/workflows/nodes/displayable/api_node/__init__.py,sha256=MoxdQSnidIj1Nf_d-hTxlOxcZXaZnsWFDbE-PkTK24o,56
         | 
| 1388 1392 | 
             
            vellum/workflows/nodes/displayable/api_node/node.py,sha256=QdpsyGVxo5PcN8nwGZpcpW_YMKHr3_VvmbK1BlrdOFk,2547
         | 
| 1389 1393 | 
             
            vellum/workflows/nodes/displayable/api_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1390 | 
            -
            vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py,sha256= | 
| 1394 | 
            +
            vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py,sha256=RtQWnFfq0HNqY2A6c5SdwHl8A91K4Vq8un5UJwwnkSw,2180
         | 
| 1391 1395 | 
             
            vellum/workflows/nodes/displayable/bases/__init__.py,sha256=0mWIx3qUrzllV7jqt7wN03vWGMuI1WrrLZeMLT2Cl2c,304
         | 
| 1392 1396 | 
             
            vellum/workflows/nodes/displayable/bases/api_node/__init__.py,sha256=1jwx4WC358CLA1jgzl_UD-rZmdMm2v9Mps39ndwCD7U,64
         | 
| 1393 1397 | 
             
            vellum/workflows/nodes/displayable/bases/api_node/node.py,sha256=-LOKjU_rY1UWgD0DS5LJwAClBI8N7zrdmwigE3y5rhc,4000
         | 
| @@ -1403,11 +1407,11 @@ vellum/workflows/nodes/displayable/bases/tests/test_utils.py,sha256=eqdqbKNRWVMD | |
| 1403 1407 | 
             
            vellum/workflows/nodes/displayable/bases/types.py,sha256=C37B2Qh2YP7s7pUjd-EYKc2Zl1TbnCgI_mENuUSb8bo,1706
         | 
| 1404 1408 | 
             
            vellum/workflows/nodes/displayable/bases/utils.py,sha256=ckMUenSsNkiYmSw6FmjSMHYaCk8Y8_sUjL6lkFFEqts,5412
         | 
| 1405 1409 | 
             
            vellum/workflows/nodes/displayable/code_execution_node/__init__.py,sha256=0FLWMMktpzSnmBMizQglBpcPrP80fzVsoJwJgf822Cg,76
         | 
| 1406 | 
            -
            vellum/workflows/nodes/displayable/code_execution_node/node.py,sha256= | 
| 1410 | 
            +
            vellum/workflows/nodes/displayable/code_execution_node/node.py,sha256=pdDrjI8wdqMyf52kK6TlSjSU-MRxV2SKDwKcK2LCgkU,9547
         | 
| 1407 1411 | 
             
            vellum/workflows/nodes/displayable/code_execution_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1408 1412 | 
             
            vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1409 1413 | 
             
            vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/main.py,sha256=5QsbmkzSlSbcbWTG_JmIqcP-JNJzOPTKxGzdHos19W4,79
         | 
| 1410 | 
            -
            vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py,sha256= | 
| 1414 | 
            +
            vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py,sha256=OTnw5jgX90xWVB3vKryL5QSIr2YnGBz-W0q9C9LpNoc,22471
         | 
| 1411 1415 | 
             
            vellum/workflows/nodes/displayable/code_execution_node/utils.py,sha256=BQraIN4I3DCzXLEuBlRYCyp7ote7hQmnnKHu4jFHCCA,5174
         | 
| 1412 1416 | 
             
            vellum/workflows/nodes/displayable/conditional_node/__init__.py,sha256=AS_EIqFdU1F9t8aLmbZU-rLh9ry6LCJ0uj0D8F0L5Uw,72
         | 
| 1413 1417 | 
             
            vellum/workflows/nodes/displayable/conditional_node/node.py,sha256=Qjfl33gZ3JEgxBA1EgzSUebboGvsARthIxxcQyvx5Gg,1152
         | 
| @@ -1444,7 +1448,7 @@ vellum/workflows/nodes/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ | |
| 1444 1448 | 
             
            vellum/workflows/nodes/experimental/openai_chat_completion_node/__init__.py,sha256=lsyD9laR9p7kx5-BXGH2gUTM242UhKy8SMV0SR6S2iE,90
         | 
| 1445 1449 | 
             
            vellum/workflows/nodes/experimental/openai_chat_completion_node/node.py,sha256=1EGeiaT-Zoo6pttQFKKBcdf3dmhAbjKGaErYD5FFwlc,10185
         | 
| 1446 1450 | 
             
            vellum/workflows/nodes/mocks.py,sha256=gvM2tyoe-V84jFbFdhQsyGAPyQBzmjn_CkhT_yxccgY,499
         | 
| 1447 | 
            -
            vellum/workflows/nodes/utils.py,sha256= | 
| 1451 | 
            +
            vellum/workflows/nodes/utils.py,sha256=fq49n624n_nBMIFcc0JiNkHy3qna-bsA1HZRPa5AOJE,4918
         | 
| 1448 1452 | 
             
            vellum/workflows/outputs/__init__.py,sha256=AyZ4pRh_ACQIGvkf0byJO46EDnSix1ZCAXfvh-ms1QE,94
         | 
| 1449 1453 | 
             
            vellum/workflows/outputs/base.py,sha256=2MtTlyzePopMZDpBWQIV8HRV-km1-z0vI8Gm012q9OQ,8665
         | 
| 1450 1454 | 
             
            vellum/workflows/ports/__init__.py,sha256=bZuMt-R7z5bKwpu4uPW7LlJeePOQWmCcDSXe5frUY5g,101
         | 
| @@ -1466,12 +1470,12 @@ vellum/workflows/references/workflow_input.py,sha256=86IuhlBz-9cGxeUzizyjdp482aj | |
| 1466 1470 | 
             
            vellum/workflows/resolvers/__init__.py,sha256=eH6hTvZO4IciDaf_cf7aM2vs-DkBDyJPycOQevJxQnI,82
         | 
| 1467 1471 | 
             
            vellum/workflows/resolvers/base.py,sha256=WHra9LRtlTuB1jmuNqkfVE2JUgB61Cyntn8f0b0WZg4,411
         | 
| 1468 1472 | 
             
            vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8vyT-bqM,72
         | 
| 1469 | 
            -
            vellum/workflows/runner/runner.py,sha256= | 
| 1473 | 
            +
            vellum/workflows/runner/runner.py,sha256=_p19T1woplSxZGabZuSUFBKSYBrXADrM7b_1YnWVN3g,31013
         | 
| 1470 1474 | 
             
            vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
         | 
| 1471 1475 | 
             
            vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
         | 
| 1472 1476 | 
             
            vellum/workflows/state/base.py,sha256=Vkhneko3VlQrPsMLU1PYSzXU_W1u7_AraJsghiv5O-4,15512
         | 
| 1473 1477 | 
             
            vellum/workflows/state/context.py,sha256=yePVr4CCTQn5bjo1697JOO24fKFQpVNzooL07xL4gL0,2702
         | 
| 1474 | 
            -
            vellum/workflows/state/encoder.py,sha256= | 
| 1478 | 
            +
            vellum/workflows/state/encoder.py,sha256=TnOQojc5lTQ83g9QbpA4UCqShJvutmTMxbpKt-9gNe4,1911
         | 
| 1475 1479 | 
             
            vellum/workflows/state/store.py,sha256=VYGBQgN1bpd1as5eGiouV_7scg8QsRs4_1aqZAGIsRQ,793
         | 
| 1476 1480 | 
             
            vellum/workflows/state/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1477 1481 | 
             
            vellum/workflows/state/tests/test_state.py,sha256=jBynFR4m74Vn51DdmKBLkxb1loTy1CnJPtzPmdAFQUo,5159
         | 
| @@ -1502,8 +1506,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad | |
| 1502 1506 | 
             
            vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 1503 1507 | 
             
            vellum/workflows/workflows/tests/test_base_workflow.py,sha256=NRteiICyJvDM5zrtUfq2fZoXcGQVaWC9xmNlLLVW0cU,7979
         | 
| 1504 1508 | 
             
            vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
         | 
| 1505 | 
            -
            vellum_ai-0.14. | 
| 1506 | 
            -
            vellum_ai-0.14. | 
| 1507 | 
            -
            vellum_ai-0.14. | 
| 1508 | 
            -
            vellum_ai-0.14. | 
| 1509 | 
            -
            vellum_ai-0.14. | 
| 1509 | 
            +
            vellum_ai-0.14.10.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
         | 
| 1510 | 
            +
            vellum_ai-0.14.10.dist-info/METADATA,sha256=XNLaqqk85P8uRcr65-_IDfNPVi1dpNP9YvZgm43wAGs,5408
         | 
| 1511 | 
            +
            vellum_ai-0.14.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
         | 
| 1512 | 
            +
            vellum_ai-0.14.10.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
         | 
| 1513 | 
            +
            vellum_ai-0.14.10.dist-info/RECORD,,
         | 
| @@ -27,6 +27,7 @@ from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpressi | |
| 27 27 | 
             
            from vellum.workflows.expressions.is_null import IsNullExpression
         | 
| 28 28 | 
             
            from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
         | 
| 29 29 | 
             
            from vellum.workflows.expressions.not_between import NotBetweenExpression
         | 
| 30 | 
            +
            from vellum.workflows.expressions.parse_json import ParseJsonExpression
         | 
| 30 31 | 
             
            from vellum.workflows.nodes.bases.base import BaseNode
         | 
| 31 32 | 
             
            from vellum.workflows.nodes.utils import get_wrapped_node
         | 
| 32 33 | 
             
            from vellum.workflows.ports import Port
         | 
| @@ -386,6 +387,9 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta): | |
| 386 387 | 
             
                            "node_id": str(node_class_display.node_id),
         | 
| 387 388 | 
             
                        }
         | 
| 388 389 |  | 
| 390 | 
            +
                    if isinstance(value, ParseJsonExpression):
         | 
| 391 | 
            +
                        raise ValueError("ParseJsonExpression is not supported in the UI")
         | 
| 392 | 
            +
             | 
| 389 393 | 
             
                    if not isinstance(value, BaseDescriptor):
         | 
| 390 394 | 
             
                        vellum_value = primitive_to_vellum_value(value)
         | 
| 391 395 | 
             
                        return {
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            import pytest
         | 
| 1 2 | 
             
            from uuid import UUID
         | 
| 2 3 | 
             
            from typing import Dict
         | 
| 3 4 |  | 
| @@ -228,3 +229,33 @@ def test_vellum_workflow_display__serialize_with_unused_nodes_and_edges(): | |
| 228 229 | 
             
                        break
         | 
| 229 230 |  | 
| 230 231 | 
             
                assert edge_found, "Edge between unused nodes NodeB and NodeC not found in serialized output"
         | 
| 232 | 
            +
             | 
| 233 | 
            +
             | 
| 234 | 
            +
            def test_parse_json_not_supported_in_ui():
         | 
| 235 | 
            +
                """
         | 
| 236 | 
            +
                Test that verifies ParseJsonExpression is not yet supported in the UI.
         | 
| 237 | 
            +
                This test should fail once UI support is added, at which point it should be updated.
         | 
| 238 | 
            +
                """
         | 
| 239 | 
            +
                # GIVEN a workflow that uses the parse_json function
         | 
| 240 | 
            +
                from vellum.workflows.references.constant import ConstantValueReference
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                class JsonNode(BaseNode):
         | 
| 243 | 
            +
                    class Outputs(BaseNode.Outputs):
         | 
| 244 | 
            +
                        json_result = ConstantValueReference('{"key": "value"}').parse_json()
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                class Workflow(BaseWorkflow):
         | 
| 247 | 
            +
                    graph = JsonNode
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                    class Outputs(BaseWorkflow.Outputs):
         | 
| 250 | 
            +
                        final = JsonNode.Outputs.json_result
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                # WHEN we attempt to serialize it
         | 
| 253 | 
            +
                workflow_display = get_workflow_display(
         | 
| 254 | 
            +
                    base_display_class=VellumWorkflowDisplay,
         | 
| 255 | 
            +
                    workflow_class=Workflow,
         | 
| 256 | 
            +
                )
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                with pytest.raises(ValueError) as exc_info:
         | 
| 259 | 
            +
                    workflow_display.serialize()
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                assert "ParseJsonExpression is not supported in the UI" == str(exc_info.value)
         | 
| @@ -1,9 +1,8 @@ | |
| 1 1 | 
             
            from dataclasses import dataclass, field
         | 
| 2 | 
            -
            from uuid import UUID
         | 
| 3 2 | 
             
            from typing import TYPE_CHECKING, Dict, Generic, Tuple, Type, TypeVar
         | 
| 4 3 |  | 
| 5 | 
            -
            from vellum.client.core import UniversalBaseModel
         | 
| 6 4 | 
             
            from vellum.workflows.descriptors.base import BaseDescriptor
         | 
| 5 | 
            +
            from vellum.workflows.events.workflow import WorkflowEventDisplayContext  # noqa: F401
         | 
| 7 6 | 
             
            from vellum.workflows.nodes import BaseNode
         | 
| 8 7 | 
             
            from vellum.workflows.ports import Port
         | 
| 9 8 | 
             
            from vellum.workflows.references import OutputReference, StateValueReference, WorkflowInputReference
         | 
| @@ -25,18 +24,6 @@ NodeDisplayType = TypeVar("NodeDisplayType", bound="BaseNodeDisplay") | |
| 25 24 | 
             
            WorkflowDisplayType = TypeVar("WorkflowDisplayType", bound="BaseWorkflowDisplay")
         | 
| 26 25 |  | 
| 27 26 |  | 
| 28 | 
            -
            class NodeDisplay(UniversalBaseModel):
         | 
| 29 | 
            -
                input_display: Dict[str, UUID]
         | 
| 30 | 
            -
                output_display: Dict[str, UUID]
         | 
| 31 | 
            -
                port_display: Dict[str, UUID]
         | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
            class WorkflowEventDisplayContext(UniversalBaseModel):
         | 
| 35 | 
            -
                node_displays: Dict[str, NodeDisplay]
         | 
| 36 | 
            -
                workflow_inputs: Dict[str, UUID]
         | 
| 37 | 
            -
                workflow_outputs: Dict[str, UUID]
         | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 27 | 
             
            @dataclass
         | 
| 41 28 | 
             
            class WorkflowDisplayContext(
         | 
| 42 29 | 
             
                Generic[
         | 
| @@ -9,6 +9,7 @@ from typing import Any, Dict, Generic, Iterator, List, Optional, Tuple, Type, Un | |
| 9 9 | 
             
            from vellum.workflows import BaseWorkflow
         | 
| 10 10 | 
             
            from vellum.workflows.descriptors.base import BaseDescriptor
         | 
| 11 11 | 
             
            from vellum.workflows.edges import Edge
         | 
| 12 | 
            +
            from vellum.workflows.events.workflow import NodeEventDisplayContext, WorkflowEventDisplayContext
         | 
| 12 13 | 
             
            from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
         | 
| 13 14 | 
             
            from vellum.workflows.nodes.bases import BaseNode
         | 
| 14 15 | 
             
            from vellum.workflows.nodes.utils import get_wrapped_node
         | 
| @@ -33,12 +34,9 @@ from vellum_ee.workflows.display.base import ( | |
| 33 34 | 
             
            from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
         | 
| 34 35 | 
             
            from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
         | 
| 35 36 | 
             
            from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay, PortDisplay, PortDisplayOverrides
         | 
| 36 | 
            -
            from vellum_ee.workflows.display. | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                WorkflowDisplayContext,
         | 
| 40 | 
            -
                WorkflowEventDisplayContext,
         | 
| 41 | 
            -
            )
         | 
| 37 | 
            +
            from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
         | 
| 38 | 
            +
            from vellum_ee.workflows.display.types import NodeDisplayType, WorkflowDisplayContext
         | 
| 39 | 
            +
            from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
         | 
| 42 40 |  | 
| 43 41 | 
             
            logger = logging.getLogger(__name__)
         | 
| 44 42 |  | 
| @@ -387,10 +385,15 @@ class BaseWorkflowDisplay( | |
| 387 385 | 
             
                    except ModuleNotFoundError:
         | 
| 388 386 | 
             
                        return None
         | 
| 389 387 |  | 
| 390 | 
            -
                     | 
| 391 | 
            -
                    if not isinstance( | 
| 388 | 
            +
                    workflow_display = display_class.WorkflowDisplay(workflow_class)
         | 
| 389 | 
            +
                    if not isinstance(workflow_display, BaseWorkflowDisplay):
         | 
| 392 390 | 
             
                        return None
         | 
| 393 391 |  | 
| 392 | 
            +
                    return workflow_display.get_event_display_context()
         | 
| 393 | 
            +
             | 
| 394 | 
            +
                def get_event_display_context(self):
         | 
| 395 | 
            +
                    display_context = self.display_context
         | 
| 396 | 
            +
             | 
| 394 397 | 
             
                    workflow_outputs = {
         | 
| 395 398 | 
             
                        output.name: display_context.workflow_output_displays[output].id
         | 
| 396 399 | 
             
                        for output in display_context.workflow_output_displays
         | 
| @@ -402,27 +405,44 @@ class BaseWorkflowDisplay( | |
| 402 405 | 
             
                    node_displays = {
         | 
| 403 406 | 
             
                        str(node.__id__): display_context.node_displays[node] for node in display_context.node_displays
         | 
| 404 407 | 
             
                    }
         | 
| 405 | 
            -
                     | 
| 406 | 
            -
                    for  | 
| 407 | 
            -
                         | 
| 408 | 
            +
                    node_event_displays = {}
         | 
| 409 | 
            +
                    for node_id in node_displays:
         | 
| 410 | 
            +
                        current_node_display = node_displays[node_id]
         | 
| 408 411 | 
             
                        input_display = {}
         | 
| 409 | 
            -
                        if isinstance( | 
| 410 | 
            -
                            input_display =  | 
| 412 | 
            +
                        if isinstance(current_node_display, BaseNodeVellumDisplay):
         | 
| 413 | 
            +
                            input_display = current_node_display.node_input_ids_by_name
         | 
| 411 414 | 
             
                        node_display_meta = {
         | 
| 412 | 
            -
                            output.name:  | 
| 415 | 
            +
                            output.name: current_node_display.output_display[output].id
         | 
| 416 | 
            +
                            for output in current_node_display.output_display
         | 
| 413 417 | 
             
                        }
         | 
| 414 | 
            -
                        port_display_meta = { | 
| 415 | 
            -
             | 
| 416 | 
            -
                         | 
| 418 | 
            +
                        port_display_meta = {
         | 
| 419 | 
            +
                            port.name: current_node_display.port_displays[port].id for port in current_node_display.port_displays
         | 
| 420 | 
            +
                        }
         | 
| 421 | 
            +
                        node = current_node_display._node
         | 
| 422 | 
            +
                        subworkflow_display_context: Optional[WorkflowEventDisplayContext] = None
         | 
| 423 | 
            +
                        if hasattr(node, "subworkflow"):
         | 
| 424 | 
            +
                            # All nodes that have a subworkflow attribute are currently expected to call them `subworkflow`
         | 
| 425 | 
            +
                            # This will change if in the future we decide to support multiple subworkflows on a single node
         | 
| 426 | 
            +
                            subworkflow_attribute = raise_if_descriptor(getattr(node, "subworkflow"))
         | 
| 427 | 
            +
                            if issubclass(subworkflow_attribute, BaseWorkflow):
         | 
| 428 | 
            +
                                subworkflow_display = get_workflow_display(
         | 
| 429 | 
            +
                                    base_display_class=display_context.workflow_display_class,
         | 
| 430 | 
            +
                                    workflow_class=subworkflow_attribute,
         | 
| 431 | 
            +
                                    parent_display_context=display_context,
         | 
| 432 | 
            +
                                )
         | 
| 433 | 
            +
                                subworkflow_display_context = subworkflow_display.get_event_display_context()
         | 
| 434 | 
            +
             | 
| 435 | 
            +
                        node_event_displays[node_id] = NodeEventDisplayContext(
         | 
| 417 436 | 
             
                            input_display=input_display,
         | 
| 418 437 | 
             
                            output_display=node_display_meta,
         | 
| 419 438 | 
             
                            port_display=port_display_meta,
         | 
| 439 | 
            +
                            subworkflow_display=subworkflow_display_context,
         | 
| 420 440 | 
             
                        )
         | 
| 421 441 |  | 
| 422 442 | 
             
                    display_meta = WorkflowEventDisplayContext(
         | 
| 423 443 | 
             
                        workflow_outputs=workflow_outputs,
         | 
| 424 444 | 
             
                        workflow_inputs=workflow_inputs,
         | 
| 425 | 
            -
                        node_displays= | 
| 445 | 
            +
                        node_displays=node_event_displays,
         | 
| 426 446 | 
             
                    )
         | 
| 427 447 | 
             
                    return display_meta
         | 
| 428 448 |  | 
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            import pytest
         | 
| 2 2 |  | 
| 3 3 | 
             
            from vellum.workflows.nodes.bases.base import BaseNode
         | 
| 4 | 
            +
            from vellum.workflows.nodes.core.inline_subworkflow_node.node import InlineSubworkflowNode
         | 
| 4 5 | 
             
            from vellum.workflows.workflows.base import BaseWorkflow
         | 
| 5 6 | 
             
            from vellum_ee.workflows.display.nodes import BaseNodeDisplay
         | 
| 6 7 | 
             
            from vellum_ee.workflows.display.vellum import NodeDisplayData, NodeDisplayPosition
         | 
| @@ -92,3 +93,29 @@ def test_serialize_workflow__node_display_class_not_registered(): | |
| 92 93 |  | 
| 93 94 | 
             
                # THEN it should should succeed
         | 
| 94 95 | 
             
                assert data is not None
         | 
| 96 | 
            +
             | 
| 97 | 
            +
             | 
| 98 | 
            +
            def test_get_event_display_context__node_display_to_include_subworkflow_display():
         | 
| 99 | 
            +
                # GIVEN a simple workflow
         | 
| 100 | 
            +
                class InnerNode(BaseNode):
         | 
| 101 | 
            +
                    pass
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                class Subworkflow(BaseWorkflow):
         | 
| 104 | 
            +
                    graph = InnerNode
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                # AND a workflow that includes the subworkflow
         | 
| 107 | 
            +
                class SubworkflowNode(InlineSubworkflowNode):
         | 
| 108 | 
            +
                    subworkflow = Subworkflow
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                class MyWorkflow(BaseWorkflow):
         | 
| 111 | 
            +
                    graph = SubworkflowNode
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                # WHEN we gather the event display context
         | 
| 114 | 
            +
                display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                # THEN the subworkflow display should be included
         | 
| 117 | 
            +
                assert str(SubworkflowNode.__id__) in display_context.node_displays
         | 
| 118 | 
            +
                node_event_display = display_context.node_displays[str(SubworkflowNode.__id__)]
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                assert node_event_display.subworkflow_display is not None
         | 
| 121 | 
            +
                assert str(InnerNode.__id__) in node_event_display.subworkflow_display.node_displays
         | 
| @@ -40,11 +40,13 @@ def test_base_class_dynamic_import(files): | |
| 40 40 | 
             
                            },
         | 
| 41 41 | 
             
                            "output_display": {"result": UUID("423bc529-1a1a-4f72-af4d-cbdb5f0a5929")},
         | 
| 42 42 | 
             
                            "port_display": {"default": UUID("afda9a19-0618-42e1-9b63-5d0db2a88f62")},
         | 
| 43 | 
            +
                            "subworkflow_display": None,
         | 
| 43 44 | 
             
                        },
         | 
| 44 45 | 
             
                        "f3ef4b2b-fec9-4026-9cc6-e5eac295307f": {
         | 
| 45 46 | 
             
                            "input_display": {"node_input": UUID("fe6cba85-2423-4b5e-8f85-06311a8be5fb")},
         | 
| 46 47 | 
             
                            "output_display": {"value": UUID("5469b810-6ea6-4362-9e79-e360d44a1405")},
         | 
| 47 48 | 
             
                            "port_display": {},
         | 
| 49 | 
            +
                            "subworkflow_display": None,
         | 
| 48 50 | 
             
                        },
         | 
| 49 51 | 
             
                    },
         | 
| 50 52 | 
             
                    "workflow_inputs": {"input_value": UUID("2268a996-bd17-4832-b3ff-f5662d54b306")},
         | 
| @@ -2,6 +2,7 @@ from vellum.client.core.pydantic_utilities import UniversalBaseModel | |
| 2 2 |  | 
| 3 3 |  | 
| 4 4 | 
             
            def test_load_workflow_event_display_context():
         | 
| 5 | 
            +
                # DEPRECATED: Use `vellum.workflows.events.workflow.WorkflowEventDisplayContext` instead. Will be removed in 0.15.0
         | 
| 5 6 | 
             
                from vellum_ee.workflows.display.types import WorkflowEventDisplayContext
         | 
| 6 7 |  | 
| 7 8 | 
             
                # We are actually just ensuring there are no circular dependencies when
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |