vellum-ai 1.7.11__py3-none-any.whl → 1.7.13__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.
Potentially problematic release.
This version of vellum-ai might be problematic. Click here for more details.
- vellum/__init__.py +2 -0
- vellum/client/core/client_wrapper.py +2 -2
- vellum/client/types/__init__.py +2 -0
- vellum/client/types/auth_type_enum.py +5 -0
- vellum/client/types/integration_name.py +4 -0
- vellum/client/types/slim_integration_auth_config_read.py +2 -0
- vellum/client/types/slim_workflow_execution_read.py +3 -3
- vellum/client/types/vellum_error_code_enum.py +1 -0
- vellum/client/types/vellum_sdk_error_code_enum.py +1 -0
- vellum/client/types/workflow_event_execution_read.py +3 -3
- vellum/client/types/workflow_execution_event_error_code.py +1 -0
- vellum/client/types/workflow_execution_snapshotted_body.py +1 -0
- vellum/types/auth_type_enum.py +3 -0
- vellum/workflows/events/workflow.py +18 -2
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +3 -0
- vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +3 -0
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +52 -0
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +2 -0
- vellum/workflows/references/trigger.py +3 -9
- vellum/workflows/runner/runner.py +14 -8
- vellum/workflows/tests/triggers/test_vellum_integration_trigger.py +134 -176
- vellum/workflows/triggers/__init__.py +1 -2
- vellum/workflows/triggers/tests/test_integration.py +2 -2
- vellum/workflows/triggers/vellum_integration.py +133 -141
- vellum/workflows/types/trigger_exec_config.py +8 -11
- vellum/workflows/utils/uuids.py +33 -0
- {vellum_ai-1.7.11.dist-info → vellum_ai-1.7.13.dist-info}/METADATA +1 -1
- {vellum_ai-1.7.11.dist-info → vellum_ai-1.7.13.dist-info}/RECORD +34 -35
- vellum_ee/workflows/display/base.py +1 -3
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +3 -1
- vellum_ee/workflows/display/workflows/base_workflow_display.py +14 -7
- vellum/workflows/triggers/slack.py +0 -101
- vellum/workflows/triggers/tests/test_slack.py +0 -180
- vellum_ee/workflows/display/tests/workflow_serialization/test_slack_trigger_serialization.py +0 -52
- {vellum_ai-1.7.11.dist-info → vellum_ai-1.7.13.dist-info}/LICENSE +0 -0
- {vellum_ai-1.7.11.dist-info → vellum_ai-1.7.13.dist-info}/WHEEL +0 -0
- {vellum_ai-1.7.11.dist-info → vellum_ai-1.7.13.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Tests for VellumIntegrationTrigger
|
|
1
|
+
"""Tests for VellumIntegrationTrigger."""
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
@@ -7,46 +7,101 @@ from vellum.workflows.references.trigger import TriggerAttributeReference
|
|
|
7
7
|
from vellum.workflows.triggers.vellum_integration import VellumIntegrationTrigger
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
10
|
+
def test_requires_config():
|
|
11
|
+
"""Trigger classes must declare Config with required fields."""
|
|
12
|
+
|
|
13
|
+
# This should fail - no Config class
|
|
14
|
+
with pytest.raises(TypeError, match="Config"):
|
|
15
|
+
|
|
16
|
+
class BadTrigger1(VellumIntegrationTrigger):
|
|
17
|
+
message: str
|
|
18
|
+
# Missing Config!
|
|
19
|
+
|
|
20
|
+
# This should fail - incomplete Config
|
|
21
|
+
with pytest.raises(TypeError, match="provider"):
|
|
22
|
+
|
|
23
|
+
class BadTrigger2(VellumIntegrationTrigger):
|
|
24
|
+
message: str
|
|
25
|
+
|
|
26
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
27
|
+
integration_name = "SLACK"
|
|
28
|
+
slug = "slack_new_message"
|
|
29
|
+
# Missing provider!
|
|
30
|
+
|
|
31
|
+
# This should work
|
|
32
|
+
class GoodTrigger(VellumIntegrationTrigger):
|
|
33
|
+
message: str
|
|
34
|
+
user: str
|
|
35
|
+
|
|
36
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
37
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
38
|
+
integration_name = "SLACK"
|
|
39
|
+
slug = "slack_new_message"
|
|
40
|
+
|
|
41
|
+
assert hasattr(GoodTrigger, "Config")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_top_level_annotations_create_references():
|
|
45
|
+
"""Top-level type annotations (webhook event attributes) automatically create TriggerAttributeReference."""
|
|
46
|
+
|
|
47
|
+
class SlackTrigger(VellumIntegrationTrigger):
|
|
48
|
+
message: str
|
|
49
|
+
user: str
|
|
50
|
+
timestamp: float
|
|
51
|
+
|
|
52
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
53
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
54
|
+
integration_name = "SLACK"
|
|
55
|
+
slug = "slack_new_message"
|
|
56
|
+
|
|
57
|
+
# Should auto-create references from annotations
|
|
58
|
+
assert isinstance(SlackTrigger.message, TriggerAttributeReference)
|
|
59
|
+
assert isinstance(SlackTrigger.user, TriggerAttributeReference)
|
|
60
|
+
assert isinstance(SlackTrigger.timestamp, TriggerAttributeReference)
|
|
61
|
+
assert SlackTrigger.message.types == (str,)
|
|
62
|
+
assert SlackTrigger.timestamp.types == (float,)
|
|
63
|
+
|
|
64
|
+
# Undeclared attributes should raise AttributeError
|
|
65
|
+
with pytest.raises(AttributeError):
|
|
66
|
+
_ = SlackTrigger.undefined_attribute
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_attribute_ids_include_class_name():
|
|
70
|
+
"""Attribute IDs should include class name (like nodes)."""
|
|
71
|
+
|
|
72
|
+
class Trigger1(VellumIntegrationTrigger):
|
|
73
|
+
message: str
|
|
74
|
+
|
|
75
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
76
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
77
|
+
integration_name = "SLACK"
|
|
78
|
+
slug = "slack_new_message"
|
|
79
|
+
|
|
80
|
+
class Trigger2(VellumIntegrationTrigger):
|
|
81
|
+
message: str
|
|
82
|
+
|
|
83
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
84
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
85
|
+
integration_name = "SLACK"
|
|
86
|
+
slug = "slack_new_message"
|
|
87
|
+
|
|
88
|
+
# Different class names = different IDs (like nodes)
|
|
89
|
+
# Type ignore: mypy sees message as str, but it's actually TriggerAttributeReference at class level
|
|
90
|
+
assert Trigger1.message.id != Trigger2.message.id # type: ignore[attr-defined]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_populates_dynamic_attributes():
|
|
44
94
|
"""Trigger dynamically populates attributes from event_data keys."""
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
95
|
+
|
|
96
|
+
class GithubPushTrigger(VellumIntegrationTrigger):
|
|
97
|
+
repository: str
|
|
98
|
+
branch: str
|
|
99
|
+
commits: list
|
|
100
|
+
|
|
101
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
102
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
103
|
+
integration_name = "GITHUB"
|
|
104
|
+
slug = "github_push_event"
|
|
50
105
|
|
|
51
106
|
event_data = {
|
|
52
107
|
"repository": "vellum-ai/workflows",
|
|
@@ -54,41 +109,27 @@ def test_populates_dynamic_attributes() -> None:
|
|
|
54
109
|
"commits": ["abc123", "def456"],
|
|
55
110
|
}
|
|
56
111
|
|
|
57
|
-
trigger =
|
|
112
|
+
trigger = GithubPushTrigger(event_data=event_data)
|
|
58
113
|
|
|
59
|
-
assert
|
|
60
|
-
assert
|
|
61
|
-
assert
|
|
114
|
+
assert trigger.repository == "vellum-ai/workflows"
|
|
115
|
+
assert trigger.branch == "main"
|
|
116
|
+
assert trigger.commits == ["abc123", "def456"]
|
|
62
117
|
|
|
63
118
|
|
|
64
|
-
def
|
|
65
|
-
"""
|
|
66
|
-
SlackNewMessage = VellumIntegrationTrigger.for_trigger(
|
|
67
|
-
integration_name="SLACK",
|
|
68
|
-
slug="slack_new_message",
|
|
69
|
-
trigger_nano_id="test_nano_123",
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
# Metaclass __getattribute__ creates references for undefined attributes
|
|
73
|
-
message_ref = SlackNewMessage.message
|
|
74
|
-
channel_ref = SlackNewMessage.channel
|
|
119
|
+
def test_to_trigger_attribute_values():
|
|
120
|
+
"""to_trigger_attribute_values returns correct attribute mappings."""
|
|
75
121
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
assert channel_ref.name == "channel"
|
|
122
|
+
class SlackTrigger(VellumIntegrationTrigger):
|
|
123
|
+
message: str
|
|
124
|
+
channel: str
|
|
80
125
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
integration_name="SLACK",
|
|
86
|
-
slug="slack_new_message",
|
|
87
|
-
trigger_nano_id="test_nano_123",
|
|
88
|
-
)
|
|
126
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
127
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
128
|
+
integration_name = "SLACK"
|
|
129
|
+
slug = "slack_new_message"
|
|
89
130
|
|
|
90
131
|
event_data = {"message": "Hello", "channel": "C123"}
|
|
91
|
-
trigger =
|
|
132
|
+
trigger = SlackTrigger(event_data=event_data)
|
|
92
133
|
|
|
93
134
|
attr_values = trigger.to_trigger_attribute_values()
|
|
94
135
|
|
|
@@ -98,128 +139,45 @@ def test_to_trigger_attribute_values() -> None:
|
|
|
98
139
|
assert set(attr_values.values()) == {"Hello", "C123"}
|
|
99
140
|
|
|
100
141
|
|
|
101
|
-
def
|
|
102
|
-
"""
|
|
103
|
-
Slack1 = VellumIntegrationTrigger.for_trigger(
|
|
104
|
-
integration_name="SLACK",
|
|
105
|
-
slug="slack_new_message",
|
|
106
|
-
trigger_nano_id="test_nano_123",
|
|
107
|
-
)
|
|
108
|
-
Slack2 = VellumIntegrationTrigger.for_trigger(
|
|
109
|
-
integration_name="SLACK",
|
|
110
|
-
slug="slack_new_message",
|
|
111
|
-
trigger_nano_id="test_nano_123",
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
# Factory caching ensures same class
|
|
115
|
-
assert Slack1 is Slack2
|
|
116
|
-
|
|
117
|
-
# Attribute references must be deterministic across accesses
|
|
118
|
-
msg_ref_1 = Slack1.message
|
|
119
|
-
msg_ref_2 = Slack2.message
|
|
142
|
+
def test_to_exec_config():
|
|
143
|
+
"""to_exec_config() produces valid ComposioIntegrationTriggerExecConfig."""
|
|
120
144
|
|
|
121
|
-
|
|
122
|
-
|
|
145
|
+
class SlackTrigger(VellumIntegrationTrigger):
|
|
146
|
+
message: str
|
|
147
|
+
user: str
|
|
123
148
|
|
|
149
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
150
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
151
|
+
integration_name = "SLACK"
|
|
152
|
+
slug = "slack_new_message"
|
|
124
153
|
|
|
125
|
-
|
|
126
|
-
"""to_exec_config() produces valid ComposioIntegrationTriggerExecConfig."""
|
|
127
|
-
SlackMessage = VellumIntegrationTrigger.for_trigger(
|
|
128
|
-
integration_name="SLACK",
|
|
129
|
-
slug="slack_new_message",
|
|
130
|
-
trigger_nano_id="abc123def456",
|
|
131
|
-
attributes={"channel": "C123456"},
|
|
132
|
-
)
|
|
154
|
+
exec_config = SlackTrigger.to_exec_config()
|
|
133
155
|
|
|
134
|
-
exec_config
|
|
135
|
-
|
|
136
|
-
assert exec_config.type == "COMPOSIO_INTEGRATION_TRIGGER"
|
|
156
|
+
assert exec_config.type == "INTEGRATION"
|
|
137
157
|
assert exec_config.provider == VellumIntegrationProviderType.COMPOSIO
|
|
138
158
|
assert exec_config.integration_name == "SLACK"
|
|
139
159
|
assert exec_config.slug == "slack_new_message"
|
|
140
|
-
assert exec_config.
|
|
141
|
-
assert exec_config.attributes == {"channel": "C123456"}
|
|
160
|
+
assert exec_config.event_attributes == {"message": str, "user": str}
|
|
142
161
|
|
|
143
162
|
|
|
144
|
-
def test_to_exec_config_base_class_fails()
|
|
163
|
+
def test_to_exec_config_base_class_fails():
|
|
145
164
|
"""to_exec_config() raises error on base class."""
|
|
146
|
-
with pytest.raises(AttributeError
|
|
165
|
+
with pytest.raises(AttributeError):
|
|
147
166
|
VellumIntegrationTrigger.to_exec_config()
|
|
148
167
|
|
|
149
168
|
|
|
150
|
-
def test_empty_event_data()
|
|
169
|
+
def test_empty_event_data():
|
|
151
170
|
"""Trigger handles empty event data gracefully."""
|
|
152
|
-
SlackMessage = VellumIntegrationTrigger.for_trigger(
|
|
153
|
-
integration_name="SLACK",
|
|
154
|
-
slug="slack_new_message",
|
|
155
|
-
trigger_nano_id="test_nano_123",
|
|
156
|
-
)
|
|
157
|
-
trigger = SlackMessage(event_data={})
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
class SlackTrigger(VellumIntegrationTrigger):
|
|
173
|
+
message: str
|
|
161
174
|
|
|
175
|
+
class Config(VellumIntegrationTrigger.Config):
|
|
176
|
+
provider = VellumIntegrationProviderType.COMPOSIO
|
|
177
|
+
integration_name = "SLACK"
|
|
178
|
+
slug = "slack_new_message"
|
|
162
179
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
slug="slack_new_message",
|
|
168
|
-
trigger_nano_id="test_nano_123",
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
# Event data with key that matches a class variable name
|
|
172
|
-
event_data = {"provider": "some_value", "message": "Hello"}
|
|
173
|
-
trigger = SlackMessage(event_data=event_data)
|
|
174
|
-
|
|
175
|
-
# Instance attribute should be set from event_data
|
|
176
|
-
assert trigger.provider == "some_value" # Instance attr from event_data
|
|
177
|
-
# But class variable should be unchanged
|
|
178
|
-
assert SlackMessage.provider == VellumIntegrationProviderType.COMPOSIO
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
def test_non_json_serializable_attributes_fail_fast() -> None:
|
|
182
|
-
"""Non-JSON-serializable attributes raise ValueError with clear message."""
|
|
183
|
-
|
|
184
|
-
# Custom objects are not JSON-serializable
|
|
185
|
-
class CustomObject:
|
|
186
|
-
pass
|
|
187
|
-
|
|
188
|
-
with pytest.raises(ValueError, match="must be JSON-serializable"):
|
|
189
|
-
VellumIntegrationTrigger.for_trigger(
|
|
190
|
-
integration_name="SLACK",
|
|
191
|
-
slug="slack_new_message",
|
|
192
|
-
trigger_nano_id="test_nano_123",
|
|
193
|
-
attributes={"custom": CustomObject()},
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
# Sets are not JSON-serializable
|
|
197
|
-
with pytest.raises(ValueError, match="must be JSON-serializable"):
|
|
198
|
-
VellumIntegrationTrigger.for_trigger(
|
|
199
|
-
integration_name="SLACK",
|
|
200
|
-
slug="slack_new_message",
|
|
201
|
-
trigger_nano_id="test_nano_123",
|
|
202
|
-
attributes={"tags": {"a", "b", "c"}},
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
def test_nested_json_serializable_attributes_work() -> None:
|
|
207
|
-
"""Nested JSON-serializable attributes work correctly."""
|
|
208
|
-
SlackMessage = VellumIntegrationTrigger.for_trigger(
|
|
209
|
-
integration_name="SLACK",
|
|
210
|
-
slug="slack_new_message",
|
|
211
|
-
trigger_nano_id="test_nano_123",
|
|
212
|
-
attributes={
|
|
213
|
-
"channel": "C123456",
|
|
214
|
-
"filters": {"status": "active", "priority": ["high", "medium"]},
|
|
215
|
-
"count": 42,
|
|
216
|
-
"enabled": True,
|
|
217
|
-
},
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
assert SlackMessage.attributes == {
|
|
221
|
-
"channel": "C123456",
|
|
222
|
-
"filters": {"status": "active", "priority": ["high", "medium"]},
|
|
223
|
-
"count": 42,
|
|
224
|
-
"enabled": True,
|
|
225
|
-
}
|
|
180
|
+
trigger = SlackTrigger(event_data={})
|
|
181
|
+
|
|
182
|
+
attr_values = trigger.to_trigger_attribute_values()
|
|
183
|
+
assert attr_values == {}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from vellum.workflows.triggers.base import BaseTrigger
|
|
2
2
|
from vellum.workflows.triggers.integration import IntegrationTrigger
|
|
3
3
|
from vellum.workflows.triggers.manual import ManualTrigger
|
|
4
|
-
from vellum.workflows.triggers.slack import SlackTrigger
|
|
5
4
|
from vellum.workflows.triggers.vellum_integration import VellumIntegrationTrigger
|
|
6
5
|
|
|
7
|
-
__all__ = ["BaseTrigger", "IntegrationTrigger", "ManualTrigger", "
|
|
6
|
+
__all__ = ["BaseTrigger", "IntegrationTrigger", "ManualTrigger", "VellumIntegrationTrigger"]
|
|
@@ -57,8 +57,8 @@ def test_integration_trigger__attribute_reference():
|
|
|
57
57
|
reference = TestTrigger.value
|
|
58
58
|
assert isinstance(reference, TriggerAttributeReference)
|
|
59
59
|
assert reference.name == "value"
|
|
60
|
-
assert TestTrigger.value
|
|
61
|
-
assert reference
|
|
60
|
+
assert TestTrigger.value == reference
|
|
61
|
+
assert reference == TestTrigger.attribute_references()["value"]
|
|
62
62
|
|
|
63
63
|
state = BaseState()
|
|
64
64
|
trigger = TestTrigger({"value": "data"})
|