vellum-ai 1.5.1__py3-none-any.whl → 1.5.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/client/core/client_wrapper.py +2 -2
- vellum/workflows/integrations/tests/test_vellum_integration_service.py +173 -192
- vellum/workflows/integrations/vellum_integration_service.py +14 -12
- vellum/workflows/types/definition.py +11 -0
- vellum/workflows/utils/functions.py +5 -3
- {vellum_ai-1.5.1.dist-info → vellum_ai-1.5.2.dist-info}/METADATA +1 -1
- {vellum_ai-1.5.1.dist-info → vellum_ai-1.5.2.dist-info}/RECORD +13 -13
- vellum_ee/assets/node-definitions.json +49 -8
- vellum_ee/scripts/generate_node_definitions.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/map_node.py +17 -3
- {vellum_ai-1.5.1.dist-info → vellum_ai-1.5.2.dist-info}/LICENSE +0 -0
- {vellum_ai-1.5.1.dist-info → vellum_ai-1.5.2.dist-info}/WHEEL +0 -0
- {vellum_ai-1.5.1.dist-info → vellum_ai-1.5.2.dist-info}/entry_points.txt +0 -0
@@ -27,10 +27,10 @@ class BaseClientWrapper:
|
|
27
27
|
|
28
28
|
def get_headers(self) -> typing.Dict[str, str]:
|
29
29
|
headers: typing.Dict[str, str] = {
|
30
|
-
"User-Agent": "vellum-ai/1.5.
|
30
|
+
"User-Agent": "vellum-ai/1.5.2",
|
31
31
|
"X-Fern-Language": "Python",
|
32
32
|
"X-Fern-SDK-Name": "vellum-ai",
|
33
|
-
"X-Fern-SDK-Version": "1.5.
|
33
|
+
"X-Fern-SDK-Version": "1.5.2",
|
34
34
|
**(self.get_custom_headers() or {}),
|
35
35
|
}
|
36
36
|
if self._api_version is not None:
|
@@ -1,225 +1,206 @@
|
|
1
1
|
import pytest
|
2
2
|
from unittest import mock
|
3
3
|
|
4
|
+
from vellum.workflows.constants import VellumIntegrationProviderType
|
4
5
|
from vellum.workflows.exceptions import NodeException
|
5
6
|
from vellum.workflows.integrations.vellum_integration_service import VellumIntegrationService
|
7
|
+
from vellum.workflows.types.definition import VellumIntegrationToolDetails
|
6
8
|
|
7
9
|
|
8
|
-
def test_vellum_integration_service_get_tool_definition_success():
|
10
|
+
def test_vellum_integration_service_get_tool_definition_success(vellum_client):
|
9
11
|
"""Test that tool definitions are successfully retrieved from Vellum API"""
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
"type": "
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
12
|
+
mock_client = vellum_client
|
13
|
+
mock_client.integrations = mock.MagicMock()
|
14
|
+
|
15
|
+
mock_response = mock.MagicMock()
|
16
|
+
mock_response.name = "GITHUB_CREATE_AN_ISSUE"
|
17
|
+
mock_response.description = "Create a new issue in a GitHub repository"
|
18
|
+
mock_response.parameters = {
|
19
|
+
"type": "object",
|
20
|
+
"properties": {
|
21
|
+
"repo": {"type": "string", "description": "Repository name"},
|
22
|
+
"title": {"type": "string", "description": "Issue title"},
|
23
|
+
"body": {"type": "string", "description": "Issue body"},
|
24
|
+
},
|
25
|
+
"required": ["repo", "title"],
|
26
|
+
}
|
27
|
+
mock_response.provider = "COMPOSIO"
|
28
|
+
|
29
|
+
mock_client.integrations.retrieve_integration_tool_definition.return_value = mock_response
|
30
|
+
|
31
|
+
# WHEN we request a tool definition
|
32
|
+
service = VellumIntegrationService(client=mock_client)
|
33
|
+
result = service.get_tool_definition(
|
34
|
+
integration="GITHUB",
|
35
|
+
provider="COMPOSIO",
|
36
|
+
tool_name="GITHUB_CREATE_AN_ISSUE",
|
37
|
+
)
|
38
|
+
|
39
|
+
# THEN the tool definition should be returned with all expected fields
|
40
|
+
assert isinstance(result, VellumIntegrationToolDetails)
|
41
|
+
assert result.name == "GITHUB_CREATE_AN_ISSUE"
|
42
|
+
assert result.description == "Create a new issue in a GitHub repository"
|
43
|
+
assert result.provider == VellumIntegrationProviderType.COMPOSIO
|
44
|
+
# Parameters should now be included in the tool details
|
45
|
+
assert result.parameters is not None
|
46
|
+
assert result.parameters["type"] == "object"
|
47
|
+
assert "properties" in result.parameters
|
48
|
+
assert "repo" in result.parameters["properties"]
|
49
|
+
assert "title" in result.parameters["properties"]
|
50
|
+
|
51
|
+
# AND the API should have been called with the correct parameters
|
52
|
+
mock_client.integrations.retrieve_integration_tool_definition.assert_called_once_with(
|
53
|
+
integration="GITHUB",
|
54
|
+
provider="COMPOSIO",
|
55
|
+
tool_name="GITHUB_CREATE_AN_ISSUE",
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
def test_vellum_integration_service_get_tool_definition_api_error(vellum_client):
|
60
|
+
"""Test that API errors are properly handled when retrieving tool definitions"""
|
61
|
+
mock_client = vellum_client
|
62
|
+
mock_client.integrations = mock.MagicMock()
|
63
|
+
mock_client.integrations.retrieve_integration_tool_definition.side_effect = Exception("Tool not found")
|
40
64
|
|
41
|
-
|
42
|
-
|
43
|
-
assert result["description"] == "Create a new issue in a GitHub repository"
|
44
|
-
assert result["provider"] == "COMPOSIO"
|
45
|
-
assert "properties" in result["parameters"]
|
46
|
-
assert "repo" in result["parameters"]["properties"]
|
65
|
+
# WHEN we attempt to get a tool definition for an invalid tool
|
66
|
+
service = VellumIntegrationService(client=mock_client)
|
47
67
|
|
48
|
-
|
49
|
-
|
68
|
+
# THEN it should raise a NodeException with appropriate error message
|
69
|
+
with pytest.raises(NodeException) as exc_info:
|
70
|
+
service.get_tool_definition(
|
50
71
|
integration="GITHUB",
|
51
72
|
provider="COMPOSIO",
|
52
|
-
tool_name="
|
73
|
+
tool_name="INVALID_TOOL",
|
53
74
|
)
|
54
75
|
|
55
|
-
|
56
|
-
|
57
|
-
"""Test that API errors are properly handled when retrieving tool definitions"""
|
58
|
-
with mock.patch(
|
59
|
-
"vellum.workflows.integrations.vellum_integration_service.create_vellum_client"
|
60
|
-
) as mock_create_client:
|
61
|
-
# GIVEN a mock client that raises an exception when retrieving tool definitions
|
62
|
-
mock_client = mock.MagicMock()
|
63
|
-
mock_create_client.return_value = mock_client
|
64
|
-
|
65
|
-
mock_client.integrations.retrieve_integration_tool_definition.side_effect = Exception("Tool not found")
|
66
|
-
|
67
|
-
# WHEN we attempt to get a tool definition for an invalid tool
|
68
|
-
service = VellumIntegrationService()
|
69
|
-
|
70
|
-
# THEN it should raise a NodeException with appropriate error message
|
71
|
-
with pytest.raises(NodeException) as exc_info:
|
72
|
-
service.get_tool_definition(
|
73
|
-
integration="GITHUB",
|
74
|
-
provider="COMPOSIO",
|
75
|
-
tool_name="INVALID_TOOL",
|
76
|
-
)
|
77
|
-
|
78
|
-
assert "Failed to retrieve tool definition" in str(exc_info.value)
|
79
|
-
assert "Tool not found" in str(exc_info.value)
|
76
|
+
assert "Failed to retrieve tool definition" in str(exc_info.value)
|
77
|
+
assert "Tool not found" in str(exc_info.value)
|
80
78
|
|
81
79
|
|
82
|
-
def test_vellum_integration_service_execute_tool_success():
|
80
|
+
def test_vellum_integration_service_execute_tool_success(vellum_client):
|
83
81
|
"""Test that tools are successfully executed via Vellum API"""
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
82
|
+
mock_client = vellum_client
|
83
|
+
mock_client.integrations = mock.MagicMock()
|
84
|
+
|
85
|
+
mock_response = mock.MagicMock()
|
86
|
+
mock_response.data = {
|
87
|
+
"success": True,
|
88
|
+
"issue_id": 123,
|
89
|
+
"issue_url": "https://github.com/user/repo/issues/123",
|
90
|
+
}
|
91
|
+
|
92
|
+
mock_client.integrations.execute_integration_tool.return_value = mock_response
|
93
|
+
|
94
|
+
# WHEN we execute a tool with valid arguments
|
95
|
+
service = VellumIntegrationService(client=mock_client)
|
96
|
+
result = service.execute_tool(
|
97
|
+
integration="GITHUB",
|
98
|
+
provider="COMPOSIO",
|
99
|
+
tool_name="GITHUB_CREATE_AN_ISSUE",
|
100
|
+
arguments={
|
101
|
+
"repo": "user/repo",
|
102
|
+
"title": "Test Issue",
|
103
|
+
"body": "Test body",
|
104
|
+
},
|
105
|
+
)
|
106
|
+
|
107
|
+
# THEN the execution result should contain expected data
|
108
|
+
assert result["success"] is True
|
109
|
+
assert result["issue_id"] == 123
|
110
|
+
assert result["issue_url"] == "https://github.com/user/repo/issues/123"
|
111
|
+
|
112
|
+
# AND the API should have been called with correct parameters
|
113
|
+
mock_client.integrations.execute_integration_tool.assert_called_once_with(
|
114
|
+
integration="GITHUB",
|
115
|
+
provider="COMPOSIO",
|
116
|
+
tool_name="GITHUB_CREATE_AN_ISSUE",
|
117
|
+
arguments={
|
118
|
+
"repo": "user/repo",
|
119
|
+
"title": "Test Issue",
|
120
|
+
"body": "Test body",
|
121
|
+
},
|
122
|
+
)
|
123
|
+
|
124
|
+
|
125
|
+
def test_vellum_integration_service_execute_tool_api_error(vellum_client):
|
126
|
+
"""Test that execution errors are properly handled"""
|
127
|
+
mock_client = vellum_client
|
128
|
+
mock_client.integrations = mock.MagicMock()
|
129
|
+
mock_client.integrations.execute_integration_tool.side_effect = Exception("Authentication failed")
|
112
130
|
|
113
|
-
|
114
|
-
|
115
|
-
assert result["issue_id"] == 123
|
116
|
-
assert result["issue_url"] == "https://github.com/user/repo/issues/123"
|
131
|
+
# WHEN we attempt to execute a tool that encounters an error
|
132
|
+
service = VellumIntegrationService(client=mock_client)
|
117
133
|
|
118
|
-
|
119
|
-
|
134
|
+
# THEN it should raise a NodeException with appropriate error message
|
135
|
+
with pytest.raises(NodeException) as exc_info:
|
136
|
+
service.execute_tool(
|
120
137
|
integration="GITHUB",
|
121
138
|
provider="COMPOSIO",
|
122
139
|
tool_name="GITHUB_CREATE_AN_ISSUE",
|
123
|
-
arguments={
|
124
|
-
"repo": "user/repo",
|
125
|
-
"title": "Test Issue",
|
126
|
-
"body": "Test body",
|
127
|
-
},
|
140
|
+
arguments={"repo": "user/repo"},
|
128
141
|
)
|
129
142
|
|
143
|
+
assert "Failed to execute tool" in str(exc_info.value)
|
144
|
+
assert "Authentication failed" in str(exc_info.value)
|
130
145
|
|
131
|
-
def test_vellum_integration_service_execute_tool_api_error():
|
132
|
-
"""Test that execution errors are properly handled"""
|
133
|
-
with mock.patch(
|
134
|
-
"vellum.workflows.integrations.vellum_integration_service.create_vellum_client"
|
135
|
-
) as mock_create_client:
|
136
|
-
# GIVEN a mock client that raises an exception during tool execution
|
137
|
-
mock_client = mock.MagicMock()
|
138
|
-
mock_create_client.return_value = mock_client
|
139
|
-
|
140
|
-
mock_client.integrations.execute_integration_tool.side_effect = Exception("Authentication failed")
|
141
|
-
|
142
|
-
# WHEN we attempt to execute a tool that encounters an error
|
143
|
-
service = VellumIntegrationService()
|
144
146
|
|
145
|
-
|
146
|
-
with pytest.raises(NodeException) as exc_info:
|
147
|
-
service.execute_tool(
|
148
|
-
integration="GITHUB",
|
149
|
-
provider="COMPOSIO",
|
150
|
-
tool_name="GITHUB_CREATE_AN_ISSUE",
|
151
|
-
arguments={"repo": "user/repo"},
|
152
|
-
)
|
153
|
-
|
154
|
-
assert "Failed to execute tool" in str(exc_info.value)
|
155
|
-
assert "Authentication failed" in str(exc_info.value)
|
156
|
-
|
157
|
-
|
158
|
-
def test_vellum_integration_service_execute_tool_empty_response():
|
147
|
+
def test_vellum_integration_service_execute_tool_empty_response(vellum_client):
|
159
148
|
"""Test that empty response data is handled gracefully"""
|
160
|
-
|
161
|
-
|
162
|
-
) as mock_create_client:
|
163
|
-
# GIVEN a mock client that returns an empty response
|
164
|
-
mock_client = mock.MagicMock()
|
165
|
-
mock_create_client.return_value = mock_client
|
166
|
-
|
167
|
-
mock_response = mock.MagicMock()
|
168
|
-
mock_response.data = {}
|
169
|
-
|
170
|
-
mock_client.integrations.execute_integration_tool.return_value = mock_response
|
171
|
-
|
172
|
-
# WHEN we execute a tool that returns empty data
|
173
|
-
service = VellumIntegrationService()
|
174
|
-
result = service.execute_tool(
|
175
|
-
integration="SLACK",
|
176
|
-
provider="COMPOSIO",
|
177
|
-
tool_name="SLACK_SEND_MESSAGE",
|
178
|
-
arguments={
|
179
|
-
"channel": "#general",
|
180
|
-
"message": "Hello, world!",
|
181
|
-
},
|
182
|
-
)
|
149
|
+
mock_client = vellum_client
|
150
|
+
mock_client.integrations = mock.MagicMock()
|
183
151
|
|
184
|
-
|
185
|
-
|
152
|
+
mock_response = mock.MagicMock()
|
153
|
+
mock_response.data = {}
|
186
154
|
|
155
|
+
mock_client.integrations.execute_integration_tool.return_value = mock_response
|
187
156
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
"
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
mock.MagicMock(data={"result": "second"}),
|
200
|
-
]
|
201
|
-
mock_client.integrations.execute_integration_tool.side_effect = responses
|
202
|
-
|
203
|
-
# WHEN we execute multiple tools in sequence
|
204
|
-
service = VellumIntegrationService()
|
205
|
-
|
206
|
-
result1 = service.execute_tool(
|
207
|
-
integration="GITHUB",
|
208
|
-
provider="COMPOSIO",
|
209
|
-
tool_name="TOOL_1",
|
210
|
-
arguments={"arg": "val1"},
|
211
|
-
)
|
157
|
+
# WHEN we execute a tool that returns empty data
|
158
|
+
service = VellumIntegrationService(client=mock_client)
|
159
|
+
result = service.execute_tool(
|
160
|
+
integration="SLACK",
|
161
|
+
provider="COMPOSIO",
|
162
|
+
tool_name="SLACK_SEND_MESSAGE",
|
163
|
+
arguments={
|
164
|
+
"channel": "#general",
|
165
|
+
"message": "Hello, world!",
|
166
|
+
},
|
167
|
+
)
|
212
168
|
|
213
|
-
|
214
|
-
|
215
|
-
provider="COMPOSIO",
|
216
|
-
tool_name="TOOL_2",
|
217
|
-
arguments={"arg": "val2"},
|
218
|
-
)
|
169
|
+
# THEN an empty dictionary should be returned without errors
|
170
|
+
assert result == {}
|
219
171
|
|
220
|
-
# THEN each tool execution should return its respective result
|
221
|
-
assert result1["result"] == "first"
|
222
|
-
assert result2["result"] == "second"
|
223
172
|
|
224
|
-
|
225
|
-
|
173
|
+
def test_vellum_integration_service_multiple_tool_executions(vellum_client):
|
174
|
+
"""Test that the service handles multiple sequential tool executions"""
|
175
|
+
mock_client = vellum_client
|
176
|
+
mock_client.integrations = mock.MagicMock()
|
177
|
+
|
178
|
+
responses = [
|
179
|
+
mock.MagicMock(data={"result": "first"}),
|
180
|
+
mock.MagicMock(data={"result": "second"}),
|
181
|
+
]
|
182
|
+
mock_client.integrations.execute_integration_tool.side_effect = responses
|
183
|
+
|
184
|
+
# WHEN we execute multiple tools in sequence
|
185
|
+
service = VellumIntegrationService(client=mock_client)
|
186
|
+
|
187
|
+
result1 = service.execute_tool(
|
188
|
+
integration="GITHUB",
|
189
|
+
provider="COMPOSIO",
|
190
|
+
tool_name="TOOL_1",
|
191
|
+
arguments={"arg": "val1"},
|
192
|
+
)
|
193
|
+
|
194
|
+
result2 = service.execute_tool(
|
195
|
+
integration="SLACK",
|
196
|
+
provider="COMPOSIO",
|
197
|
+
tool_name="TOOL_2",
|
198
|
+
arguments={"arg": "val2"},
|
199
|
+
)
|
200
|
+
|
201
|
+
# THEN each tool execution should return its respective result
|
202
|
+
assert result1["result"] == "first"
|
203
|
+
assert result2["result"] == "second"
|
204
|
+
|
205
|
+
# AND the API should have been called twice
|
206
|
+
assert mock_client.integrations.execute_integration_tool.call_count == 2
|
@@ -1,7 +1,9 @@
|
|
1
|
-
from typing import Any, Dict
|
1
|
+
from typing import Any, Dict, Optional
|
2
2
|
|
3
|
+
from vellum.workflows.constants import VellumIntegrationProviderType
|
3
4
|
from vellum.workflows.errors.types import WorkflowErrorCode
|
4
5
|
from vellum.workflows.exceptions import NodeException
|
6
|
+
from vellum.workflows.types.definition import VellumIntegrationToolDetails
|
5
7
|
from vellum.workflows.vellum_client import create_vellum_client
|
6
8
|
|
7
9
|
|
@@ -13,16 +15,16 @@ class VellumIntegrationService:
|
|
13
15
|
own integration infrastructure.
|
14
16
|
"""
|
15
17
|
|
16
|
-
def __init__(self) -> None:
|
18
|
+
def __init__(self, client: Optional[Any] = None) -> None:
|
17
19
|
"""Initialize the VellumIntegrationService with a Vellum client."""
|
18
|
-
self._client = create_vellum_client()
|
20
|
+
self._client = client or create_vellum_client()
|
19
21
|
|
20
22
|
def get_tool_definition(
|
21
23
|
self,
|
22
24
|
integration: str,
|
23
25
|
provider: str,
|
24
26
|
tool_name: str,
|
25
|
-
) ->
|
27
|
+
) -> VellumIntegrationToolDetails:
|
26
28
|
"""Retrieve a tool definition from Vellum integrations.
|
27
29
|
|
28
30
|
Args:
|
@@ -31,7 +33,7 @@ class VellumIntegrationService:
|
|
31
33
|
tool_name: The tool's unique name as specified by the provider
|
32
34
|
|
33
35
|
Returns:
|
34
|
-
|
36
|
+
VellumIntegrationToolDetails containing the tool definition with parameters
|
35
37
|
|
36
38
|
Raises:
|
37
39
|
NodeException: If the tool definition cannot be retrieved
|
@@ -43,13 +45,13 @@ class VellumIntegrationService:
|
|
43
45
|
tool_name=tool_name,
|
44
46
|
)
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
return VellumIntegrationToolDetails(
|
49
|
+
provider=VellumIntegrationProviderType(response.provider),
|
50
|
+
integration=integration,
|
51
|
+
name=response.name,
|
52
|
+
description=response.description,
|
53
|
+
parameters=response.parameters,
|
54
|
+
)
|
53
55
|
except Exception as e:
|
54
56
|
error_message = f"Failed to retrieve tool definition for {tool_name}: {str(e)}"
|
55
57
|
raise NodeException(
|
@@ -177,6 +177,17 @@ class VellumIntegrationToolDefinition(UniversalBaseModel):
|
|
177
177
|
description: str
|
178
178
|
|
179
179
|
|
180
|
+
class VellumIntegrationToolDetails(VellumIntegrationToolDefinition):
|
181
|
+
"""Extended version of VellumIntegrationToolDefinition with runtime parameters.
|
182
|
+
|
183
|
+
This class includes the parameters field which is populated during compilation
|
184
|
+
from the Vellum integrations API response. It inherits all fields from the base
|
185
|
+
VellumIntegrationToolDefinition class.
|
186
|
+
"""
|
187
|
+
|
188
|
+
parameters: Optional[Dict[str, Any]] = None
|
189
|
+
|
190
|
+
|
180
191
|
class MCPServer(UniversalBaseModel):
|
181
192
|
type: Literal["MCP_SERVER"] = "MCP_SERVER"
|
182
193
|
name: str
|
@@ -335,13 +335,15 @@ def compile_vellum_integration_tool_definition(tool_def: VellumIntegrationToolDe
|
|
335
335
|
try:
|
336
336
|
service = VellumIntegrationService()
|
337
337
|
tool_details = service.get_tool_definition(
|
338
|
-
integration=tool_def.integration,
|
338
|
+
integration=tool_def.integration,
|
339
|
+
provider=tool_def.provider.value,
|
340
|
+
tool_name=tool_def.name,
|
339
341
|
)
|
340
342
|
|
341
343
|
return FunctionDefinition(
|
342
344
|
name=tool_def.name,
|
343
|
-
description=tool_details.
|
344
|
-
parameters=tool_details.
|
345
|
+
description=tool_details.description,
|
346
|
+
parameters=tool_details.parameters or {},
|
345
347
|
)
|
346
348
|
except Exception:
|
347
349
|
# Fallback for service failures
|
@@ -22,9 +22,9 @@ vellum_cli/tests/test_ping.py,sha256=b3aQLd-N59_8w2rRiWqwpB1rlHaKEYVbAj1Y3hi7A-g
|
|
22
22
|
vellum_cli/tests/test_pull.py,sha256=e2XHzcHIx9k-FyuNAl7wMSNsSSebPGyP6U05JGcddFs,49447
|
23
23
|
vellum_cli/tests/test_push.py,sha256=2MjkNKr_9Guv5Exjsm3L1BeVXmPkKUcCSiKnp90HgW4,41996
|
24
24
|
vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
vellum_ee/assets/node-definitions.json,sha256=
|
25
|
+
vellum_ee/assets/node-definitions.json,sha256=UDx8gBZ4Vj853aY7CSHR8JipVjZSQiKdkOKwKqwwVKw,25499
|
26
26
|
vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
-
vellum_ee/scripts/generate_node_definitions.py,sha256=
|
27
|
+
vellum_ee/scripts/generate_node_definitions.py,sha256=FOYQsXIqU45I0OAcsyZUGODF9JK44yunf58rR6YaAdA,3303
|
28
28
|
vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
29
|
vellum_ee/workflows/display/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
30
|
vellum_ee/workflows/display/base.py,sha256=R3f2T8FlZrXn2FawAmpVuLB3fKFWw11mCUulWAyIKA0,1912
|
@@ -48,7 +48,7 @@ vellum_ee/workflows/display/nodes/vellum/final_output_node.py,sha256=z4oeTgKnMGV
|
|
48
48
|
vellum_ee/workflows/display/nodes/vellum/guardrail_node.py,sha256=9_AslWjzj4RHH2sq3SIaq9FU0NCg7ex5TIWrNMybqXg,2173
|
49
49
|
vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=muyLv3KMIsUnnXhiPbPhw5B0TO1Z8LUwytpVQKlz4tM,11906
|
50
50
|
vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py,sha256=m20_ZZ3Au0ZCpI3TNC9xh54ld1X13CNq-T51VOtP23k,6434
|
51
|
-
vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=
|
51
|
+
vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=AW5JuHXtmtcJKeRiZKd7iB1re_D7G7jl_OlaZs8nUl0,4219
|
52
52
|
vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=xMHaPfTSZWYprQenlHm2g47u0a5O9Me_dhAjfqo8nKQ,3116
|
53
53
|
vellum_ee/workflows/display/nodes/vellum/note_node.py,sha256=6PcAFA_EJn7vEMdqgoRjYTLHwnXCrJv80B10zuUx4jE,1026
|
54
54
|
vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=uo4YZRV48iX4peGAA1xkGniSPrepywvW_gS7codt-VQ,3378
|
@@ -158,7 +158,7 @@ vellum/client/README.md,sha256=flqu57ubZNTfpq60CdLtJC9gp4WEkyjb_n_eZ4OYf9w,6497
|
|
158
158
|
vellum/client/__init__.py,sha256=-dZaD_0KtlkpQ-pULNNWcarC5xXlGMcGc2nBKLIyRlA,73661
|
159
159
|
vellum/client/core/__init__.py,sha256=lTcqUPXcx4112yLDd70RAPeqq6tu3eFMe1pKOqkW9JQ,1562
|
160
160
|
vellum/client/core/api_error.py,sha256=44vPoTyWN59gonCIZMdzw7M1uspygiLnr3GNFOoVL2Q,614
|
161
|
-
vellum/client/core/client_wrapper.py,sha256=
|
161
|
+
vellum/client/core/client_wrapper.py,sha256=dgP8KuamHuhB9q-zUV2SOGwlGkksYCbOSO1zmJRGB7A,2840
|
162
162
|
vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
163
163
|
vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
|
164
164
|
vellum/client/core/force_multipart.py,sha256=awxh5MtcRYe74ehY8U76jzv6fYM_w_D3Rur7KQQzSDk,429
|
@@ -1824,8 +1824,8 @@ vellum/workflows/integrations/composio_service.py,sha256=rSliaZtNiBcDSvDxz9k5i1K
|
|
1824
1824
|
vellum/workflows/integrations/mcp_service.py,sha256=9DYb8dg2_kgc1UOu830kxhaFlt9yTbhKPhK3L6kb1t4,9831
|
1825
1825
|
vellum/workflows/integrations/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1826
1826
|
vellum/workflows/integrations/tests/test_mcp_service.py,sha256=q_DYrDkIqI4sQBNgID4YdbM4e9tneLVWY8YmI4R26d8,8859
|
1827
|
-
vellum/workflows/integrations/tests/test_vellum_integration_service.py,sha256=
|
1828
|
-
vellum/workflows/integrations/vellum_integration_service.py,sha256=
|
1827
|
+
vellum/workflows/integrations/tests/test_vellum_integration_service.py,sha256=qGDV1Tx3cWoaazjfnkv8MutLYscwvSZazRqtnz3EPhY,7607
|
1828
|
+
vellum/workflows/integrations/vellum_integration_service.py,sha256=AzF2QkEcLspTV5rySA2GToirNpMmTiY07OZx-6Vq3IA,3625
|
1829
1829
|
vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
|
1830
1830
|
vellum/workflows/nodes/__init__.py,sha256=zymtc3_iW2rFmMR-sayTLuN6ZsAw8VnJweWPsjQk2-Q,1197
|
1831
1831
|
vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
|
@@ -1985,7 +1985,7 @@ vellum/workflows/tests/test_undefined.py,sha256=zMCVliCXVNLrlC6hEGyOWDnQADJ2g83y
|
|
1985
1985
|
vellum/workflows/types/__init__.py,sha256=KxUTMBGzuRCfiMqzzsykOeVvrrkaZmTTo1a7SLu8gRM,68
|
1986
1986
|
vellum/workflows/types/code_execution_node_wrappers.py,sha256=fewX9bqF_4TZuK-gZYIn12s31-k03vHMGRpvFAPm11Y,3206
|
1987
1987
|
vellum/workflows/types/core.py,sha256=yKm3sE02ult969q80DTmawiwYqodVjcAW-zlaUIgIv4,1495
|
1988
|
-
vellum/workflows/types/definition.py,sha256=
|
1988
|
+
vellum/workflows/types/definition.py,sha256=_wzpa0CtS60IIEPfhrLXmj2y9datz5XqJZhLYpml-NI,7663
|
1989
1989
|
vellum/workflows/types/generics.py,sha256=8jptbEx1fnJV0Lhj0MpCJOT6yNiEWeTOYOwrEAb5CRU,1576
|
1990
1990
|
vellum/workflows/types/stack.py,sha256=h7NE0vXR7l9DevFBIzIAk1Zh59K-kECQtDTKOUunwMY,1314
|
1991
1991
|
vellum/workflows/types/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -1993,7 +1993,7 @@ vellum/workflows/types/tests/test_definition.py,sha256=rvDYjdJ1rvAv0qHBN7i7s-_WA
|
|
1993
1993
|
vellum/workflows/types/tests/test_utils.py,sha256=UnZog59tR577mVwqZRqqWn2fScoOU1H6up0EzS8zYhw,2536
|
1994
1994
|
vellum/workflows/types/utils.py,sha256=mTctHITBybpt4855x32oCKALBEcMNLn-9cCmfEKgJHQ,6498
|
1995
1995
|
vellum/workflows/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1996
|
-
vellum/workflows/utils/functions.py,sha256=
|
1996
|
+
vellum/workflows/utils/functions.py,sha256=_esuDTYKEORjBoC0YGT3ANO--OswaKu6s-_42_kzlwU,13057
|
1997
1997
|
vellum/workflows/utils/hmac.py,sha256=JJCczc6pyV6DuE1Oa0QVfYPUN_of3zEYmGFib3OZnrE,1135
|
1998
1998
|
vellum/workflows/utils/names.py,sha256=QtHquoaGqRseu5gg2OcVGI2d_CMcEOvjb9KspwH4C-A,552
|
1999
1999
|
vellum/workflows/utils/pydantic_schema.py,sha256=eR_bBtY-T0pttJP-ARwagSdCOnwPUtiT3cegm2lzDTQ,1310
|
@@ -2012,8 +2012,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
|
|
2012
2012
|
vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2013
2013
|
vellum/workflows/workflows/tests/test_base_workflow.py,sha256=Boa-_m9ii2Qsa1RvVM-VYniF7zCpzGgEGy-OnPZkrHg,23941
|
2014
2014
|
vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
|
2015
|
-
vellum_ai-1.5.
|
2016
|
-
vellum_ai-1.5.
|
2017
|
-
vellum_ai-1.5.
|
2018
|
-
vellum_ai-1.5.
|
2019
|
-
vellum_ai-1.5.
|
2015
|
+
vellum_ai-1.5.2.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
2016
|
+
vellum_ai-1.5.2.dist-info/METADATA,sha256=-qDjvOuDnllUtWah1AMWM9bItegRKH7bZAY9mDwyIQQ,5547
|
2017
|
+
vellum_ai-1.5.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
2018
|
+
vellum_ai-1.5.2.dist-info/entry_points.txt,sha256=xVavzAKN4iF_NbmhWOlOkHluka0YLkbN_pFQ9pW3gLI,117
|
2019
|
+
vellum_ai-1.5.2.dist-info/RECORD,,
|
@@ -407,6 +407,51 @@
|
|
407
407
|
}
|
408
408
|
]
|
409
409
|
},
|
410
|
+
{
|
411
|
+
"id": "527a10bc-30b2-4e36-91d6-91c8e865bac8",
|
412
|
+
"display_data": {
|
413
|
+
"position": {
|
414
|
+
"x": 0.0,
|
415
|
+
"y": 0.0
|
416
|
+
},
|
417
|
+
"comment": {
|
418
|
+
"value": "\n Used to map over a list of items and execute a Subworkflow on each iteration.\n\n items: List[MapNodeItemType] - The items to map over\n max_concurrency: Optional[int] = None - The maximum number of concurrent subworkflow executions\n subworkflow: Type[\"BaseWorkflow\"] - The Subworkflow to execute\n ",
|
419
|
+
"expanded": true
|
420
|
+
}
|
421
|
+
},
|
422
|
+
"base": {
|
423
|
+
"name": "BaseAdornmentNode",
|
424
|
+
"module": [
|
425
|
+
"vellum",
|
426
|
+
"workflows",
|
427
|
+
"nodes",
|
428
|
+
"bases",
|
429
|
+
"base_adornment_node"
|
430
|
+
]
|
431
|
+
},
|
432
|
+
"definition": {
|
433
|
+
"name": "MapNode",
|
434
|
+
"module": [
|
435
|
+
"vellum",
|
436
|
+
"workflows",
|
437
|
+
"nodes",
|
438
|
+
"core",
|
439
|
+
"map_node",
|
440
|
+
"node"
|
441
|
+
]
|
442
|
+
},
|
443
|
+
"trigger": {
|
444
|
+
"id": "3a702aac-7b68-47d3-92e1-264883e9532c",
|
445
|
+
"merge_behavior": "AWAIT_ATTRIBUTES"
|
446
|
+
},
|
447
|
+
"ports": [
|
448
|
+
{
|
449
|
+
"id": "0ae85239-a159-48af-b39c-2484eac901df",
|
450
|
+
"name": "default",
|
451
|
+
"type": "DEFAULT"
|
452
|
+
}
|
453
|
+
]
|
454
|
+
},
|
410
455
|
{
|
411
456
|
"id": "7426f273-a43d-4448-a2d2-76d0ee0d069c",
|
412
457
|
"display_data": {
|
@@ -809,25 +854,21 @@
|
|
809
854
|
}
|
810
855
|
],
|
811
856
|
"errors": [
|
812
|
-
{
|
813
|
-
"node": "MapNode",
|
814
|
-
"error": "Expected NodeReference items to have an instance"
|
815
|
-
},
|
816
857
|
{
|
817
858
|
"node": "SubworkflowDeploymentNode",
|
818
|
-
"error": "headers: {'server': 'gunicorn', 'date': '
|
859
|
+
"error": "ApiError: headers: {'server': 'gunicorn', 'date': 'Wed, 24 Sep 2025 04:58:53 GMT', 'content-type': 'application/json', 'allow': 'GET, PUT, PATCH, DELETE, HEAD, OPTIONS', 'x-frame-options': 'DENY', 'content-length': '58', 'vary': 'Accept-Language, Origin', 'content-language': 'en', 'strict-transport-security': 'max-age=60; includeSubDomains; preload', 'x-content-type-options': 'nosniff', 'referrer-policy': 'same-origin', 'cross-origin-opener-policy': 'same-origin', 'via': '1.1 google', 'alt-svc': 'h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000'}, status_code: 403, body: {'detail': 'Authentication credentials were not provided.'}"
|
819
860
|
},
|
820
861
|
{
|
821
862
|
"node": "PromptDeploymentNode",
|
822
|
-
"error": "headers: {'server': 'gunicorn', 'date': '
|
863
|
+
"error": "ApiError: headers: {'server': 'gunicorn', 'date': 'Wed, 24 Sep 2025 04:58:53 GMT', 'content-type': 'application/json', 'allow': 'GET, PUT, PATCH, DELETE, HEAD, OPTIONS', 'x-frame-options': 'DENY', 'content-length': '58', 'vary': 'Accept-Language, Origin', 'content-language': 'en', 'strict-transport-security': 'max-age=60; includeSubDomains; preload', 'x-content-type-options': 'nosniff', 'referrer-policy': 'same-origin', 'cross-origin-opener-policy': 'same-origin', 'via': '1.1 google', 'alt-svc': 'h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000'}, status_code: 403, body: {'detail': 'Authentication credentials were not provided.'}"
|
823
864
|
},
|
824
865
|
{
|
825
866
|
"node": "SearchNode",
|
826
|
-
"error": "Expected NodeReference query to have an instance"
|
867
|
+
"error": "ValueError: Expected NodeReference query to have an instance"
|
827
868
|
},
|
828
869
|
{
|
829
870
|
"node": "TemplatingNode",
|
830
|
-
"error": "TemplatingNode.Outputs.result"
|
871
|
+
"error": "KeyError: TemplatingNode.Outputs.result"
|
831
872
|
}
|
832
873
|
]
|
833
874
|
}
|
@@ -70,7 +70,7 @@ def main() -> None:
|
|
70
70
|
display_instance = display_class()
|
71
71
|
display_instance.serialize(display_context)
|
72
72
|
except Exception as e:
|
73
|
-
errors.append({"node": node_class.__name__, "error": str(e)})
|
73
|
+
errors.append({"node": node_class.__name__, "error": f"{e.__class__.__name__}: {str(e)}"})
|
74
74
|
|
75
75
|
result = {"nodes": successful_nodes, "errors": errors}
|
76
76
|
|
@@ -1,7 +1,8 @@
|
|
1
1
|
from uuid import UUID
|
2
|
-
from typing import Generic, Optional, TypeVar, cast
|
2
|
+
from typing import Generic, Optional, Type, TypeVar, cast
|
3
3
|
|
4
4
|
from vellum.workflows.nodes import MapNode
|
5
|
+
from vellum.workflows.state.base import BaseState
|
5
6
|
from vellum.workflows.types.core import JsonObject
|
6
7
|
from vellum.workflows.workflows.base import BaseWorkflow
|
7
8
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
@@ -22,12 +23,19 @@ class BaseMapNodeDisplay(BaseAdornmentNodeDisplay[_MapNodeType], Generic[_MapNod
|
|
22
23
|
node = self._node
|
23
24
|
node_id = self.node_id
|
24
25
|
|
25
|
-
|
26
|
+
subworkflow_value = raise_if_descriptor(node.subworkflow)
|
27
|
+
subworkflow = (
|
28
|
+
cast(type[BaseWorkflow], subworkflow_value)
|
29
|
+
if subworkflow_value is not None
|
30
|
+
else self._default_workflow_class()
|
31
|
+
)
|
32
|
+
|
33
|
+
items = raise_if_descriptor(node.items)
|
26
34
|
|
27
35
|
items_node_input = create_node_input(
|
28
36
|
node_id=node_id,
|
29
37
|
input_name="items",
|
30
|
-
value=
|
38
|
+
value=items or [],
|
31
39
|
display_context=display_context,
|
32
40
|
input_id=self.node_input_ids_by_name.get("items"),
|
33
41
|
)
|
@@ -81,3 +89,9 @@ class BaseMapNodeDisplay(BaseAdornmentNodeDisplay[_MapNodeType], Generic[_MapNod
|
|
81
89
|
},
|
82
90
|
**self.serialize_generic_fields(display_context),
|
83
91
|
}
|
92
|
+
|
93
|
+
def _default_workflow_class(self) -> Type[BaseWorkflow]:
|
94
|
+
class MapNodeSubworkflow(BaseWorkflow[MapNode.SubworkflowInputs, BaseState]):
|
95
|
+
pass
|
96
|
+
|
97
|
+
return MapNodeSubworkflow
|
File without changes
|
File without changes
|
File without changes
|