vellum-ai 1.3.0__py3-none-any.whl → 1.3.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.
Files changed (41) hide show
  1. vellum/__init__.py +6 -0
  2. vellum/client/README.md +5 -5
  3. vellum/client/__init__.py +20 -0
  4. vellum/client/core/client_wrapper.py +2 -2
  5. vellum/client/raw_client.py +20 -0
  6. vellum/client/reference.md +61 -27
  7. vellum/client/resources/ad_hoc/client.py +29 -29
  8. vellum/client/resources/ad_hoc/raw_client.py +13 -13
  9. vellum/client/resources/events/client.py +69 -33
  10. vellum/client/resources/events/raw_client.py +13 -9
  11. vellum/client/types/__init__.py +6 -0
  12. vellum/client/types/create_workflow_event_request.py +7 -0
  13. vellum/client/types/deprecated_prompt_request_input.py +8 -0
  14. vellum/client/types/event_create_response.py +5 -0
  15. vellum/client/types/logical_operator.py +1 -0
  16. vellum/client/types/processing_failure_reason_enum.py +3 -1
  17. vellum/client/types/slim_document.py +1 -0
  18. vellum/client/types/workflow_input.py +31 -0
  19. vellum/types/create_workflow_event_request.py +3 -0
  20. vellum/types/deprecated_prompt_request_input.py +3 -0
  21. vellum/types/workflow_input.py +3 -0
  22. vellum/workflows/constants.py +3 -0
  23. vellum/workflows/events/node.py +1 -0
  24. vellum/workflows/events/tests/test_event.py +1 -0
  25. vellum/workflows/events/workflow.py +10 -2
  26. vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +16 -0
  27. vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py +3 -13
  28. vellum/workflows/nodes/displayable/tool_calling_node/utils.py +11 -0
  29. vellum/workflows/nodes/displayable/web_search_node/tests/__init__.py +0 -0
  30. vellum/workflows/nodes/displayable/web_search_node/tests/test_node.py +319 -0
  31. vellum/workflows/nodes/tests/test_utils.py +23 -0
  32. vellum/workflows/nodes/utils.py +14 -0
  33. vellum/workflows/runner/runner.py +33 -12
  34. vellum/workflows/types/code_execution_node_wrappers.py +2 -1
  35. {vellum_ai-1.3.0.dist-info → vellum_ai-1.3.2.dist-info}/METADATA +1 -1
  36. {vellum_ai-1.3.0.dist-info → vellum_ai-1.3.2.dist-info}/RECORD +41 -32
  37. vellum_ee/workflows/display/tests/workflow_serialization/test_web_search_node_serialization.py +81 -0
  38. vellum_ee/workflows/display/utils/events.py +3 -0
  39. {vellum_ai-1.3.0.dist-info → vellum_ai-1.3.2.dist-info}/LICENSE +0 -0
  40. {vellum_ai-1.3.0.dist-info → vellum_ai-1.3.2.dist-info}/WHEEL +0 -0
  41. {vellum_ai-1.3.0.dist-info → vellum_ai-1.3.2.dist-info}/entry_points.txt +0 -0
@@ -16,10 +16,10 @@ from ...errors.forbidden_error import ForbiddenError
16
16
  from ...errors.internal_server_error import InternalServerError
17
17
  from ...types.ad_hoc_execute_prompt_event import AdHocExecutePromptEvent
18
18
  from ...types.ad_hoc_expand_meta import AdHocExpandMeta
19
+ from ...types.deprecated_prompt_request_input import DeprecatedPromptRequestInput
19
20
  from ...types.function_definition import FunctionDefinition
20
21
  from ...types.prompt_block import PromptBlock
21
22
  from ...types.prompt_parameters import PromptParameters
22
- from ...types.prompt_request_input import PromptRequestInput
23
23
  from ...types.prompt_settings import PromptSettings
24
24
  from ...types.vellum_variable import VellumVariable
25
25
 
@@ -35,7 +35,7 @@ class RawAdHocClient:
35
35
  self,
36
36
  *,
37
37
  ml_model: str,
38
- input_values: typing.Sequence[PromptRequestInput],
38
+ input_values: typing.Sequence[DeprecatedPromptRequestInput],
39
39
  input_variables: typing.Sequence[VellumVariable],
40
40
  parameters: PromptParameters,
41
41
  blocks: typing.Sequence[PromptBlock],
@@ -49,7 +49,7 @@ class RawAdHocClient:
49
49
  ----------
50
50
  ml_model : str
51
51
 
52
- input_values : typing.Sequence[PromptRequestInput]
52
+ input_values : typing.Sequence[DeprecatedPromptRequestInput]
53
53
 
54
54
  input_variables : typing.Sequence[VellumVariable]
55
55
 
@@ -78,7 +78,7 @@ class RawAdHocClient:
78
78
  json={
79
79
  "ml_model": ml_model,
80
80
  "input_values": convert_and_respect_annotation_metadata(
81
- object_=input_values, annotation=typing.Sequence[PromptRequestInput], direction="write"
81
+ object_=input_values, annotation=typing.Sequence[DeprecatedPromptRequestInput], direction="write"
82
82
  ),
83
83
  "input_variables": convert_and_respect_annotation_metadata(
84
84
  object_=input_variables, annotation=typing.Sequence[VellumVariable], direction="write"
@@ -160,7 +160,7 @@ class RawAdHocClient:
160
160
  self,
161
161
  *,
162
162
  ml_model: str,
163
- input_values: typing.Sequence[PromptRequestInput],
163
+ input_values: typing.Sequence[DeprecatedPromptRequestInput],
164
164
  input_variables: typing.Sequence[VellumVariable],
165
165
  parameters: PromptParameters,
166
166
  blocks: typing.Sequence[PromptBlock],
@@ -174,7 +174,7 @@ class RawAdHocClient:
174
174
  ----------
175
175
  ml_model : str
176
176
 
177
- input_values : typing.Sequence[PromptRequestInput]
177
+ input_values : typing.Sequence[DeprecatedPromptRequestInput]
178
178
 
179
179
  input_variables : typing.Sequence[VellumVariable]
180
180
 
@@ -203,7 +203,7 @@ class RawAdHocClient:
203
203
  json={
204
204
  "ml_model": ml_model,
205
205
  "input_values": convert_and_respect_annotation_metadata(
206
- object_=input_values, annotation=typing.Sequence[PromptRequestInput], direction="write"
206
+ object_=input_values, annotation=typing.Sequence[DeprecatedPromptRequestInput], direction="write"
207
207
  ),
208
208
  "input_variables": convert_and_respect_annotation_metadata(
209
209
  object_=input_variables, annotation=typing.Sequence[VellumVariable], direction="write"
@@ -306,7 +306,7 @@ class AsyncRawAdHocClient:
306
306
  self,
307
307
  *,
308
308
  ml_model: str,
309
- input_values: typing.Sequence[PromptRequestInput],
309
+ input_values: typing.Sequence[DeprecatedPromptRequestInput],
310
310
  input_variables: typing.Sequence[VellumVariable],
311
311
  parameters: PromptParameters,
312
312
  blocks: typing.Sequence[PromptBlock],
@@ -320,7 +320,7 @@ class AsyncRawAdHocClient:
320
320
  ----------
321
321
  ml_model : str
322
322
 
323
- input_values : typing.Sequence[PromptRequestInput]
323
+ input_values : typing.Sequence[DeprecatedPromptRequestInput]
324
324
 
325
325
  input_variables : typing.Sequence[VellumVariable]
326
326
 
@@ -349,7 +349,7 @@ class AsyncRawAdHocClient:
349
349
  json={
350
350
  "ml_model": ml_model,
351
351
  "input_values": convert_and_respect_annotation_metadata(
352
- object_=input_values, annotation=typing.Sequence[PromptRequestInput], direction="write"
352
+ object_=input_values, annotation=typing.Sequence[DeprecatedPromptRequestInput], direction="write"
353
353
  ),
354
354
  "input_variables": convert_and_respect_annotation_metadata(
355
355
  object_=input_variables, annotation=typing.Sequence[VellumVariable], direction="write"
@@ -431,7 +431,7 @@ class AsyncRawAdHocClient:
431
431
  self,
432
432
  *,
433
433
  ml_model: str,
434
- input_values: typing.Sequence[PromptRequestInput],
434
+ input_values: typing.Sequence[DeprecatedPromptRequestInput],
435
435
  input_variables: typing.Sequence[VellumVariable],
436
436
  parameters: PromptParameters,
437
437
  blocks: typing.Sequence[PromptBlock],
@@ -445,7 +445,7 @@ class AsyncRawAdHocClient:
445
445
  ----------
446
446
  ml_model : str
447
447
 
448
- input_values : typing.Sequence[PromptRequestInput]
448
+ input_values : typing.Sequence[DeprecatedPromptRequestInput]
449
449
 
450
450
  input_variables : typing.Sequence[VellumVariable]
451
451
 
@@ -474,7 +474,7 @@ class AsyncRawAdHocClient:
474
474
  json={
475
475
  "ml_model": ml_model,
476
476
  "input_values": convert_and_respect_annotation_metadata(
477
- object_=input_values, annotation=typing.Sequence[PromptRequestInput], direction="write"
477
+ object_=input_values, annotation=typing.Sequence[DeprecatedPromptRequestInput], direction="write"
478
478
  ),
479
479
  "input_variables": convert_and_respect_annotation_metadata(
480
480
  object_=input_variables, annotation=typing.Sequence[VellumVariable], direction="write"
@@ -4,8 +4,8 @@ import typing
4
4
 
5
5
  from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
6
6
  from ...core.request_options import RequestOptions
7
+ from ...types.create_workflow_event_request import CreateWorkflowEventRequest
7
8
  from ...types.event_create_response import EventCreateResponse
8
- from ...types.workflow_event import WorkflowEvent
9
9
  from .raw_client import AsyncRawEventsClient, RawEventsClient
10
10
 
11
11
  # this is used as the default value for optional parameters
@@ -32,14 +32,14 @@ class EventsClient:
32
32
  return self._raw_client
33
33
 
34
34
  def create(
35
- self, *, request: WorkflowEvent, request_options: typing.Optional[RequestOptions] = None
35
+ self, *, request: CreateWorkflowEventRequest, request_options: typing.Optional[RequestOptions] = None
36
36
  ) -> EventCreateResponse:
37
37
  """
38
- Accept an event and publish it to ClickHouse for analytics processing.
38
+ Accept an event or list of events and publish them to ClickHouse for analytics processing.
39
39
 
40
40
  Parameters
41
41
  ----------
42
- request : WorkflowEvent
42
+ request : CreateWorkflowEventRequest
43
43
 
44
44
  request_options : typing.Optional[RequestOptions]
45
45
  Request-specific configuration.
@@ -65,22 +65,40 @@ class EventsClient:
65
65
  api_key="YOUR_API_KEY",
66
66
  )
67
67
  client.events.create(
68
- request=NodeExecutionInitiatedEvent(
69
- body=NodeExecutionInitiatedBody(
70
- node_definition=VellumCodeResourceDefinition(
71
- name="name",
72
- module=["module", "module"],
73
- id="id",
68
+ request=[
69
+ NodeExecutionInitiatedEvent(
70
+ body=NodeExecutionInitiatedBody(
71
+ node_definition=VellumCodeResourceDefinition(
72
+ name="name",
73
+ module=["module", "module"],
74
+ id="id",
75
+ ),
76
+ inputs={"inputs": {"key": "value"}},
77
+ ),
78
+ id="id",
79
+ timestamp=datetime.datetime.fromisoformat(
80
+ "2024-01-15 09:30:00+00:00",
74
81
  ),
75
- inputs={"inputs": {"key": "value"}},
82
+ trace_id="trace_id",
83
+ span_id="span_id",
76
84
  ),
77
- id="id",
78
- timestamp=datetime.datetime.fromisoformat(
79
- "2024-01-15 09:30:00+00:00",
85
+ NodeExecutionInitiatedEvent(
86
+ body=NodeExecutionInitiatedBody(
87
+ node_definition=VellumCodeResourceDefinition(
88
+ name="name",
89
+ module=["module", "module"],
90
+ id="id",
91
+ ),
92
+ inputs={"inputs": {"key": "value"}},
93
+ ),
94
+ id="id",
95
+ timestamp=datetime.datetime.fromisoformat(
96
+ "2024-01-15 09:30:00+00:00",
97
+ ),
98
+ trace_id="trace_id",
99
+ span_id="span_id",
80
100
  ),
81
- trace_id="trace_id",
82
- span_id="span_id",
83
- ),
101
+ ],
84
102
  )
85
103
  """
86
104
  _response = self._raw_client.create(request=request, request_options=request_options)
@@ -103,14 +121,14 @@ class AsyncEventsClient:
103
121
  return self._raw_client
104
122
 
105
123
  async def create(
106
- self, *, request: WorkflowEvent, request_options: typing.Optional[RequestOptions] = None
124
+ self, *, request: CreateWorkflowEventRequest, request_options: typing.Optional[RequestOptions] = None
107
125
  ) -> EventCreateResponse:
108
126
  """
109
- Accept an event and publish it to ClickHouse for analytics processing.
127
+ Accept an event or list of events and publish them to ClickHouse for analytics processing.
110
128
 
111
129
  Parameters
112
130
  ----------
113
- request : WorkflowEvent
131
+ request : CreateWorkflowEventRequest
114
132
 
115
133
  request_options : typing.Optional[RequestOptions]
116
134
  Request-specific configuration.
@@ -140,22 +158,40 @@ class AsyncEventsClient:
140
158
 
141
159
  async def main() -> None:
142
160
  await client.events.create(
143
- request=NodeExecutionInitiatedEvent(
144
- body=NodeExecutionInitiatedBody(
145
- node_definition=VellumCodeResourceDefinition(
146
- name="name",
147
- module=["module", "module"],
148
- id="id",
161
+ request=[
162
+ NodeExecutionInitiatedEvent(
163
+ body=NodeExecutionInitiatedBody(
164
+ node_definition=VellumCodeResourceDefinition(
165
+ name="name",
166
+ module=["module", "module"],
167
+ id="id",
168
+ ),
169
+ inputs={"inputs": {"key": "value"}},
149
170
  ),
150
- inputs={"inputs": {"key": "value"}},
171
+ id="id",
172
+ timestamp=datetime.datetime.fromisoformat(
173
+ "2024-01-15 09:30:00+00:00",
174
+ ),
175
+ trace_id="trace_id",
176
+ span_id="span_id",
151
177
  ),
152
- id="id",
153
- timestamp=datetime.datetime.fromisoformat(
154
- "2024-01-15 09:30:00+00:00",
178
+ NodeExecutionInitiatedEvent(
179
+ body=NodeExecutionInitiatedBody(
180
+ node_definition=VellumCodeResourceDefinition(
181
+ name="name",
182
+ module=["module", "module"],
183
+ id="id",
184
+ ),
185
+ inputs={"inputs": {"key": "value"}},
186
+ ),
187
+ id="id",
188
+ timestamp=datetime.datetime.fromisoformat(
189
+ "2024-01-15 09:30:00+00:00",
190
+ ),
191
+ trace_id="trace_id",
192
+ span_id="span_id",
155
193
  ),
156
- trace_id="trace_id",
157
- span_id="span_id",
158
- ),
194
+ ],
159
195
  )
160
196
 
161
197
 
@@ -13,9 +13,9 @@ from ...errors.bad_request_error import BadRequestError
13
13
  from ...errors.forbidden_error import ForbiddenError
14
14
  from ...errors.too_many_requests_error import TooManyRequestsError
15
15
  from ...errors.unauthorized_error import UnauthorizedError
16
+ from ...types.create_workflow_event_request import CreateWorkflowEventRequest
16
17
  from ...types.error_detail_response import ErrorDetailResponse
17
18
  from ...types.event_create_response import EventCreateResponse
18
- from ...types.workflow_event import WorkflowEvent
19
19
 
20
20
  # this is used as the default value for optional parameters
21
21
  OMIT = typing.cast(typing.Any, ...)
@@ -26,14 +26,14 @@ class RawEventsClient:
26
26
  self._client_wrapper = client_wrapper
27
27
 
28
28
  def create(
29
- self, *, request: WorkflowEvent, request_options: typing.Optional[RequestOptions] = None
29
+ self, *, request: CreateWorkflowEventRequest, request_options: typing.Optional[RequestOptions] = None
30
30
  ) -> HttpResponse[EventCreateResponse]:
31
31
  """
32
- Accept an event and publish it to ClickHouse for analytics processing.
32
+ Accept an event or list of events and publish them to ClickHouse for analytics processing.
33
33
 
34
34
  Parameters
35
35
  ----------
36
- request : WorkflowEvent
36
+ request : CreateWorkflowEventRequest
37
37
 
38
38
  request_options : typing.Optional[RequestOptions]
39
39
  Request-specific configuration.
@@ -47,7 +47,9 @@ class RawEventsClient:
47
47
  "monitoring/v1/events",
48
48
  base_url=self._client_wrapper.get_environment().default,
49
49
  method="POST",
50
- json=convert_and_respect_annotation_metadata(object_=request, annotation=WorkflowEvent, direction="write"),
50
+ json=convert_and_respect_annotation_metadata(
51
+ object_=request, annotation=CreateWorkflowEventRequest, direction="write"
52
+ ),
51
53
  headers={
52
54
  "content-type": "application/json",
53
55
  },
@@ -119,14 +121,14 @@ class AsyncRawEventsClient:
119
121
  self._client_wrapper = client_wrapper
120
122
 
121
123
  async def create(
122
- self, *, request: WorkflowEvent, request_options: typing.Optional[RequestOptions] = None
124
+ self, *, request: CreateWorkflowEventRequest, request_options: typing.Optional[RequestOptions] = None
123
125
  ) -> AsyncHttpResponse[EventCreateResponse]:
124
126
  """
125
- Accept an event and publish it to ClickHouse for analytics processing.
127
+ Accept an event or list of events and publish them to ClickHouse for analytics processing.
126
128
 
127
129
  Parameters
128
130
  ----------
129
- request : WorkflowEvent
131
+ request : CreateWorkflowEventRequest
130
132
 
131
133
  request_options : typing.Optional[RequestOptions]
132
134
  Request-specific configuration.
@@ -140,7 +142,9 @@ class AsyncRawEventsClient:
140
142
  "monitoring/v1/events",
141
143
  base_url=self._client_wrapper.get_environment().default,
142
144
  method="POST",
143
- json=convert_and_respect_annotation_metadata(object_=request, annotation=WorkflowEvent, direction="write"),
145
+ json=convert_and_respect_annotation_metadata(
146
+ object_=request, annotation=CreateWorkflowEventRequest, direction="write"
147
+ ),
144
148
  headers={
145
149
  "content-type": "application/json",
146
150
  },
@@ -82,6 +82,7 @@ from .container_image_build_config import ContainerImageBuildConfig
82
82
  from .container_image_container_image_tag import ContainerImageContainerImageTag
83
83
  from .container_image_read import ContainerImageRead
84
84
  from .create_test_suite_test_case_request import CreateTestSuiteTestCaseRequest
85
+ from .create_workflow_event_request import CreateWorkflowEventRequest
85
86
  from .delimiter_chunker_config import DelimiterChunkerConfig
86
87
  from .delimiter_chunker_config_request import DelimiterChunkerConfigRequest
87
88
  from .delimiter_chunking import DelimiterChunking
@@ -92,6 +93,7 @@ from .deployment_provider_payload_response_payload import DeploymentProviderPayl
92
93
  from .deployment_read import DeploymentRead
93
94
  from .deployment_release_tag_deployment_history_item import DeploymentReleaseTagDeploymentHistoryItem
94
95
  from .deployment_release_tag_read import DeploymentReleaseTagRead
96
+ from .deprecated_prompt_request_input import DeprecatedPromptRequestInput
95
97
  from .docker_service_token import DockerServiceToken
96
98
  from .document_chat_message_content import DocumentChatMessageContent
97
99
  from .document_chat_message_content_request import DocumentChatMessageContentRequest
@@ -648,6 +650,7 @@ from .workflow_execution_view_online_eval_metric_result import WorkflowExecution
648
650
  from .workflow_execution_workflow_result_event import WorkflowExecutionWorkflowResultEvent
649
651
  from .workflow_expand_meta_request import WorkflowExpandMetaRequest
650
652
  from .workflow_initialization_error import WorkflowInitializationError
653
+ from .workflow_input import WorkflowInput
651
654
  from .workflow_node_result_data import WorkflowNodeResultData
652
655
  from .workflow_node_result_event import WorkflowNodeResultEvent
653
656
  from .workflow_node_result_event_state import WorkflowNodeResultEventState
@@ -765,6 +768,7 @@ __all__ = [
765
768
  "ContainerImageContainerImageTag",
766
769
  "ContainerImageRead",
767
770
  "CreateTestSuiteTestCaseRequest",
771
+ "CreateWorkflowEventRequest",
768
772
  "DelimiterChunkerConfig",
769
773
  "DelimiterChunkerConfigRequest",
770
774
  "DelimiterChunking",
@@ -775,6 +779,7 @@ __all__ = [
775
779
  "DeploymentRead",
776
780
  "DeploymentReleaseTagDeploymentHistoryItem",
777
781
  "DeploymentReleaseTagRead",
782
+ "DeprecatedPromptRequestInput",
778
783
  "DockerServiceToken",
779
784
  "DocumentChatMessageContent",
780
785
  "DocumentChatMessageContentRequest",
@@ -1311,6 +1316,7 @@ __all__ = [
1311
1316
  "WorkflowExecutionWorkflowResultEvent",
1312
1317
  "WorkflowExpandMetaRequest",
1313
1318
  "WorkflowInitializationError",
1319
+ "WorkflowInput",
1314
1320
  "WorkflowNodeResultData",
1315
1321
  "WorkflowNodeResultEvent",
1316
1322
  "WorkflowNodeResultEventState",
@@ -0,0 +1,7 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ from .workflow_event import WorkflowEvent
6
+
7
+ CreateWorkflowEventRequest = typing.Union[typing.List[WorkflowEvent], WorkflowEvent]
@@ -0,0 +1,8 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ from .prompt_request_input import PromptRequestInput
6
+ from .workflow_input import WorkflowInput
7
+
8
+ DeprecatedPromptRequestInput = typing.Union[WorkflowInput, PromptRequestInput]
@@ -16,6 +16,11 @@ class EventCreateResponse(UniversalBaseModel):
16
16
  Indicates whether the event was published successfully.
17
17
  """
18
18
 
19
+ count: int = pydantic.Field()
20
+ """
21
+ Number of events processed
22
+ """
23
+
19
24
  if IS_PYDANTIC_V2:
20
25
  model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
21
26
  else:
@@ -22,6 +22,7 @@ LogicalOperator = typing.Union[
22
22
  "notIn",
23
23
  "between",
24
24
  "notBetween",
25
+ "concat",
25
26
  "blank",
26
27
  "notBlank",
27
28
  "coalesce",
@@ -2,4 +2,6 @@
2
2
 
3
3
  import typing
4
4
 
5
- ProcessingFailureReasonEnum = typing.Union[typing.Literal["EXCEEDED_CHARACTER_LIMIT", "INVALID_FILE"], typing.Any]
5
+ ProcessingFailureReasonEnum = typing.Union[
6
+ typing.Literal["EXCEEDED_CHARACTER_LIMIT", "INVALID_FILE", "INVALID_CREDENTIALS"], typing.Any
7
+ ]
@@ -39,6 +39,7 @@ class SlimDocument(UniversalBaseModel):
39
39
 
40
40
  * `EXCEEDED_CHARACTER_LIMIT` - Exceeded Character Limit
41
41
  * `INVALID_FILE` - Invalid File
42
+ * `INVALID_CREDENTIALS` - Invalid Credentials
42
43
  """
43
44
 
44
45
  status: typing.Optional[DocumentStatus] = pydantic.Field(default=None)
@@ -0,0 +1,31 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ from .array_input import ArrayInput
6
+ from .audio_input import AudioInput
7
+ from .chat_history_input import ChatHistoryInput
8
+ from .document_input import DocumentInput
9
+ from .error_input import ErrorInput
10
+ from .function_call_input import FunctionCallInput
11
+ from .image_input import ImageInput
12
+ from .json_input import JsonInput
13
+ from .number_input import NumberInput
14
+ from .search_results_input import SearchResultsInput
15
+ from .string_input import StringInput
16
+ from .video_input import VideoInput
17
+
18
+ WorkflowInput = typing.Union[
19
+ StringInput,
20
+ JsonInput,
21
+ ChatHistoryInput,
22
+ NumberInput,
23
+ SearchResultsInput,
24
+ ErrorInput,
25
+ ArrayInput,
26
+ FunctionCallInput,
27
+ AudioInput,
28
+ VideoInput,
29
+ ImageInput,
30
+ DocumentInput,
31
+ ]
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.create_workflow_event_request import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.deprecated_prompt_request_input import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.workflow_input import *
@@ -22,6 +22,9 @@ class _UndefMeta(type):
22
22
 
23
23
  return super().__getattribute__(name)
24
24
 
25
+ def __str__(cls) -> str:
26
+ return ""
27
+
25
28
  def __bool__(cls) -> bool:
26
29
  return False
27
30
 
@@ -141,6 +141,7 @@ class NodeExecutionFulfilledEvent(_BaseNodeEvent, Generic[OutputsType]):
141
141
 
142
142
  class NodeExecutionRejectedBody(_BaseNodeExecutionBody):
143
143
  error: WorkflowError
144
+ traceback: Optional[str] = None
144
145
 
145
146
 
146
147
  class NodeExecutionRejectedEvent(_BaseNodeEvent):
@@ -261,6 +261,7 @@ mock_node_uuid = str(uuid4_from_hash(MockNode.__qualname__))
261
261
  "message": "Workflow failed",
262
262
  "code": "USER_DEFINED_ERROR",
263
263
  },
264
+ "traceback": None,
264
265
  },
265
266
  "parent": None,
266
267
  "links": None,
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from uuid import UUID
2
3
  from typing import TYPE_CHECKING, Any, Dict, Generic, Iterable, Literal, Optional, Type, Union
3
4
  from typing_extensions import TypeGuard
@@ -25,6 +26,8 @@ from .types import BaseEvent, default_serializer
25
26
  if TYPE_CHECKING:
26
27
  from vellum.workflows.workflows.base import BaseWorkflow
27
28
 
29
+ logger = logging.getLogger(__name__)
30
+
28
31
 
29
32
  class _BaseWorkflowExecutionBody(UniversalBaseModel):
30
33
  workflow_definition: Type["BaseWorkflow"]
@@ -107,8 +110,12 @@ class WorkflowExecutionInitiatedEvent(_BaseWorkflowEvent, Generic[InputsType, St
107
110
  ) -> WorkflowExecutionInitiatedBody[InputsType, StateType]:
108
111
  context = info.context if info and hasattr(info, "context") else {}
109
112
  if context and "event_enricher" in context and callable(context["event_enricher"]):
110
- event = context["event_enricher"](self)
111
- return event.body
113
+ try:
114
+ event = context["event_enricher"](self)
115
+ return event.body
116
+ except Exception as e:
117
+ logger.exception(f"Error in event_enricher: {e}")
118
+ return body
112
119
  else:
113
120
  return body
114
121
 
@@ -149,6 +156,7 @@ class WorkflowExecutionFulfilledEvent(_BaseWorkflowEvent, Generic[OutputsType]):
149
156
 
150
157
  class WorkflowExecutionRejectedBody(_BaseWorkflowExecutionBody):
151
158
  error: WorkflowError
159
+ traceback: Optional[str] = None
152
160
 
153
161
 
154
162
  class WorkflowExecutionRejectedEvent(_BaseWorkflowEvent):
@@ -446,3 +446,19 @@ def test_templating_node__conditional_type_checking():
446
446
 
447
447
  # THEN conditional type checking works
448
448
  assert outputs.result == "test string"
449
+
450
+
451
+ def test_templating_node__dict_wrapper_nonexistent_attribute_is_none():
452
+ """Test that non-existent attributes on DictWrapper evaluate to None."""
453
+
454
+ # GIVEN a templating node with nonexistent attr in the template
455
+ class TemplateNode(TemplatingNode[BaseState, str]):
456
+ template = "{% if data.nonexistent_attr is none %}none_value{% else %}{{ data.nonexistent_attr }}{% endif %}"
457
+ inputs = {"data": {"existing_key": "existing_value"}}
458
+
459
+ # WHEN the node is run
460
+ node = TemplateNode()
461
+ outputs = node.run()
462
+
463
+ # THEN it should recognize the non-existent attribute as ""
464
+ assert outputs.result == ""
@@ -847,21 +847,11 @@ def main(arg1: list) -> str:
847
847
  runtime = "PYTHON_3_11_6"
848
848
 
849
849
  # WHEN we run the node
850
- with pytest.raises(NodeException) as exc_info:
851
- node = ExampleCodeExecutionNode()
852
- node.run()
850
+ node = ExampleCodeExecutionNode()
851
+ outputs = node.run()
853
852
 
854
853
  # AND the result should be the correct output
855
- assert (
856
- exc_info.value.message
857
- == """\
858
- Traceback (most recent call last):
859
- File "ExampleCodeExecutionNode.code.py", line 2, in main
860
- return arg1["invalid"]
861
-
862
- AttributeError: dict has no key: 'invalid'
863
- """
864
- )
854
+ assert outputs == {"result": "", "log": ""}
865
855
 
866
856
 
867
857
  def test_run_node__execute_code__value_key_access():
@@ -54,12 +54,23 @@ class FunctionCallNodeMixin:
54
54
  return function_call.value.arguments or {}
55
55
  return {}
56
56
 
57
+ def _extract_function_call_id(self) -> Optional[str]:
58
+ """Extract function call ID from function call output."""
59
+ current_index = getattr(self, "state").current_prompt_output_index
60
+ if self.function_call_output and len(self.function_call_output) > current_index:
61
+ function_call = self.function_call_output[current_index]
62
+ if function_call.type == "FUNCTION_CALL" and function_call.value is not None:
63
+ return function_call.value.id
64
+ return None
65
+
57
66
  def _add_function_result_to_chat_history(self, result: Any, state: ToolCallingState) -> None:
58
67
  """Add function execution result to chat history."""
68
+ function_call_id = self._extract_function_call_id()
59
69
  state.chat_history.append(
60
70
  ChatMessage(
61
71
  role="FUNCTION",
62
72
  content=StringChatMessageContent(value=json.dumps(result, cls=DefaultStateEncoder)),
73
+ source=function_call_id,
63
74
  )
64
75
  )
65
76
  with state.__quiet__():