vellum-ai 1.0.3__py3-none-any.whl → 1.0.4__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 +2 -2
- vellum/client/types/organization_limit_config.py +1 -0
- vellum/prompts/blocks/compilation.py +5 -1
- vellum/prompts/blocks/tests/test_compilation.py +64 -0
- vellum/workflows/descriptors/base.py +12 -0
- vellum/workflows/expressions/concat.py +32 -0
- vellum/workflows/expressions/tests/test_concat.py +53 -0
- vellum/workflows/nodes/displayable/inline_prompt_node/node.py +1 -2
- vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +1 -2
- vellum/workflows/nodes/displayable/tool_calling_node/composio_service.py +83 -0
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_composio_service.py +122 -0
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +28 -6
- vellum/workflows/types/core.py +2 -2
- vellum/workflows/types/definition.py +20 -1
- vellum/workflows/types/tests/test_definition.py +14 -1
- {vellum_ai-1.0.3.dist-info → vellum_ai-1.0.4.dist-info}/METADATA +3 -1
- {vellum_ai-1.0.3.dist-info → vellum_ai-1.0.4.dist-info}/RECORD +20 -16
- {vellum_ai-1.0.3.dist-info → vellum_ai-1.0.4.dist-info}/LICENSE +0 -0
- {vellum_ai-1.0.3.dist-info → vellum_ai-1.0.4.dist-info}/WHEEL +0 -0
- {vellum_ai-1.0.3.dist-info → vellum_ai-1.0.4.dist-info}/entry_points.txt +0 -0
@@ -25,10 +25,10 @@ class BaseClientWrapper:
|
|
25
25
|
|
26
26
|
def get_headers(self) -> typing.Dict[str, str]:
|
27
27
|
headers: typing.Dict[str, str] = {
|
28
|
-
"User-Agent": "vellum-ai/1.0.
|
28
|
+
"User-Agent": "vellum-ai/1.0.4",
|
29
29
|
"X-Fern-Language": "Python",
|
30
30
|
"X-Fern-SDK-Name": "vellum-ai",
|
31
|
-
"X-Fern-SDK-Version": "1.0.
|
31
|
+
"X-Fern-SDK-Version": "1.0.4",
|
32
32
|
}
|
33
33
|
if self._api_version is not None:
|
34
34
|
headers["X-API-Version"] = self._api_version
|
@@ -13,6 +13,7 @@ class OrganizationLimitConfig(UniversalBaseModel):
|
|
13
13
|
prompt_executions_quota: typing.Optional[Quota] = None
|
14
14
|
workflow_executions_quota: typing.Optional[Quota] = None
|
15
15
|
workflow_runtime_seconds_quota: typing.Optional[Quota] = None
|
16
|
+
max_workflow_runtime_seconds: typing.Optional[int] = None
|
16
17
|
|
17
18
|
if IS_PYDANTIC_V2:
|
18
19
|
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
|
@@ -105,7 +105,11 @@ def compile_prompt_blocks(
|
|
105
105
|
cache_config=block.cache_config,
|
106
106
|
)
|
107
107
|
)
|
108
|
-
elif compiled_input == "JSON":
|
108
|
+
elif compiled_input.type == "JSON":
|
109
|
+
# Skip empty JSON arrays when there are chat message blocks present
|
110
|
+
if compiled_input.value == [] and any(block.block_type == "CHAT_MESSAGE" for block in compiled_blocks):
|
111
|
+
continue
|
112
|
+
|
109
113
|
compiled_blocks.append(
|
110
114
|
CompiledValuePromptBlock(
|
111
115
|
content=JsonVellumValue(value=compiled_input.value),
|
@@ -10,7 +10,10 @@ from vellum import (
|
|
10
10
|
VariablePromptBlock,
|
11
11
|
VellumVariable,
|
12
12
|
)
|
13
|
+
from vellum.client.types.json_vellum_value import JsonVellumValue
|
13
14
|
from vellum.client.types.number_input import NumberInput
|
15
|
+
from vellum.client.types.prompt_block import PromptBlock
|
16
|
+
from vellum.client.types.prompt_request_json_input import PromptRequestJsonInput
|
14
17
|
from vellum.prompts.blocks.compilation import compile_prompt_blocks
|
15
18
|
from vellum.prompts.blocks.types import CompiledChatMessagePromptBlock, CompiledValuePromptBlock
|
16
19
|
|
@@ -146,3 +149,64 @@ def test_compile_prompt_blocks__happy(blocks, inputs, input_variables, expected)
|
|
146
149
|
actual = compile_prompt_blocks(blocks=blocks, inputs=inputs, input_variables=input_variables)
|
147
150
|
|
148
151
|
assert actual == expected
|
152
|
+
|
153
|
+
|
154
|
+
def test_compile_prompt_blocks__empty_json_variable_with_chat_message_blocks():
|
155
|
+
"""Test JSON variable handling logic, specifically the empty array skipping behavior."""
|
156
|
+
|
157
|
+
# GIVEN empty array with chat message blocks
|
158
|
+
blocks_with_chat: list[PromptBlock] = [
|
159
|
+
ChatMessagePromptBlock(
|
160
|
+
chat_role="USER",
|
161
|
+
blocks=[RichTextPromptBlock(blocks=[PlainTextPromptBlock(text="User message")])],
|
162
|
+
),
|
163
|
+
VariablePromptBlock(input_variable="json_data"),
|
164
|
+
]
|
165
|
+
|
166
|
+
inputs_with_empty_json = [PromptRequestJsonInput(key="json_data", value=[], type="JSON")]
|
167
|
+
|
168
|
+
input_variables = [VellumVariable(id="901ec2d6-430c-4341-b963-ca689006f5cc", type="JSON", key="json_data")]
|
169
|
+
|
170
|
+
# THEN the empty JSON array should be skipped when there are chat message blocks
|
171
|
+
expected_with_chat = [
|
172
|
+
CompiledChatMessagePromptBlock(
|
173
|
+
role="USER",
|
174
|
+
blocks=[CompiledValuePromptBlock(content=StringVellumValue(value="User message"))],
|
175
|
+
),
|
176
|
+
]
|
177
|
+
|
178
|
+
actual = compile_prompt_blocks(
|
179
|
+
blocks=blocks_with_chat, inputs=inputs_with_empty_json, input_variables=input_variables
|
180
|
+
)
|
181
|
+
assert actual == expected_with_chat
|
182
|
+
|
183
|
+
|
184
|
+
def test_compile_prompt_blocks__non_empty_json_variable_with_chat_message_blocks():
|
185
|
+
"""Test that non-empty JSON variables are included even when there are chat message blocks."""
|
186
|
+
|
187
|
+
# GIVEN non-empty JSON with chat message blocks
|
188
|
+
blocks_with_chat: list[PromptBlock] = [
|
189
|
+
ChatMessagePromptBlock(
|
190
|
+
chat_role="USER",
|
191
|
+
blocks=[RichTextPromptBlock(blocks=[PlainTextPromptBlock(text="User message")])],
|
192
|
+
),
|
193
|
+
VariablePromptBlock(input_variable="json_data"),
|
194
|
+
]
|
195
|
+
|
196
|
+
inputs_with_non_empty_json = [PromptRequestJsonInput(key="json_data", value={"key": "value"}, type="JSON")]
|
197
|
+
|
198
|
+
input_variables = [VellumVariable(id="901ec2d6-430c-4341-b963-ca689006f5cc", type="JSON", key="json_data")]
|
199
|
+
|
200
|
+
# THEN the non-empty JSON should be included
|
201
|
+
expected_with_non_empty = [
|
202
|
+
CompiledChatMessagePromptBlock(
|
203
|
+
role="USER",
|
204
|
+
blocks=[CompiledValuePromptBlock(content=StringVellumValue(value="User message"))],
|
205
|
+
),
|
206
|
+
CompiledValuePromptBlock(content=JsonVellumValue(value={"key": "value"})),
|
207
|
+
]
|
208
|
+
|
209
|
+
actual = compile_prompt_blocks(
|
210
|
+
blocks=blocks_with_chat, inputs=inputs_with_non_empty_json, input_variables=input_variables
|
211
|
+
)
|
212
|
+
assert actual == expected_with_non_empty
|
@@ -6,6 +6,7 @@ if TYPE_CHECKING:
|
|
6
6
|
from vellum.workflows.expressions.begins_with import BeginsWithExpression
|
7
7
|
from vellum.workflows.expressions.between import BetweenExpression
|
8
8
|
from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
|
9
|
+
from vellum.workflows.expressions.concat import ConcatExpression
|
9
10
|
from vellum.workflows.expressions.contains import ContainsExpression
|
10
11
|
from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
|
11
12
|
from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
|
@@ -364,3 +365,14 @@ class BaseDescriptor(Generic[_T]):
|
|
364
365
|
from vellum.workflows.expressions.is_error import IsErrorExpression
|
365
366
|
|
366
367
|
return IsErrorExpression(expression=self)
|
368
|
+
|
369
|
+
@overload
|
370
|
+
def concat(self, other: "BaseDescriptor[_O]") -> "ConcatExpression[_T, _O]": ...
|
371
|
+
|
372
|
+
@overload
|
373
|
+
def concat(self, other: _O) -> "ConcatExpression[_T, _O]": ...
|
374
|
+
|
375
|
+
def concat(self, other: "Union[BaseDescriptor[_O], _O]") -> "ConcatExpression[_T, _O]":
|
376
|
+
from vellum.workflows.expressions.concat import ConcatExpression
|
377
|
+
|
378
|
+
return ConcatExpression(lhs=self, rhs=other)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
from typing import Generic, TypeVar, Union
|
2
|
+
|
3
|
+
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
5
|
+
from vellum.workflows.descriptors.utils import resolve_value
|
6
|
+
from vellum.workflows.state.base import BaseState
|
7
|
+
|
8
|
+
LHS = TypeVar("LHS")
|
9
|
+
RHS = TypeVar("RHS")
|
10
|
+
|
11
|
+
|
12
|
+
class ConcatExpression(BaseDescriptor[list], Generic[LHS, RHS]):
|
13
|
+
def __init__(
|
14
|
+
self,
|
15
|
+
*,
|
16
|
+
lhs: Union[BaseDescriptor[LHS], LHS],
|
17
|
+
rhs: Union[BaseDescriptor[RHS], RHS],
|
18
|
+
) -> None:
|
19
|
+
super().__init__(name=f"{lhs} + {rhs}", types=(list,))
|
20
|
+
self._lhs = lhs
|
21
|
+
self._rhs = rhs
|
22
|
+
|
23
|
+
def resolve(self, state: "BaseState") -> list:
|
24
|
+
lval = resolve_value(self._lhs, state)
|
25
|
+
rval = resolve_value(self._rhs, state)
|
26
|
+
|
27
|
+
if not isinstance(lval, list):
|
28
|
+
raise InvalidExpressionException(f"Expected LHS to be a list, got {type(lval)}")
|
29
|
+
if not isinstance(rval, list):
|
30
|
+
raise InvalidExpressionException(f"Expected RHS to be a list, got {type(rval)}")
|
31
|
+
|
32
|
+
return lval + rval
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
|
+
from vellum.workflows.references.constant import ConstantValueReference
|
5
|
+
from vellum.workflows.state.base import BaseState
|
6
|
+
|
7
|
+
|
8
|
+
class TestState(BaseState):
|
9
|
+
pass
|
10
|
+
|
11
|
+
|
12
|
+
def test_concat_expression_happy_path():
|
13
|
+
# GIVEN two lists
|
14
|
+
state = TestState()
|
15
|
+
lhs_ref = ConstantValueReference([1, 2, 3])
|
16
|
+
rhs_ref = ConstantValueReference([4, 5, 6])
|
17
|
+
concat_expr = lhs_ref.concat(rhs_ref)
|
18
|
+
|
19
|
+
# WHEN we resolve the expression
|
20
|
+
result = concat_expr.resolve(state)
|
21
|
+
|
22
|
+
# THEN the lists should be concatenated
|
23
|
+
assert result == [1, 2, 3, 4, 5, 6]
|
24
|
+
|
25
|
+
|
26
|
+
def test_concat_expression_lhs_fail():
|
27
|
+
# GIVEN a non-list lhs and a list rhs
|
28
|
+
state = TestState()
|
29
|
+
lhs_ref = ConstantValueReference(0)
|
30
|
+
rhs_ref = ConstantValueReference([4, 5, 6])
|
31
|
+
concat_expr = lhs_ref.concat(rhs_ref)
|
32
|
+
|
33
|
+
# WHEN we attempt to resolve the expression
|
34
|
+
with pytest.raises(InvalidExpressionException) as exc_info:
|
35
|
+
concat_expr.resolve(state)
|
36
|
+
|
37
|
+
# THEN an exception should be raised
|
38
|
+
assert "Expected LHS to be a list, got <class 'int'>" in str(exc_info.value)
|
39
|
+
|
40
|
+
|
41
|
+
def test_concat_expression_rhs_fail():
|
42
|
+
# GIVEN a list lhs and a non-list rhs
|
43
|
+
state = TestState()
|
44
|
+
lhs_ref = ConstantValueReference([1, 2, 3])
|
45
|
+
rhs_ref = ConstantValueReference(False)
|
46
|
+
concat_expr = lhs_ref.concat(rhs_ref)
|
47
|
+
|
48
|
+
# WHEN we attempt to resolve the expression
|
49
|
+
with pytest.raises(InvalidExpressionException) as exc_info:
|
50
|
+
concat_expr.resolve(state)
|
51
|
+
|
52
|
+
# THEN an exception should be raised
|
53
|
+
assert "Expected RHS to be a list, got <class 'bool'>" in str(exc_info.value)
|
@@ -64,8 +64,7 @@ class InlinePromptNode(BaseInlinePromptNode[StateType]):
|
|
64
64
|
elif output.type == "FUNCTION_CALL":
|
65
65
|
string_outputs.append(output.value.model_dump_json(indent=4))
|
66
66
|
elif output.type == "THINKING":
|
67
|
-
|
68
|
-
string_outputs.append(output.value.value)
|
67
|
+
continue
|
69
68
|
else:
|
70
69
|
string_outputs.append(output.value.message)
|
71
70
|
|
@@ -66,8 +66,7 @@ class PromptDeploymentNode(BasePromptDeploymentNode[StateType]):
|
|
66
66
|
elif output.type == "FUNCTION_CALL":
|
67
67
|
string_outputs.append(output.value.model_dump_json(indent=4))
|
68
68
|
elif output.type == "THINKING":
|
69
|
-
|
70
|
-
string_outputs.append(output.value.value)
|
69
|
+
continue
|
71
70
|
else:
|
72
71
|
string_outputs.append(output.value.message)
|
73
72
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from typing import Any, Dict, List
|
3
|
+
|
4
|
+
from composio import Action, Composio
|
5
|
+
from composio_client import Composio as ComposioClient
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass
|
9
|
+
class ConnectionInfo:
|
10
|
+
"""Information about a user's authorized connection"""
|
11
|
+
|
12
|
+
connection_id: str
|
13
|
+
integration_name: str
|
14
|
+
created_at: str
|
15
|
+
updated_at: str
|
16
|
+
status: str = "ACTIVE" # TODO: Use enum if we end up supporting integrations that the user has not yet connected to
|
17
|
+
|
18
|
+
|
19
|
+
class ComposioAccountService:
|
20
|
+
"""Manages user authorized connections using composio-client"""
|
21
|
+
|
22
|
+
def __init__(self, api_key: str):
|
23
|
+
self.client = ComposioClient(api_key=api_key)
|
24
|
+
|
25
|
+
def get_user_connections(self) -> List[ConnectionInfo]:
|
26
|
+
"""Get all authorized connections for the user"""
|
27
|
+
response = self.client.connected_accounts.list()
|
28
|
+
|
29
|
+
return [
|
30
|
+
ConnectionInfo(
|
31
|
+
connection_id=item.id,
|
32
|
+
integration_name=item.toolkit.slug,
|
33
|
+
status=item.status,
|
34
|
+
created_at=item.created_at,
|
35
|
+
updated_at=item.updated_at,
|
36
|
+
)
|
37
|
+
for item in response.items
|
38
|
+
]
|
39
|
+
|
40
|
+
|
41
|
+
class ComposioCoreService:
|
42
|
+
"""Handles tool execution using composio-core"""
|
43
|
+
|
44
|
+
def __init__(self, api_key: str):
|
45
|
+
self.client = Composio(api_key=api_key)
|
46
|
+
|
47
|
+
def execute_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Any:
|
48
|
+
"""Execute a tool using composio-core
|
49
|
+
|
50
|
+
Args:
|
51
|
+
tool_name: The name of the tool to execute (e.g., "HACKERNEWS_GET_USER")
|
52
|
+
arguments: Dictionary of arguments to pass to the tool
|
53
|
+
|
54
|
+
Returns:
|
55
|
+
The result of the tool execution
|
56
|
+
"""
|
57
|
+
# Convert tool name string to Action enum
|
58
|
+
action = getattr(Action, tool_name)
|
59
|
+
return self.client.actions.execute(action, params=arguments)
|
60
|
+
|
61
|
+
|
62
|
+
class ComposioService:
|
63
|
+
"""Unified interface for Composio operations"""
|
64
|
+
|
65
|
+
def __init__(self, api_key: str):
|
66
|
+
self.accounts = ComposioAccountService(api_key)
|
67
|
+
self.core = ComposioCoreService(api_key)
|
68
|
+
|
69
|
+
def get_user_connections(self) -> List[ConnectionInfo]:
|
70
|
+
"""Get user's authorized connections"""
|
71
|
+
return self.accounts.get_user_connections()
|
72
|
+
|
73
|
+
def execute_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Any:
|
74
|
+
"""Execute a tool using composio-core
|
75
|
+
|
76
|
+
Args:
|
77
|
+
tool_name: The name of the tool to execute (e.g., "HACKERNEWS_GET_USER")
|
78
|
+
arguments: Dictionary of arguments to pass to the tool
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
The result of the tool execution
|
82
|
+
"""
|
83
|
+
return self.core.execute_tool(tool_name, arguments)
|
@@ -0,0 +1,122 @@
|
|
1
|
+
import pytest
|
2
|
+
from unittest.mock import Mock, patch
|
3
|
+
|
4
|
+
from vellum.workflows.nodes.displayable.tool_calling_node.composio_service import ComposioService, ConnectionInfo
|
5
|
+
|
6
|
+
|
7
|
+
@pytest.fixture
|
8
|
+
def mock_composio_client():
|
9
|
+
"""Mock the Composio client completely"""
|
10
|
+
with patch("vellum.workflows.nodes.displayable.tool_calling_node.composio_service.ComposioClient") as mock_composio:
|
11
|
+
yield mock_composio.return_value
|
12
|
+
|
13
|
+
|
14
|
+
@pytest.fixture
|
15
|
+
def mock_connected_accounts_response():
|
16
|
+
"""Mock response for connected accounts"""
|
17
|
+
mock_item1 = Mock()
|
18
|
+
mock_item1.id = "conn-123"
|
19
|
+
mock_item1.toolkit.slug = "github"
|
20
|
+
mock_item1.status = "ACTIVE"
|
21
|
+
mock_item1.created_at = "2023-01-01T00:00:00Z"
|
22
|
+
mock_item1.updated_at = "2023-01-15T10:30:00Z"
|
23
|
+
|
24
|
+
mock_item2 = Mock()
|
25
|
+
mock_item2.id = "conn-456"
|
26
|
+
mock_item2.toolkit.slug = "slack"
|
27
|
+
mock_item2.status = "ACTIVE"
|
28
|
+
mock_item2.created_at = "2023-01-01T00:00:00Z"
|
29
|
+
mock_item2.updated_at = "2023-01-10T08:00:00Z"
|
30
|
+
|
31
|
+
mock_response = Mock()
|
32
|
+
mock_response.items = [mock_item1, mock_item2]
|
33
|
+
|
34
|
+
return mock_response
|
35
|
+
|
36
|
+
|
37
|
+
@pytest.fixture
|
38
|
+
def mock_composio_core_client():
|
39
|
+
"""Mock the composio-core Composio client"""
|
40
|
+
with patch("vellum.workflows.nodes.displayable.tool_calling_node.composio_service.Composio") as mock_composio:
|
41
|
+
yield mock_composio.return_value
|
42
|
+
|
43
|
+
|
44
|
+
@pytest.fixture
|
45
|
+
def mock_action():
|
46
|
+
"""Mock the Action class and specific actions"""
|
47
|
+
with patch("vellum.workflows.nodes.displayable.tool_calling_node.composio_service.Action") as mock_action_class:
|
48
|
+
# Mock a specific action
|
49
|
+
mock_hackernews_action = Mock()
|
50
|
+
mock_action_class.HACKERNEWS_GET_USER = mock_hackernews_action
|
51
|
+
mock_action_class.GITHUB_GET_USER = Mock()
|
52
|
+
yield mock_action_class
|
53
|
+
|
54
|
+
|
55
|
+
@pytest.fixture
|
56
|
+
def composio_service(mock_composio_client, mock_composio_core_client):
|
57
|
+
"""Create ComposioService with mocked clients"""
|
58
|
+
return ComposioService(api_key="test-key")
|
59
|
+
|
60
|
+
|
61
|
+
class TestComposioAccountService:
|
62
|
+
"""Test suite for ComposioAccountService"""
|
63
|
+
|
64
|
+
def test_get_user_connections_success(
|
65
|
+
self, composio_service, mock_composio_client, mock_connected_accounts_response
|
66
|
+
):
|
67
|
+
"""Test successful retrieval of user connections"""
|
68
|
+
# GIVEN the Composio client returns a valid response with two connections
|
69
|
+
mock_composio_client.connected_accounts.list.return_value = mock_connected_accounts_response
|
70
|
+
|
71
|
+
# WHEN we request user connections
|
72
|
+
result = composio_service.get_user_connections()
|
73
|
+
|
74
|
+
# THEN we get two properly formatted ConnectionInfo objects
|
75
|
+
assert len(result) == 2
|
76
|
+
assert isinstance(result[0], ConnectionInfo)
|
77
|
+
assert result[0].connection_id == "conn-123"
|
78
|
+
assert result[0].integration_name == "github"
|
79
|
+
assert result[0].status == "ACTIVE"
|
80
|
+
assert result[0].created_at == "2023-01-01T00:00:00Z"
|
81
|
+
assert result[0].updated_at == "2023-01-15T10:30:00Z"
|
82
|
+
|
83
|
+
assert result[1].connection_id == "conn-456"
|
84
|
+
assert result[1].integration_name == "slack"
|
85
|
+
assert result[1].status == "ACTIVE"
|
86
|
+
assert result[1].created_at == "2023-01-01T00:00:00Z"
|
87
|
+
assert result[1].updated_at == "2023-01-10T08:00:00Z"
|
88
|
+
|
89
|
+
mock_composio_client.connected_accounts.list.assert_called_once()
|
90
|
+
|
91
|
+
def test_get_user_connections_empty_response(self, composio_service, mock_composio_client):
|
92
|
+
"""Test handling of empty connections response"""
|
93
|
+
# GIVEN the Composio client returns an empty response
|
94
|
+
mock_response = Mock()
|
95
|
+
mock_response.items = []
|
96
|
+
mock_composio_client.connected_accounts.list.return_value = mock_response
|
97
|
+
|
98
|
+
# WHEN we request user connections
|
99
|
+
result = composio_service.get_user_connections()
|
100
|
+
|
101
|
+
# THEN we get an empty list
|
102
|
+
assert result == []
|
103
|
+
|
104
|
+
|
105
|
+
class TestComposioCoreService:
|
106
|
+
"""Test suite for ComposioCoreService"""
|
107
|
+
|
108
|
+
def test_execute_tool_success(self, composio_service, mock_composio_core_client, mock_action):
|
109
|
+
"""Test executing a tool with complex argument structure"""
|
110
|
+
# GIVEN complex arguments and a mock response
|
111
|
+
complex_args = {"filters": {"status": "active"}, "limit": 10, "sort": "created_at"}
|
112
|
+
expected_result = {"items": [], "total": 0}
|
113
|
+
mock_composio_core_client.actions.execute.return_value = expected_result
|
114
|
+
|
115
|
+
# WHEN we execute a tool with complex arguments
|
116
|
+
result = composio_service.execute_tool("HACKERNEWS_GET_USER", complex_args)
|
117
|
+
|
118
|
+
# THEN the arguments are passed through correctly
|
119
|
+
mock_composio_core_client.actions.execute.assert_called_once_with(
|
120
|
+
mock_action.HACKERNEWS_GET_USER, params=complex_args
|
121
|
+
)
|
122
|
+
assert result == expected_result
|
@@ -12,6 +12,7 @@ from vellum.client.types.string_chat_message_content import StringChatMessageCon
|
|
12
12
|
from vellum.client.types.variable_prompt_block import VariablePromptBlock
|
13
13
|
from vellum.workflows.errors.types import WorkflowErrorCode
|
14
14
|
from vellum.workflows.exceptions import NodeException
|
15
|
+
from vellum.workflows.expressions.concat import ConcatExpression
|
15
16
|
from vellum.workflows.inputs import BaseInputs
|
16
17
|
from vellum.workflows.nodes.bases import BaseNode
|
17
18
|
from vellum.workflows.nodes.core.inline_subworkflow_node.node import InlineSubworkflowNode
|
@@ -24,7 +25,7 @@ from vellum.workflows.references.lazy import LazyReference
|
|
24
25
|
from vellum.workflows.state import BaseState
|
25
26
|
from vellum.workflows.state.encoder import DefaultStateEncoder
|
26
27
|
from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior, Tool
|
27
|
-
from vellum.workflows.types.definition import DeploymentDefinition
|
28
|
+
from vellum.workflows.types.definition import ComposioToolDefinition, DeploymentDefinition
|
28
29
|
from vellum.workflows.types.generics import is_workflow_class
|
29
30
|
|
30
31
|
CHAT_HISTORY_VARIABLE = "chat_history"
|
@@ -41,10 +42,6 @@ class ToolRouterNode(InlinePromptNode[ToolCallingState]):
|
|
41
42
|
max_iterations_message = f"Maximum number of prompt iterations `{self.max_prompt_iterations}` reached."
|
42
43
|
raise NodeException(message=max_iterations_message, code=WorkflowErrorCode.NODE_EXECUTION)
|
43
44
|
|
44
|
-
# Merge user-provided chat history with node's chat history
|
45
|
-
user_chat_history = self.prompt_inputs.get(CHAT_HISTORY_VARIABLE, []) if self.prompt_inputs else []
|
46
|
-
merged_chat_history = user_chat_history + self.state.chat_history
|
47
|
-
self.prompt_inputs = {**self.prompt_inputs, CHAT_HISTORY_VARIABLE: merged_chat_history} # type: ignore
|
48
45
|
generator = super().run()
|
49
46
|
for output in generator:
|
50
47
|
if output.name == "results" and output.value:
|
@@ -234,6 +231,14 @@ def create_tool_router_node(
|
|
234
231
|
)
|
235
232
|
)
|
236
233
|
|
234
|
+
node_prompt_inputs = {
|
235
|
+
**(prompt_inputs or {}),
|
236
|
+
CHAT_HISTORY_VARIABLE: ConcatExpression[List[ChatMessage], List[ChatMessage]](
|
237
|
+
lhs=(prompt_inputs or {}).get(CHAT_HISTORY_VARIABLE, []),
|
238
|
+
rhs=ToolCallingState.chat_history,
|
239
|
+
),
|
240
|
+
}
|
241
|
+
|
237
242
|
node = cast(
|
238
243
|
Type[ToolRouterNode],
|
239
244
|
type(
|
@@ -243,7 +248,7 @@ def create_tool_router_node(
|
|
243
248
|
"ml_model": ml_model,
|
244
249
|
"blocks": blocks,
|
245
250
|
"functions": functions,
|
246
|
-
"prompt_inputs":
|
251
|
+
"prompt_inputs": node_prompt_inputs,
|
247
252
|
"parameters": parameters,
|
248
253
|
"max_prompt_iterations": max_prompt_iterations,
|
249
254
|
"Ports": Ports,
|
@@ -285,6 +290,21 @@ def create_function_node(
|
|
285
290
|
|
286
291
|
return node
|
287
292
|
|
293
|
+
elif isinstance(function, ComposioToolDefinition):
|
294
|
+
# ComposioToolDefinition execution not yet implemented
|
295
|
+
def composio_not_implemented(**kwargs):
|
296
|
+
raise NotImplementedError("ComposioToolDefinition execution not yet implemented")
|
297
|
+
|
298
|
+
node = type(
|
299
|
+
f"ComposioNode_{function.name}",
|
300
|
+
(FunctionNode,),
|
301
|
+
{
|
302
|
+
"function_definition": composio_not_implemented,
|
303
|
+
"function_call_output": tool_router_node.Outputs.results,
|
304
|
+
"__module__": __name__,
|
305
|
+
},
|
306
|
+
)
|
307
|
+
|
288
308
|
elif is_workflow_class(function):
|
289
309
|
node = type(
|
290
310
|
f"DynamicInlineSubworkflowNode_{function.__name__}",
|
@@ -314,5 +334,7 @@ def get_function_name(function: Tool) -> str:
|
|
314
334
|
if isinstance(function, DeploymentDefinition):
|
315
335
|
name = str(function.deployment_id or function.deployment_name)
|
316
336
|
return name.replace("-", "")
|
337
|
+
elif isinstance(function, ComposioToolDefinition):
|
338
|
+
return function.name
|
317
339
|
else:
|
318
340
|
return snake_case(function.__name__)
|
vellum/workflows/types/core.py
CHANGED
@@ -13,7 +13,7 @@ from typing import ( # type: ignore[attr-defined]
|
|
13
13
|
)
|
14
14
|
|
15
15
|
from vellum.client.core.pydantic_utilities import UniversalBaseModel
|
16
|
-
from vellum.workflows.types.definition import DeploymentDefinition
|
16
|
+
from vellum.workflows.types.definition import ComposioToolDefinition, DeploymentDefinition
|
17
17
|
|
18
18
|
if TYPE_CHECKING:
|
19
19
|
from vellum.workflows.workflows.base import BaseWorkflow
|
@@ -50,4 +50,4 @@ class ConditionType(Enum):
|
|
50
50
|
|
51
51
|
|
52
52
|
# Type alias for functions that can be called in tool calling nodes
|
53
|
-
Tool = Union[Callable[..., Any], DeploymentDefinition, Type["BaseWorkflow"]]
|
53
|
+
Tool = Union[Callable[..., Any], DeploymentDefinition, Type["BaseWorkflow"], ComposioToolDefinition]
|
@@ -2,7 +2,7 @@ import importlib
|
|
2
2
|
import inspect
|
3
3
|
from types import FrameType
|
4
4
|
from uuid import UUID
|
5
|
-
from typing import Annotated, Any, Dict, Optional, Union
|
5
|
+
from typing import Annotated, Any, Dict, Literal, Optional, Union
|
6
6
|
|
7
7
|
from pydantic import BeforeValidator
|
8
8
|
|
@@ -97,3 +97,22 @@ class DeploymentDefinition(UniversalBaseModel):
|
|
97
97
|
if not self._is_uuid():
|
98
98
|
return self.deployment
|
99
99
|
return None
|
100
|
+
|
101
|
+
|
102
|
+
class ComposioToolDefinition(UniversalBaseModel):
|
103
|
+
"""Represents a specific Composio action that can be used in Tool Calling Node"""
|
104
|
+
|
105
|
+
type: Literal["COMPOSIO"] = "COMPOSIO"
|
106
|
+
|
107
|
+
# Core identification
|
108
|
+
toolkit: str # "GITHUB", "SLACK", etc.
|
109
|
+
action: str # Specific action like "GITHUB_CREATE_AN_ISSUE"
|
110
|
+
description: str
|
111
|
+
|
112
|
+
# Optional cached metadata
|
113
|
+
display_name: Optional[str] = None
|
114
|
+
|
115
|
+
@property
|
116
|
+
def name(self) -> str:
|
117
|
+
"""Generate a function name for this tool"""
|
118
|
+
return self.action.lower()
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import pytest
|
2
2
|
from uuid import UUID
|
3
3
|
|
4
|
-
from vellum.workflows.types.definition import DeploymentDefinition
|
4
|
+
from vellum.workflows.types.definition import ComposioToolDefinition, DeploymentDefinition
|
5
5
|
|
6
6
|
|
7
7
|
@pytest.mark.parametrize(
|
@@ -31,3 +31,16 @@ def test_deployment_definition(deployment_value, expected_deployment_id, expecte
|
|
31
31
|
|
32
32
|
assert deployment.deployment_id == expected_deployment_id
|
33
33
|
assert deployment.deployment_name == expected_deployment_name
|
34
|
+
|
35
|
+
|
36
|
+
def test_composio_tool_definition_creation():
|
37
|
+
"""Test that ComposioToolDefinition can be created with required fields."""
|
38
|
+
composio_tool = ComposioToolDefinition(
|
39
|
+
toolkit="GITHUB", action="GITHUB_CREATE_AN_ISSUE", description="Create a new issue in a GitHub repository"
|
40
|
+
)
|
41
|
+
|
42
|
+
assert composio_tool.toolkit == "GITHUB"
|
43
|
+
assert composio_tool.action == "GITHUB_CREATE_AN_ISSUE"
|
44
|
+
assert composio_tool.description == "Create a new issue in a GitHub repository"
|
45
|
+
assert composio_tool.display_name is None
|
46
|
+
assert composio_tool.name == "github_create_an_issue"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: vellum-ai
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.4
|
4
4
|
Summary:
|
5
5
|
License: MIT
|
6
6
|
Requires-Python: >=3.9,<4.0
|
@@ -22,6 +22,8 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
22
|
Classifier: Typing :: Typed
|
23
23
|
Requires-Dist: Jinja2 (>=3.1.0,<4.0.0)
|
24
24
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
25
|
+
Requires-Dist: composio-client (>=1.5.0,<2.0.0)
|
26
|
+
Requires-Dist: composio-core (>=0.7.20,<1.0.0)
|
25
27
|
Requires-Dist: docker (>=7.1.0,<8.0.0)
|
26
28
|
Requires-Dist: httpx (>=0.21.2)
|
27
29
|
Requires-Dist: openai (>=1.0.0,<2.0.0)
|
@@ -144,7 +144,7 @@ vellum/client/README.md,sha256=Dle5iytCXxP1pNeNd7uZyhFo0rl7tp7vU7s8gmi10OQ,4863
|
|
144
144
|
vellum/client/__init__.py,sha256=KmkyOgReuTsjmXF3WC_dPQ9QqJgYrB3Sr8_LcSUIQyI,125258
|
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=
|
147
|
+
vellum/client/core/client_wrapper.py,sha256=im_0U7PdkUrr4begxJ1IwohjLbmzi8c2diHiklFefHE,2383
|
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=cKs2w0ybDBk1wHQf-fTALm_MmvaMe3cZKcYJxqmCxkE,19539
|
@@ -499,7 +499,7 @@ vellum/client/types/open_ai_vectorizer_text_embedding_3_small.py,sha256=T_-P7qGj
|
|
499
499
|
vellum/client/types/open_ai_vectorizer_text_embedding_3_small_request.py,sha256=-lwNeWj7ExP-JLncUp1Uyd20FxweVIDu-aEnenPB98A,841
|
500
500
|
vellum/client/types/open_ai_vectorizer_text_embedding_ada_002.py,sha256=c4vNlR6lRvUjq-67M06sroDMNMG_qC4JUBqwmKEJQ2I,812
|
501
501
|
vellum/client/types/open_ai_vectorizer_text_embedding_ada_002_request.py,sha256=FdpkkNBGgRwfqFjBwpfH4t2zKIM0pIYminX2iZQUzvY,841
|
502
|
-
vellum/client/types/organization_limit_config.py,sha256=-
|
502
|
+
vellum/client/types/organization_limit_config.py,sha256=-RXRY_Rpt8hHbJtNxJZvfKo1cUEnlvvGCRhk401jLU0,956
|
503
503
|
vellum/client/types/organization_read.py,sha256=c5Wl5KY6plC7DuPJq6zAK_UTH2XVhT7H8OdEtxLqN98,854
|
504
504
|
vellum/client/types/paginated_container_image_read_list.py,sha256=7lwIgs1q7Z0xDYPGWPnjSNC1kU_peu79CotzaaQfRdA,801
|
505
505
|
vellum/client/types/paginated_deployment_release_tag_read_list.py,sha256=hp7D74CxPY14dEPRZ-fnTCwp63upxkYquL1e74oYXh4,826
|
@@ -853,11 +853,11 @@ vellum/plugins/utils.py,sha256=cPmxE9R2CK1bki2jKE8rB-G9zMf2pzHjSPDHFPXwd3Q,878
|
|
853
853
|
vellum/plugins/vellum_mypy.py,sha256=hfjC2rIxNdQuJa6fIN4PDgODnQ3YaUszyaV2eNbLJlE,27952
|
854
854
|
vellum/prompts/__init__.py,sha256=kn-btvQOMNnnBuyQiUpie48_VBJAk7tFFU-ul5dwK60,107
|
855
855
|
vellum/prompts/blocks/__init__.py,sha256=Zwvncjd8sUCPmT-8pFpgLYsKJl0xB6td1GTQzjV9hYA,108
|
856
|
-
vellum/prompts/blocks/compilation.py,sha256=
|
856
|
+
vellum/prompts/blocks/compilation.py,sha256=wI9IRj-atd8GYJnOhBnyumhH25e3rUYC5uTcMVEyktw,10212
|
857
857
|
vellum/prompts/blocks/exceptions.py,sha256=vmk5PV6Vyw9nKjZYQDUDW0LH8MfQNIgFvFb_mFWdIRI,50
|
858
858
|
vellum/prompts/blocks/helpers.py,sha256=7G1Qi6N3V1K73iqTypMTcl6Rum7wk449yHStkakLy-U,961
|
859
859
|
vellum/prompts/blocks/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
860
|
-
vellum/prompts/blocks/tests/test_compilation.py,sha256=
|
860
|
+
vellum/prompts/blocks/tests/test_compilation.py,sha256=r8Z2x6QUiHhP183MtRTYxNxoxADWx_DN2HM5iStnfAg,7885
|
861
861
|
vellum/prompts/blocks/types.py,sha256=6aSJQco-5kKeadfKVVXF_SrQPlIJgMYVNc-C7so1sY8,975
|
862
862
|
vellum/prompts/constants.py,sha256=fnjiRWLoRlC4Puo5oQcpZD5Hd-EesxsAo9l5tGAkpZQ,270
|
863
863
|
vellum/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -1535,7 +1535,7 @@ vellum/workflows/__init__.py,sha256=CssPsbNvN6rDhoLuqpEv7MMKGa51vE6dvAh6U31Pcio,
|
|
1535
1535
|
vellum/workflows/constants.py,sha256=2yg4_uo5gpqViy3ZLSwfC8qTybleYCtOnhA4Rj6bacM,1310
|
1536
1536
|
vellum/workflows/context.py,sha256=jvMuyeRluay8BQa7GX1TqUlmoHLCycAVYKkp87sfXSo,1644
|
1537
1537
|
vellum/workflows/descriptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1538
|
-
vellum/workflows/descriptors/base.py,sha256=
|
1538
|
+
vellum/workflows/descriptors/base.py,sha256=nZeCuuoJj3eJJjhrqOyfBB4FLUkN6fuO8PDdx6YDkzc,15373
|
1539
1539
|
vellum/workflows/descriptors/exceptions.py,sha256=gUy4UD9JFUKSeQnQpeuDSLiRqWjWiIsxLahB7p_q3JY,54
|
1540
1540
|
vellum/workflows/descriptors/tests/test_utils.py,sha256=HJ5DoRz0sJvViGxyZ_FtytZjxN2J8xTkGtaVwCy6Q90,6928
|
1541
1541
|
vellum/workflows/descriptors/utils.py,sha256=1siECBf6AI54gwwUwkF6mP9rYsRryUGaOYBbMpQaceM,3848
|
@@ -1561,6 +1561,7 @@ vellum/workflows/expressions/and_.py,sha256=I7lNqrUM3-m_5hmjjiMhaHhJtKcLj39kEFVW
|
|
1561
1561
|
vellum/workflows/expressions/begins_with.py,sha256=FnWsQXbENm0ZwkfEP7dR8Qx4_MMrzj6C1yqAV2KaNHw,1123
|
1562
1562
|
vellum/workflows/expressions/between.py,sha256=dVeddT6YA91eOAlE1Utg7C7gnCiYE7WP-dg17yXUeAY,1492
|
1563
1563
|
vellum/workflows/expressions/coalesce_expression.py,sha256=s4pcfu8KkUaUlQkB6BoQUKitGmV1FIQfV4agHHZtd98,1194
|
1564
|
+
vellum/workflows/expressions/concat.py,sha256=bFiHeCpZWfMMO_nvFmM5RgN-hoh-5ThBtxP0EJ2F7BE,1105
|
1564
1565
|
vellum/workflows/expressions/contains.py,sha256=B1Ub63119QmwPKvBt8vDqQbuiaJWh-_2k5ZUnUNZZak,1392
|
1565
1566
|
vellum/workflows/expressions/does_not_begin_with.py,sha256=qcnIJsxg4Jt82i2L-PW6ZhKP3C-OlEiXbiIgwHQc5RE,1137
|
1566
1567
|
vellum/workflows/expressions/does_not_contain.py,sha256=ZdHVewTe_pbPGB0cGv_gIq_4jKkv_oG2tX3RBdEGWoA,1266
|
@@ -1588,6 +1589,7 @@ vellum/workflows/expressions/or_.py,sha256=s-8YdMSSCDS2yijR38kguwok3iqmDMMgDYKV9
|
|
1588
1589
|
vellum/workflows/expressions/parse_json.py,sha256=xsk6j3HF7bU1yF6fwt5P9Ugcyd5D9ZXrdng11FRilUI,1088
|
1589
1590
|
vellum/workflows/expressions/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1590
1591
|
vellum/workflows/expressions/tests/test_accessor.py,sha256=g2z0mJjuWwVKeXS0yGoFW-aRmT5n_LrhfuBorSmj9kI,7585
|
1592
|
+
vellum/workflows/expressions/tests/test_concat.py,sha256=fDHXlmFvCtqPkdZQD9Qs22i6sJq_MJjbUXCnTlSMvA0,1666
|
1591
1593
|
vellum/workflows/expressions/tests/test_expressions.py,sha256=3b6k8xs-CItBBw95NygFLUNoNPKxI4VA1GyWbkMtqyI,11623
|
1592
1594
|
vellum/workflows/expressions/tests/test_parse_json.py,sha256=zpB_qE5_EwWQL7ULQUJm0o1PRSfWZdAqZNW6Ah13oJE,1059
|
1593
1595
|
vellum/workflows/graph/__init__.py,sha256=3sHlay5d_-uD7j3QJXiGl0WHFZZ_QScRvgyDhN2GhHY,74
|
@@ -1668,7 +1670,7 @@ vellum/workflows/nodes/displayable/guardrail_node/test_node.py,sha256=SAGv6hSFcB
|
|
1668
1670
|
vellum/workflows/nodes/displayable/guardrail_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1669
1671
|
vellum/workflows/nodes/displayable/guardrail_node/tests/test_node.py,sha256=X2pd6TI8miYxIa7rgvs1pHTEreyWcf77EyR0_Jsa700,2055
|
1670
1672
|
vellum/workflows/nodes/displayable/inline_prompt_node/__init__.py,sha256=gSUOoEZLlrx35-tQhSAd3An8WDwBqyiQh-sIebLU9wU,74
|
1671
|
-
vellum/workflows/nodes/displayable/inline_prompt_node/node.py,sha256=
|
1673
|
+
vellum/workflows/nodes/displayable/inline_prompt_node/node.py,sha256=wgZ9bt9IFe5cqWSghfMlD1NgmFhRnuDLRzXzMhJomV0,2912
|
1672
1674
|
vellum/workflows/nodes/displayable/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1673
1675
|
vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py,sha256=bBHs90mV5SZ3rJPAL0wx4WWyawUA406LgMPOdvpZC_A,10923
|
1674
1676
|
vellum/workflows/nodes/displayable/merge_node/__init__.py,sha256=J8IC08dSH7P76wKlNuxe1sn7toNGtSQdFirUbtPDEs0,60
|
@@ -1676,7 +1678,7 @@ vellum/workflows/nodes/displayable/merge_node/node.py,sha256=nZtGGVAvY4fvGg8vwV6
|
|
1676
1678
|
vellum/workflows/nodes/displayable/note_node/__init__.py,sha256=KWA3P4fyYJ-fOTky8qNGlcOotQ-HeHJ9AjZt6mRQmCE,58
|
1677
1679
|
vellum/workflows/nodes/displayable/note_node/node.py,sha256=sIN1VBQ7zeT3GhN0kupXbFfdpvgedWV79k4woJNp5IQ,394
|
1678
1680
|
vellum/workflows/nodes/displayable/prompt_deployment_node/__init__.py,sha256=krX1Hds-TSVYZsx0wJFX4wsAKkEFYOX1ifwRGiIM-EA,82
|
1679
|
-
vellum/workflows/nodes/displayable/prompt_deployment_node/node.py,sha256=
|
1681
|
+
vellum/workflows/nodes/displayable/prompt_deployment_node/node.py,sha256=r-HGevtJ0wXPPW58dNfF3euuDmXO-p1Qm8WuJTJqVtg,3312
|
1680
1682
|
vellum/workflows/nodes/displayable/prompt_deployment_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1681
1683
|
vellum/workflows/nodes/displayable/prompt_deployment_node/tests/test_node.py,sha256=c_nuuqrwiIjgj4qIbVypfDuOc-3TlgO6CbXFqQl2Nqw,19725
|
1682
1684
|
vellum/workflows/nodes/displayable/search_node/__init__.py,sha256=hpBpvbrDYf43DElRZFLzieSn8weXiwNiiNOJurERQbs,62
|
@@ -1693,12 +1695,14 @@ vellum/workflows/nodes/displayable/tests/test_search_node_error_handling.py,sha2
|
|
1693
1695
|
vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py,sha256=VepO5z1277c1y5N6LLIC31nnWD1aak2m5oPFplfJHHs,6935
|
1694
1696
|
vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py,sha256=dc3EEn1sOICpr3GdS8eyeFtExaGwWWcw9eHSdkRhQJU,2584
|
1695
1697
|
vellum/workflows/nodes/displayable/tool_calling_node/__init__.py,sha256=3n0-ysmFKsr40CVxPthc0rfJgqVJeZuUEsCmYudLVRg,117
|
1698
|
+
vellum/workflows/nodes/displayable/tool_calling_node/composio_service.py,sha256=C53hgStA-BHe7EFu4j_N650LqsLBOiMovs_nGW8J7nc,2669
|
1696
1699
|
vellum/workflows/nodes/displayable/tool_calling_node/node.py,sha256=BRA6YRCEOk0Nw3DCIT13WY7WCZ7Gx30s-egJe_md0FA,6504
|
1697
1700
|
vellum/workflows/nodes/displayable/tool_calling_node/state.py,sha256=oQg_GAtc349nPB5BL_oeDYYD7q1qSDPAqjj8iA8OoAw,215
|
1698
1701
|
vellum/workflows/nodes/displayable/tool_calling_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1702
|
+
vellum/workflows/nodes/displayable/tool_calling_node/tests/test_composio_service.py,sha256=BOb4LTAELS-cX5xPH8fH4E2CKl1IBBjiOBYhQl51PpI,4758
|
1699
1703
|
vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py,sha256=raY_E5-EgtYNXEPbO2I-Ythe4YeuFdGsXGZ_BAN98uI,7979
|
1700
1704
|
vellum/workflows/nodes/displayable/tool_calling_node/tests/test_utils.py,sha256=eu6WTyENhGLg9pGp_j69rysZjf_qiQXske1YdZn9PzU,1718
|
1701
|
-
vellum/workflows/nodes/displayable/tool_calling_node/utils.py,sha256=
|
1705
|
+
vellum/workflows/nodes/displayable/tool_calling_node/utils.py,sha256=jMXStMKr3BFfQKdQa9hFFxI7RQp8eAMAknpqkbY0Nk0,13344
|
1702
1706
|
vellum/workflows/nodes/experimental/README.md,sha256=eF6DfIL8t-HbF9-mcofOMymKrraiBHDLKTlnBa51ZiE,284
|
1703
1707
|
vellum/workflows/nodes/experimental/__init__.py,sha256=jCQgvZEknXKfuNhGSOou4XPfrPqZ1_XBj5F0n0fgiWM,106
|
1704
1708
|
vellum/workflows/nodes/experimental/openai_chat_completion_node/__init__.py,sha256=lsyD9laR9p7kx5-BXGH2gUTM242UhKy8SMV0SR6S2iE,90
|
@@ -1745,12 +1749,12 @@ vellum/workflows/tests/test_sandbox.py,sha256=JKwaluI-lODQo7Ek9sjDstjL_WTdSqUlVi
|
|
1745
1749
|
vellum/workflows/tests/test_undefined.py,sha256=zMCVliCXVNLrlC6hEGyOWDnQADJ2g83yc5FIM33zuo8,353
|
1746
1750
|
vellum/workflows/types/__init__.py,sha256=KxUTMBGzuRCfiMqzzsykOeVvrrkaZmTTo1a7SLu8gRM,68
|
1747
1751
|
vellum/workflows/types/code_execution_node_wrappers.py,sha256=3MNIoFZKzVzNS5qFLVuDwMV17QJw72zo7NRf52yMq5A,3074
|
1748
|
-
vellum/workflows/types/core.py,sha256=
|
1749
|
-
vellum/workflows/types/definition.py,sha256=
|
1752
|
+
vellum/workflows/types/core.py,sha256=6MW_BRLcx4oEJpItQWQa64xfCrsk76suZSsMKKEsJLg,1314
|
1753
|
+
vellum/workflows/types/definition.py,sha256=Oq2E5Ae6AsvqAOLWzP0k6H5M7su00JZP_QFhlV2rz7s,3721
|
1750
1754
|
vellum/workflows/types/generics.py,sha256=8jptbEx1fnJV0Lhj0MpCJOT6yNiEWeTOYOwrEAb5CRU,1576
|
1751
1755
|
vellum/workflows/types/stack.py,sha256=h7NE0vXR7l9DevFBIzIAk1Zh59K-kECQtDTKOUunwMY,1314
|
1752
1756
|
vellum/workflows/types/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1753
|
-
vellum/workflows/types/tests/test_definition.py,sha256=
|
1757
|
+
vellum/workflows/types/tests/test_definition.py,sha256=c3GczPtWxuH3BOULwZacxYTQlP2ryqH7rvT_anDORVo,1604
|
1754
1758
|
vellum/workflows/types/tests/test_utils.py,sha256=UnZog59tR577mVwqZRqqWn2fScoOU1H6up0EzS8zYhw,2536
|
1755
1759
|
vellum/workflows/types/utils.py,sha256=mTctHITBybpt4855x32oCKALBEcMNLn-9cCmfEKgJHQ,6498
|
1756
1760
|
vellum/workflows/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -1771,8 +1775,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
|
|
1771
1775
|
vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1772
1776
|
vellum/workflows/workflows/tests/test_base_workflow.py,sha256=ptMntHzVyy8ZuzNgeTuk7hREgKQ5UBdgq8VJFSGaW4Y,20832
|
1773
1777
|
vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
|
1774
|
-
vellum_ai-1.0.
|
1775
|
-
vellum_ai-1.0.
|
1776
|
-
vellum_ai-1.0.
|
1777
|
-
vellum_ai-1.0.
|
1778
|
-
vellum_ai-1.0.
|
1778
|
+
vellum_ai-1.0.4.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
1779
|
+
vellum_ai-1.0.4.dist-info/METADATA,sha256=a7IAzLZ3FlACUej3-52w1DORsAgXM5tpzkLJ8XAgnIQ,5649
|
1780
|
+
vellum_ai-1.0.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
1781
|
+
vellum_ai-1.0.4.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
|
1782
|
+
vellum_ai-1.0.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|