aidial-client 0.11.0.dev6__tar.gz → 0.12.0.dev2__tar.gz
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.
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/PKG-INFO +55 -1
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/README.md +54 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/__init__.py +2 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_client.py +2 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_http_client/_async.py +31 -11
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_http_client/_base.py +19 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_http_client/_sync.py +4 -11
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/helpers/storage_resource.py +24 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/__init__.py +3 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/files.py +21 -31
- aidial_client-0.12.0.dev2/aidial_client/resources/user.py +19 -0
- aidial_client-0.12.0.dev2/aidial_client/types/user.py +11 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/pyproject.toml +1 -1
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/LICENSE +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_auth.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_client_pool.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/openai.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/pydantic.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/pydantic_v1.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_constants.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_exception.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_http_client/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_http_client/_sse.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_defaults.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_generic.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_http_request.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_json_rpc.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_model.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_log.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_utils/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_utils/_alias.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_utils/_dict.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_utils/_openai.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_utils/_response_processing.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_utils/_type_guard.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/helpers/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/helpers/_url.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/py.typed +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/application.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/base.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/bucket.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/chat/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/chat/completions.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/client_channel.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/deployments.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/metadata.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/model.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/prompts.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/resource_permissions.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/toolset.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/application.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/bucket.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/function.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/legacy/__init__.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/legacy/application_request.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/legacy/chat_completion.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/request.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/request_param.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/response.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/tool.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/client_channel.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/deployment.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/file.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/metadata.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/model.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/prompt.py +0 -0
- {aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/toolset.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aidial-client
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0.dev2
|
|
4
4
|
Summary: A Python client library for the AI DIAL API
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -61,6 +61,8 @@ Description-Content-Type: text/markdown
|
|
|
61
61
|
- [Get Application by Id](#get-application-by-id)
|
|
62
62
|
- [Models](#models)
|
|
63
63
|
- [Get Model by Name](#get-model-by-name)
|
|
64
|
+
- [User](#user)
|
|
65
|
+
- [Get Authenticated User Info](#get-authenticated-user-info)
|
|
64
66
|
- [Toolsets](#toolsets)
|
|
65
67
|
- [Get Toolset by Id](#get-toolset-by-id)
|
|
66
68
|
- [Resource Permissions](#resource-permissions)
|
|
@@ -554,6 +556,16 @@ result = await async_client.files.download(
|
|
|
554
556
|
)
|
|
555
557
|
```
|
|
556
558
|
|
|
559
|
+
For large async downloads, use `stream_download()` to process bytes as they arrive without buffering the full response in memory:
|
|
560
|
+
|
|
561
|
+
```python
|
|
562
|
+
async with async_client.files.stream_download(
|
|
563
|
+
url=await async_client.my_files_home() / "relative_folder/my-file.txt"
|
|
564
|
+
) as result:
|
|
565
|
+
async for bytes_chunk in result:
|
|
566
|
+
...
|
|
567
|
+
```
|
|
568
|
+
|
|
557
569
|
As a result, you will receive an object of type `FileDownloadResponse`, that you can iterate by byte chunks:
|
|
558
570
|
|
|
559
571
|
```python
|
|
@@ -868,6 +880,48 @@ ModelInfo(
|
|
|
868
880
|
)
|
|
869
881
|
```
|
|
870
882
|
|
|
883
|
+
### User
|
|
884
|
+
|
|
885
|
+
#### Get Authenticated User Info
|
|
886
|
+
|
|
887
|
+
To retrieve information about the currently authenticated user:
|
|
888
|
+
|
|
889
|
+
```python
|
|
890
|
+
# Sync
|
|
891
|
+
user_info = client.user.info()
|
|
892
|
+
|
|
893
|
+
# Async
|
|
894
|
+
user_info = await async_client.user.info()
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
As a result, you will receive a `UserInfo` object. When authenticated with an
|
|
898
|
+
API key:
|
|
899
|
+
|
|
900
|
+
```python
|
|
901
|
+
UserInfo(
|
|
902
|
+
roles=["default"],
|
|
903
|
+
project="PROJECT-NAME",
|
|
904
|
+
userClaims=None,
|
|
905
|
+
)
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
When authenticated with an access token:
|
|
909
|
+
|
|
910
|
+
```python
|
|
911
|
+
UserInfo(
|
|
912
|
+
roles=["BA"],
|
|
913
|
+
project=None,
|
|
914
|
+
userClaims={
|
|
915
|
+
"email": ["user_email"],
|
|
916
|
+
"sub": ["user_sub"],
|
|
917
|
+
},
|
|
918
|
+
)
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
`userClaims` is returned as an opaque `dict` because its contents depend on the
|
|
922
|
+
identity provider. `UserInfo` also preserves any additional fields the DIAL
|
|
923
|
+
deployment may return, so forward compatibility is retained.
|
|
924
|
+
|
|
871
925
|
### Toolsets
|
|
872
926
|
|
|
873
927
|
#### Get Toolset by Id
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
- [Get Application by Id](#get-application-by-id)
|
|
40
40
|
- [Models](#models)
|
|
41
41
|
- [Get Model by Name](#get-model-by-name)
|
|
42
|
+
- [User](#user)
|
|
43
|
+
- [Get Authenticated User Info](#get-authenticated-user-info)
|
|
42
44
|
- [Toolsets](#toolsets)
|
|
43
45
|
- [Get Toolset by Id](#get-toolset-by-id)
|
|
44
46
|
- [Resource Permissions](#resource-permissions)
|
|
@@ -532,6 +534,16 @@ result = await async_client.files.download(
|
|
|
532
534
|
)
|
|
533
535
|
```
|
|
534
536
|
|
|
537
|
+
For large async downloads, use `stream_download()` to process bytes as they arrive without buffering the full response in memory:
|
|
538
|
+
|
|
539
|
+
```python
|
|
540
|
+
async with async_client.files.stream_download(
|
|
541
|
+
url=await async_client.my_files_home() / "relative_folder/my-file.txt"
|
|
542
|
+
) as result:
|
|
543
|
+
async for bytes_chunk in result:
|
|
544
|
+
...
|
|
545
|
+
```
|
|
546
|
+
|
|
535
547
|
As a result, you will receive an object of type `FileDownloadResponse`, that you can iterate by byte chunks:
|
|
536
548
|
|
|
537
549
|
```python
|
|
@@ -846,6 +858,48 @@ ModelInfo(
|
|
|
846
858
|
)
|
|
847
859
|
```
|
|
848
860
|
|
|
861
|
+
### User
|
|
862
|
+
|
|
863
|
+
#### Get Authenticated User Info
|
|
864
|
+
|
|
865
|
+
To retrieve information about the currently authenticated user:
|
|
866
|
+
|
|
867
|
+
```python
|
|
868
|
+
# Sync
|
|
869
|
+
user_info = client.user.info()
|
|
870
|
+
|
|
871
|
+
# Async
|
|
872
|
+
user_info = await async_client.user.info()
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
As a result, you will receive a `UserInfo` object. When authenticated with an
|
|
876
|
+
API key:
|
|
877
|
+
|
|
878
|
+
```python
|
|
879
|
+
UserInfo(
|
|
880
|
+
roles=["default"],
|
|
881
|
+
project="PROJECT-NAME",
|
|
882
|
+
userClaims=None,
|
|
883
|
+
)
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
When authenticated with an access token:
|
|
887
|
+
|
|
888
|
+
```python
|
|
889
|
+
UserInfo(
|
|
890
|
+
roles=["BA"],
|
|
891
|
+
project=None,
|
|
892
|
+
userClaims={
|
|
893
|
+
"email": ["user_email"],
|
|
894
|
+
"sub": ["user_sub"],
|
|
895
|
+
},
|
|
896
|
+
)
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
`userClaims` is returned as an opaque `dict` because its contents depend on the
|
|
900
|
+
identity provider. `UserInfo` also preserves any additional fields the DIAL
|
|
901
|
+
deployment may return, so forward compatibility is retained.
|
|
902
|
+
|
|
849
903
|
### Toolsets
|
|
850
904
|
|
|
851
905
|
#### Get Toolset by Id
|
|
@@ -12,6 +12,7 @@ from aidial_client._exception import (
|
|
|
12
12
|
from aidial_client.types.client_channel import SigninResult
|
|
13
13
|
from aidial_client.types.model import ModelInfo, ModelLimits, ModelPricing
|
|
14
14
|
from aidial_client.types.toolset import ToolsetInfo
|
|
15
|
+
from aidial_client.types.user import UserInfo
|
|
15
16
|
|
|
16
17
|
__all__ = [
|
|
17
18
|
"Dial",
|
|
@@ -32,4 +33,5 @@ __all__ = [
|
|
|
32
33
|
"ModelPricing",
|
|
33
34
|
"ModelLimits",
|
|
34
35
|
"SigninResult",
|
|
36
|
+
"UserInfo",
|
|
35
37
|
]
|
|
@@ -120,6 +120,7 @@ class Dial(BaseDialClient[SyncHTTPClient, SyncAuthValue]):
|
|
|
120
120
|
self.client_channel = resources.ClientChannel(
|
|
121
121
|
http_client=self._http_client
|
|
122
122
|
)
|
|
123
|
+
self.user = resources.User(http_client=self._http_client)
|
|
123
124
|
|
|
124
125
|
def _create_http_client(self) -> SyncHTTPClient:
|
|
125
126
|
return SyncHTTPClient(
|
|
@@ -224,6 +225,7 @@ class AsyncDial(BaseDialClient[AsyncHTTPClient, AsyncAuthValue]):
|
|
|
224
225
|
self.client_channel = resources.AsyncClientChannel(
|
|
225
226
|
http_client=self._http_client
|
|
226
227
|
)
|
|
228
|
+
self.user = resources.AsyncUser(http_client=self._http_client)
|
|
227
229
|
|
|
228
230
|
def _create_http_client(self) -> AsyncHTTPClient:
|
|
229
231
|
return AsyncHTTPClient(
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_http_client/_async.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from collections.abc import AsyncIterator,
|
|
2
|
+
from collections.abc import AsyncIterator, Mapping
|
|
3
3
|
from contextlib import asynccontextmanager, suppress
|
|
4
4
|
from http import HTTPStatus
|
|
5
5
|
from typing import Any
|
|
@@ -8,7 +8,7 @@ import httpx
|
|
|
8
8
|
|
|
9
9
|
from aidial_client._auth import AsyncAuthValue, aget_combined_auth_headers
|
|
10
10
|
from aidial_client._exception import DialException
|
|
11
|
-
from aidial_client._http_client._base import BaseHTTPClient
|
|
11
|
+
from aidial_client._http_client._base import BaseHTTPClient, ErrorHandler
|
|
12
12
|
from aidial_client._internal_types._defaults import NOT_GIVEN, NotGiven
|
|
13
13
|
from aidial_client._internal_types._generic import ResponseT
|
|
14
14
|
from aidial_client._internal_types._http_request import FinalRequestOptions
|
|
@@ -51,8 +51,7 @@ class AsyncHTTPClient(BaseHTTPClient[httpx.AsyncClient, AsyncAuthValue]):
|
|
|
51
51
|
options: FinalRequestOptions,
|
|
52
52
|
cast_to: type[ResponseT],
|
|
53
53
|
remaining_retries: int | None = None,
|
|
54
|
-
on_http_error:
|
|
55
|
-
| None = None,
|
|
54
|
+
on_http_error: ErrorHandler | None = None,
|
|
56
55
|
) -> ResponseT:
|
|
57
56
|
retries = self._remaining_retries(remaining_retries, options)
|
|
58
57
|
auth_headers = await self.auth_headers()
|
|
@@ -101,16 +100,37 @@ class AsyncHTTPClient(BaseHTTPClient[httpx.AsyncClient, AsyncAuthValue]):
|
|
|
101
100
|
cast_to=cast_to,
|
|
102
101
|
remaining_retries=retries,
|
|
103
102
|
)
|
|
104
|
-
|
|
105
|
-
custom_error = on_http_error(err) if on_http_error else None
|
|
106
|
-
# or fallback to default processing
|
|
107
|
-
raised_error = custom_error or self._make_dial_error_from_response(
|
|
108
|
-
err.response
|
|
109
|
-
)
|
|
110
|
-
raise raised_error from err
|
|
103
|
+
self._raise_for_status(response, on_http_error)
|
|
111
104
|
|
|
112
105
|
return process_block_response(cast_to=cast_to, response=response)
|
|
113
106
|
|
|
107
|
+
@asynccontextmanager
|
|
108
|
+
async def stream(
|
|
109
|
+
self,
|
|
110
|
+
*,
|
|
111
|
+
options: FinalRequestOptions,
|
|
112
|
+
on_http_error: ErrorHandler | None = None,
|
|
113
|
+
) -> AsyncIterator[httpx.Response]:
|
|
114
|
+
auth_headers = await self.auth_headers()
|
|
115
|
+
request = self._build_request(options, auth_headers)
|
|
116
|
+
try:
|
|
117
|
+
response = await self._internal_http_client.send(
|
|
118
|
+
request, stream=True
|
|
119
|
+
)
|
|
120
|
+
except httpx.TimeoutException as err:
|
|
121
|
+
raise DialException(
|
|
122
|
+
message="Request timed out",
|
|
123
|
+
status_code=HTTPStatus.REQUEST_TIMEOUT,
|
|
124
|
+
) from err
|
|
125
|
+
except httpx.HTTPError as err:
|
|
126
|
+
raise DialException(message=f"Request failed: {err}") from err
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
self._raise_for_status(response, on_http_error)
|
|
130
|
+
yield response
|
|
131
|
+
finally:
|
|
132
|
+
await response.aclose()
|
|
133
|
+
|
|
114
134
|
@asynccontextmanager
|
|
115
135
|
async def stream_sse(
|
|
116
136
|
self,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
+
from collections.abc import Callable
|
|
2
3
|
from http import HTTPStatus
|
|
3
4
|
from random import uniform
|
|
4
5
|
from typing import Generic, TypeVar
|
|
@@ -16,6 +17,8 @@ _HttpInternalClientT = TypeVar(
|
|
|
16
17
|
"_HttpInternalClientT", bound=httpx.Client | httpx.AsyncClient
|
|
17
18
|
)
|
|
18
19
|
|
|
20
|
+
ErrorHandler = Callable[[httpx.HTTPStatusError], DialException | None]
|
|
21
|
+
|
|
19
22
|
|
|
20
23
|
class BaseHTTPClient(ABC, Generic[_HttpInternalClientT, AuthValueT]):
|
|
21
24
|
_internal_http_client: _HttpInternalClientT
|
|
@@ -106,6 +109,22 @@ class BaseHTTPClient(ABC, Generic[_HttpInternalClientT, AuthValueT]):
|
|
|
106
109
|
timeout = sleep_seconds + uniform(-0.5, 0.5) # noqa: S311
|
|
107
110
|
return max(0, timeout)
|
|
108
111
|
|
|
112
|
+
def _raise_for_status(
|
|
113
|
+
self,
|
|
114
|
+
response: httpx.Response,
|
|
115
|
+
on_http_error: ErrorHandler | None,
|
|
116
|
+
) -> None:
|
|
117
|
+
try:
|
|
118
|
+
response.raise_for_status()
|
|
119
|
+
except httpx.HTTPStatusError as err:
|
|
120
|
+
# Try to get a custom error from response status_code/code/message
|
|
121
|
+
custom_error = on_http_error(err) if on_http_error else None
|
|
122
|
+
# or fallback to default processing
|
|
123
|
+
raised_error = custom_error or self._make_dial_error_from_response(
|
|
124
|
+
err.response
|
|
125
|
+
)
|
|
126
|
+
raise raised_error from err
|
|
127
|
+
|
|
109
128
|
def _make_dial_error_from_response(
|
|
110
129
|
self,
|
|
111
130
|
response: httpx.Response,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import time
|
|
2
|
-
from collections.abc import
|
|
2
|
+
from collections.abc import Iterator, Mapping
|
|
3
3
|
from contextlib import contextmanager, suppress
|
|
4
4
|
from http import HTTPStatus
|
|
5
5
|
from typing import Any
|
|
@@ -8,7 +8,7 @@ import httpx
|
|
|
8
8
|
|
|
9
9
|
from aidial_client._auth import SyncAuthValue, get_combined_auth_headers
|
|
10
10
|
from aidial_client._exception import DialException
|
|
11
|
-
from aidial_client._http_client._base import BaseHTTPClient
|
|
11
|
+
from aidial_client._http_client._base import BaseHTTPClient, ErrorHandler
|
|
12
12
|
from aidial_client._internal_types._defaults import NOT_GIVEN, NotGiven
|
|
13
13
|
from aidial_client._internal_types._generic import ResponseT
|
|
14
14
|
from aidial_client._internal_types._http_request import FinalRequestOptions
|
|
@@ -50,8 +50,7 @@ class SyncHTTPClient(BaseHTTPClient[httpx.Client, SyncAuthValue]):
|
|
|
50
50
|
cast_to: type[ResponseT],
|
|
51
51
|
options: FinalRequestOptions,
|
|
52
52
|
remaining_retries: int | None = None,
|
|
53
|
-
on_http_error:
|
|
54
|
-
| None = None,
|
|
53
|
+
on_http_error: ErrorHandler | None = None,
|
|
55
54
|
) -> ResponseT:
|
|
56
55
|
retries = self._remaining_retries(remaining_retries, options)
|
|
57
56
|
auth_headers = self.auth_headers()
|
|
@@ -101,13 +100,7 @@ class SyncHTTPClient(BaseHTTPClient[httpx.Client, SyncAuthValue]):
|
|
|
101
100
|
cast_to=cast_to,
|
|
102
101
|
remaining_retries=retries,
|
|
103
102
|
)
|
|
104
|
-
|
|
105
|
-
custom_error = on_http_error(err) if on_http_error else None
|
|
106
|
-
# or fallback to default processing
|
|
107
|
-
raised_error = custom_error or self._make_dial_error_from_response(
|
|
108
|
-
err.response
|
|
109
|
-
)
|
|
110
|
-
raise raised_error from err
|
|
103
|
+
self._raise_for_status(response, on_http_error)
|
|
111
104
|
|
|
112
105
|
return process_block_response(cast_to=cast_to, response=response)
|
|
113
106
|
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/helpers/storage_resource.py
RENAMED
|
@@ -5,6 +5,8 @@ from urllib.parse import urljoin, urlparse
|
|
|
5
5
|
from aidial_client._compatibility.pydantic_v1 import BaseModel
|
|
6
6
|
from aidial_client._constants import API_PREFIX
|
|
7
7
|
from aidial_client._exception import InvalidDialURLError, NotDialURLError
|
|
8
|
+
from aidial_client._internal_types._http_request import FinalRequestOptions
|
|
9
|
+
from aidial_client._utils._dict import remove_none
|
|
8
10
|
from aidial_client.helpers._url import enforce_trailing_slash
|
|
9
11
|
|
|
10
12
|
StorageResourceType = Literal["files", "conversations", "prompts"]
|
|
@@ -156,3 +158,25 @@ class DialStorageResourceMixin(BaseModel):
|
|
|
156
158
|
Get the display name of the resource from the URL
|
|
157
159
|
"""
|
|
158
160
|
return self.get_storage_resource(url).bucket_path
|
|
161
|
+
|
|
162
|
+
def _prepare_download_request(
|
|
163
|
+
self,
|
|
164
|
+
url: str | PurePosixPath,
|
|
165
|
+
etag_if_match: str | None,
|
|
166
|
+
) -> tuple[FinalRequestOptions, str]:
|
|
167
|
+
storage_resource = self.get_storage_resource(str(url))
|
|
168
|
+
|
|
169
|
+
if storage_resource.filename is None:
|
|
170
|
+
raise InvalidDialURLError("URL points to a directory, not a file")
|
|
171
|
+
|
|
172
|
+
options = FinalRequestOptions(
|
|
173
|
+
method="GET",
|
|
174
|
+
url=urljoin(API_PREFIX, storage_resource.api_path),
|
|
175
|
+
headers=remove_none(
|
|
176
|
+
{
|
|
177
|
+
"If-Match": etag_if_match,
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return options, storage_resource.filename
|
|
@@ -10,6 +10,7 @@ from aidial_client.resources.resource_permissions import (
|
|
|
10
10
|
ResourcePermissions,
|
|
11
11
|
)
|
|
12
12
|
from aidial_client.resources.toolset import AsyncToolset, Toolset
|
|
13
|
+
from aidial_client.resources.user import AsyncUser, User
|
|
13
14
|
|
|
14
15
|
from .application import Application, AsyncApplication
|
|
15
16
|
from .bucket import AsyncBucket, Bucket
|
|
@@ -40,4 +41,6 @@ __all__ = [
|
|
|
40
41
|
"AsyncResourcePermissions",
|
|
41
42
|
"ClientChannel",
|
|
42
43
|
"AsyncClientChannel",
|
|
44
|
+
"User",
|
|
45
|
+
"AsyncUser",
|
|
43
46
|
]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from collections.abc import AsyncIterator
|
|
2
|
+
from contextlib import asynccontextmanager
|
|
1
3
|
from pathlib import PurePosixPath
|
|
2
4
|
from typing import Literal
|
|
3
5
|
from urllib.parse import urljoin
|
|
@@ -8,7 +10,6 @@ from aidial_client._constants import API_PREFIX
|
|
|
8
10
|
from aidial_client._exception import (
|
|
9
11
|
DialException,
|
|
10
12
|
EtagMismatchError,
|
|
11
|
-
InvalidDialURLError,
|
|
12
13
|
ResourceNotFoundError,
|
|
13
14
|
)
|
|
14
15
|
from aidial_client._internal_types._generic import NoneType
|
|
@@ -70,25 +71,13 @@ class Files(Resource, DialStorageResourceMixin):
|
|
|
70
71
|
url: str | PurePosixPath,
|
|
71
72
|
etag_if_match: str | None = None,
|
|
72
73
|
) -> FileDownloadResponse:
|
|
73
|
-
|
|
74
|
-
if storage_resource.filename is None:
|
|
75
|
-
raise InvalidDialURLError("URL points to a directory, not a file")
|
|
74
|
+
options, filename = self._prepare_download_request(url, etag_if_match)
|
|
76
75
|
response = self.http_client.request(
|
|
77
76
|
cast_to=httpx.Response,
|
|
78
|
-
options=
|
|
79
|
-
method="GET",
|
|
80
|
-
url=urljoin(API_PREFIX, storage_resource.api_path),
|
|
81
|
-
headers=remove_none(
|
|
82
|
-
{
|
|
83
|
-
"If-Match": etag_if_match,
|
|
84
|
-
}
|
|
85
|
-
),
|
|
86
|
-
),
|
|
77
|
+
options=options,
|
|
87
78
|
on_http_error=_files_error_processor,
|
|
88
79
|
)
|
|
89
|
-
return FileDownloadResponse(
|
|
90
|
-
response=response, filename=storage_resource.filename
|
|
91
|
-
)
|
|
80
|
+
return FileDownloadResponse(response=response, filename=filename)
|
|
92
81
|
|
|
93
82
|
def delete(
|
|
94
83
|
self,
|
|
@@ -188,25 +177,26 @@ class AsyncFiles(AsyncResource, DialStorageResourceMixin):
|
|
|
188
177
|
url: str | PurePosixPath,
|
|
189
178
|
etag_if_match: str | None = None,
|
|
190
179
|
) -> FileDownloadResponse:
|
|
191
|
-
|
|
192
|
-
if storage_resource.filename is None:
|
|
193
|
-
raise InvalidDialURLError("URL points to a directory, not a file")
|
|
180
|
+
options, filename = self._prepare_download_request(url, etag_if_match)
|
|
194
181
|
response = await self.http_client.request(
|
|
195
182
|
cast_to=httpx.Response,
|
|
196
|
-
options=
|
|
197
|
-
method="GET",
|
|
198
|
-
url=urljoin(API_PREFIX, storage_resource.api_path),
|
|
199
|
-
headers=remove_none(
|
|
200
|
-
{
|
|
201
|
-
"If-Match": etag_if_match,
|
|
202
|
-
}
|
|
203
|
-
),
|
|
204
|
-
),
|
|
183
|
+
options=options,
|
|
205
184
|
on_http_error=_files_error_processor,
|
|
206
185
|
)
|
|
207
|
-
return FileDownloadResponse(
|
|
208
|
-
|
|
209
|
-
|
|
186
|
+
return FileDownloadResponse(response=response, filename=filename)
|
|
187
|
+
|
|
188
|
+
@asynccontextmanager
|
|
189
|
+
async def stream_download(
|
|
190
|
+
self,
|
|
191
|
+
url: str | PurePosixPath,
|
|
192
|
+
etag_if_match: str | None = None,
|
|
193
|
+
) -> AsyncIterator[FileDownloadResponse]:
|
|
194
|
+
options, filename = self._prepare_download_request(url, etag_if_match)
|
|
195
|
+
async with self.http_client.stream(
|
|
196
|
+
options=options,
|
|
197
|
+
on_http_error=_files_error_processor,
|
|
198
|
+
) as response:
|
|
199
|
+
yield FileDownloadResponse(response=response, filename=filename)
|
|
210
200
|
|
|
211
201
|
async def delete(
|
|
212
202
|
self,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from aidial_client._internal_types._http_request import FinalRequestOptions
|
|
2
|
+
from aidial_client.resources.base import AsyncResource, Resource
|
|
3
|
+
from aidial_client.types.user import UserInfo
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class User(Resource):
|
|
7
|
+
def info(self) -> UserInfo:
|
|
8
|
+
return self.http_client.request(
|
|
9
|
+
cast_to=UserInfo,
|
|
10
|
+
options=FinalRequestOptions(method="GET", url="v1/user/info"),
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AsyncUser(AsyncResource):
|
|
15
|
+
async def info(self) -> UserInfo:
|
|
16
|
+
return await self.http_client.request(
|
|
17
|
+
cast_to=UserInfo,
|
|
18
|
+
options=FinalRequestOptions(method="GET", url="v1/user/info"),
|
|
19
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from aidial_client._internal_types._model import ExtraAllowModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class UserInfo(ExtraAllowModel):
|
|
7
|
+
"""Information about the authenticated user or API key."""
|
|
8
|
+
|
|
9
|
+
roles: list[str]
|
|
10
|
+
project: str | None = None
|
|
11
|
+
userClaims: dict[str, Any] | None = None # depends on the IdP, so opaque
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/__init__.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/openai.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/pydantic.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_compatibility/pydantic_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_http_client/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/__init__.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_defaults.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_generic.py
RENAMED
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_json_rpc.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_internal_types/_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/_utils/_response_processing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/application.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/chat/__init__.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/chat/completions.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/client_channel.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/resources/deployments.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/__init__.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/function.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/legacy/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/request_param.py
RENAMED
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/chat/response.py
RENAMED
|
File without changes
|
|
File without changes
|
{aidial_client-0.11.0.dev6 → aidial_client-0.12.0.dev2}/aidial_client/types/client_channel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|