vellum-ai 0.14.80__py3-none-any.whl → 0.14.82__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.
Files changed (39) hide show
  1. vellum/__init__.py +6 -0
  2. vellum/client/core/client_wrapper.py +1 -1
  3. vellum/client/types/__init__.py +6 -0
  4. vellum/client/types/execution_thinking_vellum_value.py +31 -0
  5. vellum/client/types/execution_vellum_value.py +2 -0
  6. vellum/client/types/prompt_output.py +4 -1
  7. vellum/client/types/thinking_vellum_value.py +25 -0
  8. vellum/client/types/thinking_vellum_value_request.py +25 -0
  9. vellum/client/types/vellum_value.py +2 -0
  10. vellum/client/types/vellum_value_request.py +2 -0
  11. vellum/client/types/vellum_variable_type.py +1 -0
  12. vellum/types/execution_thinking_vellum_value.py +3 -0
  13. vellum/types/thinking_vellum_value.py +3 -0
  14. vellum/types/thinking_vellum_value_request.py +3 -0
  15. vellum/workflows/nodes/displayable/__init__.py +2 -0
  16. vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py +2 -0
  17. vellum/workflows/nodes/displayable/inline_prompt_node/node.py +3 -0
  18. vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +3 -0
  19. vellum/workflows/nodes/displayable/tool_calling_node/__init__.py +3 -0
  20. vellum/workflows/nodes/{experimental → displayable}/tool_calling_node/node.py +4 -21
  21. vellum/workflows/nodes/{experimental → displayable}/tool_calling_node/tests/test_node.py +1 -1
  22. vellum/workflows/nodes/{experimental → displayable}/tool_calling_node/tests/test_utils.py +1 -1
  23. vellum/workflows/nodes/{experimental → displayable}/tool_calling_node/utils.py +22 -57
  24. vellum/workflows/nodes/experimental/__init__.py +1 -1
  25. vellum/workflows/nodes/experimental/tool_calling_node/__init__.py +1 -1
  26. vellum/workflows/state/encoder.py +2 -2
  27. {vellum_ai-0.14.80.dist-info → vellum_ai-0.14.82.dist-info}/METADATA +1 -1
  28. {vellum_ai-0.14.80.dist-info → vellum_ai-0.14.82.dist-info}/RECORD +39 -32
  29. vellum_cli/image_push.py +10 -0
  30. vellum_cli/tests/test_image_push.py +87 -1
  31. vellum_cli/tests/test_image_push_error_handling.py +6 -0
  32. vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +1 -104
  33. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +1 -1
  34. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +1 -6
  35. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +1 -17
  36. /vellum/workflows/nodes/{experimental → displayable}/tool_calling_node/tests/__init__.py +0 -0
  37. {vellum_ai-0.14.80.dist-info → vellum_ai-0.14.82.dist-info}/LICENSE +0 -0
  38. {vellum_ai-0.14.80.dist-info → vellum_ai-0.14.82.dist-info}/WHEEL +0 -0
  39. {vellum_ai-0.14.80.dist-info → vellum_ai-0.14.82.dist-info}/entry_points.txt +0 -0
vellum/__init__.py CHANGED
@@ -121,6 +121,7 @@ from .types import (
121
121
  ExecutionNumberVellumValue,
122
122
  ExecutionSearchResultsVellumValue,
123
123
  ExecutionStringVellumValue,
124
+ ExecutionThinkingVellumValue,
124
125
  ExecutionVellumValue,
125
126
  ExternalInputDescriptor,
126
127
  ExternalTestCaseExecution,
@@ -487,6 +488,8 @@ from .types import (
487
488
  TestSuiteTestCaseReplacedBulkResult,
488
489
  TestSuiteTestCaseReplacedBulkResultData,
489
490
  TestSuiteTestCaseUpsertBulkOperationRequest,
491
+ ThinkingVellumValue,
492
+ ThinkingVellumValueRequest,
490
493
  TokenOverlappingWindowChunkerConfig,
491
494
  TokenOverlappingWindowChunkerConfigRequest,
492
495
  TokenOverlappingWindowChunking,
@@ -754,6 +757,7 @@ __all__ = [
754
757
  "ExecutionNumberVellumValue",
755
758
  "ExecutionSearchResultsVellumValue",
756
759
  "ExecutionStringVellumValue",
760
+ "ExecutionThinkingVellumValue",
757
761
  "ExecutionVellumValue",
758
762
  "ExternalInputDescriptor",
759
763
  "ExternalTestCaseExecution",
@@ -1127,6 +1131,8 @@ __all__ = [
1127
1131
  "TestSuiteTestCaseReplacedBulkResult",
1128
1132
  "TestSuiteTestCaseReplacedBulkResultData",
1129
1133
  "TestSuiteTestCaseUpsertBulkOperationRequest",
1134
+ "ThinkingVellumValue",
1135
+ "ThinkingVellumValueRequest",
1130
1136
  "TokenOverlappingWindowChunkerConfig",
1131
1137
  "TokenOverlappingWindowChunkerConfigRequest",
1132
1138
  "TokenOverlappingWindowChunking",
@@ -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.14.80",
21
+ "X-Fern-SDK-Version": "0.14.82",
22
22
  }
23
23
  headers["X-API-KEY"] = self.api_key
24
24
  return headers
@@ -125,6 +125,7 @@ from .execution_json_vellum_value import ExecutionJsonVellumValue
125
125
  from .execution_number_vellum_value import ExecutionNumberVellumValue
126
126
  from .execution_search_results_vellum_value import ExecutionSearchResultsVellumValue
127
127
  from .execution_string_vellum_value import ExecutionStringVellumValue
128
+ from .execution_thinking_vellum_value import ExecutionThinkingVellumValue
128
129
  from .execution_vellum_value import ExecutionVellumValue
129
130
  from .external_input_descriptor import ExternalInputDescriptor
130
131
  from .external_test_case_execution import ExternalTestCaseExecution
@@ -511,6 +512,8 @@ from .test_suite_test_case_replace_bulk_operation_request import TestSuiteTestCa
511
512
  from .test_suite_test_case_replaced_bulk_result import TestSuiteTestCaseReplacedBulkResult
512
513
  from .test_suite_test_case_replaced_bulk_result_data import TestSuiteTestCaseReplacedBulkResultData
513
514
  from .test_suite_test_case_upsert_bulk_operation_request import TestSuiteTestCaseUpsertBulkOperationRequest
515
+ from .thinking_vellum_value import ThinkingVellumValue
516
+ from .thinking_vellum_value_request import ThinkingVellumValueRequest
514
517
  from .token_overlapping_window_chunker_config import TokenOverlappingWindowChunkerConfig
515
518
  from .token_overlapping_window_chunker_config_request import TokenOverlappingWindowChunkerConfigRequest
516
519
  from .token_overlapping_window_chunking import TokenOverlappingWindowChunking
@@ -741,6 +744,7 @@ __all__ = [
741
744
  "ExecutionNumberVellumValue",
742
745
  "ExecutionSearchResultsVellumValue",
743
746
  "ExecutionStringVellumValue",
747
+ "ExecutionThinkingVellumValue",
744
748
  "ExecutionVellumValue",
745
749
  "ExternalInputDescriptor",
746
750
  "ExternalTestCaseExecution",
@@ -1107,6 +1111,8 @@ __all__ = [
1107
1111
  "TestSuiteTestCaseReplacedBulkResult",
1108
1112
  "TestSuiteTestCaseReplacedBulkResultData",
1109
1113
  "TestSuiteTestCaseUpsertBulkOperationRequest",
1114
+ "ThinkingVellumValue",
1115
+ "ThinkingVellumValueRequest",
1110
1116
  "TokenOverlappingWindowChunkerConfig",
1111
1117
  "TokenOverlappingWindowChunkerConfigRequest",
1112
1118
  "TokenOverlappingWindowChunking",
@@ -0,0 +1,31 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import pydantic
5
+ import typing
6
+ from .string_vellum_value import StringVellumValue
7
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
8
+
9
+
10
+ class ExecutionThinkingVellumValue(UniversalBaseModel):
11
+ """
12
+ A value representing Thinking mode output.
13
+ """
14
+
15
+ id: str = pydantic.Field()
16
+ """
17
+ The variable's uniquely identifying internal id.
18
+ """
19
+
20
+ name: str
21
+ type: typing.Literal["THINKING"] = "THINKING"
22
+ value: typing.List[StringVellumValue]
23
+
24
+ if IS_PYDANTIC_V2:
25
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
26
+ else:
27
+
28
+ class Config:
29
+ frozen = True
30
+ smart_union = True
31
+ extra = pydantic.Extra.allow
@@ -9,6 +9,7 @@ from .execution_search_results_vellum_value import ExecutionSearchResultsVellumV
9
9
  from .execution_error_vellum_value import ExecutionErrorVellumValue
10
10
  from .execution_array_vellum_value import ExecutionArrayVellumValue
11
11
  from .execution_function_call_vellum_value import ExecutionFunctionCallVellumValue
12
+ from .execution_thinking_vellum_value import ExecutionThinkingVellumValue
12
13
 
13
14
  ExecutionVellumValue = typing.Union[
14
15
  ExecutionStringVellumValue,
@@ -19,4 +20,5 @@ ExecutionVellumValue = typing.Union[
19
20
  ExecutionErrorVellumValue,
20
21
  ExecutionArrayVellumValue,
21
22
  ExecutionFunctionCallVellumValue,
23
+ ExecutionThinkingVellumValue,
22
24
  ]
@@ -5,5 +5,8 @@ from .string_vellum_value import StringVellumValue
5
5
  from .json_vellum_value import JsonVellumValue
6
6
  from .error_vellum_value import ErrorVellumValue
7
7
  from .function_call_vellum_value import FunctionCallVellumValue
8
+ from .thinking_vellum_value import ThinkingVellumValue
8
9
 
9
- PromptOutput = typing.Union[StringVellumValue, JsonVellumValue, ErrorVellumValue, FunctionCallVellumValue]
10
+ PromptOutput = typing.Union[
11
+ StringVellumValue, JsonVellumValue, ErrorVellumValue, FunctionCallVellumValue, ThinkingVellumValue
12
+ ]
@@ -0,0 +1,25 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from .string_vellum_value import StringVellumValue
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
+ import pydantic
8
+
9
+
10
+ class ThinkingVellumValue(UniversalBaseModel):
11
+ """
12
+ A value representing Thinking mode output.
13
+ """
14
+
15
+ type: typing.Literal["THINKING"] = "THINKING"
16
+ value: typing.List[StringVellumValue]
17
+
18
+ if IS_PYDANTIC_V2:
19
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
20
+ else:
21
+
22
+ class Config:
23
+ frozen = True
24
+ smart_union = True
25
+ extra = pydantic.Extra.allow
@@ -0,0 +1,25 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from .string_vellum_value_request import StringVellumValueRequest
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
+ import pydantic
8
+
9
+
10
+ class ThinkingVellumValueRequest(UniversalBaseModel):
11
+ """
12
+ A value representing Thinking mode output.
13
+ """
14
+
15
+ type: typing.Literal["THINKING"] = "THINKING"
16
+ value: typing.List[StringVellumValueRequest]
17
+
18
+ if IS_PYDANTIC_V2:
19
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
20
+ else:
21
+
22
+ class Config:
23
+ frozen = True
24
+ smart_union = True
25
+ extra = pydantic.Extra.allow
@@ -12,6 +12,7 @@ from .function_call_vellum_value import FunctionCallVellumValue
12
12
  from .error_vellum_value import ErrorVellumValue
13
13
  from .chat_history_vellum_value import ChatHistoryVellumValue
14
14
  from .search_results_vellum_value import SearchResultsVellumValue
15
+ from .thinking_vellum_value import ThinkingVellumValue
15
16
  import typing
16
17
 
17
18
  if typing.TYPE_CHECKING:
@@ -28,4 +29,5 @@ VellumValue = typing.Union[
28
29
  "ArrayVellumValue",
29
30
  ChatHistoryVellumValue,
30
31
  SearchResultsVellumValue,
32
+ ThinkingVellumValue,
31
33
  ]
@@ -12,6 +12,7 @@ from .function_call_vellum_value_request import FunctionCallVellumValueRequest
12
12
  from .error_vellum_value_request import ErrorVellumValueRequest
13
13
  from .chat_history_vellum_value_request import ChatHistoryVellumValueRequest
14
14
  from .search_results_vellum_value_request import SearchResultsVellumValueRequest
15
+ from .thinking_vellum_value_request import ThinkingVellumValueRequest
15
16
  import typing
16
17
 
17
18
  if typing.TYPE_CHECKING:
@@ -28,4 +29,5 @@ VellumValueRequest = typing.Union[
28
29
  "ArrayVellumValueRequest",
29
30
  ChatHistoryVellumValueRequest,
30
31
  SearchResultsVellumValueRequest,
32
+ ThinkingVellumValueRequest,
31
33
  ]
@@ -16,6 +16,7 @@ VellumVariableType = typing.Union[
16
16
  "AUDIO",
17
17
  "DOCUMENT",
18
18
  "NULL",
19
+ "THINKING",
19
20
  ],
20
21
  typing.Any,
21
22
  ]
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.execution_thinking_vellum_value import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.thinking_vellum_value import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.thinking_vellum_value_request import *
@@ -13,6 +13,7 @@ from .note_node import NoteNode
13
13
  from .prompt_deployment_node import PromptDeploymentNode
14
14
  from .search_node import SearchNode
15
15
  from .subworkflow_deployment_node import SubworkflowDeploymentNode
16
+ from .tool_calling_node import ToolCallingNode
16
17
 
17
18
  __all__ = [
18
19
  "APINode",
@@ -29,5 +30,6 @@ __all__ = [
29
30
  "PromptDeploymentNode",
30
31
  "SearchNode",
31
32
  "TemplatingNode",
33
+ "ToolCallingNode",
32
34
  "FinalOutputNode",
33
35
  ]
@@ -109,6 +109,7 @@ def main(word: str) -> int:
109
109
  CodeExecutionPackage(
110
110
  name="openai",
111
111
  version="1.0.0",
112
+ repository="test-repo",
112
113
  )
113
114
  ]
114
115
 
@@ -150,6 +151,7 @@ def main(word: str) -> int:
150
151
  CodeExecutionPackage(
151
152
  name="openai",
152
153
  version="1.0.0",
154
+ repository="test-repo",
153
155
  )
154
156
  ],
155
157
  request_options=None,
@@ -63,6 +63,9 @@ class InlinePromptNode(BaseInlinePromptNode[StateType]):
63
63
  json_output = output.value
64
64
  elif output.type == "FUNCTION_CALL":
65
65
  string_outputs.append(output.value.model_dump_json(indent=4))
66
+ elif output.type == "THINKING":
67
+ thinking_strings = [item.value for item in output.value if item.value is not None]
68
+ string_outputs.append("\n".join(thinking_strings))
66
69
  else:
67
70
  string_outputs.append(output.value.message)
68
71
 
@@ -65,6 +65,9 @@ class PromptDeploymentNode(BasePromptDeploymentNode[StateType]):
65
65
  string_outputs.append(json.dumps(output.value, indent=4))
66
66
  elif output.type == "FUNCTION_CALL":
67
67
  string_outputs.append(output.value.model_dump_json(indent=4))
68
+ elif output.type == "THINKING":
69
+ thinking_strings = [item.value for item in output.value if item.value is not None]
70
+ string_outputs.append("\n".join(thinking_strings))
68
71
  else:
69
72
  string_outputs.append(output.value.message)
70
73
 
@@ -0,0 +1,3 @@
1
+ from vellum.workflows.nodes.displayable.tool_calling_node.node import ToolCallingNode
2
+
3
+ __all__ = ["ToolCallingNode"]
@@ -1,16 +1,13 @@
1
- from collections.abc import Sequence
2
- from typing import Any, ClassVar, Dict, List, Optional, cast
1
+ from typing import ClassVar, List, Optional
3
2
 
4
3
  from vellum import ChatMessage, PromptBlock
5
- from vellum.client.types.code_execution_package import CodeExecutionPackage
6
- from vellum.client.types.code_execution_runtime import CodeExecutionRuntime
7
4
  from vellum.workflows.context import execution_context, get_parent_context
8
5
  from vellum.workflows.errors.types import WorkflowErrorCode
9
6
  from vellum.workflows.exceptions import NodeException
10
7
  from vellum.workflows.graph.graph import Graph
11
8
  from vellum.workflows.inputs.base import BaseInputs
12
9
  from vellum.workflows.nodes.bases import BaseNode
13
- from vellum.workflows.nodes.experimental.tool_calling_node.utils import (
10
+ from vellum.workflows.nodes.displayable.tool_calling_node.utils import (
14
11
  create_function_node,
15
12
  create_tool_router_node,
16
13
  get_function_name,
@@ -19,7 +16,6 @@ from vellum.workflows.outputs.base import BaseOutputs
19
16
  from vellum.workflows.state.base import BaseState
20
17
  from vellum.workflows.state.context import WorkflowContext
21
18
  from vellum.workflows.types.core import EntityInputsInterface, Tool
22
- from vellum.workflows.workflows.base import BaseWorkflow
23
19
 
24
20
 
25
21
  class ToolCallingNode(BaseNode):
@@ -31,7 +27,6 @@ class ToolCallingNode(BaseNode):
31
27
  blocks: List[PromptBlock] - The prompt blocks to use (same format as InlinePromptNode)
32
28
  functions: List[Tool] - The functions that can be called
33
29
  prompt_inputs: Optional[EntityInputsInterface] - Mapping of input variable names to values
34
- function_configs: Optional[Dict[str, Dict[str, Any]]] - Mapping of function names to their configuration
35
30
  max_prompt_iterations: Optional[int] - Maximum number of prompt iterations before stopping
36
31
  """
37
32
 
@@ -39,7 +34,6 @@ class ToolCallingNode(BaseNode):
39
34
  blocks: ClassVar[List[PromptBlock]] = []
40
35
  functions: ClassVar[List[Tool]] = []
41
36
  prompt_inputs: ClassVar[Optional[EntityInputsInterface]] = None
42
- function_configs: ClassVar[Optional[Dict[str, Dict[str, Any]]]] = None
43
37
  max_prompt_iterations: ClassVar[Optional[int]] = 5
44
38
 
45
39
  class Outputs(BaseOutputs):
@@ -69,6 +63,8 @@ class ToolCallingNode(BaseNode):
69
63
  chat_history: List[ChatMessage] = []
70
64
  prompt_iterations: int = 0
71
65
 
66
+ from vellum.workflows.workflows.base import BaseWorkflow
67
+
72
68
  class ToolCallingWorkflow(BaseWorkflow[BaseInputs, ToolCallingState]):
73
69
  graph = self._graph
74
70
 
@@ -112,23 +108,10 @@ class ToolCallingNode(BaseNode):
112
108
  self._function_nodes = {}
113
109
  for function in self.functions:
114
110
  function_name = get_function_name(function)
115
- # Get configuration for this function
116
- config = {}
117
- if callable(function) and self.function_configs and function.__name__ in self.function_configs:
118
- config = self.function_configs[function.__name__]
119
-
120
- packages = config.get("packages", None)
121
- if packages is not None:
122
- packages = cast(Sequence[CodeExecutionPackage], packages)
123
-
124
- runtime_raw = config.get("runtime", "PYTHON_3_11_6")
125
- runtime = cast(CodeExecutionRuntime, runtime_raw)
126
111
 
127
112
  self._function_nodes[function_name] = create_function_node(
128
113
  function=function,
129
114
  tool_router_node=self.tool_router_node,
130
- packages=packages,
131
- runtime=runtime,
132
115
  )
133
116
 
134
117
  graph_set = set()
@@ -8,7 +8,7 @@ from vellum.client.types.string_chat_message_content import StringChatMessageCon
8
8
  from vellum.workflows import BaseWorkflow
9
9
  from vellum.workflows.inputs.base import BaseInputs
10
10
  from vellum.workflows.nodes.bases import BaseNode
11
- from vellum.workflows.nodes.experimental.tool_calling_node.utils import create_function_node, create_tool_router_node
11
+ from vellum.workflows.nodes.displayable.tool_calling_node.utils import create_function_node, create_tool_router_node
12
12
  from vellum.workflows.outputs.base import BaseOutputs
13
13
  from vellum.workflows.state.base import BaseState, StateMeta
14
14
  from vellum.workflows.state.context import WorkflowContext
@@ -1,7 +1,7 @@
1
1
  from vellum.workflows import BaseWorkflow
2
2
  from vellum.workflows.inputs.base import BaseInputs
3
3
  from vellum.workflows.nodes.bases import BaseNode
4
- from vellum.workflows.nodes.experimental.tool_calling_node.utils import get_function_name
4
+ from vellum.workflows.nodes.displayable.tool_calling_node.utils import get_function_name
5
5
  from vellum.workflows.outputs.base import BaseOutputs
6
6
  from vellum.workflows.state.base import BaseState
7
7
  from vellum.workflows.types.definition import DeploymentDefinition
@@ -1,14 +1,9 @@
1
- from collections.abc import Sequence
2
- import inspect
3
1
  import json
4
- import types
5
2
  from typing import Any, Iterator, List, Optional, Type, cast
6
3
 
7
4
  from pydash import snake_case
8
5
 
9
6
  from vellum import ChatMessage, PromptBlock
10
- from vellum.client.types.code_execution_package import CodeExecutionPackage
11
- from vellum.client.types.code_execution_runtime import CodeExecutionRuntime
12
7
  from vellum.client.types.function_call_chat_message_content import FunctionCallChatMessageContent
13
8
  from vellum.client.types.function_call_chat_message_content_value import FunctionCallChatMessageContentValue
14
9
  from vellum.client.types.string_chat_message_content import StringChatMessageContent
@@ -16,13 +11,11 @@ from vellum.client.types.variable_prompt_block import VariablePromptBlock
16
11
  from vellum.workflows.errors.types import WorkflowErrorCode
17
12
  from vellum.workflows.exceptions import NodeException
18
13
  from vellum.workflows.nodes.bases import BaseNode
19
- from vellum.workflows.nodes.displayable.code_execution_node.node import CodeExecutionNode
20
14
  from vellum.workflows.nodes.displayable.inline_prompt_node.node import InlinePromptNode
21
15
  from vellum.workflows.nodes.displayable.subworkflow_deployment_node.node import SubworkflowDeploymentNode
22
16
  from vellum.workflows.outputs.base import BaseOutput
23
17
  from vellum.workflows.ports.port import Port
24
18
  from vellum.workflows.references.lazy import LazyReference
25
- from vellum.workflows.state.base import BaseState
26
19
  from vellum.workflows.state.context import WorkflowContext
27
20
  from vellum.workflows.state.encoder import DefaultStateEncoder
28
21
  from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior, Tool
@@ -141,19 +134,16 @@ def create_tool_router_node(
141
134
  def create_function_node(
142
135
  function: Tool,
143
136
  tool_router_node: Type[ToolRouterNode],
144
- packages: Optional[Sequence[CodeExecutionPackage]] = None,
145
- runtime: CodeExecutionRuntime = "PYTHON_3_11_6",
146
137
  ) -> Type[FunctionNode]:
147
138
  """
148
139
  Create a FunctionNode class for a given function.
149
140
 
150
141
  For workflow functions: BaseNode
151
- For regular functions: CodeExecutionNode with embedded function
142
+ For regular functions: BaseNode with direct function call
143
+
152
144
  Args:
153
145
  function: The function to create a node for
154
146
  tool_router_node: The tool router node class
155
- packages: Optional list of packages to install for code execution (only used for regular functions)
156
- runtime: The runtime to use for code execution (default: "PYTHON_3_11_6")
157
147
  """
158
148
  if isinstance(function, DeploymentDefinition):
159
149
  deployment = function.deployment_id or function.deployment_name
@@ -250,24 +240,8 @@ def create_function_node(
250
240
  },
251
241
  )
252
242
  else:
253
- # For regular functions, use CodeExecutionNode approach
254
- # function tool must be put in another file (no need to have the same name)
255
- source_path = inspect.getmodule(function)
256
- if source_path is not None:
257
- function_source = inspect.getsource(source_path)
258
- else:
259
- function_source = f"<source code not available for {function.__name__}>"
260
- function_name = function.__name__
261
-
262
- code = f'''
263
- {function_source}
264
-
265
- def main(arguments):
266
- """Main function that calls the original function with the provided arguments."""
267
- return {function_name}(**arguments)
268
- '''
269
-
270
- def execute_code_execution_function(self) -> BaseNode.Outputs:
243
+ # For regular functions, call them directly
244
+ def execute_regular_function(self) -> BaseNode.Outputs:
271
245
  # Get the function call from the tool router output
272
246
  function_call_output = self.state.meta.node_outputs.get(tool_router_node.Outputs.results)
273
247
  if function_call_output and len(function_call_output) > 0:
@@ -276,42 +250,33 @@ def main(arguments):
276
250
  else:
277
251
  arguments = {}
278
252
 
279
- self.code_inputs = {"arguments": arguments}
280
-
281
- outputs = base_class.run(self)
253
+ # Call the function directly
254
+ try:
255
+ result = function(**arguments)
256
+ except Exception as e:
257
+ raise NodeException(
258
+ message=f"Error executing function '{function.__name__}': {str(e)}",
259
+ code=WorkflowErrorCode.NODE_EXECUTION,
260
+ )
282
261
 
262
+ # Add the result to the chat history
283
263
  self.state.chat_history.append(
284
264
  ChatMessage(
285
265
  role="FUNCTION",
286
- content=StringChatMessageContent(value=json.dumps(outputs.result, cls=DefaultStateEncoder)),
266
+ content=StringChatMessageContent(value=json.dumps(result, cls=DefaultStateEncoder)),
287
267
  )
288
268
  )
289
269
 
290
270
  return self.Outputs()
291
271
 
292
- # Create the properly typed base class with explicit type annotation
293
- def get_function_output_type() -> Type:
294
- return function.__annotations__.get("return", Any)
295
-
296
- output_type = get_function_output_type()
297
-
298
- base_class: Type[CodeExecutionNode] = CodeExecutionNode[BaseState, output_type] # type: ignore[valid-type]
299
-
300
- # Create the class with basic attributes
301
- node = types.new_class(
302
- f"CodeExecutionNode_{function.__name__}",
303
- (base_class,),
304
- {},
305
- lambda ns: ns.update(
306
- {
307
- "code": code,
308
- "code_inputs": {}, # No inputs needed since we handle function call extraction in run()
309
- "run": execute_code_execution_function,
310
- "runtime": runtime,
311
- "packages": packages,
312
- "__module__": __name__,
313
- }
314
- ),
272
+ # Create BaseNode for regular functions
273
+ node = type(
274
+ f"FunctionNode_{function.__name__}",
275
+ (FunctionNode,),
276
+ {
277
+ "run": execute_regular_function,
278
+ "__module__": __name__,
279
+ },
315
280
  )
316
281
 
317
282
  return node
@@ -1,3 +1,3 @@
1
- from .tool_calling_node import ToolCallingNode
1
+ from ..displayable.tool_calling_node import ToolCallingNode
2
2
 
3
3
  __all__ = ["ToolCallingNode"]
@@ -1,3 +1,3 @@
1
- from vellum.workflows.nodes.experimental.tool_calling_node.node import ToolCallingNode
1
+ from vellum.workflows.nodes.displayable.tool_calling_node import ToolCallingNode
2
2
 
3
3
  __all__ = ["ToolCallingNode"]
@@ -68,10 +68,10 @@ class DefaultStateEncoder(JSONEncoder):
68
68
  function_definition = compile_function_definition(obj)
69
69
  source_path = inspect.getsourcefile(obj)
70
70
  if source_path is not None:
71
- with open(source_path, "r") as f:
71
+ with open(source_path) as f:
72
72
  source_code = f.read()
73
73
  else:
74
- source_code = f"<source code not available for {obj.__name__}>"
74
+ source_code = f"# Error: Source code not available for {obj.__name__}"
75
75
 
76
76
  return {
77
77
  "type": "CODE_EXECUTION",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.14.80
3
+ Version: 0.14.82
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -3,7 +3,7 @@ vellum_cli/README.md,sha256=2NudRoLzWxNKqnuVy1JuQ7DerIaxWGYkrH8kMd-asIE,90
3
3
  vellum_cli/__init__.py,sha256=50dYVkBzGUS1i-UKf_9zv1JMif1lLClriNUSs-Z7i4E,12678
4
4
  vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
5
5
  vellum_cli/config.py,sha256=v5BmZ-t_v4Jmqd7KVuQMZF2pRI-rbMspSkVYXIRoTmI,9448
6
- vellum_cli/image_push.py,sha256=rPeSfTlFpdTzwTdnXRL82OVd61qMoGFGLxnLjZLU98Q,10596
6
+ vellum_cli/image_push.py,sha256=eeOBqKtKkPu6Kgm_jQCVCivogzAcdlIlkv61-QxH67c,11006
7
7
  vellum_cli/init.py,sha256=WpnMXPItPmh0f0bBGIer3p-e5gu8DUGwSArT_FuoMEw,5093
8
8
  vellum_cli/logger.py,sha256=dcM_OmgqXLo93vDYswO5ylyUQQcTfnA5GTd5tbIt3wM,1446
9
9
  vellum_cli/ping.py,sha256=p_BCCRjgPhng6JktuECtkDQLbhopt6JpmrtGoLnLJT8,1161
@@ -12,8 +12,8 @@ vellum_cli/push.py,sha256=sUo0d7lm7saGxQciH-JW2FB_gWfP2gwoEHO1wGnNQR0,10933
12
12
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  vellum_cli/tests/conftest.py,sha256=wx3PlJjVB0HRf5dr2b_idOIw27WPPl0J0FNbhIJJaVk,1689
14
14
  vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
15
- vellum_cli/tests/test_image_push.py,sha256=qrlSZVMkPYc0ieqYaY2HCI8bBzwwL_Sx1G2nLb9_pSo,9199
16
- vellum_cli/tests/test_image_push_error_handling.py,sha256=_Wjfkn1orI2K4Ahzqz4u8T13or7NOX01K4BtcTuTIOM,7107
15
+ vellum_cli/tests/test_image_push.py,sha256=X0YOPdoaAnWtK9IQTxaN_wWpw08-5G3v76k1Wu53JpU,12801
16
+ vellum_cli/tests/test_image_push_error_handling.py,sha256=QRH0eYNEEIkD2-EVFQWYexOKlhMB6puh1GouovrE-VU,7647
17
17
  vellum_cli/tests/test_init.py,sha256=8UOc_ThfouR4ja5cCl_URuLk7ohr9JXfCnG4yka1OUQ,18754
18
18
  vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
19
19
  vellum_cli/tests/test_ping.py,sha256=178EJHxPZtnnPMNXXynsQt8DIFhsrdc2bL17_YsG17M,2580
@@ -62,7 +62,7 @@ vellum_ee/workflows/display/nodes/vellum/tests/test_retry_node.py,sha256=h93ysol
62
62
  vellum_ee/workflows/display/nodes/vellum/tests/test_search_node.py,sha256=KvByxgbUkVyfPIVxTUBUk6a92JiJMi8eReZWxzfPExU,3864
63
63
  vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py,sha256=BUzHJgjdWnPeZxjFjHfDBKnbFjYjnbXPjc-1hne1B2Y,3965
64
64
  vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py,sha256=LSk2gx9TpGXbAqKe8dggQW8yJZqj-Cf0EGJFeGGlEcw,3321
65
- vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py,sha256=YMoLNWknmSsFj7MtprenOYuXTX1VWUQ2bXZs_p76gBg,8163
65
+ vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py,sha256=bSMWCwD-niSx3MQPtgsLXjIf6zynQxZdpmeaOM6H3QA,4580
66
66
  vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py,sha256=Khjsb53PKpZuyhKoRMgKAL45eGp5hZqXvHmVeQWRw4w,2289
67
67
  vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=3LS1O4DGPWit05oj_ubeW8AlHGnoBxdUMferGQuAiZs,4851
68
68
  vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=z9Omo676RRc7mQjLoL7hjiHhUj0OWVLhrrb97YTN4QA,4086
@@ -78,7 +78,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outp
78
78
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=PkSgghJDz0fpDB72HHPjLjo8LkZk-HpUkCQzRLX-iVw,40611
79
79
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=dsJr8I9AdPwMOGszirfNDzZP2Ychd94aAKuPXAzknMk,4632
80
80
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=Q3QOzzF7KE_9EukJ9yNFgYL7Qio_vTqDVd-6kc40wd4,15834
81
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=SrpLTehz__k9DFGMTWQfTKxuzDxY2rLi8TJ27-h0UKE,29681
81
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=B4DC2e5nqEk5NZeUwR4vKmBoEyToHkAuq4cCqbsidFo,29708
82
82
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=cBHGuY-DeyqQlLbpRZrrQyDh7em8rPkB7bV9Vi0EFoE,53608
83
83
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py,sha256=E1ww97BFoGbnRkxf84TScat5NQhP8nLVrdaOlpGnSKU,8615
84
84
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=w1BYEZXIMjWmcKGQXzhelHnKFlEAXmsgjkI9fcgqKXA,5850
@@ -93,8 +93,8 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_
93
93
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py,sha256=XWrhHg_acLsRHwjstBAii9Pmes9oXFtAUWSAVF1oSBc,11225
94
94
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py,sha256=V8b6gKghLlO7PJI8xeNdnfn8aII0W_IFQvSQBQM62UQ,7721
95
95
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=hDWtKXmGI1CKhTwTNqpu_d5RkE5n7SolMLtgd87KqTI,3856
96
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py,sha256=6q-lTGMp5HbQba3NsHUFSit8_zEBxIVPGE8yCw4SVx0,25720
97
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py,sha256=aY76l9s_2nezx7hCfUZsPYFzvYMy-Rjd73G0DlL6s6A,9348
96
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py,sha256=Nu5XZeGbqev638Osd9Vu17JE74ZWAHsrhYi9Uk-xLr8,25489
97
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py,sha256=PR2bLdtl0QuA9WbvZGNBpPeQy1xOV6UeALKpJSRSCEY,8712
98
98
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py,sha256=mova0sPD3evHiHIN1O0VynxlCp-uOcEIKve5Pd_oCDg,4069
99
99
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=pLCyMScV88DTBXRH7jXaXOEA1GBq8NIipCUFwIAWnwI,2771
100
100
  vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=J4ouI8KxbMfxQP2Zq_9cWMGYgbjCWmKzjCJEtnSJb0I,5829
@@ -139,12 +139,12 @@ vellum_ee/workflows/tests/test_display_meta.py,sha256=PkXJVnMZs9GNooDkd59n4YTBAX
139
139
  vellum_ee/workflows/tests/test_serialize_module.py,sha256=qcHbl6YaKtJebQJvw0OXCVlJXLkj6sjkbSMu05zXI0U,1874
140
140
  vellum_ee/workflows/tests/test_server.py,sha256=SsOkS6sGO7uGC4mxvk4iv8AtcXs058P9hgFHzTWmpII,14519
141
141
  vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
142
- vellum/__init__.py,sha256=GQqR0tDU6_sjyk9pP-0qqV7Rrk1p5b8ObQKR5Xnr4o8,42510
142
+ vellum/__init__.py,sha256=I8qQZ9GWQ_u-rMZlCWj-Zl2Z_YM1NGY3fAG5BrPeZb8,42698
143
143
  vellum/client/README.md,sha256=CuGUYnaE0Imt0KqQ4sIPaUghCjLHkF3DdEvZWu14-8s,4807
144
144
  vellum/client/__init__.py,sha256=AYopGv2ZRVn3zsU8_km6KOvEHDbXiTPCVuYVI7bWvdA,120166
145
145
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
146
146
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
147
- vellum/client/core/client_wrapper.py,sha256=28--LC1-hrUv3Yo5HQtt5VDbxX6iu7PRzaZPVD9oylU,1869
147
+ vellum/client/core/client_wrapper.py,sha256=xroZld9rUgZBqi4t2PSZNmSpW0hkjl8W5dkudogh9PI,1869
148
148
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
149
149
  vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
150
150
  vellum/client/core/http_client.py,sha256=Z77OIxIbL4OAB2IDqjRq_sYa5yNYAWfmdhdCSSvh6Y4,19552
@@ -212,7 +212,7 @@ vellum/client/resources/workspace_secrets/__init__.py,sha256=FTtvy8EDg9nNNg9WCat
212
212
  vellum/client/resources/workspace_secrets/client.py,sha256=zlBdbeTP6sqvtyl_DlrpfG-W5hSP7tJ1NYLSygi4CLU,8205
213
213
  vellum/client/resources/workspaces/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
214
214
  vellum/client/resources/workspaces/client.py,sha256=RthwzN1o-Jxwg5yyNNodavFyNUSxfLoTv26w3mRR5g8,3595
215
- vellum/client/types/__init__.py,sha256=DPbl8CjtbEKqhlsrTZxdRgx2vvJ9ZVvD20RO2AERRGM,64415
215
+ vellum/client/types/__init__.py,sha256=gl1Lb4alZrG7SqoSibiKJY4I5sSCcqH-QH560_vwGUw,64711
216
216
  vellum/client/types/ad_hoc_execute_prompt_event.py,sha256=bCjujA2XsOgyF3bRZbcEqV2rOIymRgsLoIRtZpB14xg,607
217
217
  vellum/client/types/ad_hoc_expand_meta.py,sha256=1gv-NCsy_6xBYupLvZH979yf2VMdxAU-l0y0ynMKZaw,1331
218
218
  vellum/client/types/ad_hoc_fulfilled_prompt_execution_meta.py,sha256=oDG60TpwK1YNSKhRsBbiP2O3ZF9PKR-M9chGIfKw4R4,1004
@@ -330,7 +330,8 @@ vellum/client/types/execution_json_vellum_value.py,sha256=oGY3CsJBKeOuEexmITfRYc
330
330
  vellum/client/types/execution_number_vellum_value.py,sha256=b2TpqyafRHCdl6EhgctNgUSLU-JBdouU6OgM8Jk_O78,809
331
331
  vellum/client/types/execution_search_results_vellum_value.py,sha256=HkxoXaUF6pMbfXd5wLk5VKmcXed2IRfEzkxsoGpwmg0,898
332
332
  vellum/client/types/execution_string_vellum_value.py,sha256=4w0ottwB5F2NL3uEXBBggP7XkcdE_D2lGmEobkXWY7o,807
333
- vellum/client/types/execution_vellum_value.py,sha256=PpbrbJdSioqaqT2gZ6mx2Ht0Oy8XGyxBDcLFfPqUBIA,980
333
+ vellum/client/types/execution_thinking_vellum_value.py,sha256=n66gPYgiDpOGhOniQlRE6jDUOBnPkHnfOvz8RVyzw1g,879
334
+ vellum/client/types/execution_vellum_value.py,sha256=gJ4UWA4KKzWGJZpEZGQV8Efqh27PmyWz6RZSsbtNux8,1088
334
335
  vellum/client/types/external_input_descriptor.py,sha256=ErOW2OfFMz1FDGmVY6NgiUBPsleaWhdJBekwFp4ru7o,805
335
336
  vellum/client/types/external_test_case_execution.py,sha256=TkO1CQcEI8LA7sdYJfAqhbdkj27sXEkF8VL7zBeDBM4,877
336
337
  vellum/client/types/external_test_case_execution_request.py,sha256=xd80GZg4FbZP6FZRIhZL9V1uFetI3bcCj-wzanco5tQ,921
@@ -524,7 +525,7 @@ vellum/client/types/prompt_execution_meta.py,sha256=3hhMZgdAR5mKfnh2e_eVN3oKfT0E
524
525
  vellum/client/types/prompt_node_execution_meta.py,sha256=IyWH__nCp5uwS0N32b2ZEsA-Fv7AZDB4nnlRZayU2Gc,888
525
526
  vellum/client/types/prompt_node_result.py,sha256=3jewO-nPodoXTq_5RxgwhKfDZrvoPjRZ_vUXLeqiuHY,749
526
527
  vellum/client/types/prompt_node_result_data.py,sha256=fNOxBfK3ablDBxkUWVVstJMYaGdHGgu27WxP87E6UQ4,872
527
- vellum/client/types/prompt_output.py,sha256=NpDGJNIYIivzQJnBeoJLpJlCk7gqBESLwv5Qtn_20qQ,398
528
+ vellum/client/types/prompt_output.py,sha256=YRHDKRB2Yn3GS7pzY-cH17gtjcvew0vP0hls_tzWF3o,480
528
529
  vellum/client/types/prompt_parameters.py,sha256=Vkwh4zI9gX1DuGQxrWiUUa1TshTfnPlS7_yRrziD5qg,1046
529
530
  vellum/client/types/prompt_push_response.py,sha256=Un61pv4kVH0Omd8OKVfTk1yZ1RWrwuquAgl1vanb04Y,601
530
531
  vellum/client/types/prompt_request_chat_history_input.py,sha256=DB2io5piMSyA89f5lnIVYO4MLZoNALNSufx8Y-oOwOE,790
@@ -696,6 +697,8 @@ vellum/client/types/test_suite_test_case_replace_bulk_operation_request.py,sha25
696
697
  vellum/client/types/test_suite_test_case_replaced_bulk_result.py,sha256=BIlXI7udygWrwtyRhCl8hmExHbkAl9lI8s3sm1G5iGc,1019
697
698
  vellum/client/types/test_suite_test_case_replaced_bulk_result_data.py,sha256=ORmcUvwzvRLRaoFhxdXFIKzPxOI6PU1kESl0R6rsJuw,651
698
699
  vellum/client/types/test_suite_test_case_upsert_bulk_operation_request.py,sha256=PrKuqePiXBQv6iLAxsk4xQg29KGdOlqMDhIVdGNxuz4,1071
700
+ vellum/client/types/thinking_vellum_value.py,sha256=XLeSzCwbO9kVek6zdMn6pQChLKDYFeyabE9OiFeoq_I,755
701
+ vellum/client/types/thinking_vellum_value_request.py,sha256=n6FqEZs5TKhhNZqe9yau_Vcn55ktXxFQO5sWa0aRNbg,784
699
702
  vellum/client/types/token_overlapping_window_chunker_config.py,sha256=_8vR9AiZQmb5OA3OojbjuTOGiGNTS9EY0vXrmej_TM0,731
700
703
  vellum/client/types/token_overlapping_window_chunker_config_request.py,sha256=O58w5om6EsCgZeqM7n3KSzwo1PqINyHWln46EFW4Inc,738
701
704
  vellum/client/types/token_overlapping_window_chunking.py,sha256=TghiPKWZg3Eg_UzGI9VmjQgVPZFABrnhfsz4iPLEem8,889
@@ -719,14 +722,14 @@ vellum/client/types/vellum_sdk_error.py,sha256=1AyCu_sUa8gx5wUJg5EtDYbvs9uQPhZfH
719
722
  vellum/client/types/vellum_sdk_error_code_enum.py,sha256=a2K6XJvl72tNn82zyx5QpzYGgLfYWVBKY-o8jeDqKoM,504
720
723
  vellum/client/types/vellum_secret.py,sha256=jru3nBCquZHZ3wEdpgKZNmy2WFh26PVKrTNaXeVSsZQ,555
721
724
  vellum/client/types/vellum_span.py,sha256=V5P1z-OFqgQQAZjek2toYudlh-fCu0NTt5uKuKm9hd0,258
722
- vellum/client/types/vellum_value.py,sha256=Un9AeNlx0QZA9-eIGgA5nEdZU0_0vHfibiafJR0q8V4,1049
725
+ vellum/client/types/vellum_value.py,sha256=eMg1StXImnx5ow09AbQmjz3YfoJndCYP23LU5y1M0I8,1129
723
726
  vellum/client/types/vellum_value_logical_condition_group_request.py,sha256=zdcBnm-qQbHHexNdM17WjMXNVRCPF8Vp7Sbs0a1d8Qw,1270
724
727
  vellum/client/types/vellum_value_logical_condition_request.py,sha256=c2gnVEmsrsJSRbx7DGlv8lBpgLRlOHSW1RNo-akbyWo,966
725
728
  vellum/client/types/vellum_value_logical_expression_request.py,sha256=vjNsI1NUAkwxLwIXJM_DVXTObyAM63gOfHj6aHw7osc,479
726
- vellum/client/types/vellum_value_request.py,sha256=WAUV4RnyAG6t0k94QTY1FE4F8HvpqhptDDGcCinwjis,1298
729
+ vellum/client/types/vellum_value_request.py,sha256=zmu0DFiXuCkt7PxbhJc7giM_U0GPoMPjN5xE9LKhqhA,1400
727
730
  vellum/client/types/vellum_variable.py,sha256=BDcccISJsycsrW3E5A5RTIOfxS_83ofkleOPP1upqW4,959
728
731
  vellum/client/types/vellum_variable_extensions.py,sha256=PsrRo0STOKhxrkSFRrOXCPlf1x5Uxpy3vVMJz02O20E,685
729
- vellum/client/types/vellum_variable_type.py,sha256=XUBG699lv7iXtpG3vUeBmTGfKE9u164IuJfzHeXWKJ8,391
732
+ vellum/client/types/vellum_variable_type.py,sha256=epYV-PY0NkvUntKzgzqelWMq9Dzmh7Y32c19GB_2mh0,411
730
733
  vellum/client/types/vellum_workflow_execution_event.py,sha256=H8rP3_6a6LTvemoHfsmI2THpTRf8PYrZQcjoeTzf-44,934
731
734
  vellum/client/types/workflow_deployment_event_executions_response.py,sha256=_X9hfsfpCf7DaQpfg83AAcbadZxEVi1NKNf2PZ7PRY8,1190
732
735
  vellum/client/types/workflow_deployment_history_item.py,sha256=w5yqAtmYWw8kTljYEVBa8-fLxKsrBA8Img7IC3GjZG4,1226
@@ -1017,6 +1020,7 @@ vellum/types/execution_json_vellum_value.py,sha256=AvcmBTxlf41ivq5KeMU8MRHAgRYxl
1017
1020
  vellum/types/execution_number_vellum_value.py,sha256=rs7w_72tN3TFVpx-tlD-IGrap25xWkPQ7o4yyUlqGk4,167
1018
1021
  vellum/types/execution_search_results_vellum_value.py,sha256=of3CXBuKUjHW0ZU3SeOe5XZKrSNz7HFnKwBVaPa7Lzg,175
1019
1022
  vellum/types/execution_string_vellum_value.py,sha256=MY47d3IJQj9PPThKsCZUFS8y80f3so3kDDaSW5pJYsA,167
1023
+ vellum/types/execution_thinking_vellum_value.py,sha256=Mx9C-vjS0LCGK60CARSyuDI2bHPJFA9AOoSKSfnICG0,169
1020
1024
  vellum/types/execution_vellum_value.py,sha256=VRe64r540rkdVWjWijd7Y5JsYM_9zw09QUUuorKHeXU,160
1021
1025
  vellum/types/external_input_descriptor.py,sha256=-r6xPo7-1Ioq4XZ2nwcrg8OBoyVItKr-BeXspJwDWDQ,163
1022
1026
  vellum/types/external_test_case_execution.py,sha256=Av4H59SBBCZ9CZtT-eKD3n05lgljTqdtSZSjtsDpbc4,166
@@ -1383,6 +1387,8 @@ vellum/types/test_suite_test_case_replace_bulk_operation_request.py,sha256=CvjbM
1383
1387
  vellum/types/test_suite_test_case_replaced_bulk_result.py,sha256=Aj-4gz999ma3K8q5uF6uMueQ1VomCwn9921oZE8lres,179
1384
1388
  vellum/types/test_suite_test_case_replaced_bulk_result_data.py,sha256=4qxVM1fTuPIo_sndTuV1_cSA9AR1wVfi5bFwIzLzdvA,184
1385
1389
  vellum/types/test_suite_test_case_upsert_bulk_operation_request.py,sha256=xDvR6dJbgCtVT-zwvIE-bO42ySq-3QLlXtwxK30s2LY,188
1390
+ vellum/types/thinking_vellum_value.py,sha256=-aDVQ7sFbAkbf2Eab-z_27fSf91pzqkIfS_65eT4Cks,159
1391
+ vellum/types/thinking_vellum_value_request.py,sha256=cxfwr_RWpepYUp3BHfq0Ui9I8XPqERCLosnpZpLfsNk,167
1386
1392
  vellum/types/token_overlapping_window_chunker_config.py,sha256=NFoh8PAQCFXMnmHJ-FHZIbJjdZoVvrSaFsZ-5UOvldI,177
1387
1393
  vellum/types/token_overlapping_window_chunker_config_request.py,sha256=C1_P8TQXCRkKD6zcy2O7l2eMaPH_atBMdQOW8ZB-HCg,185
1388
1394
  vellum/types/token_overlapping_window_chunking.py,sha256=fgVxqPWWRIwTyb1_MZxwmjbIMeCzEKBeWFbdk9cw4PU,171
@@ -1603,7 +1609,7 @@ vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWC
1603
1609
  vellum/workflows/nodes/core/try_node/node.py,sha256=XdyOvlwQ3m4h0-_WNtaBl2t_CdlzPXclulkLOtUcX3E,4388
1604
1610
  vellum/workflows/nodes/core/try_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1605
1611
  vellum/workflows/nodes/core/try_node/tests/test_node.py,sha256=h6eUc3SggvhzBWlOD0PrPUlkoCSQHwjqYn81VkxSIxU,4948
1606
- vellum/workflows/nodes/displayable/__init__.py,sha256=6F_4DlSwvHuilWnIalp8iDjjDXl0Nmz4QzJV2PYe5RI,1023
1612
+ vellum/workflows/nodes/displayable/__init__.py,sha256=zH7SFotr4i8sO-r5_k53yPipQwDouDmHxTfCE6dXAoU,1093
1607
1613
  vellum/workflows/nodes/displayable/api_node/__init__.py,sha256=MoxdQSnidIj1Nf_d-hTxlOxcZXaZnsWFDbE-PkTK24o,56
1608
1614
  vellum/workflows/nodes/displayable/api_node/node.py,sha256=kGvKPxXj4XcAsNLtvE1RBGI58MiSNTkQcQU2g2JHC3E,2922
1609
1615
  vellum/workflows/nodes/displayable/api_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1629,7 +1635,7 @@ vellum/workflows/nodes/displayable/code_execution_node/node.py,sha256=Qh4SPafzdR
1629
1635
  vellum/workflows/nodes/displayable/code_execution_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1630
1636
  vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1631
1637
  vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/main.py,sha256=5QsbmkzSlSbcbWTG_JmIqcP-JNJzOPTKxGzdHos19W4,79
1632
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py,sha256=47W5fPLpDcaKhCVuauKOwcivx1NfhpbsRMPrs-WBnlY,38441
1638
+ vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py,sha256=0lxmU-XXie6qu35qAEfZJ3vKZ1XGvWV4eq9y2RMelOE,38521
1633
1639
  vellum/workflows/nodes/displayable/code_execution_node/utils.py,sha256=VRTKms59vrSR9mDk99cojParZVAP4lzjEeDwDNXU1tk,3837
1634
1640
  vellum/workflows/nodes/displayable/conditional_node/__init__.py,sha256=AS_EIqFdU1F9t8aLmbZU-rLh9ry6LCJ0uj0D8F0L5Uw,72
1635
1641
  vellum/workflows/nodes/displayable/conditional_node/node.py,sha256=71ZUNfTiD7t2Kai2ypw0tmv1lSf1brQaHAQD-SeUrGE,1101
@@ -1644,7 +1650,7 @@ vellum/workflows/nodes/displayable/guardrail_node/test_node.py,sha256=SAGv6hSFcB
1644
1650
  vellum/workflows/nodes/displayable/guardrail_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1645
1651
  vellum/workflows/nodes/displayable/guardrail_node/tests/test_node.py,sha256=X2pd6TI8miYxIa7rgvs1pHTEreyWcf77EyR0_Jsa700,2055
1646
1652
  vellum/workflows/nodes/displayable/inline_prompt_node/__init__.py,sha256=gSUOoEZLlrx35-tQhSAd3An8WDwBqyiQh-sIebLU9wU,74
1647
- vellum/workflows/nodes/displayable/inline_prompt_node/node.py,sha256=ST_V1Z3-7lzZ__Ntfm6iry70u9D3GD2a2vxsl2d4Q_c,2843
1653
+ vellum/workflows/nodes/displayable/inline_prompt_node/node.py,sha256=ApPcHc5beGL2ReONT6MF-A4DGWZFCdKJ4ha-204bRoU,3053
1648
1654
  vellum/workflows/nodes/displayable/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1649
1655
  vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py,sha256=bBHs90mV5SZ3rJPAL0wx4WWyawUA406LgMPOdvpZC_A,10923
1650
1656
  vellum/workflows/nodes/displayable/merge_node/__init__.py,sha256=J8IC08dSH7P76wKlNuxe1sn7toNGtSQdFirUbtPDEs0,60
@@ -1652,7 +1658,7 @@ vellum/workflows/nodes/displayable/merge_node/node.py,sha256=nZtGGVAvY4fvGg8vwV6
1652
1658
  vellum/workflows/nodes/displayable/note_node/__init__.py,sha256=KWA3P4fyYJ-fOTky8qNGlcOotQ-HeHJ9AjZt6mRQmCE,58
1653
1659
  vellum/workflows/nodes/displayable/note_node/node.py,sha256=sIN1VBQ7zeT3GhN0kupXbFfdpvgedWV79k4woJNp5IQ,394
1654
1660
  vellum/workflows/nodes/displayable/prompt_deployment_node/__init__.py,sha256=krX1Hds-TSVYZsx0wJFX4wsAKkEFYOX1ifwRGiIM-EA,82
1655
- vellum/workflows/nodes/displayable/prompt_deployment_node/node.py,sha256=eUiQYdqJTrWhVcUgGAPJYEnRk6S71Yrzu5-c-XcVFs4,3243
1661
+ vellum/workflows/nodes/displayable/prompt_deployment_node/node.py,sha256=KBMylYcEIoqTG438s5I-rv4uRejB8-Yc_4QA7XyALy0,3453
1656
1662
  vellum/workflows/nodes/displayable/prompt_deployment_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1657
1663
  vellum/workflows/nodes/displayable/prompt_deployment_node/tests/test_node.py,sha256=c_nuuqrwiIjgj4qIbVypfDuOc-3TlgO6CbXFqQl2Nqw,19725
1658
1664
  vellum/workflows/nodes/displayable/search_node/__init__.py,sha256=hpBpvbrDYf43DElRZFLzieSn8weXiwNiiNOJurERQbs,62
@@ -1668,16 +1674,17 @@ vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py,sha256=
1668
1674
  vellum/workflows/nodes/displayable/tests/test_search_node_error_handling.py,sha256=8aw8hDFL0ZXThvAa7yxrJN026EYGD4-Q1si3Phu9-_0,6307
1669
1675
  vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py,sha256=VepO5z1277c1y5N6LLIC31nnWD1aak2m5oPFplfJHHs,6935
1670
1676
  vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py,sha256=dc3EEn1sOICpr3GdS8eyeFtExaGwWWcw9eHSdkRhQJU,2584
1677
+ vellum/workflows/nodes/displayable/tool_calling_node/__init__.py,sha256=3n0-ysmFKsr40CVxPthc0rfJgqVJeZuUEsCmYudLVRg,117
1678
+ vellum/workflows/nodes/displayable/tool_calling_node/node.py,sha256=PPu8JPDHUAHU95d73WDwq75sfsUH-I47BdnOuZXkIm8,4976
1679
+ vellum/workflows/nodes/displayable/tool_calling_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1680
+ vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py,sha256=X9kl8qntn0cQOOvyn0noDayhU0hXenqYJ0XO1FkOjAs,5071
1681
+ vellum/workflows/nodes/displayable/tool_calling_node/tests/test_utils.py,sha256=eu6WTyENhGLg9pGp_j69rysZjf_qiQXske1YdZn9PzU,1718
1682
+ vellum/workflows/nodes/displayable/tool_calling_node/utils.py,sha256=f2hCLciTqjHXj9tVdnnTAVY0BLUCMBoH0emQeOJCB7I,11309
1671
1683
  vellum/workflows/nodes/experimental/README.md,sha256=eF6DfIL8t-HbF9-mcofOMymKrraiBHDLKTlnBa51ZiE,284
1672
- vellum/workflows/nodes/experimental/__init__.py,sha256=_tpZGWAZLydcKxfrj1-plrZeTajskVhUr1A6mHoSaWM,78
1684
+ vellum/workflows/nodes/experimental/__init__.py,sha256=k7VQEyvgEdnrEZ-icXx3fiByPnyMOnMXNGGuqacyyik,91
1673
1685
  vellum/workflows/nodes/experimental/openai_chat_completion_node/__init__.py,sha256=lsyD9laR9p7kx5-BXGH2gUTM242UhKy8SMV0SR6S2iE,90
1674
1686
  vellum/workflows/nodes/experimental/openai_chat_completion_node/node.py,sha256=cKI2Ls25L-JVt4z4a2ozQa-YBeVy21Z7BQ32Sj7iBPE,10460
1675
- vellum/workflows/nodes/experimental/tool_calling_node/__init__.py,sha256=S7OzT3I4cyOU5Beoz87nPwCejCMP2FsHBFL8OcVmxJ4,118
1676
- vellum/workflows/nodes/experimental/tool_calling_node/node.py,sha256=jwL1sbitmm1CpTOAEI0IIuc6VRr8d7yxUpS4Y5s9Bk8,5966
1677
- vellum/workflows/nodes/experimental/tool_calling_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1678
- vellum/workflows/nodes/experimental/tool_calling_node/tests/test_node.py,sha256=XK1H_QAT_nVFmFP442RYyPvpTfSgtU6kSGu3-OQPBNU,5072
1679
- vellum/workflows/nodes/experimental/tool_calling_node/tests/test_utils.py,sha256=-g90SdXscuikF7JP0lFGvSvPc8jl2vBuHwBeiYJIiXk,1719
1680
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py,sha256=t18ye2wY9jtTjKXJs8oChNGI5xCdxlUUyVYbRJfJLFI,12959
1687
+ vellum/workflows/nodes/experimental/tool_calling_node/__init__.py,sha256=8R5HQtDDfo0hgFX6VdM45-FiyxK-IMTI9B9LL4TRUbw,112
1681
1688
  vellum/workflows/nodes/mocks.py,sha256=a1FjWEIocseMfjzM-i8DNozpUsaW0IONRpZmXBoWlyc,10455
1682
1689
  vellum/workflows/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1683
1690
  vellum/workflows/nodes/tests/test_mocks.py,sha256=mfPvrs75PKcsNsbJLQAN6PDFoVqs9TmQxpdyFKDdO60,7837
@@ -1710,7 +1717,7 @@ vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2
1710
1717
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
1711
1718
  vellum/workflows/state/base.py,sha256=WIMJYyuHUrP4zt0Nudk66HAK1L6GgGmsU_GQp7BGE2U,22189
1712
1719
  vellum/workflows/state/context.py,sha256=KOAI1wEGn8dGmhmAemJaf4SZbitP3jpIBcwKfznQaRE,3076
1713
- vellum/workflows/state/encoder.py,sha256=xtKpDAR5qWbxIN61dz3X_5_D47MTrbvvas8n15jys18,2881
1720
+ vellum/workflows/state/encoder.py,sha256=sV80h-lAo66isD2ezK1_YLzj75Aa5dAtF2YA1c3BYKo,2883
1714
1721
  vellum/workflows/state/store.py,sha256=uVe-oN73KwGV6M6YLhwZMMUQhzTQomsVfVnb8V91gVo,1147
1715
1722
  vellum/workflows/state/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1716
1723
  vellum/workflows/state/tests/test_state.py,sha256=YOiC9qZAzkdiqb7nRarNWeDwxo7xHv3y3czlHl81ezg,6741
@@ -1745,8 +1752,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
1745
1752
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1746
1753
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=fROqff6AZpCIzaSwOKSdtYy4XR0UZQ6ejxL3RJOSJVs,20447
1747
1754
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
1748
- vellum_ai-0.14.80.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1749
- vellum_ai-0.14.80.dist-info/METADATA,sha256=AOpjIQ_DNiOeABYs3Y-0JAxvRnzf2jeZLJ0aQZMBcD0,5556
1750
- vellum_ai-0.14.80.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1751
- vellum_ai-0.14.80.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1752
- vellum_ai-0.14.80.dist-info/RECORD,,
1755
+ vellum_ai-0.14.82.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1756
+ vellum_ai-0.14.82.dist-info/METADATA,sha256=GhPQ5ikBeUMKXXz9PYx9SzIWCkT1puQg6cdTzveC7Zk,5556
1757
+ vellum_ai-0.14.82.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1758
+ vellum_ai-0.14.82.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1759
+ vellum_ai-0.14.82.dist-info/RECORD,,
vellum_cli/image_push.py CHANGED
@@ -24,6 +24,16 @@ def image_push_command(
24
24
  logger = load_cli_logger()
25
25
  config = load_vellum_cli_config()
26
26
 
27
+ logger.info("Cleaning up unused Docker images...")
28
+ try:
29
+ subprocess.run(
30
+ ["docker", "image", "prune", "--all", "-f", "--filter", "label=image-type=python-workflow-runtime"],
31
+ check=True,
32
+ )
33
+ logger.info("Docker image pruning completed successfully")
34
+ except subprocess.CalledProcessError as e:
35
+ logger.warning(f"Docker image pruning failed: {e}")
36
+
27
37
  if source:
28
38
  logger.info(f"Building Docker image from Dockerfile: {source}")
29
39
 
@@ -48,6 +48,7 @@ def test_image_push__self_hosted_happy_path(mock_docker_from_env, mock_subproces
48
48
  mock_docker_from_env.return_value = mock_docker_client
49
49
 
50
50
  mock_subprocess_run.side_effect = [
51
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
51
52
  subprocess.CompletedProcess(
52
53
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
53
54
  ),
@@ -100,6 +101,7 @@ def test_image_push__self_hosted_happy_path__workspace_option(
100
101
  mock_docker_from_env.return_value = mock_docker_client
101
102
 
102
103
  mock_subprocess_run.side_effect = [
104
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
103
105
  subprocess.CompletedProcess(
104
106
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
105
107
  ),
@@ -189,6 +191,7 @@ def test_image_push_with_source_success(
189
191
  mock_docker_client.images.push.return_value = [b'{"status": "Pushed"}']
190
192
 
191
193
  mock_subprocess_run.side_effect = [
194
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
192
195
  subprocess.CompletedProcess(args="", returncode=0, stdout=b"Build successful"),
193
196
  subprocess.CompletedProcess(
194
197
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
@@ -205,7 +208,7 @@ def test_image_push_with_source_success(
205
208
 
206
209
  assert result.exit_code == 0, result.output
207
210
 
208
- build_call = mock_subprocess_run.call_args_list[0]
211
+ build_call = mock_subprocess_run.call_args_list[1]
209
212
  assert build_call[0][0] == [
210
213
  "docker",
211
214
  "buildx",
@@ -246,6 +249,7 @@ def test_image_push_with_source_build_fails(mock_subprocess_run, monkeypatch, mo
246
249
  f.write("FROM alpine:latest\n")
247
250
 
248
251
  mock_subprocess_run.side_effect = [
252
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
249
253
  subprocess.CompletedProcess(args="", returncode=1, stderr=b"Build failed: missing dependency"),
250
254
  ]
251
255
 
@@ -255,3 +259,85 @@ def test_image_push_with_source_build_fails(mock_subprocess_run, monkeypatch, mo
255
259
  assert result.exit_code == 1
256
260
  assert "Docker build failed" in result.output
257
261
  assert "Build failed: missing dependency" in result.output
262
+
263
+
264
+ @pytest.mark.usefixtures("vellum_client", "info_log_level")
265
+ def test_image_push_includes_docker_prune(mock_docker_from_env, mock_subprocess_run, monkeypatch):
266
+ """
267
+ Tests that image_push_command calls docker image prune before validation.
268
+ """
269
+ # GIVEN a self hosted vellum api URL env var
270
+ monkeypatch.setenv("VELLUM_API_URL", "mycompany.api.com")
271
+ monkeypatch.setenv("VELLUM_API_KEY", "123456abcdef")
272
+
273
+ # AND a mock Docker client
274
+ mock_docker_client = MagicMock()
275
+ mock_docker_from_env.return_value = mock_docker_client
276
+
277
+ mock_subprocess_run.side_effect = [
278
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
279
+ subprocess.CompletedProcess(
280
+ args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
281
+ ),
282
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"manifest"),
283
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"sha256:hellosha"),
284
+ ]
285
+
286
+ # WHEN the user runs the image push command with any image
287
+ runner = CliRunner()
288
+ result = runner.invoke(cli_main, ["image", "push", "myrepo.net/myimage:latest"])
289
+
290
+ # THEN the command exits successfully
291
+ assert result.exit_code == 0, result.output
292
+
293
+ prune_call = mock_subprocess_run.call_args_list[0]
294
+ assert prune_call[0][0] == [
295
+ "docker",
296
+ "image",
297
+ "prune",
298
+ "--all",
299
+ "-f",
300
+ "--filter",
301
+ "label=image-type=python-workflow-runtime",
302
+ ]
303
+
304
+ # AND the success message includes pruning completion
305
+ assert "Docker image pruning completed successfully" in result.output
306
+
307
+
308
+ @pytest.mark.usefixtures("vellum_client", "info_log_level")
309
+ def test_image_push_continues_if_prune_fails(mock_docker_from_env, mock_subprocess_run, monkeypatch):
310
+ """
311
+ Tests that image_push_command continues if docker image prune fails.
312
+ """
313
+ # GIVEN a self hosted vellum api URL env var
314
+ monkeypatch.setenv("VELLUM_API_URL", "mycompany.api.com")
315
+ monkeypatch.setenv("VELLUM_API_KEY", "123456abcdef")
316
+
317
+ # AND a mock Docker client
318
+ mock_docker_client = MagicMock()
319
+ mock_docker_from_env.return_value = mock_docker_client
320
+
321
+ mock_subprocess_run.side_effect = [
322
+ subprocess.CalledProcessError(
323
+ 1, ["docker", "image", "prune", "--all", "-f", "--filter", "label=image-type=python-workflow-runtime"]
324
+ ),
325
+ subprocess.CompletedProcess(
326
+ args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
327
+ ),
328
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"manifest"),
329
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"sha256:hellosha"),
330
+ ]
331
+
332
+ # WHEN the user runs the image push command with any image
333
+ runner = CliRunner()
334
+ result = runner.invoke(cli_main, ["image", "push", "myrepo.net/myimage:latest"])
335
+
336
+ # THEN the command exits successfully despite pruning failure
337
+ assert result.exit_code == 0, result.output
338
+
339
+ # AND the warning message about pruning failure is shown
340
+ assert "Docker image pruning failed" in result.output
341
+
342
+ # AND the success message is still shown
343
+ assert "Image successfully pushed" in result.output
@@ -18,6 +18,7 @@ def test_image_push_docker_service_token_401_error(mock_docker_from_env, mock_ru
18
18
  mock_docker_client.images.get.return_value.id = "test-image-id"
19
19
 
20
20
  mock_run.side_effect = [
21
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
21
22
  subprocess.CompletedProcess(
22
23
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
23
24
  ),
@@ -43,6 +44,7 @@ def test_image_push_docker_service_token_500_error(mock_docker_from_env, mock_ru
43
44
  mock_docker_client.images.get.return_value.id = "test-image-id"
44
45
 
45
46
  mock_run.side_effect = [
47
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
46
48
  subprocess.CompletedProcess(
47
49
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
48
50
  ),
@@ -70,6 +72,7 @@ def test_image_push_docker_service_token_other_error(mock_docker_from_env, mock_
70
72
  mock_docker_client.images.get.return_value.id = "test-image-id"
71
73
 
72
74
  mock_run.side_effect = [
75
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
73
76
  subprocess.CompletedProcess(
74
77
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
75
78
  ),
@@ -98,6 +101,7 @@ def test_image_push_container_image_401_error(mock_docker_from_env, mock_run, ve
98
101
  mock_docker_client.images.push.return_value = ["pushed"]
99
102
 
100
103
  mock_run.side_effect = [
104
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
101
105
  subprocess.CompletedProcess(
102
106
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
103
107
  ),
@@ -129,6 +133,7 @@ def test_image_push_container_image_500_error(mock_docker_from_env, mock_run, ve
129
133
  mock_docker_client.images.push.return_value = ["pushed"]
130
134
 
131
135
  mock_run.side_effect = [
136
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
132
137
  subprocess.CompletedProcess(
133
138
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
134
139
  ),
@@ -162,6 +167,7 @@ def test_image_push_container_image_other_error(mock_docker_from_env, mock_run,
162
167
  mock_docker_client.images.push.return_value = ["pushed"]
163
168
 
164
169
  mock_run.side_effect = [
170
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"Pruning successful"),
165
171
  subprocess.CompletedProcess(
166
172
  args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
167
173
  ),
@@ -1,8 +1,7 @@
1
- from vellum.client.types.code_execution_package import CodeExecutionPackage
2
1
  from vellum.workflows import BaseWorkflow
3
2
  from vellum.workflows.inputs import BaseInputs
4
3
  from vellum.workflows.nodes.displayable.inline_prompt_node.node import InlinePromptNode
5
- from vellum.workflows.nodes.experimental.tool_calling_node.node import ToolCallingNode
4
+ from vellum.workflows.nodes.displayable.tool_calling_node.node import ToolCallingNode
6
5
  from vellum.workflows.state.base import BaseState
7
6
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
8
7
 
@@ -123,105 +122,3 @@ def test_serialize_node__prompt_inputs__mixed_values():
123
122
  ],
124
123
  },
125
124
  }
126
-
127
-
128
- def test_serialize_node__function_configs():
129
- # GIVEN a tool calling node with function packages
130
- def foo():
131
- pass
132
-
133
- def bar():
134
- pass
135
-
136
- class MyToolCallingNode(ToolCallingNode):
137
- functions = [foo, bar]
138
- function_configs = {
139
- "foo": {
140
- "runtime": "PYTHON_3_11_6",
141
- "packages": [
142
- CodeExecutionPackage(name="first_package", version="1.0.0", repository="test-repo"),
143
- CodeExecutionPackage(name="second_package", version="2.0.0", repository="test-repo"),
144
- ],
145
- },
146
- "bar": {
147
- "runtime": "PYTHON_3_11_6",
148
- "packages": [CodeExecutionPackage(name="third_package", version="3.0.0")],
149
- },
150
- }
151
-
152
- # AND a workflow with the tool calling node
153
- class Workflow(BaseWorkflow):
154
- graph = MyToolCallingNode
155
-
156
- # WHEN the workflow is serialized
157
- workflow_display = get_workflow_display(workflow_class=Workflow)
158
- serialized_workflow: dict = workflow_display.serialize()
159
-
160
- # THEN the node should properly serialize the function packages
161
- my_tool_calling_node = next(
162
- node
163
- for node in serialized_workflow["workflow_raw_data"]["nodes"]
164
- if node["id"] == str(MyToolCallingNode.__id__)
165
- )
166
-
167
- function_configs_attribute = next(
168
- attribute for attribute in my_tool_calling_node["attributes"] if attribute["name"] == "function_configs"
169
- )
170
-
171
- assert function_configs_attribute == {
172
- "id": "90cc5fc7-9fb3-450f-be5a-e90e7412a601",
173
- "name": "function_configs",
174
- "value": {
175
- "type": "CONSTANT_VALUE",
176
- "value": {
177
- "type": "JSON",
178
- "value": {
179
- "foo": {
180
- "runtime": "PYTHON_3_11_6",
181
- "packages": [
182
- {"version": "1.0.0", "name": "first_package", "repository": "test-repo"},
183
- {"version": "2.0.0", "name": "second_package", "repository": "test-repo"},
184
- ],
185
- },
186
- "bar": {
187
- "runtime": "PYTHON_3_11_6",
188
- "packages": [{"version": "3.0.0", "name": "third_package", "repository": None}],
189
- },
190
- },
191
- },
192
- },
193
- }
194
-
195
-
196
- def test_serialize_node__function_configs__none():
197
- # GIVEN a tool calling node with no function configs
198
- def foo():
199
- pass
200
-
201
- class MyToolCallingNode(ToolCallingNode):
202
- functions = [foo]
203
-
204
- # AND a workflow with the tool calling node
205
- class Workflow(BaseWorkflow):
206
- graph = MyToolCallingNode
207
-
208
- # WHEN the workflow is serialized
209
- workflow_display = get_workflow_display(workflow_class=Workflow)
210
- serialized_workflow: dict = workflow_display.serialize()
211
-
212
- # THEN the node should properly serialize the functions
213
- my_tool_calling_node = next(
214
- node
215
- for node in serialized_workflow["workflow_raw_data"]["nodes"]
216
- if node["id"] == str(MyToolCallingNode.__id__)
217
- )
218
-
219
- function_configs_attribute = next(
220
- attribute for attribute in my_tool_calling_node["attributes"] if attribute["name"] == "function_configs"
221
- )
222
-
223
- assert function_configs_attribute == {
224
- "id": "5f63f2aa-72d7-47ad-a552-630753418b7d",
225
- "name": "function_configs",
226
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
227
- }
@@ -561,7 +561,7 @@ def test_serialize_workflow__try_wrapped():
561
561
  "code_input_id": "f2e8a4fa-b54e-41e9-b314-0e5443519ac7",
562
562
  "runtime_input_id": "19d64948-f22b-4103-a7f5-3add184b31cc",
563
563
  "output_type": "NUMBER",
564
- "packages": [{"name": "openai", "version": "1.0.0"}],
564
+ "packages": [{"name": "openai", "version": "1.0.0", "repository": "test-repo"}],
565
565
  "output_id": "0fde9607-353f-42c2-85c4-20f720ebc1ec",
566
566
  "log_output_id": "7cac05e3-b7c3-475e-8df8-422b496c3398",
567
567
  },
@@ -48,7 +48,7 @@ def test_serialize_workflow():
48
48
  },
49
49
  "base": {
50
50
  "name": "ToolCallingNode",
51
- "module": ["vellum", "workflows", "nodes", "experimental", "tool_calling_node", "node"],
51
+ "module": ["vellum", "workflows", "nodes", "displayable", "tool_calling_node", "node"],
52
52
  },
53
53
  "definition": {
54
54
  "name": "GetCurrentWeatherNode",
@@ -407,11 +407,6 @@ def test_serialize_workflow():
407
407
  ],
408
408
  },
409
409
  },
410
- {
411
- "id": "a4e3bc9f-7112-4d2f-94fb-7362a85db27a",
412
- "name": "function_configs",
413
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
414
- },
415
410
  {
416
411
  "id": "1668419e-a193-43a5-8a97-3394e89bf278",
417
412
  "name": "max_prompt_iterations",
@@ -48,7 +48,7 @@ def test_serialize_workflow():
48
48
  },
49
49
  "base": {
50
50
  "name": "ToolCallingNode",
51
- "module": ["vellum", "workflows", "nodes", "experimental", "tool_calling_node", "node"],
51
+ "module": ["vellum", "workflows", "nodes", "displayable", "tool_calling_node", "node"],
52
52
  },
53
53
  "definition": {
54
54
  "name": "GetCurrentWeatherNode",
@@ -152,22 +152,6 @@ def test_serialize_workflow():
152
152
  },
153
153
  },
154
154
  },
155
- {
156
- "id": "a4e3bc9f-7112-4d2f-94fb-7362a85db27a",
157
- "name": "function_configs",
158
- "value": {
159
- "type": "CONSTANT_VALUE",
160
- "value": {
161
- "type": "JSON",
162
- "value": {
163
- "get_current_weather": {
164
- "runtime": "PYTHON_3_11_6",
165
- "packages": [{"version": "2.26.0", "name": "requests", "repository": None}],
166
- }
167
- },
168
- },
169
- },
170
- },
171
155
  {
172
156
  "id": "0f6dc102-3460-4963-91fa-7ba85d65ef7a",
173
157
  "name": "prompt_inputs",