vellum-ai 0.14.15__py3-none-any.whl → 0.14.16__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.
@@ -18,7 +18,7 @@ class BaseClientWrapper:
18
18
  headers: typing.Dict[str, str] = {
19
19
  "X-Fern-Language": "Python",
20
20
  "X-Fern-SDK-Name": "vellum-ai",
21
- "X-Fern-SDK-Version": "0.14.15",
21
+ "X-Fern-SDK-Version": "0.14.16",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -10,7 +10,6 @@ from json.decoder import JSONDecodeError
10
10
  from ...core.api_error import ApiError
11
11
  from ...types.document_index_indexing_config_request import DocumentIndexIndexingConfigRequest
12
12
  from ...types.entity_status import EntityStatus
13
- from ...types.environment_enum import EnvironmentEnum
14
13
  from ...types.document_index_read import DocumentIndexRead
15
14
  from ...core.serialization import convert_and_respect_annotation_metadata
16
15
  from ...core.jsonable_encoder import jsonable_encoder
@@ -108,7 +107,6 @@ class DocumentIndexesClient:
108
107
  name: str,
109
108
  indexing_config: DocumentIndexIndexingConfigRequest,
110
109
  status: typing.Optional[EntityStatus] = OMIT,
111
- environment: typing.Optional[EnvironmentEnum] = OMIT,
112
110
  copy_documents_from_index_id: typing.Optional[str] = OMIT,
113
111
  request_options: typing.Optional[RequestOptions] = None,
114
112
  ) -> DocumentIndexRead:
@@ -131,13 +129,6 @@ class DocumentIndexesClient:
131
129
  * `ACTIVE` - Active
132
130
  * `ARCHIVED` - Archived
133
131
 
134
- environment : typing.Optional[EnvironmentEnum]
135
- The environment this document index is used in
136
-
137
- * `DEVELOPMENT` - Development
138
- * `STAGING` - Staging
139
- * `PRODUCTION` - Production
140
-
141
132
  copy_documents_from_index_id : typing.Optional[str]
142
133
  Optionally specify the id of a document index from which you'd like to copy and re-index its documents into this newly created index
143
134
 
@@ -191,7 +182,6 @@ class DocumentIndexesClient:
191
182
  "label": label,
192
183
  "name": name,
193
184
  "status": status,
194
- "environment": environment,
195
185
  "indexing_config": convert_and_respect_annotation_metadata(
196
186
  object_=indexing_config, annotation=DocumentIndexIndexingConfigRequest, direction="write"
197
187
  ),
@@ -268,7 +258,6 @@ class DocumentIndexesClient:
268
258
  *,
269
259
  label: str,
270
260
  status: typing.Optional[EntityStatus] = OMIT,
271
- environment: typing.Optional[EnvironmentEnum] = OMIT,
272
261
  request_options: typing.Optional[RequestOptions] = None,
273
262
  ) -> DocumentIndexRead:
274
263
  """
@@ -288,13 +277,6 @@ class DocumentIndexesClient:
288
277
  * `ACTIVE` - Active
289
278
  * `ARCHIVED` - Archived
290
279
 
291
- environment : typing.Optional[EnvironmentEnum]
292
- The environment this document index is used in
293
-
294
- * `DEVELOPMENT` - Development
295
- * `STAGING` - Staging
296
- * `PRODUCTION` - Production
297
-
298
280
  request_options : typing.Optional[RequestOptions]
299
281
  Request-specific configuration.
300
282
 
@@ -322,7 +304,6 @@ class DocumentIndexesClient:
322
304
  json={
323
305
  "label": label,
324
306
  "status": status,
325
- "environment": environment,
326
307
  },
327
308
  request_options=request_options,
328
309
  omit=OMIT,
@@ -388,7 +369,6 @@ class DocumentIndexesClient:
388
369
  *,
389
370
  label: typing.Optional[str] = OMIT,
390
371
  status: typing.Optional[EntityStatus] = OMIT,
391
- environment: typing.Optional[EnvironmentEnum] = OMIT,
392
372
  request_options: typing.Optional[RequestOptions] = None,
393
373
  ) -> DocumentIndexRead:
394
374
  """
@@ -408,13 +388,6 @@ class DocumentIndexesClient:
408
388
  * `ACTIVE` - Active
409
389
  * `ARCHIVED` - Archived
410
390
 
411
- environment : typing.Optional[EnvironmentEnum]
412
- The environment this document index is used in
413
-
414
- * `DEVELOPMENT` - Development
415
- * `STAGING` - Staging
416
- * `PRODUCTION` - Production
417
-
418
391
  request_options : typing.Optional[RequestOptions]
419
392
  Request-specific configuration.
420
393
 
@@ -441,7 +414,6 @@ class DocumentIndexesClient:
441
414
  json={
442
415
  "label": label,
443
416
  "status": status,
444
- "environment": environment,
445
417
  },
446
418
  request_options=request_options,
447
419
  omit=OMIT,
@@ -651,7 +623,6 @@ class AsyncDocumentIndexesClient:
651
623
  name: str,
652
624
  indexing_config: DocumentIndexIndexingConfigRequest,
653
625
  status: typing.Optional[EntityStatus] = OMIT,
654
- environment: typing.Optional[EnvironmentEnum] = OMIT,
655
626
  copy_documents_from_index_id: typing.Optional[str] = OMIT,
656
627
  request_options: typing.Optional[RequestOptions] = None,
657
628
  ) -> DocumentIndexRead:
@@ -674,13 +645,6 @@ class AsyncDocumentIndexesClient:
674
645
  * `ACTIVE` - Active
675
646
  * `ARCHIVED` - Archived
676
647
 
677
- environment : typing.Optional[EnvironmentEnum]
678
- The environment this document index is used in
679
-
680
- * `DEVELOPMENT` - Development
681
- * `STAGING` - Staging
682
- * `PRODUCTION` - Production
683
-
684
648
  copy_documents_from_index_id : typing.Optional[str]
685
649
  Optionally specify the id of a document index from which you'd like to copy and re-index its documents into this newly created index
686
650
 
@@ -742,7 +706,6 @@ class AsyncDocumentIndexesClient:
742
706
  "label": label,
743
707
  "name": name,
744
708
  "status": status,
745
- "environment": environment,
746
709
  "indexing_config": convert_and_respect_annotation_metadata(
747
710
  object_=indexing_config, annotation=DocumentIndexIndexingConfigRequest, direction="write"
748
711
  ),
@@ -827,7 +790,6 @@ class AsyncDocumentIndexesClient:
827
790
  *,
828
791
  label: str,
829
792
  status: typing.Optional[EntityStatus] = OMIT,
830
- environment: typing.Optional[EnvironmentEnum] = OMIT,
831
793
  request_options: typing.Optional[RequestOptions] = None,
832
794
  ) -> DocumentIndexRead:
833
795
  """
@@ -847,13 +809,6 @@ class AsyncDocumentIndexesClient:
847
809
  * `ACTIVE` - Active
848
810
  * `ARCHIVED` - Archived
849
811
 
850
- environment : typing.Optional[EnvironmentEnum]
851
- The environment this document index is used in
852
-
853
- * `DEVELOPMENT` - Development
854
- * `STAGING` - Staging
855
- * `PRODUCTION` - Production
856
-
857
812
  request_options : typing.Optional[RequestOptions]
858
813
  Request-specific configuration.
859
814
 
@@ -889,7 +844,6 @@ class AsyncDocumentIndexesClient:
889
844
  json={
890
845
  "label": label,
891
846
  "status": status,
892
- "environment": environment,
893
847
  },
894
848
  request_options=request_options,
895
849
  omit=OMIT,
@@ -963,7 +917,6 @@ class AsyncDocumentIndexesClient:
963
917
  *,
964
918
  label: typing.Optional[str] = OMIT,
965
919
  status: typing.Optional[EntityStatus] = OMIT,
966
- environment: typing.Optional[EnvironmentEnum] = OMIT,
967
920
  request_options: typing.Optional[RequestOptions] = None,
968
921
  ) -> DocumentIndexRead:
969
922
  """
@@ -983,13 +936,6 @@ class AsyncDocumentIndexesClient:
983
936
  * `ACTIVE` - Active
984
937
  * `ARCHIVED` - Archived
985
938
 
986
- environment : typing.Optional[EnvironmentEnum]
987
- The environment this document index is used in
988
-
989
- * `DEVELOPMENT` - Development
990
- * `STAGING` - Staging
991
- * `PRODUCTION` - Production
992
-
993
939
  request_options : typing.Optional[RequestOptions]
994
940
  Request-specific configuration.
995
941
 
@@ -1024,7 +970,6 @@ class AsyncDocumentIndexesClient:
1024
970
  json={
1025
971
  "label": label,
1026
972
  "status": status,
1027
- "environment": environment,
1028
973
  },
1029
974
  request_options=request_options,
1030
975
  omit=OMIT,
@@ -5,7 +5,6 @@ import datetime as dt
5
5
  import pydantic
6
6
  import typing
7
7
  from .entity_status import EntityStatus
8
- from .environment_enum import EnvironmentEnum
9
8
  from .document_index_indexing_config import DocumentIndexIndexingConfig
10
9
  from ..core.pydantic_utilities import IS_PYDANTIC_V2
11
10
 
@@ -31,15 +30,6 @@ class DocumentIndexRead(UniversalBaseModel):
31
30
  * `ARCHIVED` - Archived
32
31
  """
33
32
 
34
- environment: typing.Optional[EnvironmentEnum] = pydantic.Field(default=None)
35
- """
36
- The environment this document index is used in
37
-
38
- * `DEVELOPMENT` - Development
39
- * `STAGING` - Staging
40
- * `PRODUCTION` - Production
41
- """
42
-
43
33
  indexing_config: DocumentIndexIndexingConfig
44
34
 
45
35
  if IS_PYDANTIC_V2:
@@ -1,17 +1,27 @@
1
1
  from functools import lru_cache
2
- from typing import Any, Dict, Literal, Optional, Tuple, Union
2
+ from typing import Any, Dict, Literal, NamedTuple, Optional, Tuple, Union
3
+ from typing_extensions import TypeAlias
3
4
 
4
5
  from pydantic.fields import FieldInfo
5
6
  from pydantic.plugin import (
6
7
  PydanticPluginProtocol,
7
- SchemaKind,
8
- SchemaTypePath,
9
8
  ValidateJsonHandlerProtocol,
10
9
  ValidatePythonHandlerProtocol,
11
10
  ValidateStringsHandlerProtocol,
12
11
  )
13
12
  from pydantic_core import CoreSchema
14
13
 
14
+ # Redefined manually instead of imported from pydantic to support versions < 2.5
15
+ SchemaKind: TypeAlias = Literal["BaseModel", "TypeAdapter", "dataclass", "create_model", "validate_call"]
16
+
17
+
18
+ # Redefined manually instead of imported from pydantic to support versions < 2.5
19
+ class SchemaTypePath(NamedTuple):
20
+ """Path defining where `schema_type` was defined, or where `TypeAdapter` was called."""
21
+
22
+ module: str
23
+ name: str
24
+
15
25
 
16
26
  @lru_cache(maxsize=1)
17
27
  def import_base_descriptor():
@@ -81,7 +91,7 @@ class VellumPydanticPlugin(PydanticPluginProtocol):
81
91
  self,
82
92
  schema: CoreSchema,
83
93
  schema_type: Any,
84
- schema_type_path: SchemaTypePath,
94
+ schema_type_path: SchemaTypePath, # type: ignore
85
95
  schema_kind: SchemaKind,
86
96
  config: Any,
87
97
  plugin_settings: Dict[str, Any],
@@ -10,9 +10,13 @@ def create_vellum_client(api_key: Optional[str] = None) -> Vellum:
10
10
 
11
11
  return Vellum(
12
12
  api_key=api_key,
13
- environment=VellumEnvironment(
14
- default=os.getenv("VELLUM_DEFAULT_API_URL", os.getenv("VELLUM_API_URL", "https://api.vellum.ai")),
15
- documents=os.getenv("VELLUM_DOCUMENTS_API_URL", os.getenv("VELLUM_API_URL", "https://documents.vellum.ai")),
16
- predict=os.getenv("VELLUM_PREDICT_API_URL", os.getenv("VELLUM_API_URL", "https://predict.vellum.ai")),
17
- ),
13
+ environment=create_vellum_environment(),
14
+ )
15
+
16
+
17
+ def create_vellum_environment() -> VellumEnvironment:
18
+ return VellumEnvironment(
19
+ default=os.getenv("VELLUM_DEFAULT_API_URL", os.getenv("VELLUM_API_URL", "https://api.vellum.ai")),
20
+ documents=os.getenv("VELLUM_DOCUMENTS_API_URL", os.getenv("VELLUM_API_URL", "https://documents.vellum.ai")),
21
+ predict=os.getenv("VELLUM_PREDICT_API_URL", os.getenv("VELLUM_API_URL", "https://predict.vellum.ai")),
18
22
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.14.15
3
+ Version: 0.14.16
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -3,7 +3,7 @@ vellum_cli/README.md,sha256=2NudRoLzWxNKqnuVy1JuQ7DerIaxWGYkrH8kMd-asIE,90
3
3
  vellum_cli/__init__.py,sha256=7aO9XFnaEVRiVshn86cFudebFUccT-gV8xIARJWqKYo,12257
4
4
  vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
5
5
  vellum_cli/config.py,sha256=aKnhvM5B8QdPA4cQC5Sqg7ImP-vNcVdSkZmk_OBpQTw,9309
6
- vellum_cli/image_push.py,sha256=4auU15Pb6c8DTGvT-AQ5HHXXrvIvEDs6L02d4OvJYI8,5199
6
+ vellum_cli/image_push.py,sha256=8DDvRDJEZ-FukUCqGW1827bg1ybF4xBbx9WyqWYQE-g,6816
7
7
  vellum_cli/init.py,sha256=WpnMXPItPmh0f0bBGIer3p-e5gu8DUGwSArT_FuoMEw,5093
8
8
  vellum_cli/logger.py,sha256=PuRFa0WCh4sAGFS5aqWB0QIYpS6nBWwPJrIXpWxugV4,1022
9
9
  vellum_cli/ping.py,sha256=lWyJw6sziXjyTopTYRdFF5hV-sYPVDdX0yVbG5fzcY4,585
@@ -12,6 +12,7 @@ vellum_cli/push.py,sha256=xjTNbLwOVFNU3kpBrm56Bk5QkSRrJ9z86qceghCzfIA,9655
12
12
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  vellum_cli/tests/conftest.py,sha256=AFYZryKA2qnUuCPBxBKmHLFoPiE0WhBFFej9tNwSHdc,1526
14
14
  vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
15
+ vellum_cli/tests/test_image_push.py,sha256=i3lJuW8nFRwL1M1OF6752IZYvGAFgKmkB2hd_rYlsmg,2028
15
16
  vellum_cli/tests/test_init.py,sha256=8UOc_ThfouR4ja5cCl_URuLk7ohr9JXfCnG4yka1OUQ,18754
16
17
  vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
17
18
  vellum_cli/tests/test_ping.py,sha256=QtbhYKMYn1DFnDyBij2mkQO32j9KOpZ5Pf0yek7k_Ao,1284
@@ -61,11 +62,11 @@ vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=VD-4USi
61
62
  vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
63
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
64
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=A1-tIpC5KIKG9JA_rkd1nLS8zUG3Kb4QiVdvb3boFxE,2509
64
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=mFmxXfnUPrwndaBurW9E-VSBUQjF3cGv3JpRuNmwWh8,15475
65
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=1cszL6N6FNGVm61MOa7AEiHnF0QjZWqDQuPOp4yiG94,18277
66
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=-12ZkZb3f5gyoNASV2yeQtMo5HmNsVEo8nXwL6IC-I8,6261
67
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=FD94h96w5wWYlLVC8_tqr2aUHPyO2UQh4f03jDX4re4,39783
68
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=EbVgg_3_ipTt3MOop4RARX0fmNjwqZtkhIXzx9nGw7Y,4487
65
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=2ZDTmpiU2CcZe4ukxoQ79SJx8V8kDRQHgUxP5Vtesus,15605
66
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=lScpUiz8fvUmJK18Cpygs9xQrfHQlkSIlmxapGYTS0g,18770
67
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=KgxSN8L5AWPL8EpQfSZiTqK428nAIElcWrV-sR17528,6456
68
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=yS8GpjbH0objjcNYK73j8rDHbhqinIbG7CcoNjnolBg,40611
69
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=_-ADur28OkVy4YEgMHkkVYqMbS1j3GcOtX9MTYmmvf0,4632
69
70
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=IRazH2QR6F8RGqNemEnHueyj5DtEa6rFTYhT16S4jI8,15917
70
71
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=V__y7uu-dy6TJjPeu4UDvaoO2yYwBRbPiW9uJdzWRx4,29828
71
72
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=R8DW1DUb0DOSLtnF2E1HaCTmtpG-ski0LfcM2WeLVNo,47672
@@ -123,7 +124,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
123
124
  vellum/client/__init__.py,sha256=tKtdM1_GqmGq1gpi9ydWD_T-MM7fPn8QdHh8ww19cNI,117564
124
125
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
125
126
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
126
- vellum/client/core/client_wrapper.py,sha256=x6cZlx3EA5bHNlGRnX0klOVCrqkvqWv_oUW4xjYEehU,1869
127
+ vellum/client/core/client_wrapper.py,sha256=0XmYpWbtLyEE04hBfhFVCncXeuj0BKKSGnpz2iz-nyA,1869
127
128
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
128
129
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
129
130
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -150,7 +151,7 @@ vellum/client/resources/deployments/types/__init__.py,sha256=29GVdoLOJsADSSSqZwb
150
151
  vellum/client/resources/deployments/types/deployments_list_request_status.py,sha256=CxlQD16KZXme7x31YYCe_3aAgEueutDTeJo5A4Au-aU,174
151
152
  vellum/client/resources/deployments/types/list_deployment_release_tags_request_source.py,sha256=hRGgWMYZL9uKCmD_2dU8-u9RCPUUGItpNn1tUY-NXKY,180
152
153
  vellum/client/resources/document_indexes/__init__.py,sha256=YpOl_9IV7xOlH4OmusQxtAJB11kxQfCSMDyT1_UD0oM,165
153
- vellum/client/resources/document_indexes/client.py,sha256=XDrceFkbX1MtrR4hoFR4b-UIC2PFS1AAlKPCWR6OcZQ,37520
154
+ vellum/client/resources/document_indexes/client.py,sha256=UcznU0NyvdNBpV4UCsTqG3Ejj6w4dK4UBmgrTWzZFtw,35438
154
155
  vellum/client/resources/document_indexes/types/__init__.py,sha256=IoFqKHN_VBdEhC7VL8_6Jbatrn0e0zuYEJAJUahcUR0,196
155
156
  vellum/client/resources/document_indexes/types/document_indexes_list_request_status.py,sha256=sfUEB0cvOSmlE2iITqnMVyHv05Zy2fWP4QjCIYqMg0M,178
156
157
  vellum/client/resources/documents/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
@@ -266,7 +267,7 @@ vellum/client/types/document_index_chunking.py,sha256=TU0Y7z0Xacm3dhzEDuDIG3ZKJC
266
267
  vellum/client/types/document_index_chunking_request.py,sha256=g9BKCsHKg5kzjG7YYeMNQ_5R8TXLeSgumJlMXoSfBcs,435
267
268
  vellum/client/types/document_index_indexing_config.py,sha256=xL1pCzUOkw5sSie1OrBpasE3bVnv0UyZBn7uZztbhbs,781
268
269
  vellum/client/types/document_index_indexing_config_request.py,sha256=Wt-ys1o_acHNyLU0c1laG2PVT7rgCfwO54f5nudAxk4,832
269
- vellum/client/types/document_index_read.py,sha256=cXL115A4h-TFiGc29tAkXb1pkuK0RzIquyOu1Pv7Jug,1469
270
+ vellum/client/types/document_index_read.py,sha256=ePngiRszr65HLl9D0_FUdhAdMe84nRwyM3cKbr8rFpg,1177
270
271
  vellum/client/types/document_processing_state.py,sha256=ISlurj7jQzwHzxPzDZTqeAIgSIIGMBBPgcOSoe04pTU,211
271
272
  vellum/client/types/document_prompt_block.py,sha256=sgFxN48PILFuuF2KUIwks6PbJ3XH6sCE_8ydLEE_doU,1019
272
273
  vellum/client/types/document_read.py,sha256=6nwEvVvVe-6y2vtPNYB7KtcFoaydH2ow-WhCmCAvMQ8,1713
@@ -719,7 +720,7 @@ vellum/evaluations/utils/env.py,sha256=Xj_nxsoU5ox06EOTjRopR4lrigQI6Le6qbWGltYoE
719
720
  vellum/evaluations/utils/exceptions.py,sha256=dXMAkzqbHV_AP5FjjbegPlfUE0zQDlpA3qOsoOJUxfg,49
720
721
  vellum/evaluations/utils/paginator.py,sha256=rEED_BJAXAM6tM1yMwHePNzszjq_tTq4NbQvi1jWQ_Q,697
721
722
  vellum/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
722
- vellum/plugins/pydantic.py,sha256=BMUwC4OkxtNf6hpLwb0T4MBUKgkGy55T_5Ww7GHpHYo,3068
723
+ vellum/plugins/pydantic.py,sha256=XpQQs_o8DQY_5gFFDzJzaXahUqR_l5TEI4b5ZoH9ob8,3528
723
724
  vellum/plugins/utils.py,sha256=cPmxE9R2CK1bki2jKE8rB-G9zMf2pzHjSPDHFPXwd3Q,878
724
725
  vellum/plugins/vellum_mypy.py,sha256=QTuMSq6PiZW1dyTUZ5Bf1d4XkgFj0TKAgZLP8f4UgL4,27914
725
726
  vellum/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1505,15 +1506,15 @@ vellum/workflows/utils/tests/test_uuids.py,sha256=i77ABQ0M3S-aFLzDXHJq_yr5FPkJEW
1505
1506
  vellum/workflows/utils/tests/test_vellum_variables.py,sha256=6H-BpmbIEmVRO75QQ3Rfy4bEUMMP2qwGzx2Gp1uXbfw,879
1506
1507
  vellum/workflows/utils/uuids.py,sha256=DFzPv9RCvsKhvdTEIQyfSek2A31D6S_QcmeLPbgrgTY,739
1507
1508
  vellum/workflows/utils/vellum_variables.py,sha256=fC2aSLvlS31D15dOWu43LBRR0QsgUKNXBiCUvvaLXSs,3231
1508
- vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528t75s,683
1509
+ vellum/workflows/vellum_client.py,sha256=GxOy3dX6A04xiY69vPv1S4YGuQ_TMxwHi6WRMimQBBE,762
1509
1510
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1510
1511
  vellum/workflows/workflows/base.py,sha256=TSS2BHC8LAi-N5GdEa75BeChwzwTzL7yldFnTlLINro,22665
1511
1512
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1512
1513
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1513
1514
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=NRteiICyJvDM5zrtUfq2fZoXcGQVaWC9xmNlLLVW0cU,7979
1514
1515
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
1515
- vellum_ai-0.14.15.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1516
- vellum_ai-0.14.15.dist-info/METADATA,sha256=8TM16vJdsQpUXVDgasscuRmbLESHxIgmMj8QlKoLUQU,5408
1517
- vellum_ai-0.14.15.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1518
- vellum_ai-0.14.15.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1519
- vellum_ai-0.14.15.dist-info/RECORD,,
1516
+ vellum_ai-0.14.16.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1517
+ vellum_ai-0.14.16.dist-info/METADATA,sha256=yxCtedPJiwtcov54unW-4jIJErky44J7Mhs3BEedjW8,5408
1518
+ vellum_ai-0.14.16.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1519
+ vellum_ai-0.14.16.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1520
+ vellum_ai-0.14.16.dist-info/RECORD,,
vellum_cli/image_push.py CHANGED
@@ -8,7 +8,7 @@ import docker
8
8
  from docker import DockerClient
9
9
  from dotenv import load_dotenv
10
10
 
11
- from vellum.workflows.vellum_client import create_vellum_client
11
+ from vellum.workflows.vellum_client import create_vellum_client, create_vellum_environment
12
12
  from vellum_cli.logger import load_cli_logger
13
13
 
14
14
  _SUPPORTED_ARCHITECTURE = "amd64"
@@ -19,6 +19,21 @@ def image_push_command(image: str, tags: Optional[List[str]] = None) -> None:
19
19
  logger = load_cli_logger()
20
20
  vellum_client = create_vellum_client()
21
21
 
22
+ # Check if we are self hosted by looking at our base url
23
+ api_url = create_vellum_environment().default
24
+ is_self_hosted = not api_url.endswith("vellum.ai") and "localhost:" not in api_url and "127.0.0.1" not in api_url
25
+ if is_self_hosted:
26
+ logger.info("Self hosted install detected...")
27
+
28
+ if is_self_hosted and "/" not in image:
29
+ logger.error(
30
+ "For adding images to your self hosted install you must include the "
31
+ "repository address in the provided image name. You must also have "
32
+ "already pushed the image to the docker repository that your self "
33
+ "hosted install is using."
34
+ )
35
+ exit(1)
36
+
22
37
  # We're using docker python SDK here instead of subprocess since it connects to the docker host directly
23
38
  # instead of using the command line so it seemed like it would possibly be a little more robust since
24
39
  # it might avoid peoples' wonky paths, unfortunately it doesn't support the manifest command which we need for
@@ -29,59 +44,78 @@ def image_push_command(image: str, tags: Optional[List[str]] = None) -> None:
29
44
  docker_client = docker.from_env()
30
45
  check_architecture(docker_client, image, logger)
31
46
 
32
- logger.info("Authenticating...")
33
- auth = vellum_client.container_images.docker_service_token()
34
-
35
- docker_client.login(
36
- username="oauth2accesstoken",
37
- password=auth.access_token,
38
- registry=auth.repository,
39
- )
40
-
41
47
  repo_split = image.split("/")
42
48
  tag_split = repo_split[-1].split(":")
43
49
  image_name = tag_split[0]
44
50
  main_tag = tag_split[1] if len(tag_split) > 1 else "latest"
45
-
46
51
  all_tags = [main_tag, *(tags or [])]
47
- for tag in all_tags:
48
- vellum_image_name = f"{auth.repository}/{image_name}:{tag}"
49
-
50
- docker_client.api.tag(image, vellum_image_name)
51
-
52
- push_result = docker_client.images.push(repository=vellum_image_name, stream=True)
53
-
54
- # Here were trying to mime the output you would get from a normal docker push, which
55
- # the python sdk makes as hard as possible.
56
- for raw_line in push_result:
57
- try:
58
- for sub_line in raw_line.decode("utf-8").split("\r\n"):
59
- line = json.loads(sub_line)
60
- error_message = line.get("errorDetail", {}).get("message")
61
- status = line.get("status")
62
- id = line.get("id", "")
63
-
64
- if error_message:
65
- logger.error(error_message)
66
- exit(1)
67
- elif status == "Waiting":
68
- continue
69
- elif status:
70
- logger.info(f"{id}{': ' if id else ''}{status}")
71
- else:
72
- logger.info(line)
73
- except Exception:
74
- continue
75
52
 
76
- result = subprocess.run(
53
+ if is_self_hosted:
54
+ # Include the repo for self hosted since we skip pushing it to our internal repo and expect
55
+ # the user the push it themselves and provide us with the repo name.
56
+ image_name = image.split(":")[0]
57
+
58
+ logger.info("Checking if image already exists in repository...")
59
+ exists_result = subprocess.run(
60
+ ["docker", "manifest", "inspect", image],
61
+ stdout=subprocess.PIPE,
62
+ stderr=subprocess.PIPE,
63
+ )
64
+
65
+ if exists_result.returncode != 0:
66
+ logger.error(
67
+ "Image does not exist in repository. Push the image to the "
68
+ "repository your self hosted install is using and try again."
69
+ )
70
+ exit(1)
71
+ else:
72
+ logger.info("Authenticating...")
73
+ auth = vellum_client.container_images.docker_service_token()
74
+
75
+ docker_client.login(
76
+ username="oauth2accesstoken",
77
+ password=auth.access_token,
78
+ registry=auth.repository,
79
+ )
80
+
81
+ for tag in all_tags:
82
+ vellum_image_name = f"{auth.repository}/{image_name}:{tag}"
83
+
84
+ docker_client.api.tag(image, vellum_image_name)
85
+
86
+ push_result = docker_client.images.push(repository=vellum_image_name, stream=True)
87
+
88
+ # Here were trying to mime the output you would get from a normal docker push, which
89
+ # the python sdk makes as hard as possible.
90
+ for raw_line in push_result:
91
+ try:
92
+ for sub_line in raw_line.decode("utf-8").split("\r\n"):
93
+ line = json.loads(sub_line)
94
+ error_message = line.get("errorDetail", {}).get("message")
95
+ status = line.get("status")
96
+ id = line.get("id", "")
97
+
98
+ if error_message:
99
+ logger.error(error_message)
100
+ exit(1)
101
+ elif status == "Waiting":
102
+ continue
103
+ elif status:
104
+ logger.info(f"{id}{': ' if id else ''}{status}")
105
+ else:
106
+ logger.info(line)
107
+ except Exception:
108
+ continue
109
+
110
+ inspect_result = subprocess.run(
77
111
  ["docker", "inspect", "--format='{{index .RepoDigests 0}}'", image],
78
112
  stdout=subprocess.PIPE,
79
113
  stderr=subprocess.PIPE,
80
114
  )
81
115
 
82
116
  sha = ""
83
- if result.returncode == 0:
84
- match = re.search(r"sha256[^']*", result.stdout.decode("utf-8"))
117
+ if inspect_result.returncode == 0:
118
+ match = re.search(r"sha256[^']*", inspect_result.stdout.decode("utf-8"))
85
119
  if match and match.group(0):
86
120
  sha = match.group(0)
87
121
 
@@ -0,0 +1,56 @@
1
+ import subprocess
2
+ from unittest.mock import MagicMock, patch
3
+
4
+ from click.testing import CliRunner
5
+
6
+ from vellum_cli import main as cli_main
7
+
8
+
9
+ @patch("subprocess.run")
10
+ @patch("docker.from_env")
11
+ def test_image_push__self_hosted_happy_path(mock_docker_from_env, mock_run, vellum_client, monkeypatch):
12
+ # GIVEN a self hosted vellum api URL env var
13
+ monkeypatch.setenv("VELLUM_API_URL", "mycompany.api.com")
14
+
15
+ # Mock Docker client
16
+ mock_docker_client = MagicMock()
17
+ mock_docker_from_env.return_value = mock_docker_client
18
+
19
+ mock_run.side_effect = [
20
+ subprocess.CompletedProcess(
21
+ args="", returncode=0, stdout=b'{"manifests": [{"platform": {"architecture": "amd64"}}]}'
22
+ ),
23
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"manifest"),
24
+ subprocess.CompletedProcess(args="", returncode=0, stdout=b"sha256:hellosha"),
25
+ ]
26
+
27
+ # WHEN the user runs the image push command
28
+ runner = CliRunner()
29
+ result = runner.invoke(cli_main, ["image", "push", "myrepo.net/myimage:latest"])
30
+
31
+ # THEN the command exits successfully
32
+ assert result.exit_code == 0, result.output
33
+
34
+ # AND gives the success message
35
+ assert "Image successfully pushed" in result.output
36
+
37
+
38
+ @patch("subprocess.run")
39
+ @patch("docker.from_env")
40
+ def test_image_push__self_hosted_blocks_repo(mock_docker_from_env, mock_run, vellum_client, monkeypatch):
41
+ # GIVEN a self hosted vellum api URL env var
42
+ monkeypatch.setenv("VELLUM_API_URL", "mycompany.api.com")
43
+
44
+ # Mock Docker client
45
+ mock_docker_client = MagicMock()
46
+ mock_docker_from_env.return_value = mock_docker_client
47
+
48
+ # WHEN the user runs the image push command
49
+ runner = CliRunner()
50
+ result = runner.invoke(cli_main, ["image", "push", "myimage"])
51
+
52
+ # THEN the command exits unsuccessfully
53
+ assert result.exit_code == 1, result.output
54
+
55
+ # AND gives the error message for self hosted installs not including the repo
56
+ assert "For adding images to your self hosted install you must include" in result.output