vellum-ai 0.14.52__py3-none-any.whl → 0.14.54__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/__init__.py +12 -24
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/resources/workflows/client.py +2 -1
- vellum/workflows/nodes/bases/base.py +32 -1
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py +4 -1
- vellum/workflows/runner/runner.py +1 -1
- vellum/workflows/state/base.py +0 -18
- {vellum_ai-0.14.52.dist-info → vellum_ai-0.14.54.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.52.dist-info → vellum_ai-0.14.54.dist-info}/RECORD +17 -17
- vellum_cli/logger.py +12 -0
- vellum_cli/push.py +36 -32
- vellum_cli/tests/test_push.py +31 -0
- vellum_ee/workflows/display/workflows/base_workflow_display.py +20 -4
- vellum_ee/workflows/tests/test_display_meta.py +48 -0
- {vellum_ai-0.14.52.dist-info → vellum_ai-0.14.54.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.52.dist-info → vellum_ai-0.14.54.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.52.dist-info → vellum_ai-0.14.54.dist-info}/entry_points.txt +0 -0
vellum/client/__init__.py
CHANGED
@@ -133,15 +133,11 @@ class Vellum:
|
|
133
133
|
self._client_wrapper = SyncClientWrapper(
|
134
134
|
environment=environment,
|
135
135
|
api_key=api_key,
|
136
|
-
httpx_client=
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
if follow_redirects is not None
|
142
|
-
else httpx.Client(timeout=_defaulted_timeout)
|
143
|
-
)
|
144
|
-
),
|
136
|
+
httpx_client=httpx_client
|
137
|
+
if httpx_client is not None
|
138
|
+
else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
|
139
|
+
if follow_redirects is not None
|
140
|
+
else httpx.Client(timeout=_defaulted_timeout),
|
145
141
|
timeout=_defaulted_timeout,
|
146
142
|
)
|
147
143
|
self.ad_hoc = AdHocClient(client_wrapper=self._client_wrapper)
|
@@ -1446,9 +1442,7 @@ class Vellum:
|
|
1446
1442
|
method="POST",
|
1447
1443
|
json={
|
1448
1444
|
"actuals": convert_and_respect_annotation_metadata(
|
1449
|
-
object_=actuals,
|
1450
|
-
annotation=typing.Sequence[SubmitWorkflowExecutionActualRequest],
|
1451
|
-
direction="write",
|
1445
|
+
object_=actuals, annotation=typing.Sequence[SubmitWorkflowExecutionActualRequest], direction="write"
|
1452
1446
|
),
|
1453
1447
|
"execution_id": execution_id,
|
1454
1448
|
"external_id": external_id,
|
@@ -1515,15 +1509,11 @@ class AsyncVellum:
|
|
1515
1509
|
self._client_wrapper = AsyncClientWrapper(
|
1516
1510
|
environment=environment,
|
1517
1511
|
api_key=api_key,
|
1518
|
-
httpx_client=
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
if follow_redirects is not None
|
1524
|
-
else httpx.AsyncClient(timeout=_defaulted_timeout)
|
1525
|
-
)
|
1526
|
-
),
|
1512
|
+
httpx_client=httpx_client
|
1513
|
+
if httpx_client is not None
|
1514
|
+
else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
|
1515
|
+
if follow_redirects is not None
|
1516
|
+
else httpx.AsyncClient(timeout=_defaulted_timeout),
|
1527
1517
|
timeout=_defaulted_timeout,
|
1528
1518
|
)
|
1529
1519
|
self.ad_hoc = AsyncAdHocClient(client_wrapper=self._client_wrapper)
|
@@ -2916,9 +2906,7 @@ class AsyncVellum:
|
|
2916
2906
|
method="POST",
|
2917
2907
|
json={
|
2918
2908
|
"actuals": convert_and_respect_annotation_metadata(
|
2919
|
-
object_=actuals,
|
2920
|
-
annotation=typing.Sequence[SubmitWorkflowExecutionActualRequest],
|
2921
|
-
direction="write",
|
2909
|
+
object_=actuals, annotation=typing.Sequence[SubmitWorkflowExecutionActualRequest], direction="write"
|
2922
2910
|
),
|
2923
2911
|
"execution_id": execution_id,
|
2924
2912
|
"external_id": external_id,
|
@@ -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.
|
21
|
+
"X-Fern-SDK-Version": "0.14.54",
|
22
22
|
}
|
23
23
|
headers["X-API-KEY"] = self.api_key
|
24
24
|
return headers
|
@@ -69,7 +69,8 @@ class WorkflowsClient:
|
|
69
69
|
try:
|
70
70
|
if 200 <= _response.status_code < 300:
|
71
71
|
_chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
|
72
|
-
|
72
|
+
for _chunk in _response.iter_bytes(chunk_size=_chunk_size):
|
73
|
+
yield _chunk
|
73
74
|
return
|
74
75
|
_response.read()
|
75
76
|
if _response.status_code == 400:
|
@@ -2,12 +2,13 @@ from dataclasses import field
|
|
2
2
|
from functools import cached_property, reduce
|
3
3
|
import inspect
|
4
4
|
from types import MappingProxyType
|
5
|
-
from uuid import UUID
|
5
|
+
from uuid import UUID, uuid4
|
6
6
|
from typing import Any, Dict, Generic, Iterator, Optional, Set, Tuple, Type, TypeVar, Union, cast, get_args
|
7
7
|
|
8
8
|
from vellum.workflows.constants import undefined
|
9
9
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
10
10
|
from vellum.workflows.descriptors.utils import is_unresolved, resolve_value
|
11
|
+
from vellum.workflows.edges.edge import Edge
|
11
12
|
from vellum.workflows.errors.types import WorkflowErrorCode
|
12
13
|
from vellum.workflows.exceptions import NodeException
|
13
14
|
from vellum.workflows.graph import Graph
|
@@ -325,6 +326,36 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
|
|
325
326
|
code=WorkflowErrorCode.INVALID_INPUTS,
|
326
327
|
)
|
327
328
|
|
329
|
+
@classmethod
|
330
|
+
def _queue_node_execution(
|
331
|
+
cls, state: StateType, dependencies: Set["Type[BaseNode]"], invoked_by: Optional[Edge] = None
|
332
|
+
) -> UUID:
|
333
|
+
"""
|
334
|
+
Queues a future execution of a node, returning the span id of the execution.
|
335
|
+
|
336
|
+
We may combine this into the should_initiate method, but we'll keep it separate for now to avoid
|
337
|
+
breaking changes until the 0.15.0 release.
|
338
|
+
"""
|
339
|
+
|
340
|
+
execution_id = uuid4()
|
341
|
+
if not invoked_by:
|
342
|
+
return execution_id
|
343
|
+
|
344
|
+
if cls.merge_behavior not in {MergeBehavior.AWAIT_ANY, MergeBehavior.AWAIT_ALL}:
|
345
|
+
return execution_id
|
346
|
+
|
347
|
+
source_node = invoked_by.from_port.node_class
|
348
|
+
for queued_node_execution_id in state.meta.node_execution_cache._node_executions_queued[cls.node_class]:
|
349
|
+
if source_node not in state.meta.node_execution_cache._dependencies_invoked[queued_node_execution_id]:
|
350
|
+
state.meta.node_execution_cache._invoke_dependency(
|
351
|
+
queued_node_execution_id, cls.node_class, source_node, dependencies
|
352
|
+
)
|
353
|
+
return queued_node_execution_id
|
354
|
+
|
355
|
+
state.meta.node_execution_cache._node_executions_queued[cls.node_class].append(execution_id)
|
356
|
+
state.meta.node_execution_cache._invoke_dependency(execution_id, cls.node_class, source_node, dependencies)
|
357
|
+
return execution_id
|
358
|
+
|
328
359
|
class Execution(metaclass=_BaseNodeExecutionMeta):
|
329
360
|
node_class: Type["BaseNode"]
|
330
361
|
count: int
|
@@ -11,7 +11,7 @@ from vellum.workflows.nodes.displayable.inline_prompt_node.node import InlinePro
|
|
11
11
|
from vellum.workflows.outputs.base import BaseOutput
|
12
12
|
from vellum.workflows.ports.port import Port
|
13
13
|
from vellum.workflows.references.lazy import LazyReference
|
14
|
-
from vellum.workflows.types.core import EntityInputsInterface
|
14
|
+
from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior
|
15
15
|
|
16
16
|
|
17
17
|
class FunctionNode(BaseNode):
|
@@ -21,6 +21,9 @@ class FunctionNode(BaseNode):
|
|
21
21
|
|
22
22
|
|
23
23
|
class ToolRouterNode(InlinePromptNode):
|
24
|
+
class Trigger(InlinePromptNode.Trigger):
|
25
|
+
merge_behavior = MergeBehavior.AWAIT_ATTRIBUTES
|
26
|
+
|
24
27
|
def run(self) -> Iterator[BaseOutput]:
|
25
28
|
self.prompt_inputs = {**self.prompt_inputs, "chat_history": self.state.chat_history} # type: ignore
|
26
29
|
generator = super().run()
|
@@ -431,7 +431,7 @@ class WorkflowRunner(Generic[StateType]):
|
|
431
431
|
return
|
432
432
|
|
433
433
|
all_deps = self._dependencies[node_class]
|
434
|
-
node_span_id =
|
434
|
+
node_span_id = node_class.Trigger._queue_node_execution(state, all_deps, invoked_by)
|
435
435
|
if not node_class.Trigger.should_initiate(state, all_deps, node_span_id):
|
436
436
|
return
|
437
437
|
|
vellum/workflows/state/base.py
CHANGED
@@ -16,7 +16,6 @@ from pydantic_core import core_schema
|
|
16
16
|
from vellum.core.pydantic_utilities import UniversalBaseModel
|
17
17
|
from vellum.utils.uuid import is_valid_uuid
|
18
18
|
from vellum.workflows.constants import undefined
|
19
|
-
from vellum.workflows.edges.edge import Edge
|
20
19
|
from vellum.workflows.inputs.base import BaseInputs
|
21
20
|
from vellum.workflows.references import ExternalInputReference, OutputReference, StateValueReference
|
22
21
|
from vellum.workflows.types.definition import CodeResourceDefinition, serialize_type_encoder_with_id
|
@@ -174,23 +173,6 @@ class NodeExecutionCache:
|
|
174
173
|
if all(dep in self._dependencies_invoked[execution_id] for dep in dependencies):
|
175
174
|
self._node_executions_queued[node].remove(execution_id)
|
176
175
|
|
177
|
-
def queue_node_execution(
|
178
|
-
self, node: Type["BaseNode"], dependencies: Set["Type[BaseNode]"], invoked_by: Optional[Edge] = None
|
179
|
-
) -> UUID:
|
180
|
-
execution_id = uuid4()
|
181
|
-
if not invoked_by:
|
182
|
-
return execution_id
|
183
|
-
|
184
|
-
source_node = invoked_by.from_port.node_class
|
185
|
-
for queued_node_execution_id in self._node_executions_queued[node]:
|
186
|
-
if source_node not in self._dependencies_invoked[queued_node_execution_id]:
|
187
|
-
self._invoke_dependency(queued_node_execution_id, node, source_node, dependencies)
|
188
|
-
return queued_node_execution_id
|
189
|
-
|
190
|
-
self._node_executions_queued[node].append(execution_id)
|
191
|
-
self._invoke_dependency(execution_id, node, source_node, dependencies)
|
192
|
-
return execution_id
|
193
|
-
|
194
176
|
def is_node_execution_initiated(self, node: Type["BaseNode"], execution_id: UUID) -> bool:
|
195
177
|
return execution_id in self._node_executions_initiated[node]
|
196
178
|
|
@@ -5,10 +5,10 @@ vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3
|
|
5
5
|
vellum_cli/config.py,sha256=v5BmZ-t_v4Jmqd7KVuQMZF2pRI-rbMspSkVYXIRoTmI,9448
|
6
6
|
vellum_cli/image_push.py,sha256=skFXf25ixMOX1yfcyAtii-RivYYv-_hsv-Z-bVB6m5Q,7380
|
7
7
|
vellum_cli/init.py,sha256=WpnMXPItPmh0f0bBGIer3p-e5gu8DUGwSArT_FuoMEw,5093
|
8
|
-
vellum_cli/logger.py,sha256=
|
8
|
+
vellum_cli/logger.py,sha256=p0OGmF6URHVpiIRjxtYiHIVlzxfwPjBqn8MW0C5FgsU,1486
|
9
9
|
vellum_cli/ping.py,sha256=p_BCCRjgPhng6JktuECtkDQLbhopt6JpmrtGoLnLJT8,1161
|
10
10
|
vellum_cli/pull.py,sha256=M50yXzA_35N35gk1Y8KjLbXrzdRG86--XFQvEukxGtA,13371
|
11
|
-
vellum_cli/push.py,sha256=
|
11
|
+
vellum_cli/push.py,sha256=wxRlFu2mYW9SvwODYxwajri1mDQ2be0n-9i0d9QAc30,10194
|
12
12
|
vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
vellum_cli/tests/conftest.py,sha256=AFYZryKA2qnUuCPBxBKmHLFoPiE0WhBFFej9tNwSHdc,1526
|
14
14
|
vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
|
@@ -17,7 +17,7 @@ vellum_cli/tests/test_init.py,sha256=8UOc_ThfouR4ja5cCl_URuLk7ohr9JXfCnG4yka1OUQ
|
|
17
17
|
vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
|
18
18
|
vellum_cli/tests/test_ping.py,sha256=3ucVRThEmTadlV9LrJdCCrr1Ofj3rOjG6ue0BNR2UC0,2523
|
19
19
|
vellum_cli/tests/test_pull.py,sha256=7HRAhIdkVW5mR2VckEaNDjp4rt-MlIxOWMMI2XNUPE8,49814
|
20
|
-
vellum_cli/tests/test_push.py,sha256=
|
20
|
+
vellum_cli/tests/test_push.py,sha256=I8XICg3pUb3yxAFLXziVHHf5CRm354LO-uUfwtca3bU,33897
|
21
21
|
vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
23
|
vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -100,7 +100,7 @@ vellum_ee/workflows/display/utils/registry.py,sha256=fWIm5Jj-10gNFjgn34iBu4RWv3V
|
|
100
100
|
vellum_ee/workflows/display/utils/vellum.py,sha256=mtoXmSYwR7rvrq-d6CzCW_auaJXTct0Mi1F0xpRCiNQ,5627
|
101
101
|
vellum_ee/workflows/display/vellum.py,sha256=o7mq_vk2Yapu9DDKRz5l76h8EmCAypWGQYe6pryrbB8,3576
|
102
102
|
vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
|
103
|
-
vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=
|
103
|
+
vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=dVOe3TOV00uvllxsDziM3pFfL2HYTkWRq9iKDlj_xyU,33162
|
104
104
|
vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=gxz76AeCqgAZ9D2lZeTiZzxY9eMgn3qOSfVgiqYcOh8,2028
|
105
105
|
vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=rRwXLgsXqiaSn3jzP7lc--pytRW3Jmnj2-zNq5l-FQ4,29472
|
106
106
|
vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=aaKdmWrgEe5YyV4zuDY_4E3y-l59rIHQnNGiPj2OWxQ,359
|
@@ -125,15 +125,15 @@ vellum_ee/workflows/tests/local_workflow/nodes/__init__.py,sha256=1F6jxUpSKfPXPj
|
|
125
125
|
vellum_ee/workflows/tests/local_workflow/nodes/final_output.py,sha256=ZX7zBv87zirg0w9VKUW3QVDSdBLDqcqAMZjCL_oWbpU,297
|
126
126
|
vellum_ee/workflows/tests/local_workflow/nodes/templating_node.py,sha256=NQwFN61QkHfI3Vssz-B0NKGfupK8PU0FDSAIAhYBLi0,325
|
127
127
|
vellum_ee/workflows/tests/local_workflow/workflow.py,sha256=A4qOzOPNwePYxWbcAgIPLsmrVS_aVEZEc-wULSv787Q,393
|
128
|
-
vellum_ee/workflows/tests/test_display_meta.py,sha256=
|
128
|
+
vellum_ee/workflows/tests/test_display_meta.py,sha256=DIzjNbwK1-4mlttPML6NskQ4rPVMXhj5zeOmBEyPqKI,3728
|
129
129
|
vellum_ee/workflows/tests/test_server.py,sha256=SsOkS6sGO7uGC4mxvk4iv8AtcXs058P9hgFHzTWmpII,14519
|
130
130
|
vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
|
131
131
|
vellum/__init__.py,sha256=Hqfl49WZJzzqOKzVsTGi-j9twIqFOoRmACJsrEsjL44,41918
|
132
132
|
vellum/client/README.md,sha256=qmaVIP42MnxAu8jV7u-CsgVFfs3-pHQODrXdZdFxtaw,4749
|
133
|
-
vellum/client/__init__.py,sha256=
|
133
|
+
vellum/client/__init__.py,sha256=PEnFl7LbXQcvAi3bVN2qyt5xm2FtVtq7xWKkcWM3Tg4,120166
|
134
134
|
vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
|
135
135
|
vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
|
136
|
-
vellum/client/core/client_wrapper.py,sha256=
|
136
|
+
vellum/client/core/client_wrapper.py,sha256=kZK3hw4JmWRWNhWYDC2kTCPv6kwNoNAA0GRUJt89dT8,1869
|
137
137
|
vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
138
138
|
vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
|
139
139
|
vellum/client/core/http_client.py,sha256=Z77OIxIbL4OAB2IDqjRq_sYa5yNYAWfmdhdCSSvh6Y4,19552
|
@@ -196,7 +196,7 @@ vellum/client/resources/workflow_sandboxes/client.py,sha256=XfMcbvSTF1_iTGIXsk1F
|
|
196
196
|
vellum/client/resources/workflow_sandboxes/types/__init__.py,sha256=EaGVRU1w6kJiiHrbZOeEa0c3ggjfgv_jBqsyOkCRWOI,212
|
197
197
|
vellum/client/resources/workflow_sandboxes/types/list_workflow_sandbox_examples_request_tag.py,sha256=TEwWit20W3X-zWPPLAhmUG05UudG9gaBSJ4Q4-rNJws,188
|
198
198
|
vellum/client/resources/workflows/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
199
|
-
vellum/client/resources/workflows/client.py,sha256=
|
199
|
+
vellum/client/resources/workflows/client.py,sha256=uDC61aybVmgxPiLKuLpAB-fK3sagnFFX06zzmQngInA,11285
|
200
200
|
vellum/client/resources/workspace_secrets/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
201
201
|
vellum/client/resources/workspace_secrets/client.py,sha256=zlBdbeTP6sqvtyl_DlrpfG-W5hSP7tJ1NYLSygi4CLU,8205
|
202
202
|
vellum/client/resources/workspaces/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
@@ -1543,7 +1543,7 @@ vellum/workflows/inputs/tests/test_inputs.py,sha256=lioA8917mFLYq7Ml69UNkqUjcWbb
|
|
1543
1543
|
vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
|
1544
1544
|
vellum/workflows/nodes/__init__.py,sha256=aVdQVv7Y3Ro3JlqXGpxwaU2zrI06plDHD2aumH5WUIs,1157
|
1545
1545
|
vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
|
1546
|
-
vellum/workflows/nodes/bases/base.py,sha256=
|
1546
|
+
vellum/workflows/nodes/bases/base.py,sha256=3yWWY6ZYpUIMzGyKeu_7xs8qC58uef0ly6EVUbWIAQ0,17170
|
1547
1547
|
vellum/workflows/nodes/bases/base_adornment_node.py,sha256=Ao2opOW4kgNoYXFF9Pk7IMpVZdy6luwrjcqEwU5Q9V0,3404
|
1548
1548
|
vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1549
1549
|
vellum/workflows/nodes/bases/tests/test_base_adornment_node.py,sha256=fXZI9KqpS4XMBrBnIEkK3foHaBVvyHwYcQWWDKay7ic,1148
|
@@ -1641,7 +1641,7 @@ vellum/workflows/nodes/experimental/openai_chat_completion_node/node.py,sha256=c
|
|
1641
1641
|
vellum/workflows/nodes/experimental/tool_calling_node/__init__.py,sha256=S7OzT3I4cyOU5Beoz87nPwCejCMP2FsHBFL8OcVmxJ4,118
|
1642
1642
|
vellum/workflows/nodes/experimental/tool_calling_node/node.py,sha256=NUC7VZj2D86IDQzjCq_a3-Xeqj_b3BE8T1kOMIfN7V8,4878
|
1643
1643
|
vellum/workflows/nodes/experimental/tool_calling_node/tests/test_tool_calling_node.py,sha256=sxG26mOwt4N36RLoPJ-ngginPqC5qFzD_kGj9izdCFI,1833
|
1644
|
-
vellum/workflows/nodes/experimental/tool_calling_node/utils.py,sha256=
|
1644
|
+
vellum/workflows/nodes/experimental/tool_calling_node/utils.py,sha256=mIQpAxLT2IF4SNQvUpRsX-t0jODxQ3Xvb_LEF7bRMF8,5214
|
1645
1645
|
vellum/workflows/nodes/mocks.py,sha256=a1FjWEIocseMfjzM-i8DNozpUsaW0IONRpZmXBoWlyc,10455
|
1646
1646
|
vellum/workflows/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1647
1647
|
vellum/workflows/nodes/tests/test_mocks.py,sha256=mfPvrs75PKcsNsbJLQAN6PDFoVqs9TmQxpdyFKDdO60,7837
|
@@ -1669,10 +1669,10 @@ vellum/workflows/references/workflow_input.py,sha256=W3rOK1EPd2gYHb04WJwmNm1CUSd
|
|
1669
1669
|
vellum/workflows/resolvers/__init__.py,sha256=eH6hTvZO4IciDaf_cf7aM2vs-DkBDyJPycOQevJxQnI,82
|
1670
1670
|
vellum/workflows/resolvers/base.py,sha256=WHra9LRtlTuB1jmuNqkfVE2JUgB61Cyntn8f0b0WZg4,411
|
1671
1671
|
vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8vyT-bqM,72
|
1672
|
-
vellum/workflows/runner/runner.py,sha256=
|
1672
|
+
vellum/workflows/runner/runner.py,sha256=0Ufxyl3nwWVI--w_iVTAVXUOKJXuZiEn6-BrrUAGVBs,32983
|
1673
1673
|
vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
|
1674
1674
|
vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
|
1675
|
-
vellum/workflows/state/base.py,sha256
|
1675
|
+
vellum/workflows/state/base.py,sha256=-0b-nNBEXvGVau4c1BUwmCsXfo5wZD5VjLb8-eqi0Y8,21502
|
1676
1676
|
vellum/workflows/state/context.py,sha256=KOAI1wEGn8dGmhmAemJaf4SZbitP3jpIBcwKfznQaRE,3076
|
1677
1677
|
vellum/workflows/state/encoder.py,sha256=z7Mk6jQC-92wCj6XTK7VEnJ8px_lU8qy0BINqwGDN4I,2063
|
1678
1678
|
vellum/workflows/state/store.py,sha256=uVe-oN73KwGV6M6YLhwZMMUQhzTQomsVfVnb8V91gVo,1147
|
@@ -1707,8 +1707,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
|
|
1707
1707
|
vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1708
1708
|
vellum/workflows/workflows/tests/test_base_workflow.py,sha256=8P5YIsNMO78_CR1NNK6wkEdkMB4b3Q_Ni1qxh78OnHo,20481
|
1709
1709
|
vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
|
1710
|
-
vellum_ai-0.14.
|
1711
|
-
vellum_ai-0.14.
|
1712
|
-
vellum_ai-0.14.
|
1713
|
-
vellum_ai-0.14.
|
1714
|
-
vellum_ai-0.14.
|
1710
|
+
vellum_ai-0.14.54.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
1711
|
+
vellum_ai-0.14.54.dist-info/METADATA,sha256=uwF0Sw7FcZnvFQcsUZvPH5POXx6DlpH16vKfUlk4DdQ,5484
|
1712
|
+
vellum_ai-0.14.54.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
1713
|
+
vellum_ai-0.14.54.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
|
1714
|
+
vellum_ai-0.14.54.dist-info/RECORD,,
|
vellum_cli/logger.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import os
|
3
|
+
from typing import Optional
|
3
4
|
|
4
5
|
|
5
6
|
class CLIFormatter(logging.Formatter):
|
@@ -34,3 +35,14 @@ def load_cli_logger() -> logging.Logger:
|
|
34
35
|
logger.addHandler(handler)
|
35
36
|
|
36
37
|
return logger
|
38
|
+
|
39
|
+
|
40
|
+
def handle_cli_error(logger: logging.Logger, title: str, message: str, suggestion: Optional[str] = None):
|
41
|
+
logger.error("\n\033[1;31m✖ {}\033[0m".format(title)) # Bold red X and title
|
42
|
+
logger.error("\n\033[1m{}\033[0m".format(message)) # Bold message
|
43
|
+
if suggestion:
|
44
|
+
logger.error("\n\033[1;34mNext steps:\033[0m") # Bold blue
|
45
|
+
logger.error(suggestion)
|
46
|
+
|
47
|
+
logger.error(f"{title}: {message}")
|
48
|
+
exit(1)
|
vellum_cli/push.py
CHANGED
@@ -15,7 +15,7 @@ from vellum.types import WorkflowPushDeploymentConfigRequest
|
|
15
15
|
from vellum.workflows.vellum_client import create_vellum_client
|
16
16
|
from vellum.workflows.workflows.base import BaseWorkflow
|
17
17
|
from vellum_cli.config import DEFAULT_WORKSPACE_CONFIG, WorkflowConfig, WorkflowDeploymentConfig, load_vellum_cli_config
|
18
|
-
from vellum_cli.logger import load_cli_logger
|
18
|
+
from vellum_cli.logger import handle_cli_error, load_cli_logger
|
19
19
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
20
20
|
|
21
21
|
|
@@ -178,41 +178,39 @@ def push_command(
|
|
178
178
|
strict=strict,
|
179
179
|
)
|
180
180
|
except ApiError as e:
|
181
|
-
if e.status_code
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
181
|
+
if e.status_code == 400 and isinstance(e.body, dict) and "diffs" in e.body:
|
182
|
+
diffs: dict = e.body["diffs"]
|
183
|
+
generated_only = diffs.get("generated_only", [])
|
184
|
+
generated_only_str = (
|
185
|
+
"\n".join(
|
186
|
+
["Files that were generated but not found in the original project:"]
|
187
|
+
+ [f"- {file}" for file in generated_only]
|
188
|
+
)
|
189
|
+
if generated_only
|
190
|
+
else ""
|
190
191
|
)
|
191
|
-
if generated_only
|
192
|
-
else ""
|
193
|
-
)
|
194
192
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
193
|
+
original_only = diffs.get("original_only", [])
|
194
|
+
original_only_str = (
|
195
|
+
"\n".join(
|
196
|
+
["Files that were found in the original project but not generated:"]
|
197
|
+
+ [f"- {file}" for file in original_only]
|
198
|
+
)
|
199
|
+
if original_only
|
200
|
+
else ""
|
200
201
|
)
|
201
|
-
if original_only
|
202
|
-
else ""
|
203
|
-
)
|
204
202
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
203
|
+
modified = diffs.get("modified", {})
|
204
|
+
modified_str = (
|
205
|
+
"\n\n".join(
|
206
|
+
["Files that were different between the original project and the generated artifact:"]
|
207
|
+
+ ["\n".join(line.strip() for line in lines) for lines in modified.values()]
|
208
|
+
)
|
209
|
+
if modified
|
210
|
+
else ""
|
210
211
|
)
|
211
|
-
if modified
|
212
|
-
else ""
|
213
|
-
)
|
214
212
|
|
215
|
-
|
213
|
+
reported_diffs = f"""\
|
216
214
|
{e.body.get("detail")}
|
217
215
|
|
218
216
|
{generated_only_str}
|
@@ -221,8 +219,14 @@ def push_command(
|
|
221
219
|
|
222
220
|
{modified_str}
|
223
221
|
"""
|
224
|
-
|
225
|
-
|
222
|
+
logger.error(reported_diffs)
|
223
|
+
return
|
224
|
+
|
225
|
+
if e.status_code == 400 and isinstance(e.body, dict) and "detail" in e.body:
|
226
|
+
handle_cli_error(logger, title="API request to /workflows/push failed.", message=e.body["detail"])
|
227
|
+
return
|
228
|
+
|
229
|
+
raise e
|
226
230
|
|
227
231
|
if dry_run:
|
228
232
|
error_messages = [str(e) for e in workflow_display.errors]
|
vellum_cli/tests/test_push.py
CHANGED
@@ -525,6 +525,37 @@ Files that were different between the original project and the generated artifac
|
|
525
525
|
)
|
526
526
|
|
527
527
|
|
528
|
+
def test_push__push_fails_due_to_400_error(mock_module, vellum_client):
|
529
|
+
# GIVEN a single workflow configured
|
530
|
+
temp_dir = mock_module.temp_dir
|
531
|
+
module = mock_module.module
|
532
|
+
|
533
|
+
# AND a workflow exists in the module successfully
|
534
|
+
_ensure_workflow_py(temp_dir, module)
|
535
|
+
|
536
|
+
# AND the push API call returns a 4xx response
|
537
|
+
vellum_client.workflows.push.side_effect = ApiError(
|
538
|
+
status_code=400,
|
539
|
+
body={
|
540
|
+
"detail": "Pushing the Workflow failed because you did something wrong",
|
541
|
+
},
|
542
|
+
)
|
543
|
+
|
544
|
+
# WHEN calling `vellum push` on strict mode
|
545
|
+
runner = CliRunner()
|
546
|
+
result = runner.invoke(cli_main, ["push", module])
|
547
|
+
|
548
|
+
# THEN it should fail with a user error code
|
549
|
+
assert result.exit_code == 1
|
550
|
+
|
551
|
+
# AND the error message should be in the error message
|
552
|
+
assert "API request to /workflows/push failed." in result.output
|
553
|
+
assert "Pushing the Workflow failed because you did something wrong" in result.output
|
554
|
+
|
555
|
+
# AND the stack trace should not be
|
556
|
+
assert "Traceback" not in result.output
|
557
|
+
|
558
|
+
|
528
559
|
@pytest.mark.parametrize(
|
529
560
|
"file_data",
|
530
561
|
[
|
@@ -583,14 +583,30 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
583
583
|
# DEPRECATED: This will be removed in the 0.15.0 release
|
584
584
|
workflow_class: Optional[Type[BaseWorkflow]] = None,
|
585
585
|
) -> Union[WorkflowEventDisplayContext, None]:
|
586
|
-
|
586
|
+
full_workflow_display_module_path = f"{module_path}.display.workflow"
|
587
587
|
try:
|
588
|
-
|
588
|
+
display_module = importlib.import_module(full_workflow_display_module_path)
|
589
589
|
except ModuleNotFoundError:
|
590
|
+
logger.exception("Failed to import workflow display module: %s", full_workflow_display_module_path)
|
590
591
|
return None
|
591
592
|
|
592
|
-
WorkflowDisplayClass =
|
593
|
-
|
593
|
+
WorkflowDisplayClass: Optional[Type[BaseWorkflowDisplay]] = None
|
594
|
+
for name, definition in display_module.__dict__.items():
|
595
|
+
if name.startswith("_"):
|
596
|
+
continue
|
597
|
+
|
598
|
+
if (
|
599
|
+
not isinstance(definition, type)
|
600
|
+
or not issubclass(definition, BaseWorkflowDisplay)
|
601
|
+
or definition == BaseWorkflowDisplay
|
602
|
+
):
|
603
|
+
continue
|
604
|
+
|
605
|
+
WorkflowDisplayClass = definition
|
606
|
+
break
|
607
|
+
|
608
|
+
if not WorkflowDisplayClass:
|
609
|
+
logger.exception("No workflow display class found in module: %s", full_workflow_display_module_path)
|
594
610
|
return None
|
595
611
|
|
596
612
|
return WorkflowDisplayClass().get_event_display_context()
|
@@ -54,3 +54,51 @@ def test_base_class_dynamic_import(files):
|
|
54
54
|
}
|
55
55
|
assert display_meta
|
56
56
|
assert display_meta.model_dump(mode="json") == expected_result
|
57
|
+
|
58
|
+
|
59
|
+
def test_gather_event_display_context__custom_workflow_name():
|
60
|
+
# GIVEN a workflow module with a custom workflow name
|
61
|
+
workflow_output_id = uuid4()
|
62
|
+
files = {
|
63
|
+
"__init__.py": "",
|
64
|
+
"workflow.py": """\
|
65
|
+
from vellum.workflows import BaseWorkflow
|
66
|
+
|
67
|
+
class MyCustomWorkflow(BaseWorkflow):
|
68
|
+
class Outputs(BaseWorkflow.Outputs):
|
69
|
+
answer = "foo"
|
70
|
+
""",
|
71
|
+
"display/__init__.py": """\
|
72
|
+
# flake8: noqa: F401, F403
|
73
|
+
|
74
|
+
from .workflow import *
|
75
|
+
""",
|
76
|
+
"display/workflow.py": f"""\
|
77
|
+
from uuid import UUID
|
78
|
+
from vellum_ee.workflows.display.workflows import BaseWorkflowDisplay
|
79
|
+
from vellum_ee.workflows.display.base import WorkflowOutputDisplay
|
80
|
+
from ..workflow import MyCustomWorkflow
|
81
|
+
|
82
|
+
class MyCustomWorkflowDisplay(BaseWorkflowDisplay[MyCustomWorkflow]):
|
83
|
+
output_displays = {{
|
84
|
+
MyCustomWorkflow.Outputs.answer: WorkflowOutputDisplay(
|
85
|
+
id=UUID("{workflow_output_id}"), name="answer"
|
86
|
+
)
|
87
|
+
}}
|
88
|
+
""",
|
89
|
+
}
|
90
|
+
|
91
|
+
namespace = str(uuid4())
|
92
|
+
|
93
|
+
# AND the virtual file loader is registered
|
94
|
+
sys.meta_path.append(VirtualFileFinder(files, namespace))
|
95
|
+
|
96
|
+
# WHEN the workflow display context is gathered
|
97
|
+
Workflow = BaseWorkflow.load_from_module(namespace)
|
98
|
+
display_meta = BaseWorkflowDisplay.gather_event_display_context(namespace, Workflow)
|
99
|
+
|
100
|
+
# THEN the workflow display context is successfully gathered
|
101
|
+
assert display_meta
|
102
|
+
assert display_meta.workflow_outputs == {
|
103
|
+
"answer": workflow_output_id,
|
104
|
+
}
|
File without changes
|
File without changes
|
File without changes
|