vellum-ai 1.2.0__py3-none-any.whl → 1.2.2__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/__init__.py +18 -1
- vellum/client/__init__.py +3 -0
- vellum/client/core/client_wrapper.py +2 -2
- vellum/client/errors/__init__.py +10 -1
- vellum/client/errors/too_many_requests_error.py +11 -0
- vellum/client/errors/unauthorized_error.py +11 -0
- vellum/client/reference.md +94 -0
- vellum/client/resources/__init__.py +2 -0
- vellum/client/resources/events/__init__.py +4 -0
- vellum/client/resources/events/client.py +165 -0
- vellum/client/resources/events/raw_client.py +207 -0
- vellum/client/types/__init__.py +6 -0
- vellum/client/types/error_detail_response.py +22 -0
- vellum/client/types/event_create_response.py +26 -0
- vellum/client/types/execution_thinking_vellum_value.py +1 -1
- vellum/client/types/thinking_vellum_value.py +1 -1
- vellum/client/types/thinking_vellum_value_request.py +1 -1
- vellum/client/types/workflow_event.py +33 -0
- vellum/errors/too_many_requests_error.py +3 -0
- vellum/errors/unauthorized_error.py +3 -0
- vellum/prompts/blocks/compilation.py +13 -11
- vellum/resources/events/__init__.py +3 -0
- vellum/resources/events/client.py +3 -0
- vellum/resources/events/raw_client.py +3 -0
- vellum/types/error_detail_response.py +3 -0
- vellum/types/event_create_response.py +3 -0
- vellum/types/workflow_event.py +3 -0
- vellum/workflows/emitters/vellum_emitter.py +16 -69
- vellum/workflows/events/tests/test_event.py +1 -0
- vellum/workflows/events/workflow.py +3 -0
- vellum/workflows/nodes/bases/base.py +0 -1
- vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py +35 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +4 -0
- vellum/workflows/nodes/displayable/bases/api_node/tests/test_node.py +26 -0
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +6 -1
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py +22 -0
- vellum/workflows/nodes/displayable/bases/utils.py +4 -2
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +88 -2
- vellum/workflows/nodes/displayable/tool_calling_node/node.py +1 -0
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +85 -1
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_utils.py +12 -0
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +5 -2
- vellum/workflows/ports/port.py +1 -11
- vellum/workflows/sandbox.py +6 -3
- vellum/workflows/state/context.py +14 -0
- vellum/workflows/state/encoder.py +19 -1
- vellum/workflows/types/definition.py +4 -4
- vellum/workflows/utils/hmac.py +44 -0
- vellum/workflows/utils/vellum_variables.py +5 -3
- vellum/workflows/workflows/base.py +1 -0
- {vellum_ai-1.2.0.dist-info → vellum_ai-1.2.2.dist-info}/METADATA +1 -1
- {vellum_ai-1.2.0.dist-info → vellum_ai-1.2.2.dist-info}/RECORD +94 -76
- vellum_ee/workflows/display/nodes/base_node_display.py +19 -10
- vellum_ee/workflows/display/nodes/vellum/api_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/error_node.py +6 -4
- vellum_ee/workflows/display/nodes/vellum/final_output_node.py +6 -4
- vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +34 -15
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/map_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/merge_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/note_node.py +2 -4
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/search_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -4
- vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +1 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +239 -1
- vellum_ee/workflows/display/tests/test_base_workflow_display.py +53 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +12 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +16 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +5 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +12 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +4 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +5 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_composio_serialization.py +1 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +5 -0
- vellum_ee/workflows/display/utils/expressions.py +4 -0
- vellum_ee/workflows/display/utils/registry.py +46 -0
- vellum_ee/workflows/display/workflows/base_workflow_display.py +1 -1
- vellum_ee/workflows/tests/test_registry.py +169 -0
- vellum_ee/workflows/tests/test_server.py +72 -0
- {vellum_ai-1.2.0.dist-info → vellum_ai-1.2.2.dist-info}/LICENSE +0 -0
- {vellum_ai-1.2.0.dist-info → vellum_ai-1.2.2.dist-info}/WHEEL +0 -0
- {vellum_ai-1.2.0.dist-info → vellum_ai-1.2.2.dist-info}/entry_points.txt +0 -0
@@ -1,12 +1,14 @@
|
|
1
1
|
import json
|
2
2
|
from uuid import uuid4
|
3
|
-
from typing import Any, Iterator
|
3
|
+
from typing import Any, Iterator, List
|
4
4
|
|
5
5
|
from vellum import ChatMessage
|
6
|
+
from vellum.client.types.execute_prompt_event import ExecutePromptEvent
|
6
7
|
from vellum.client.types.fulfilled_execute_prompt_event import FulfilledExecutePromptEvent
|
7
8
|
from vellum.client.types.function_call import FunctionCall
|
8
9
|
from vellum.client.types.function_call_vellum_value import FunctionCallVellumValue
|
9
10
|
from vellum.client.types.initiated_execute_prompt_event import InitiatedExecutePromptEvent
|
11
|
+
from vellum.client.types.prompt_output import PromptOutput
|
10
12
|
from vellum.client.types.string_chat_message_content import StringChatMessageContent
|
11
13
|
from vellum.client.types.string_vellum_value import StringVellumValue
|
12
14
|
from vellum.client.types.variable_prompt_block import VariablePromptBlock
|
@@ -25,6 +27,7 @@ from vellum.workflows.outputs.base import BaseOutputs
|
|
25
27
|
from vellum.workflows.state.base import BaseState, StateMeta
|
26
28
|
from vellum.workflows.state.context import WorkflowContext
|
27
29
|
from vellum.workflows.types.definition import DeploymentDefinition
|
30
|
+
from vellum.workflows.workflows.event_filters import all_workflow_event_filter
|
28
31
|
|
29
32
|
|
30
33
|
def first_function() -> str:
|
@@ -238,3 +241,84 @@ def test_tool_calling_node_with_generic_type_parameter():
|
|
238
241
|
assert node is not None
|
239
242
|
assert isinstance(node, TestToolCallingNode)
|
240
243
|
assert node.state == state
|
244
|
+
|
245
|
+
|
246
|
+
def test_tool_calling_node_workflow_is_dynamic(vellum_adhoc_prompt_client):
|
247
|
+
"""
|
248
|
+
Test workflow_version_exec_config without any mocks to see if that's the issue.
|
249
|
+
"""
|
250
|
+
|
251
|
+
def generate_prompt_events(*args, **kwargs) -> Iterator[ExecutePromptEvent]:
|
252
|
+
execution_id = str(uuid4())
|
253
|
+
|
254
|
+
call_count = vellum_adhoc_prompt_client.adhoc_execute_prompt_stream.call_count
|
255
|
+
expected_outputs: List[PromptOutput]
|
256
|
+
if call_count == 1:
|
257
|
+
expected_outputs = [
|
258
|
+
FunctionCallVellumValue(
|
259
|
+
value=FunctionCall(
|
260
|
+
arguments={"var_1": 1, "var_2": 2},
|
261
|
+
id="call_123",
|
262
|
+
name="add_numbers_workflow",
|
263
|
+
state="FULFILLED",
|
264
|
+
),
|
265
|
+
),
|
266
|
+
]
|
267
|
+
else:
|
268
|
+
expected_outputs = [StringVellumValue(value="The result is 3")]
|
269
|
+
|
270
|
+
events: List[ExecutePromptEvent] = [
|
271
|
+
InitiatedExecutePromptEvent(execution_id=execution_id),
|
272
|
+
FulfilledExecutePromptEvent(
|
273
|
+
execution_id=execution_id,
|
274
|
+
outputs=expected_outputs,
|
275
|
+
),
|
276
|
+
]
|
277
|
+
yield from events
|
278
|
+
|
279
|
+
vellum_adhoc_prompt_client.adhoc_execute_prompt_stream.side_effect = generate_prompt_events
|
280
|
+
|
281
|
+
class AddNode(BaseNode):
|
282
|
+
|
283
|
+
class Outputs(BaseNode.Outputs):
|
284
|
+
result: int
|
285
|
+
|
286
|
+
def run(self) -> Outputs:
|
287
|
+
return self.Outputs(result=1)
|
288
|
+
|
289
|
+
class AddNumbersWorkflow(BaseWorkflow[BaseInputs, BaseState]):
|
290
|
+
"""
|
291
|
+
A simple workflow that adds two numbers.
|
292
|
+
"""
|
293
|
+
|
294
|
+
graph = AddNode
|
295
|
+
|
296
|
+
class Outputs(BaseWorkflow.Outputs):
|
297
|
+
result = AddNode.Outputs.result
|
298
|
+
|
299
|
+
class TestToolCallingNode(ToolCallingNode):
|
300
|
+
ml_model = "gpt-4o-mini"
|
301
|
+
blocks = []
|
302
|
+
functions = [AddNumbersWorkflow]
|
303
|
+
prompt_inputs = {}
|
304
|
+
|
305
|
+
# GIVEN a workflow with just a tool calling node
|
306
|
+
class ToolCallingWorkflow(BaseWorkflow[BaseInputs, BaseState]):
|
307
|
+
graph = TestToolCallingNode
|
308
|
+
|
309
|
+
class Outputs(BaseWorkflow.Outputs):
|
310
|
+
text: str = TestToolCallingNode.Outputs.text
|
311
|
+
chat_history: List[ChatMessage] = TestToolCallingNode.Outputs.chat_history
|
312
|
+
|
313
|
+
workflow = ToolCallingWorkflow()
|
314
|
+
|
315
|
+
# WHEN the workflow is executed and we capture all events
|
316
|
+
events = list(workflow.stream(event_filter=all_workflow_event_filter))
|
317
|
+
|
318
|
+
# AND we should find workflow execution initiated events
|
319
|
+
initiated_events = [event for event in events if event.name == "workflow.execution.initiated"]
|
320
|
+
assert len(initiated_events) == 3 # Main workflow + tool calling internal + inline workflow
|
321
|
+
|
322
|
+
assert initiated_events[0].body.workflow_definition.is_dynamic is False # Main workflow
|
323
|
+
assert initiated_events[1].body.workflow_definition.is_dynamic is True # Tool calling internal
|
324
|
+
assert initiated_events[2].body.workflow_definition.is_dynamic is True # Inline workflow
|
@@ -238,3 +238,15 @@ def test_create_tool_prompt_node_chat_history_block_dict(vellum_adhoc_prompt_cli
|
|
238
238
|
),
|
239
239
|
VariablePromptBlock(block_type="VARIABLE", state=None, cache_config=None, input_variable="chat_history"),
|
240
240
|
]
|
241
|
+
|
242
|
+
|
243
|
+
def test_get_mcp_tool_name_snake_case():
|
244
|
+
"""Test MCPToolDefinition function name generation with snake case."""
|
245
|
+
mcp_tool = MCPToolDefinition(
|
246
|
+
name="create_repository",
|
247
|
+
server=MCPServer(name="Github Server", url="https://api.github.com"),
|
248
|
+
parameters={"repository_name": "string", "description": "string"},
|
249
|
+
)
|
250
|
+
|
251
|
+
result = get_mcp_tool_name(mcp_tool)
|
252
|
+
assert result == "github_server__create_repository"
|
@@ -505,6 +505,7 @@ def create_function_node(
|
|
505
505
|
)
|
506
506
|
return node
|
507
507
|
elif is_workflow_class(function):
|
508
|
+
function.is_dynamic = True
|
508
509
|
node = type(
|
509
510
|
f"DynamicInlineSubworkflowNode_{function.__name__}",
|
510
511
|
(DynamicInlineSubworkflowNode,),
|
@@ -574,10 +575,12 @@ def get_function_name(function: ToolBase) -> str:
|
|
574
575
|
name = str(function.deployment_id or function.deployment_name)
|
575
576
|
return name.replace("-", "")
|
576
577
|
elif isinstance(function, ComposioToolDefinition):
|
577
|
-
|
578
|
+
# model post init sets the name to the action if it's not set
|
579
|
+
return function.name # type: ignore[return-value]
|
578
580
|
else:
|
579
581
|
return snake_case(function.__name__)
|
580
582
|
|
581
583
|
|
582
584
|
def get_mcp_tool_name(tool_def: MCPToolDefinition) -> str:
|
583
|
-
|
585
|
+
server_name = snake_case(tool_def.server.name)
|
586
|
+
return f"{server_name}__{tool_def.name}"
|
vellum/workflows/ports/port.py
CHANGED
@@ -7,7 +7,7 @@ from vellum.workflows.descriptors.base import BaseDescriptor
|
|
7
7
|
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
8
8
|
from vellum.workflows.edges.edge import Edge
|
9
9
|
from vellum.workflows.errors.types import WorkflowErrorCode
|
10
|
-
from vellum.workflows.exceptions import NodeException
|
10
|
+
from vellum.workflows.exceptions import NodeException
|
11
11
|
from vellum.workflows.graph import Graph, GraphTarget
|
12
12
|
from vellum.workflows.state.base import BaseState
|
13
13
|
from vellum.workflows.types.core import ConditionType
|
@@ -107,13 +107,3 @@ class Port:
|
|
107
107
|
cls, source_type: Type[Any], handler: GetCoreSchemaHandler
|
108
108
|
) -> core_schema.CoreSchema:
|
109
109
|
return core_schema.is_instance_schema(cls)
|
110
|
-
|
111
|
-
def validate(self):
|
112
|
-
if (
|
113
|
-
not self.default
|
114
|
-
and self._condition_type in (ConditionType.IF, ConditionType.ELIF)
|
115
|
-
and self._condition is None
|
116
|
-
):
|
117
|
-
raise WorkflowInitializationException(
|
118
|
-
f"Class {self.node_class.__name__}'s {self.name} should have a defined condition and cannot be empty."
|
119
|
-
)
|
vellum/workflows/sandbox.py
CHANGED
@@ -16,6 +16,9 @@ class WorkflowSandboxRunner(Generic[WorkflowType]):
|
|
16
16
|
inputs: Optional[Sequence[BaseInputs]] = None, # DEPRECATED - remove in v2.0.0
|
17
17
|
dataset: Optional[Sequence[BaseInputs]] = None,
|
18
18
|
):
|
19
|
+
dotenv.load_dotenv()
|
20
|
+
self._logger = load_logger()
|
21
|
+
|
19
22
|
if dataset is not None and inputs is not None:
|
20
23
|
raise ValueError(
|
21
24
|
"Cannot specify both 'dataset' and 'inputs' parameters. " "Use 'dataset' as 'inputs' is deprecated."
|
@@ -24,6 +27,9 @@ class WorkflowSandboxRunner(Generic[WorkflowType]):
|
|
24
27
|
if dataset is not None:
|
25
28
|
actual_inputs = dataset
|
26
29
|
elif inputs is not None:
|
30
|
+
self._logger.warning(
|
31
|
+
"The 'inputs' parameter is deprecated and will be removed in v2.0.0. " "Please use 'dataset' instead."
|
32
|
+
)
|
27
33
|
actual_inputs = inputs
|
28
34
|
else:
|
29
35
|
raise ValueError("Either 'dataset' or 'inputs' parameter is required")
|
@@ -34,9 +40,6 @@ class WorkflowSandboxRunner(Generic[WorkflowType]):
|
|
34
40
|
self._workflow = workflow
|
35
41
|
self._inputs = actual_inputs
|
36
42
|
|
37
|
-
dotenv.load_dotenv()
|
38
|
-
self._logger = load_logger()
|
39
|
-
|
40
43
|
def run(self, index: int = 0):
|
41
44
|
if index < 0:
|
42
45
|
self._logger.warning("Index is less than 0, running first input")
|
@@ -13,6 +13,7 @@ from vellum.workflows.vellum_client import create_vellum_client
|
|
13
13
|
|
14
14
|
if TYPE_CHECKING:
|
15
15
|
from vellum.workflows.events.workflow import WorkflowEvent
|
16
|
+
from vellum.workflows.workflows.base import BaseWorkflow
|
16
17
|
|
17
18
|
|
18
19
|
class WorkflowContext:
|
@@ -131,6 +132,19 @@ class WorkflowContext:
|
|
131
132
|
def _get_all_node_output_mocks(self) -> List[MockNodeExecution]:
|
132
133
|
return [mock for mocks in self._node_output_mocks_map.values() for mock in mocks]
|
133
134
|
|
135
|
+
def resolve_workflow_deployment(self, deployment_name: str, release_tag: str) -> Optional["BaseWorkflow"]:
|
136
|
+
"""
|
137
|
+
Resolve a workflow deployment by name and release tag.
|
138
|
+
|
139
|
+
Args:
|
140
|
+
deployment_name: The name of the workflow deployment
|
141
|
+
release_tag: The release tag to resolve
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
BaseWorkflow instance if found, None otherwise
|
145
|
+
"""
|
146
|
+
return None
|
147
|
+
|
134
148
|
@classmethod
|
135
149
|
def create_from(cls, context):
|
136
150
|
return cls(vellum_client=context.vellum_client, generated_files=context.generated_files)
|
@@ -2,8 +2,10 @@ from dataclasses import asdict, is_dataclass
|
|
2
2
|
from datetime import datetime
|
3
3
|
import enum
|
4
4
|
import inspect
|
5
|
+
from io import StringIO
|
5
6
|
from json import JSONEncoder
|
6
7
|
from queue import Queue
|
8
|
+
import sys
|
7
9
|
from uuid import UUID
|
8
10
|
from typing import Any, Callable, Dict, Type
|
9
11
|
|
@@ -18,6 +20,22 @@ from vellum.workflows.state.base import BaseState, NodeExecutionCache
|
|
18
20
|
from vellum.workflows.utils.functions import compile_function_definition
|
19
21
|
|
20
22
|
|
23
|
+
def virtual_open(file_path: str, mode: str = "r"):
|
24
|
+
"""
|
25
|
+
Open a file, checking VirtualFileFinder instances first before falling back to regular open().
|
26
|
+
"""
|
27
|
+
for finder in sys.meta_path:
|
28
|
+
if hasattr(finder, "loader") and hasattr(finder.loader, "_get_code"):
|
29
|
+
namespace = finder.loader.namespace
|
30
|
+
if file_path.startswith(namespace + "/"):
|
31
|
+
relative_path = file_path[len(namespace) + 1 :]
|
32
|
+
content = finder.loader._get_code(relative_path)
|
33
|
+
if content is not None:
|
34
|
+
return StringIO(content)
|
35
|
+
|
36
|
+
return open(file_path, mode)
|
37
|
+
|
38
|
+
|
21
39
|
class DefaultStateEncoder(JSONEncoder):
|
22
40
|
encoders: Dict[Type, Callable] = {}
|
23
41
|
|
@@ -66,7 +84,7 @@ class DefaultStateEncoder(JSONEncoder):
|
|
66
84
|
function_definition = compile_function_definition(obj)
|
67
85
|
source_path = inspect.getsourcefile(obj)
|
68
86
|
if source_path is not None:
|
69
|
-
with
|
87
|
+
with virtual_open(source_path) as f:
|
70
88
|
source_code = f.read()
|
71
89
|
else:
|
72
90
|
source_code = f"# Error: Source code not available for {obj.__name__}"
|
@@ -111,11 +111,11 @@ class ComposioToolDefinition(UniversalBaseModel):
|
|
111
111
|
action: str # Specific action like "GITHUB_CREATE_AN_ISSUE"
|
112
112
|
description: str
|
113
113
|
user_id: Optional[str] = None
|
114
|
+
name: str = ""
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
return self.action.lower()
|
116
|
+
def model_post_init(self, __context: Any):
|
117
|
+
if self.name == "":
|
118
|
+
self.name = self.action.lower()
|
119
119
|
|
120
120
|
|
121
121
|
class MCPServer(UniversalBaseModel):
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import hashlib
|
2
|
+
import hmac
|
3
|
+
import os
|
4
|
+
import time
|
5
|
+
|
6
|
+
from requests import PreparedRequest
|
7
|
+
|
8
|
+
|
9
|
+
def _sign_request(request: PreparedRequest, secret: str) -> None:
|
10
|
+
"""
|
11
|
+
Sign a request with HMAC using the same pattern as Django implementation.
|
12
|
+
|
13
|
+
Args:
|
14
|
+
request: The prepared request to sign
|
15
|
+
secret: The HMAC secret string
|
16
|
+
"""
|
17
|
+
timestamp = str(int(time.time()))
|
18
|
+
|
19
|
+
body = request.body or b""
|
20
|
+
if isinstance(body, str):
|
21
|
+
body = body.encode()
|
22
|
+
|
23
|
+
message = f"{timestamp}\n{request.method}\n{request.url}\n".encode() + body
|
24
|
+
|
25
|
+
signature = hmac.new(secret.encode("utf-8"), message, hashlib.sha256).hexdigest()
|
26
|
+
|
27
|
+
hmac_headers = {
|
28
|
+
"X-Vellum-Timestamp": timestamp,
|
29
|
+
"X-Vellum-Signature": signature,
|
30
|
+
}
|
31
|
+
|
32
|
+
request.headers.update(hmac_headers)
|
33
|
+
|
34
|
+
|
35
|
+
def sign_request_with_env_secret(request: PreparedRequest) -> None:
|
36
|
+
"""
|
37
|
+
Sign a request using VELLUM_HMAC_SECRET environment variable if available.
|
38
|
+
|
39
|
+
Args:
|
40
|
+
request: The prepared request to sign
|
41
|
+
"""
|
42
|
+
hmac_secret = os.environ.get("VELLUM_HMAC_SECRET")
|
43
|
+
if hmac_secret:
|
44
|
+
_sign_request(request, hmac_secret)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import typing
|
2
2
|
from typing import List, Tuple, Type, Union, get_args, get_origin
|
3
3
|
|
4
|
-
from vellum import (
|
4
|
+
from vellum import (
|
5
5
|
ChatMessage,
|
6
6
|
ChatMessageRequest,
|
7
7
|
FunctionCall,
|
@@ -19,6 +19,8 @@ from vellum import ( # VellumVideo,; VellumVideoRequest,
|
|
19
19
|
VellumValue,
|
20
20
|
VellumValueRequest,
|
21
21
|
VellumVariableType,
|
22
|
+
VellumVideo,
|
23
|
+
VellumVideoRequest,
|
22
24
|
)
|
23
25
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
24
26
|
from vellum.workflows.types.core import Json
|
@@ -67,8 +69,8 @@ def primitive_type_to_vellum_variable_type(type_: Union[Type, BaseDescriptor]) -
|
|
67
69
|
return "FUNCTION_CALL"
|
68
70
|
elif _is_type_optionally_in(type_, (VellumAudio, VellumAudioRequest)):
|
69
71
|
return "AUDIO"
|
70
|
-
|
71
|
-
|
72
|
+
elif _is_type_optionally_in(type_, (VellumVideo, VellumVideoRequest)):
|
73
|
+
return "VIDEO"
|
72
74
|
elif _is_type_optionally_in(type_, (VellumImage, VellumImageRequest)):
|
73
75
|
return "IMAGE"
|
74
76
|
elif _is_type_optionally_in(type_, (VellumDocument, VellumDocumentRequest)):
|
@@ -211,6 +211,7 @@ class BaseWorkflow(Generic[InputsType, StateType], metaclass=_BaseWorkflowMeta):
|
|
211
211
|
unused_graphs: ClassVar[Set[GraphAttribute]] # nodes or graphs that are defined but not used in the graph
|
212
212
|
emitters: List[BaseWorkflowEmitter]
|
213
213
|
resolvers: List[BaseWorkflowResolver]
|
214
|
+
is_dynamic: ClassVar[bool] = False
|
214
215
|
|
215
216
|
class Outputs(BaseOutputs):
|
216
217
|
pass
|