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.
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/resources/document_indexes/client.py +0 -55
- vellum/client/types/document_index_read.py +0 -10
- vellum/plugins/pydantic.py +14 -4
- vellum/workflows/vellum_client.py +9 -5
- {vellum_ai-0.14.15.dist-info → vellum_ai-0.14.16.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.15.dist-info → vellum_ai-0.14.16.dist-info}/RECORD +17 -16
- vellum_cli/image_push.py +76 -42
- vellum_cli/tests/test_image_push.py +56 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +29 -33
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +91 -106
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +33 -38
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +138 -153
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +23 -26
- {vellum_ai-0.14.15.dist-info → vellum_ai-0.14.16.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.15.dist-info → vellum_ai-0.14.16.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.15.dist-info → vellum_ai-0.14.16.dist-info}/entry_points.txt +0 -0
@@ -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.
|
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:
|
vellum/plugins/pydantic.py
CHANGED
@@ -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=
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
)
|
@@ -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=
|
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=
|
65
|
-
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=
|
66
|
-
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256
|
67
|
-
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=
|
68
|
-
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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.
|
1516
|
-
vellum_ai-0.14.
|
1517
|
-
vellum_ai-0.14.
|
1518
|
-
vellum_ai-0.14.
|
1519
|
-
vellum_ai-0.14.
|
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
|
-
|
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
|
84
|
-
match = re.search(r"sha256[^']*",
|
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
|