vellum-ai 0.12.16__py3-none-any.whl → 0.12.17__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/plugins/vellum_mypy.py +80 -11
- vellum/utils/templating/render.py +3 -0
- vellum/workflows/nodes/bases/base.py +4 -0
- vellum/workflows/nodes/core/retry_node/node.py +24 -3
- vellum/workflows/nodes/core/retry_node/tests/test_node.py +40 -0
- vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +20 -1
- vellum/workflows/nodes/displayable/api_node/node.py +3 -3
- {vellum_ai-0.12.16.dist-info → vellum_ai-0.12.17.dist-info}/METADATA +1 -1
- {vellum_ai-0.12.16.dist-info → vellum_ai-0.12.17.dist-info}/RECORD +16 -16
- vellum_cli/pull.py +7 -4
- vellum_cli/tests/conftest.py +4 -2
- vellum_cli/tests/test_push.py +13 -5
- {vellum_ai-0.12.16.dist-info → vellum_ai-0.12.17.dist-info}/LICENSE +0 -0
- {vellum_ai-0.12.16.dist-info → vellum_ai-0.12.17.dist-info}/WHEEL +0 -0
- {vellum_ai-0.12.16.dist-info → vellum_ai-0.12.17.dist-info}/entry_points.txt +0 -0
@@ -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.12.
|
21
|
+
"X-Fern-SDK-Version": "0.12.17",
|
22
22
|
}
|
23
23
|
headers["X_API_KEY"] = self.api_key
|
24
24
|
return headers
|
vellum/plugins/vellum_mypy.py
CHANGED
@@ -4,6 +4,7 @@ from typing import Callable, Dict, List, Optional, Set, Type
|
|
4
4
|
from mypy.nodes import (
|
5
5
|
AssignmentStmt,
|
6
6
|
CallExpr,
|
7
|
+
ClassDef,
|
7
8
|
Decorator,
|
8
9
|
MemberExpr,
|
9
10
|
NameExpr,
|
@@ -198,13 +199,27 @@ class VellumMypyPlugin(Plugin):
|
|
198
199
|
return
|
199
200
|
|
200
201
|
current_node_outputs = node_info.names.get("Outputs")
|
201
|
-
if not current_node_outputs:
|
202
|
+
if not current_node_outputs and isinstance(base_node_outputs.node, TypeInfo):
|
202
203
|
node_info.names["Outputs"] = base_node_outputs.copy()
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
204
|
+
|
205
|
+
new_outputs_fullname = f"{node_info.fullname}.Outputs"
|
206
|
+
new_outputs_defn_raw = base_node_outputs.node.defn.serialize()
|
207
|
+
new_outputs_defn_raw["fullname"] = new_outputs_fullname
|
208
|
+
new_outputs_defn = ClassDef.deserialize(new_outputs_defn_raw)
|
209
|
+
new_outputs_sym = TypeInfo(
|
210
|
+
names=base_node_outputs.node.names.copy(),
|
211
|
+
defn=new_outputs_defn,
|
212
|
+
module_name=node_info.module_name,
|
213
|
+
)
|
214
|
+
|
215
|
+
base_result_sym = base_node_outputs.node.names[attribute_name].node
|
216
|
+
if isinstance(base_result_sym, Var):
|
217
|
+
new_result_sym = Var.deserialize(base_result_sym.serialize())
|
218
|
+
new_result_sym._fullname = f"{new_outputs_fullname}.{attribute_name}"
|
219
|
+
new_result_sym.type = base_node_resolved_type
|
220
|
+
new_outputs_sym.names[attribute_name].node = new_result_sym
|
221
|
+
new_outputs_sym.bases.append(Instance(base_node_outputs.node, []))
|
222
|
+
node_info.names["Outputs"].node = new_outputs_sym
|
208
223
|
|
209
224
|
def _base_node_class_hook(self, ctx: ClassDefContext) -> None:
|
210
225
|
"""
|
@@ -472,10 +487,22 @@ class VellumMypyPlugin(Plugin):
|
|
472
487
|
|
473
488
|
def _run_method_hook(self, ctx: MethodContext) -> MypyType:
|
474
489
|
"""
|
475
|
-
We use this to target
|
476
|
-
|
490
|
+
We use this to target:
|
491
|
+
- `BaseWorkflow.run()`, so that the WorkflowExecutionFulfilledEvent is properly typed
|
492
|
+
using the `Outputs` class defined on the user-defined subclass of `Workflow`.
|
493
|
+
- `BaseNode.run()`, so that the `Outputs` class defined on the user-defined subclass of `Node`
|
494
|
+
is properly typed.
|
477
495
|
"""
|
478
496
|
|
497
|
+
if isinstance(ctx.default_return_type, TypeAliasType):
|
498
|
+
return self._workflow_run_method_hook(ctx)
|
499
|
+
|
500
|
+
if isinstance(ctx.default_return_type, Instance):
|
501
|
+
return self._node_run_method_hook(ctx)
|
502
|
+
|
503
|
+
return ctx.default_return_type
|
504
|
+
|
505
|
+
def _workflow_run_method_hook(self, ctx: MethodContext) -> MypyType:
|
479
506
|
if not isinstance(ctx.default_return_type, TypeAliasType):
|
480
507
|
return ctx.default_return_type
|
481
508
|
|
@@ -494,7 +521,7 @@ class VellumMypyPlugin(Plugin):
|
|
494
521
|
if fulfilled_event.type.fullname != "vellum.workflows.events.workflow.WorkflowExecutionFulfilledEvent":
|
495
522
|
return ctx.default_return_type
|
496
523
|
|
497
|
-
outputs_node = self.
|
524
|
+
outputs_node = self._get_workflow_outputs_type_info(ctx)
|
498
525
|
if not outputs_node:
|
499
526
|
return ctx.default_return_type
|
500
527
|
|
@@ -513,6 +540,19 @@ class VellumMypyPlugin(Plugin):
|
|
513
540
|
column=ctx.default_return_type.column,
|
514
541
|
)
|
515
542
|
|
543
|
+
def _node_run_method_hook(self, ctx: MethodContext) -> MypyType:
|
544
|
+
if not isinstance(ctx.default_return_type, Instance):
|
545
|
+
return ctx.default_return_type
|
546
|
+
|
547
|
+
if not _is_subclass(ctx.default_return_type.type, "vellum.workflows.nodes.bases.base.BaseNode.Outputs"):
|
548
|
+
return ctx.default_return_type
|
549
|
+
|
550
|
+
outputs_node = self._get_node_outputs_type_info(ctx)
|
551
|
+
if not outputs_node:
|
552
|
+
return ctx.default_return_type
|
553
|
+
|
554
|
+
return Instance(outputs_node, [])
|
555
|
+
|
516
556
|
def _stream_method_hook(self, ctx: MethodContext) -> MypyType:
|
517
557
|
"""
|
518
558
|
We use this to target `Workflow.stream()` so that the WorkflowExecutionFulfilledEvent is properly typed
|
@@ -557,7 +597,7 @@ class VellumMypyPlugin(Plugin):
|
|
557
597
|
if fulfilled_event_index == -1 or not fulfilled_event:
|
558
598
|
return ctx.default_return_type
|
559
599
|
|
560
|
-
outputs_node = self.
|
600
|
+
outputs_node = self._get_workflow_outputs_type_info(ctx)
|
561
601
|
if not outputs_node:
|
562
602
|
return ctx.default_return_type
|
563
603
|
|
@@ -594,7 +634,7 @@ class VellumMypyPlugin(Plugin):
|
|
594
634
|
column=ctx.default_return_type.column,
|
595
635
|
)
|
596
636
|
|
597
|
-
def
|
637
|
+
def _get_workflow_outputs_type_info(self, ctx: MethodContext) -> Optional[TypeInfo]:
|
598
638
|
if not isinstance(ctx.context, CallExpr):
|
599
639
|
return None
|
600
640
|
|
@@ -624,6 +664,35 @@ class VellumMypyPlugin(Plugin):
|
|
624
664
|
|
625
665
|
return resolved_outputs_node.node
|
626
666
|
|
667
|
+
def _get_node_outputs_type_info(self, ctx: MethodContext) -> Optional[TypeInfo]:
|
668
|
+
if not isinstance(ctx.context, CallExpr):
|
669
|
+
return None
|
670
|
+
|
671
|
+
if not isinstance(ctx.context.callee, MemberExpr):
|
672
|
+
return None
|
673
|
+
|
674
|
+
expr = ctx.context.callee.expr
|
675
|
+
instance = ctx.api.get_expression_type(expr)
|
676
|
+
if not isinstance(instance, Instance) or not _is_subclass(
|
677
|
+
instance.type, "vellum.workflows.nodes.bases.base.BaseNode"
|
678
|
+
):
|
679
|
+
return None
|
680
|
+
|
681
|
+
outputs_node = instance.type.names.get("Outputs")
|
682
|
+
|
683
|
+
if (
|
684
|
+
not outputs_node
|
685
|
+
or not isinstance(outputs_node.node, TypeInfo)
|
686
|
+
or not _is_subclass(outputs_node.node, "vellum.workflows.outputs.base.BaseOutputs")
|
687
|
+
):
|
688
|
+
return None
|
689
|
+
|
690
|
+
# TODO: For some reason, returning the correct Outputs type info is causing `result` to not
|
691
|
+
# be found. `test_templating_node.py` is the best place to test this.
|
692
|
+
# https://app.shortcut.com/vellum/story/6132
|
693
|
+
# return outputs_node.node
|
694
|
+
return None
|
695
|
+
|
627
696
|
def _resolve_descriptors_in_outputs(self, type_info: SymbolTableNode) -> SymbolTableNode:
|
628
697
|
new_type_info = type_info.copy()
|
629
698
|
if not isinstance(new_type_info.node, TypeInfo):
|
@@ -28,6 +28,9 @@ def render_sandboxed_jinja_template(
|
|
28
28
|
keep_trailing_newline=True,
|
29
29
|
finalize=finalize,
|
30
30
|
)
|
31
|
+
environment.policies["json.dumps_kwargs"] = {
|
32
|
+
"cls": DefaultStateEncoder,
|
33
|
+
}
|
31
34
|
|
32
35
|
if jinja_custom_filters:
|
33
36
|
environment.filters.update(jinja_custom_filters)
|
@@ -324,6 +324,10 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
|
|
324
324
|
if not descriptor.instance:
|
325
325
|
continue
|
326
326
|
|
327
|
+
if any(isinstance(t, type) and issubclass(t, BaseDescriptor) for t in descriptor.types):
|
328
|
+
# We don't want to resolve attributes that are _meant_ to be descriptors
|
329
|
+
continue
|
330
|
+
|
327
331
|
resolved_value = resolve_value(descriptor.instance, self.state, path=descriptor.name, memo=inputs)
|
328
332
|
setattr(self, descriptor.name, resolved_value)
|
329
333
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
from typing import Callable, Generic, Optional, Type
|
2
2
|
|
3
|
+
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.utils import resolve_value
|
3
5
|
from vellum.workflows.errors.types import WorkflowErrorCode
|
4
6
|
from vellum.workflows.exceptions import NodeException
|
5
7
|
from vellum.workflows.inputs.base import BaseInputs
|
@@ -21,6 +23,7 @@ class RetryNode(BaseAdornmentNode[StateType], Generic[StateType]):
|
|
21
23
|
|
22
24
|
max_attempts: int
|
23
25
|
retry_on_error_code: Optional[WorkflowErrorCode] = None
|
26
|
+
retry_on_condition: Optional[BaseDescriptor] = None
|
24
27
|
|
25
28
|
class SubworkflowInputs(BaseInputs):
|
26
29
|
attempt_number: int
|
@@ -55,18 +58,36 @@ class RetryNode(BaseAdornmentNode[StateType], Generic[StateType]):
|
|
55
58
|
last_exception = NodeException(
|
56
59
|
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
57
60
|
message=f"""Unexpected rejection on attempt {attempt_number}: {terminal_event.error.code.value}.
|
61
|
+
Message: {terminal_event.error.message}""",
|
62
|
+
)
|
63
|
+
break
|
64
|
+
elif self.retry_on_condition and not resolve_value(self.retry_on_condition, self.state):
|
65
|
+
last_exception = NodeException(
|
66
|
+
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
67
|
+
message=f"""Rejection failed on attempt {attempt_number}: {terminal_event.error.code.value}.
|
58
68
|
Message: {terminal_event.error.message}""",
|
59
69
|
)
|
60
70
|
break
|
61
71
|
else:
|
62
|
-
last_exception =
|
72
|
+
last_exception = NodeException(
|
73
|
+
terminal_event.error.message,
|
74
|
+
code=terminal_event.error.code,
|
75
|
+
)
|
63
76
|
|
64
77
|
raise last_exception
|
65
78
|
|
66
79
|
@classmethod
|
67
80
|
def wrap(
|
68
|
-
cls,
|
81
|
+
cls,
|
82
|
+
max_attempts: int,
|
83
|
+
retry_on_error_code: Optional[WorkflowErrorCode] = None,
|
84
|
+
retry_on_condition: Optional[BaseDescriptor] = None,
|
69
85
|
) -> Callable[..., Type["RetryNode"]]:
|
70
86
|
return create_adornment(
|
71
|
-
cls,
|
87
|
+
cls,
|
88
|
+
attributes={
|
89
|
+
"max_attempts": max_attempts,
|
90
|
+
"retry_on_error_code": retry_on_error_code,
|
91
|
+
"retry_on_condition": retry_on_condition,
|
92
|
+
},
|
72
93
|
)
|
@@ -6,6 +6,7 @@ from vellum.workflows.inputs.base import BaseInputs
|
|
6
6
|
from vellum.workflows.nodes.bases import BaseNode
|
7
7
|
from vellum.workflows.nodes.core.retry_node.node import RetryNode
|
8
8
|
from vellum.workflows.outputs import BaseOutputs
|
9
|
+
from vellum.workflows.references.lazy import LazyReference
|
9
10
|
from vellum.workflows.state.base import BaseState, StateMeta
|
10
11
|
|
11
12
|
|
@@ -91,3 +92,42 @@ def test_retry_node__use_parent_inputs_and_state():
|
|
91
92
|
|
92
93
|
# THEN the data is used successfully
|
93
94
|
assert outputs.value == "foo bar"
|
95
|
+
|
96
|
+
|
97
|
+
def test_retry_node__condition_arg_successfully_retries():
|
98
|
+
# GIVEN workflow Inputs and State
|
99
|
+
class State(BaseState):
|
100
|
+
count = 0
|
101
|
+
|
102
|
+
# AND a retry node that retries on a condition
|
103
|
+
@RetryNode.wrap(
|
104
|
+
max_attempts=5,
|
105
|
+
retry_on_condition=LazyReference(lambda: State.count.less_than(3)),
|
106
|
+
)
|
107
|
+
class TestNode(BaseNode[State]):
|
108
|
+
attempt_number = RetryNode.SubworkflowInputs.attempt_number
|
109
|
+
|
110
|
+
class Outputs(BaseOutputs):
|
111
|
+
value: str
|
112
|
+
|
113
|
+
def run(self) -> Outputs:
|
114
|
+
if not isinstance(self.state.meta.parent, State):
|
115
|
+
raise NodeException(message="Failed to resolve parent state")
|
116
|
+
|
117
|
+
self.state.meta.parent.count += 1
|
118
|
+
raise NodeException(message=f"This is failure attempt {self.attempt_number}")
|
119
|
+
|
120
|
+
# WHEN the node is run
|
121
|
+
node = TestNode(state=State())
|
122
|
+
with pytest.raises(NodeException) as exc_info:
|
123
|
+
node.run()
|
124
|
+
|
125
|
+
# THEN the exception raised is the last one
|
126
|
+
assert (
|
127
|
+
exc_info.value.message
|
128
|
+
== """Rejection failed on attempt 3: INTERNAL_ERROR.
|
129
|
+
Message: This is failure attempt 3"""
|
130
|
+
)
|
131
|
+
|
132
|
+
# AND the state was updated each time
|
133
|
+
assert node.state.count == 3
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import json
|
2
2
|
|
3
|
+
from vellum.client.types.function_call import FunctionCall
|
3
4
|
from vellum.workflows.nodes.bases.base import BaseNode
|
4
5
|
from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
|
5
6
|
from vellum.workflows.state import BaseState
|
@@ -21,7 +22,9 @@ def test_templating_node__dict_output():
|
|
21
22
|
outputs = node.run()
|
22
23
|
|
23
24
|
# THEN the output is json serializable
|
24
|
-
|
25
|
+
# https://app.shortcut.com/vellum/story/6132
|
26
|
+
dump: str = outputs.result # type: ignore[assignment]
|
27
|
+
assert json.loads(dump) == {"key": "value"}
|
25
28
|
|
26
29
|
|
27
30
|
def test_templating_node__int_output():
|
@@ -106,3 +109,19 @@ def test_templating_node__execution_count_reference():
|
|
106
109
|
|
107
110
|
# THEN the output is just the total
|
108
111
|
assert outputs.result == "0"
|
112
|
+
|
113
|
+
|
114
|
+
def test_templating_node__pydantic_to_json():
|
115
|
+
# GIVEN a templating node that uses tojson on a pydantic model
|
116
|
+
class JSONTemplateNode(TemplatingNode[BaseState, Json]):
|
117
|
+
template = "{{ function_call | tojson }}"
|
118
|
+
inputs = {
|
119
|
+
"function_call": FunctionCall(name="test", arguments={"key": "value"}),
|
120
|
+
}
|
121
|
+
|
122
|
+
# WHEN the node is run
|
123
|
+
node = JSONTemplateNode()
|
124
|
+
outputs = node.run()
|
125
|
+
|
126
|
+
# THEN the output is the expected JSON
|
127
|
+
assert outputs.result == {"name": "test", "arguments": {"key": "value"}, "id": None}
|
@@ -2,7 +2,7 @@ from typing import Optional, Union
|
|
2
2
|
|
3
3
|
from vellum.workflows.constants import AuthorizationType
|
4
4
|
from vellum.workflows.nodes.displayable.bases.api_node import BaseAPINode
|
5
|
-
from vellum.workflows.
|
5
|
+
from vellum.workflows.types.core import VellumSecret
|
6
6
|
|
7
7
|
|
8
8
|
class APINode(BaseAPINode):
|
@@ -24,8 +24,8 @@ class APINode(BaseAPINode):
|
|
24
24
|
|
25
25
|
authorization_type: Optional[AuthorizationType] = None
|
26
26
|
api_key_header_key: Optional[str] = None
|
27
|
-
api_key_header_value: Optional[Union[str,
|
28
|
-
bearer_token_value: Optional[Union[str,
|
27
|
+
api_key_header_value: Optional[Union[str, VellumSecret]] = None
|
28
|
+
bearer_token_value: Optional[Union[str, VellumSecret]] = None
|
29
29
|
|
30
30
|
def run(self) -> BaseAPINode.Outputs:
|
31
31
|
headers = self.headers or {}
|
@@ -5,14 +5,14 @@ vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3
|
|
5
5
|
vellum_cli/config.py,sha256=998IZbvkrw2avjbvs8bw6NrbEgGz5UBKRbvKAcastJg,5493
|
6
6
|
vellum_cli/image_push.py,sha256=SJwhwWJsLjwGNezNVd_oCVpFMfPsAB3dfLWmriZZUtw,4419
|
7
7
|
vellum_cli/logger.py,sha256=PuRFa0WCh4sAGFS5aqWB0QIYpS6nBWwPJrIXpWxugV4,1022
|
8
|
-
vellum_cli/pull.py,sha256=
|
8
|
+
vellum_cli/pull.py,sha256=zf0y22XptUYI_hMP_4Q1CEo9s2wALsTJcCXNd-_ibd8,7551
|
9
9
|
vellum_cli/push.py,sha256=iQ2H-vY8njqiYgIifGooqopqkb1BUUA3I7IN7VIHKv8,6149
|
10
10
|
vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
vellum_cli/tests/conftest.py,sha256=
|
11
|
+
vellum_cli/tests/conftest.py,sha256=Jv-QUjXoCDhsvVvXEjOenNqRArO_xXhtNuCYt4wiOyE,1421
|
12
12
|
vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
|
13
13
|
vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
|
14
14
|
vellum_cli/tests/test_pull.py,sha256=6gbASF6ASy5YcdWjOCt6b5K0u2VWsFegdrTWu6sEVKs,19613
|
15
|
-
vellum_cli/tests/test_push.py,sha256=
|
15
|
+
vellum_cli/tests/test_push.py,sha256=8o8DFW9HCakhfZMS1Iql13RC90hF9pM630Y-rQbo234,8593
|
16
16
|
vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
18
|
vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -84,7 +84,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
|
|
84
84
|
vellum/client/__init__.py,sha256=7yb5YnhvHQUJusa1WyUZcAKGol3z-Lfu07EfD03eEW4,111291
|
85
85
|
vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
|
86
86
|
vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
|
87
|
-
vellum/client/core/client_wrapper.py,sha256=
|
87
|
+
vellum/client/core/client_wrapper.py,sha256=Ip_JnKYTedcuVV4puh0iLeYLzPtHAxgnmwqZyCKXSCY,1869
|
88
88
|
vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
89
89
|
vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
|
90
90
|
vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
|
@@ -668,7 +668,7 @@ vellum/evaluations/utils/paginator.py,sha256=rEED_BJAXAM6tM1yMwHePNzszjq_tTq4NbQ
|
|
668
668
|
vellum/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
669
669
|
vellum/plugins/pydantic.py,sha256=dNtZWHo-IdseG52C2RoTanxyTJg0AhPZrH-9lbNqwYg,2604
|
670
670
|
vellum/plugins/utils.py,sha256=U9ZY9KdE3RRvbcG01hXxu9CvfJD6Fo7nJDgcHjQn0FI,606
|
671
|
-
vellum/plugins/vellum_mypy.py,sha256=
|
671
|
+
vellum/plugins/vellum_mypy.py,sha256=7JmyuTX723-XWnWoE6afiUNOkHyAufCUZwxck9BP2aI,27784
|
672
672
|
vellum/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
673
673
|
vellum/prompts/blocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
674
674
|
vellum/prompts/blocks/compilation.py,sha256=ISuvDHaeVCPb1L7l4umORCECkDn0-rvE49hopz6c2gM,9222
|
@@ -1221,7 +1221,7 @@ vellum/utils/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
1221
1221
|
vellum/utils/templating/constants.py,sha256=XTNmDsKa7byjw4GMZmzx2dUeYUTeMLZrPgRHcc80Kvc,613
|
1222
1222
|
vellum/utils/templating/custom_filters.py,sha256=Q0DahYRHP4KfaUXDt9XxN-DFLBrAxlv90yaVqxScoUw,264
|
1223
1223
|
vellum/utils/templating/exceptions.py,sha256=cDp140PP4OnInW4qAvg3KqiSiF70C71UyEAKRBR1Abo,46
|
1224
|
-
vellum/utils/templating/render.py,sha256=
|
1224
|
+
vellum/utils/templating/render.py,sha256=OwdZTJlQv_qsygMX3LOFr4d1_2oz3r9vGKyj7cX05VE,1876
|
1225
1225
|
vellum/utils/typing.py,sha256=wx_daFqD69cYkuJTVnvNrpjhqC3uuhbnyJ9_bIwC9OU,327
|
1226
1226
|
vellum/utils/uuid.py,sha256=Ch6wWRgwICxLxJCTl5iE3EdRlZj2zADR-zUMUtjcMWM,214
|
1227
1227
|
vellum/version.py,sha256=jq-1PlAYxN9AXuaZqbYk9ak27SgE2lw9Ia5gx1b1gVI,76
|
@@ -1286,7 +1286,7 @@ vellum/workflows/inputs/base.py,sha256=1kMgr0WqCYdWUqgFvgSoAMw2067FAlgwhGXLgbIOr
|
|
1286
1286
|
vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
|
1287
1287
|
vellum/workflows/nodes/__init__.py,sha256=aVdQVv7Y3Ro3JlqXGpxwaU2zrI06plDHD2aumH5WUIs,1157
|
1288
1288
|
vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
|
1289
|
-
vellum/workflows/nodes/bases/base.py,sha256=
|
1289
|
+
vellum/workflows/nodes/bases/base.py,sha256=CcWQBMR3cx5vftqQp_oJ_GncULJIbOLMyNP4KZNgU10,14487
|
1290
1290
|
vellum/workflows/nodes/bases/base_adornment_node.py,sha256=eFTgsPCYb3eyGS0-kw7C6crFnwFx437R5wh9-8bWYts,2905
|
1291
1291
|
vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1292
1292
|
vellum/workflows/nodes/bases/tests/test_base_node.py,sha256=51CueFVty9XYASC0rKr1cXWejho5WElmhfhp6cCONy0,3811
|
@@ -1302,19 +1302,19 @@ vellum/workflows/nodes/core/map_node/node.py,sha256=DTMoGqtR8MyfZ8jy8apNoN-4KFFF
|
|
1302
1302
|
vellum/workflows/nodes/core/map_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1303
1303
|
vellum/workflows/nodes/core/map_node/tests/test_node.py,sha256=RHSZs7t6mW3UWvRrXnHZqaXVdRT2ZquOK_YHJ-gzXsU,1871
|
1304
1304
|
vellum/workflows/nodes/core/retry_node/__init__.py,sha256=lN2bIy5a3Uzhs_FYCrooADyYU6ZGShtvLKFWpelwPvo,60
|
1305
|
-
vellum/workflows/nodes/core/retry_node/node.py,sha256=
|
1305
|
+
vellum/workflows/nodes/core/retry_node/node.py,sha256=QEpxhKOyxDkRoAn2b0PToZWtAGQetSQYVTpb9yCOLlw,4028
|
1306
1306
|
vellum/workflows/nodes/core/retry_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1307
|
-
vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=
|
1307
|
+
vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=RM_OHwxrHwyxvlQQBJPqVBxpedFuWQ9h2-Xa3kP75sc,4399
|
1308
1308
|
vellum/workflows/nodes/core/templating_node/__init__.py,sha256=GmyuYo81_A1_Bz6id69ozVFS6FKiuDsZTiA3I6MaL2U,70
|
1309
1309
|
vellum/workflows/nodes/core/templating_node/node.py,sha256=N-NOBd-UY91qO9orCcW4KEbhNvDQivZPA-PCxs-M0RM,4204
|
1310
|
-
vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=
|
1310
|
+
vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=3rN5Ncwq87Y2YKyobNXALCih6OnUTJf55otnR4V20C8,3557
|
1311
1311
|
vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWCCc0YCAc7Fzol5ZWIWeM,56
|
1312
1312
|
vellum/workflows/nodes/core/try_node/node.py,sha256=_lTmSYCiz7lktaxpNWUCglNi8_5Sfy8Rpiov5SeKVMw,3920
|
1313
1313
|
vellum/workflows/nodes/core/try_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1314
1314
|
vellum/workflows/nodes/core/try_node/tests/test_node.py,sha256=Wc2kLl-MkffsBxl3IiFaqLd16e2Iosxhk7qBnojPvQg,4092
|
1315
1315
|
vellum/workflows/nodes/displayable/__init__.py,sha256=6F_4DlSwvHuilWnIalp8iDjjDXl0Nmz4QzJV2PYe5RI,1023
|
1316
1316
|
vellum/workflows/nodes/displayable/api_node/__init__.py,sha256=MoxdQSnidIj1Nf_d-hTxlOxcZXaZnsWFDbE-PkTK24o,56
|
1317
|
-
vellum/workflows/nodes/displayable/api_node/node.py,sha256=
|
1317
|
+
vellum/workflows/nodes/displayable/api_node/node.py,sha256=ocXjg0Sp52V6DllTDZXUgOp9qBw6l_KbtWcaxowsDM4,2070
|
1318
1318
|
vellum/workflows/nodes/displayable/bases/__init__.py,sha256=0mWIx3qUrzllV7jqt7wN03vWGMuI1WrrLZeMLT2Cl2c,304
|
1319
1319
|
vellum/workflows/nodes/displayable/bases/api_node/__init__.py,sha256=1jwx4WC358CLA1jgzl_UD-rZmdMm2v9Mps39ndwCD7U,64
|
1320
1320
|
vellum/workflows/nodes/displayable/bases/api_node/node.py,sha256=ywPwCxDesgnE86Wjyf2ZyG2Dr2O7xW8D4tPHZB5Se_s,2477
|
@@ -1415,8 +1415,8 @@ vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528
|
|
1415
1415
|
vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
|
1416
1416
|
vellum/workflows/workflows/base.py,sha256=qdZYQq-jjdr0fYT0FCfmFuI5ypE3pANupgYcOqqML0o,18884
|
1417
1417
|
vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
|
1418
|
-
vellum_ai-0.12.
|
1419
|
-
vellum_ai-0.12.
|
1420
|
-
vellum_ai-0.12.
|
1421
|
-
vellum_ai-0.12.
|
1422
|
-
vellum_ai-0.12.
|
1418
|
+
vellum_ai-0.12.17.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
1419
|
+
vellum_ai-0.12.17.dist-info/METADATA,sha256=01ujt39Or2zqLaKV_VsarQ9H_hkgSc1YfrsEOMokUUk,5328
|
1420
|
+
vellum_ai-0.12.17.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
1421
|
+
vellum_ai-0.12.17.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
|
1422
|
+
vellum_ai-0.12.17.dist-info/RECORD,,
|
vellum_cli/pull.py
CHANGED
@@ -173,10 +173,13 @@ def pull_command(
|
|
173
173
|
target.write(content)
|
174
174
|
|
175
175
|
if metadata_json:
|
176
|
-
|
177
|
-
|
178
|
-
if
|
179
|
-
workflow_config.
|
176
|
+
runner_config = metadata_json.get("runner_config")
|
177
|
+
|
178
|
+
if runner_config:
|
179
|
+
workflow_config.container_image_name = runner_config.get("container_image_name")
|
180
|
+
workflow_config.container_image_tag = runner_config.get("container_image_tag")
|
181
|
+
if workflow_config.container_image_name and not workflow_config.container_image_tag:
|
182
|
+
workflow_config.container_image_tag = "latest"
|
180
183
|
|
181
184
|
if include_json:
|
182
185
|
logger.warning(
|
vellum_cli/tests/conftest.py
CHANGED
@@ -18,11 +18,13 @@ class MockModuleResult:
|
|
18
18
|
|
19
19
|
|
20
20
|
@pytest.fixture
|
21
|
-
def mock_module() -> Generator[MockModuleResult, None, None]:
|
21
|
+
def mock_module(request) -> Generator[MockModuleResult, None, None]:
|
22
22
|
current_dir = os.getcwd()
|
23
23
|
temp_dir = tempfile.mkdtemp()
|
24
24
|
os.chdir(temp_dir)
|
25
|
-
|
25
|
+
|
26
|
+
# Use the test name to create a unique module path
|
27
|
+
module = f"examples.mock.{request.node.name}"
|
26
28
|
workflow_sandbox_id = str(uuid4())
|
27
29
|
|
28
30
|
def set_pyproject_toml(vellum_config: Dict[str, Any]) -> None:
|
vellum_cli/tests/test_push.py
CHANGED
@@ -110,13 +110,17 @@ class ExampleWorkflow(BaseWorkflow):
|
|
110
110
|
# THEN it should succeed
|
111
111
|
assert result.exit_code == 0
|
112
112
|
|
113
|
+
# Get the last part of the module path and format it
|
114
|
+
expected_label = mock_module.module.split(".")[-1].replace("_", " ").title()
|
115
|
+
expected_artifact_name = f"{mock_module.module.replace('.', '__')}.tar.gz"
|
116
|
+
|
113
117
|
# AND we should have called the push API with the correct args
|
114
118
|
vellum_client.workflows.push.assert_called_once()
|
115
119
|
call_args = vellum_client.workflows.push.call_args.kwargs
|
116
120
|
assert json.loads(call_args["exec_config"])["workflow_raw_data"]["definition"]["name"] == "ExampleWorkflow"
|
117
|
-
assert call_args["label"] ==
|
121
|
+
assert call_args["label"] == expected_label
|
118
122
|
assert is_valid_uuid(call_args["workflow_sandbox_id"])
|
119
|
-
assert call_args["artifact"].name ==
|
123
|
+
assert call_args["artifact"].name == expected_artifact_name
|
120
124
|
assert "deplyment_config" not in call_args
|
121
125
|
|
122
126
|
extracted_files = _extract_tar_gz(call_args["artifact"].read())
|
@@ -160,13 +164,17 @@ class ExampleWorkflow(BaseWorkflow):
|
|
160
164
|
# THEN it should succeed
|
161
165
|
assert result.exit_code == 0
|
162
166
|
|
167
|
+
# Get the last part of the module path and format it
|
168
|
+
expected_label = mock_module.module.split(".")[-1].replace("_", " ").title()
|
169
|
+
expected_artifact_name = f"{mock_module.module.replace('.', '__')}.tar.gz"
|
170
|
+
|
163
171
|
# AND we should have called the push API with the correct args
|
164
172
|
vellum_client.workflows.push.assert_called_once()
|
165
173
|
call_args = vellum_client.workflows.push.call_args.kwargs
|
166
174
|
assert json.loads(call_args["exec_config"])["workflow_raw_data"]["definition"]["name"] == "ExampleWorkflow"
|
167
|
-
assert call_args["label"] ==
|
175
|
+
assert call_args["label"] == expected_label
|
168
176
|
assert is_valid_uuid(call_args["workflow_sandbox_id"])
|
169
|
-
assert call_args["artifact"].name ==
|
177
|
+
assert call_args["artifact"].name == expected_artifact_name
|
170
178
|
assert call_args["deployment_config"] == "{}"
|
171
179
|
|
172
180
|
extracted_files = _extract_tar_gz(call_args["artifact"].read())
|
@@ -231,6 +239,6 @@ class ExampleWorkflow(BaseWorkflow):
|
|
231
239
|
|
232
240
|
# AND the report should be in the output
|
233
241
|
assert "## Errors" in result.output
|
234
|
-
|
242
|
+
assert "Serialization is not supported." in result.output
|
235
243
|
assert "## Proposed Diffs" in result.output
|
236
244
|
assert "iterable_item_added" in result.output
|
File without changes
|
File without changes
|
File without changes
|