aidial-client 0.10.0.dev2__tar.gz → 0.10.0.dev4__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.10.0.dev2 → aidial_client-0.10.0.dev4}/PKG-INFO +52 -1
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/README.md +51 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/__init__.py +2 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_client.py +6 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_http_client/_async.py +63 -1
- aidial_client-0.10.0.dev4/aidial_client/_http_client/_sse.py +47 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_http_client/_sync.py +54 -1
- aidial_client-0.10.0.dev4/aidial_client/_internal_types/_json_rpc.py +75 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/__init__.py +6 -0
- aidial_client-0.10.0.dev4/aidial_client/resources/client_channel.py +218 -0
- aidial_client-0.10.0.dev4/aidial_client/types/client_channel.py +9 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/pyproject.toml +1 -1
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/LICENSE +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_auth.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_client_pool.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/openai.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/pydantic.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/pydantic_v1.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_constants.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_exception.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_http_client/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_http_client/_base.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/_defaults.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/_generic.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/_http_request.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/_model.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_log.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_utils/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_utils/_alias.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_utils/_dict.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_utils/_openai.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_utils/_response_processing.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_utils/_type_guard.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/helpers/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/helpers/_url.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/helpers/storage_resource.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/py.typed +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/application.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/base.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/bucket.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/chat/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/chat/completions.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/deployments.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/files.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/metadata.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/model.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/prompts.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/resource_permissions.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/toolset.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/application.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/bucket.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/addon.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/function.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/legacy/__init__.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/legacy/application_request.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/legacy/chat_completion.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/request.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/request_param.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/response.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/tool.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/deployment.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/file.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/metadata.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/model.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/prompt.py +0 -0
- {aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/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.10.0.
|
|
3
|
+
Version: 0.10.0.dev4
|
|
4
4
|
Summary: A Python client library for the AI DIAL API
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -64,6 +64,8 @@ Description-Content-Type: text/markdown
|
|
|
64
64
|
- [Get Toolset by Id](#get-toolset-by-id)
|
|
65
65
|
- [Resource Permissions](#resource-permissions)
|
|
66
66
|
- [Grant Permissions](#grant-permissions)
|
|
67
|
+
- [Client Channel](#client-channel)
|
|
68
|
+
- [Sign In to Toolsets](#sign-in-to-toolsets)
|
|
67
69
|
- [Client Pool](#client-pool)
|
|
68
70
|
- [Synchronous Client Pool](#synchronous-client-pool)
|
|
69
71
|
- [Asynchronous Client Pool](#asynchronous-client-pool)
|
|
@@ -876,6 +878,55 @@ await async_client.resource_permissions.grant(
|
|
|
876
878
|
|
|
877
879
|
The method returns `None` on success and raises `DialException` on HTTP error.
|
|
878
880
|
|
|
881
|
+
### Client Channel
|
|
882
|
+
|
|
883
|
+
DIAL Core's [client channel API](https://dialx.ai/universal_chat_api.yaml) lets a deployment ask an interactive client (e.g. the chat UI) to take some action and report the result back. The channel id is propagated to the deployment via the `X-DIAL-CLIENT-CHANNEL-ID` forwarded header on the inbound request.
|
|
884
|
+
|
|
885
|
+
#### Sign In to Toolsets
|
|
886
|
+
|
|
887
|
+
Use `client_channel.signin_toolsets()` to request interactive sign-in for one or more toolsets on the active client channel. The method returns a `dict[str, SigninResult]` mapping each input toolset id to its outcome — responses are correlated by the client, so the caller never has to deal with the underlying JSON-RPC ids.
|
|
888
|
+
|
|
889
|
+
```python
|
|
890
|
+
from aidial_client import SigninResult
|
|
891
|
+
|
|
892
|
+
# Sync
|
|
893
|
+
results = client.client_channel.signin_toolsets(
|
|
894
|
+
channel_id="<channel-id-from-X-DIAL-CLIENT-CHANNEL-ID>",
|
|
895
|
+
toolset_ids=[
|
|
896
|
+
"toolsets/public/toolset-a",
|
|
897
|
+
"toolsets/public/toolset-b",
|
|
898
|
+
],
|
|
899
|
+
timeout=120.0,
|
|
900
|
+
)
|
|
901
|
+
|
|
902
|
+
# Async
|
|
903
|
+
results = await async_client.client_channel.signin_toolsets(
|
|
904
|
+
channel_id="<channel-id>",
|
|
905
|
+
toolset_ids=["toolsets/public/my-toolset"],
|
|
906
|
+
)
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
Each value is a `SigninResult` enum:
|
|
910
|
+
|
|
911
|
+
```python
|
|
912
|
+
{
|
|
913
|
+
"toolsets/public/toolset-a": SigninResult.SUCCESS,
|
|
914
|
+
"toolsets/public/toolset-b": SigninResult.DENIED,
|
|
915
|
+
}
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
- `SigninResult.SUCCESS` — the user signed in.
|
|
919
|
+
- `SigninResult.DENIED` — the user declined.
|
|
920
|
+
- `SigninResult.ERROR` — the server returned a JSON-RPC error, or the response was missing/unrecognized.
|
|
921
|
+
|
|
922
|
+
Arguments:
|
|
923
|
+
|
|
924
|
+
- `channel_id` — required; the channel id received via the `X-DIAL-CLIENT-CHANNEL-ID` header on the inbound request.
|
|
925
|
+
- `toolset_ids` — sequence of toolset ids to request sign-in for; an empty sequence returns `{}` without contacting the server.
|
|
926
|
+
- `timeout` — optional `float` seconds or `httpx.Timeout`; defaults to the client-wide timeout. Useful for interactive flows where the user may take a while to respond.
|
|
927
|
+
|
|
928
|
+
Raises `DialException` on HTTP errors (e.g. unauthorized, missing channel), transport failures (timeouts, network errors), or if the SSE stream closes without a response event.
|
|
929
|
+
|
|
879
930
|
### Client Pool
|
|
880
931
|
|
|
881
932
|
When you need to create multiple DIAL clients and wish to enhance performance by reusing the HTTP connection for the same DIAL instance, consider using synchronous and asynchronous **client pools**.
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
- [Get Toolset by Id](#get-toolset-by-id)
|
|
43
43
|
- [Resource Permissions](#resource-permissions)
|
|
44
44
|
- [Grant Permissions](#grant-permissions)
|
|
45
|
+
- [Client Channel](#client-channel)
|
|
46
|
+
- [Sign In to Toolsets](#sign-in-to-toolsets)
|
|
45
47
|
- [Client Pool](#client-pool)
|
|
46
48
|
- [Synchronous Client Pool](#synchronous-client-pool)
|
|
47
49
|
- [Asynchronous Client Pool](#asynchronous-client-pool)
|
|
@@ -854,6 +856,55 @@ await async_client.resource_permissions.grant(
|
|
|
854
856
|
|
|
855
857
|
The method returns `None` on success and raises `DialException` on HTTP error.
|
|
856
858
|
|
|
859
|
+
### Client Channel
|
|
860
|
+
|
|
861
|
+
DIAL Core's [client channel API](https://dialx.ai/universal_chat_api.yaml) lets a deployment ask an interactive client (e.g. the chat UI) to take some action and report the result back. The channel id is propagated to the deployment via the `X-DIAL-CLIENT-CHANNEL-ID` forwarded header on the inbound request.
|
|
862
|
+
|
|
863
|
+
#### Sign In to Toolsets
|
|
864
|
+
|
|
865
|
+
Use `client_channel.signin_toolsets()` to request interactive sign-in for one or more toolsets on the active client channel. The method returns a `dict[str, SigninResult]` mapping each input toolset id to its outcome — responses are correlated by the client, so the caller never has to deal with the underlying JSON-RPC ids.
|
|
866
|
+
|
|
867
|
+
```python
|
|
868
|
+
from aidial_client import SigninResult
|
|
869
|
+
|
|
870
|
+
# Sync
|
|
871
|
+
results = client.client_channel.signin_toolsets(
|
|
872
|
+
channel_id="<channel-id-from-X-DIAL-CLIENT-CHANNEL-ID>",
|
|
873
|
+
toolset_ids=[
|
|
874
|
+
"toolsets/public/toolset-a",
|
|
875
|
+
"toolsets/public/toolset-b",
|
|
876
|
+
],
|
|
877
|
+
timeout=120.0,
|
|
878
|
+
)
|
|
879
|
+
|
|
880
|
+
# Async
|
|
881
|
+
results = await async_client.client_channel.signin_toolsets(
|
|
882
|
+
channel_id="<channel-id>",
|
|
883
|
+
toolset_ids=["toolsets/public/my-toolset"],
|
|
884
|
+
)
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
Each value is a `SigninResult` enum:
|
|
888
|
+
|
|
889
|
+
```python
|
|
890
|
+
{
|
|
891
|
+
"toolsets/public/toolset-a": SigninResult.SUCCESS,
|
|
892
|
+
"toolsets/public/toolset-b": SigninResult.DENIED,
|
|
893
|
+
}
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
- `SigninResult.SUCCESS` — the user signed in.
|
|
897
|
+
- `SigninResult.DENIED` — the user declined.
|
|
898
|
+
- `SigninResult.ERROR` — the server returned a JSON-RPC error, or the response was missing/unrecognized.
|
|
899
|
+
|
|
900
|
+
Arguments:
|
|
901
|
+
|
|
902
|
+
- `channel_id` — required; the channel id received via the `X-DIAL-CLIENT-CHANNEL-ID` header on the inbound request.
|
|
903
|
+
- `toolset_ids` — sequence of toolset ids to request sign-in for; an empty sequence returns `{}` without contacting the server.
|
|
904
|
+
- `timeout` — optional `float` seconds or `httpx.Timeout`; defaults to the client-wide timeout. Useful for interactive flows where the user may take a while to respond.
|
|
905
|
+
|
|
906
|
+
Raises `DialException` on HTTP errors (e.g. unauthorized, missing channel), transport failures (timeouts, network errors), or if the SSE stream closes without a response event.
|
|
907
|
+
|
|
857
908
|
### Client Pool
|
|
858
909
|
|
|
859
910
|
When you need to create multiple DIAL clients and wish to enhance performance by reusing the HTTP connection for the same DIAL instance, consider using synchronous and asynchronous **client pools**.
|
|
@@ -9,6 +9,7 @@ from aidial_client._exception import (
|
|
|
9
9
|
ParsingDataError,
|
|
10
10
|
ResourceNotFoundError,
|
|
11
11
|
)
|
|
12
|
+
from aidial_client.types.client_channel import SigninResult
|
|
12
13
|
from aidial_client.types.model import ModelInfo, ModelLimits, ModelPricing
|
|
13
14
|
from aidial_client.types.toolset import ToolsetInfo
|
|
14
15
|
|
|
@@ -30,4 +31,5 @@ __all__ = [
|
|
|
30
31
|
"ModelInfo",
|
|
31
32
|
"ModelPricing",
|
|
32
33
|
"ModelLimits",
|
|
34
|
+
"SigninResult",
|
|
33
35
|
]
|
|
@@ -119,6 +119,9 @@ class Dial(BaseDialClient[SyncHTTPClient, SyncAuthValue]):
|
|
|
119
119
|
self.resource_permissions = resources.ResourcePermissions(
|
|
120
120
|
http_client=self._http_client
|
|
121
121
|
)
|
|
122
|
+
self.client_channel = resources.ClientChannel(
|
|
123
|
+
http_client=self._http_client
|
|
124
|
+
)
|
|
122
125
|
|
|
123
126
|
def _create_http_client(self) -> SyncHTTPClient:
|
|
124
127
|
return SyncHTTPClient(
|
|
@@ -207,6 +210,9 @@ class AsyncDial(BaseDialClient[AsyncHTTPClient, AsyncAuthValue]):
|
|
|
207
210
|
self.resource_permissions = resources.AsyncResourcePermissions(
|
|
208
211
|
http_client=self._http_client
|
|
209
212
|
)
|
|
213
|
+
self.client_channel = resources.AsyncClientChannel(
|
|
214
|
+
http_client=self._http_client
|
|
215
|
+
)
|
|
210
216
|
|
|
211
217
|
def _create_http_client(self) -> AsyncHTTPClient:
|
|
212
218
|
return AsyncHTTPClient(
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_http_client/_async.py
RENAMED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from contextlib import asynccontextmanager
|
|
2
3
|
from http import HTTPStatus
|
|
3
|
-
from typing import
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
AsyncIterator,
|
|
7
|
+
Callable,
|
|
8
|
+
Dict,
|
|
9
|
+
Mapping,
|
|
10
|
+
Optional,
|
|
11
|
+
Type,
|
|
12
|
+
Union,
|
|
13
|
+
)
|
|
4
14
|
|
|
5
15
|
import httpx
|
|
6
16
|
|
|
7
17
|
from aidial_client._auth import AsyncAuthValue, aget_combined_auth_headers
|
|
8
18
|
from aidial_client._exception import DialException
|
|
9
19
|
from aidial_client._http_client._base import BaseHTTPClient
|
|
20
|
+
from aidial_client._internal_types._defaults import NOT_GIVEN, NotGiven
|
|
10
21
|
from aidial_client._internal_types._generic import ResponseT
|
|
11
22
|
from aidial_client._internal_types._http_request import FinalRequestOptions
|
|
12
23
|
from aidial_client._log import logger
|
|
@@ -108,3 +119,54 @@ class AsyncHTTPClient(BaseHTTPClient[httpx.AsyncClient, AsyncAuthValue]):
|
|
|
108
119
|
raise raised_error from err
|
|
109
120
|
|
|
110
121
|
return process_block_response(cast_to=cast_to, response=response)
|
|
122
|
+
|
|
123
|
+
@asynccontextmanager
|
|
124
|
+
async def stream_sse(
|
|
125
|
+
self,
|
|
126
|
+
*,
|
|
127
|
+
method: str,
|
|
128
|
+
url: str,
|
|
129
|
+
json_data: Any,
|
|
130
|
+
headers: Optional[Mapping[str, str]] = None,
|
|
131
|
+
timeout: Union[float, httpx.Timeout, None, NotGiven] = NOT_GIVEN,
|
|
132
|
+
) -> AsyncIterator[httpx.Response]:
|
|
133
|
+
"""Open an SSE streaming response. Yields the open httpx.Response.
|
|
134
|
+
|
|
135
|
+
Auth headers are merged in. On non-2xx, reads the body and raises
|
|
136
|
+
a DialException; transport errors (timeouts, network failures) are
|
|
137
|
+
also wrapped so the caller always sees DialException. Retries are
|
|
138
|
+
not performed for streaming requests.
|
|
139
|
+
|
|
140
|
+
``timeout`` defaults to the client-wide timeout; pass an explicit
|
|
141
|
+
``None`` (or ``httpx.Timeout(None)``) for no timeout.
|
|
142
|
+
"""
|
|
143
|
+
merged_headers = {**(await self.auth_headers()), **(headers or {})}
|
|
144
|
+
effective_timeout = (
|
|
145
|
+
self._timeout if isinstance(timeout, NotGiven) else timeout
|
|
146
|
+
)
|
|
147
|
+
try:
|
|
148
|
+
async with self._internal_http_client.stream(
|
|
149
|
+
method=method,
|
|
150
|
+
url=self._prepare_url(url),
|
|
151
|
+
headers=merged_headers,
|
|
152
|
+
json=json_data,
|
|
153
|
+
timeout=effective_timeout,
|
|
154
|
+
) as response:
|
|
155
|
+
try:
|
|
156
|
+
response.raise_for_status()
|
|
157
|
+
except httpx.HTTPStatusError as err:
|
|
158
|
+
try:
|
|
159
|
+
await response.aread()
|
|
160
|
+
except httpx.HTTPError:
|
|
161
|
+
pass
|
|
162
|
+
raise self._make_dial_error_from_response(
|
|
163
|
+
err.response
|
|
164
|
+
) from err
|
|
165
|
+
yield response
|
|
166
|
+
except httpx.TimeoutException as err:
|
|
167
|
+
raise DialException(
|
|
168
|
+
message="Request timed out",
|
|
169
|
+
status_code=HTTPStatus.REQUEST_TIMEOUT,
|
|
170
|
+
) from err
|
|
171
|
+
except httpx.HTTPError as err:
|
|
172
|
+
raise DialException(message=f"Request failed: {err}") from err
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import AsyncIterator, Iterator, List
|
|
2
|
+
|
|
3
|
+
from aidial_client._log import logger
|
|
4
|
+
|
|
5
|
+
_UNCOMMITTED_BUFFER_WARNING = (
|
|
6
|
+
"Uncommitted data chunks in SSE stream "
|
|
7
|
+
"(stream ended without a terminating blank line); discarding."
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _strip_field(line: str, prefix: str) -> str:
|
|
12
|
+
"""Strip a single leading U+0020 SPACE after the field colon, per the SSE spec."""
|
|
13
|
+
value = line[len(prefix) :]
|
|
14
|
+
return value[1:] if value.startswith(" ") else value
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def iter_data_events(lines: Iterator[str]) -> Iterator[str]:
|
|
18
|
+
"""Yield the payload of each complete ``data:`` event from an SSE line stream.
|
|
19
|
+
|
|
20
|
+
An event is complete when a blank line follows the ``data:`` line(s). Per
|
|
21
|
+
the SSE dispatch rule, a buffer that has not been terminated by a blank
|
|
22
|
+
line is discarded (we do NOT flush partial events at end of stream).
|
|
23
|
+
Comment lines (``:``) and other field names are ignored.
|
|
24
|
+
"""
|
|
25
|
+
buffer: List[str] = []
|
|
26
|
+
for line in lines:
|
|
27
|
+
if line == "":
|
|
28
|
+
if buffer:
|
|
29
|
+
yield "\n".join(buffer)
|
|
30
|
+
buffer = []
|
|
31
|
+
elif line.startswith("data:"):
|
|
32
|
+
buffer.append(_strip_field(line, "data:"))
|
|
33
|
+
if buffer:
|
|
34
|
+
logger.warning(_UNCOMMITTED_BUFFER_WARNING)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def aiter_data_events(lines: AsyncIterator[str]) -> AsyncIterator[str]:
|
|
38
|
+
buffer: List[str] = []
|
|
39
|
+
async for line in lines:
|
|
40
|
+
if line == "":
|
|
41
|
+
if buffer:
|
|
42
|
+
yield "\n".join(buffer)
|
|
43
|
+
buffer = []
|
|
44
|
+
elif line.startswith("data:"):
|
|
45
|
+
buffer.append(_strip_field(line, "data:"))
|
|
46
|
+
if buffer:
|
|
47
|
+
logger.warning(_UNCOMMITTED_BUFFER_WARNING)
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import time
|
|
2
|
+
from contextlib import contextmanager
|
|
2
3
|
from http import HTTPStatus
|
|
3
|
-
from typing import Callable, Dict, Optional, Type
|
|
4
|
+
from typing import Any, Callable, Dict, Iterator, Mapping, Optional, Type, Union
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
7
8
|
from aidial_client._auth import SyncAuthValue, get_combined_auth_headers
|
|
8
9
|
from aidial_client._exception import DialException
|
|
9
10
|
from aidial_client._http_client._base import BaseHTTPClient
|
|
11
|
+
from aidial_client._internal_types._defaults import NOT_GIVEN, NotGiven
|
|
10
12
|
from aidial_client._internal_types._generic import ResponseT
|
|
11
13
|
from aidial_client._internal_types._http_request import FinalRequestOptions
|
|
12
14
|
from aidial_client._log import logger
|
|
@@ -108,3 +110,54 @@ class SyncHTTPClient(BaseHTTPClient[httpx.Client, SyncAuthValue]):
|
|
|
108
110
|
raise raised_error from err
|
|
109
111
|
|
|
110
112
|
return process_block_response(cast_to=cast_to, response=response)
|
|
113
|
+
|
|
114
|
+
@contextmanager
|
|
115
|
+
def stream_sse(
|
|
116
|
+
self,
|
|
117
|
+
*,
|
|
118
|
+
method: str,
|
|
119
|
+
url: str,
|
|
120
|
+
json_data: Any,
|
|
121
|
+
headers: Optional[Mapping[str, str]] = None,
|
|
122
|
+
timeout: Union[float, httpx.Timeout, None, NotGiven] = NOT_GIVEN,
|
|
123
|
+
) -> Iterator[httpx.Response]:
|
|
124
|
+
"""Open an SSE streaming response. Yields the open httpx.Response.
|
|
125
|
+
|
|
126
|
+
Auth headers are merged in. On non-2xx, reads the body and raises
|
|
127
|
+
a DialException; transport errors (timeouts, network failures) are
|
|
128
|
+
also wrapped so the caller always sees DialException. Retries are
|
|
129
|
+
not performed for streaming requests.
|
|
130
|
+
|
|
131
|
+
``timeout`` defaults to the client-wide timeout; pass an explicit
|
|
132
|
+
``None`` (or ``httpx.Timeout(None)``) for no timeout.
|
|
133
|
+
"""
|
|
134
|
+
merged_headers = {**self.auth_headers(), **(headers or {})}
|
|
135
|
+
effective_timeout = (
|
|
136
|
+
self._timeout if isinstance(timeout, NotGiven) else timeout
|
|
137
|
+
)
|
|
138
|
+
try:
|
|
139
|
+
with self._internal_http_client.stream(
|
|
140
|
+
method=method,
|
|
141
|
+
url=self._prepare_url(url),
|
|
142
|
+
headers=merged_headers,
|
|
143
|
+
json=json_data,
|
|
144
|
+
timeout=effective_timeout,
|
|
145
|
+
) as response:
|
|
146
|
+
try:
|
|
147
|
+
response.raise_for_status()
|
|
148
|
+
except httpx.HTTPStatusError as err:
|
|
149
|
+
try:
|
|
150
|
+
response.read()
|
|
151
|
+
except httpx.HTTPError:
|
|
152
|
+
pass
|
|
153
|
+
raise self._make_dial_error_from_response(
|
|
154
|
+
err.response
|
|
155
|
+
) from err
|
|
156
|
+
yield response
|
|
157
|
+
except httpx.TimeoutException as err:
|
|
158
|
+
raise DialException(
|
|
159
|
+
message="Request timed out",
|
|
160
|
+
status_code=HTTPStatus.REQUEST_TIMEOUT,
|
|
161
|
+
) from err
|
|
162
|
+
except httpx.HTTPError as err:
|
|
163
|
+
raise DialException(message=f"Request failed: {err}") from err
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
2
|
+
|
|
3
|
+
from aidial_client._compatibility.pydantic_v1 import (
|
|
4
|
+
BaseModel,
|
|
5
|
+
Extra,
|
|
6
|
+
Field,
|
|
7
|
+
root_validator,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class JsonRpcError(BaseModel):
|
|
12
|
+
code: int
|
|
13
|
+
message: str
|
|
14
|
+
data: Optional[Any] = None
|
|
15
|
+
|
|
16
|
+
class Config:
|
|
17
|
+
extra = Extra.allow
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class JsonRpcRequest(BaseModel):
|
|
21
|
+
jsonrpc: Literal["2.0"] = "2.0"
|
|
22
|
+
method: str
|
|
23
|
+
params: Optional[Union[List[Any], Dict[str, Any]]] = None
|
|
24
|
+
id: Optional[Union[int, str]] = None
|
|
25
|
+
|
|
26
|
+
class Config:
|
|
27
|
+
smart_union = True
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class JsonRpcResponse(BaseModel):
|
|
31
|
+
jsonrpc: Literal["2.0"]
|
|
32
|
+
result: Optional[Any] = None
|
|
33
|
+
error: Optional[JsonRpcError] = None
|
|
34
|
+
id: Optional[Union[int, str]] = Field(...)
|
|
35
|
+
|
|
36
|
+
class Config:
|
|
37
|
+
smart_union = True
|
|
38
|
+
extra = Extra.allow
|
|
39
|
+
|
|
40
|
+
@root_validator(pre=True)
|
|
41
|
+
def _validate_result_xor_error(cls, values):
|
|
42
|
+
"""Per JSON-RPC 2.0 (https://www.jsonrpc.org/specification#response_object),
|
|
43
|
+
either ``result`` or ``error`` MUST be included (presence-wise — ``null``
|
|
44
|
+
is a valid result value), and both MUST NOT be included.
|
|
45
|
+
"""
|
|
46
|
+
if not isinstance(values, dict):
|
|
47
|
+
return values
|
|
48
|
+
has_result = "result" in values
|
|
49
|
+
has_error = "error" in values
|
|
50
|
+
if has_result and has_error:
|
|
51
|
+
raise ValueError(
|
|
52
|
+
"JSON-RPC response must not contain both 'result' and 'error'"
|
|
53
|
+
)
|
|
54
|
+
if not has_result and not has_error:
|
|
55
|
+
raise ValueError(
|
|
56
|
+
"JSON-RPC response must contain either 'result' or 'error'"
|
|
57
|
+
)
|
|
58
|
+
return values
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class JsonRpcResponses(BaseModel):
|
|
62
|
+
"""Pydantic root model that accepts a single JSON-RPC response object or
|
|
63
|
+
a batch array, normalizing both to a list via the ``responses`` property.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
__root__: Union[JsonRpcResponse, List[JsonRpcResponse]]
|
|
67
|
+
|
|
68
|
+
class Config:
|
|
69
|
+
smart_union = True
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def responses(self) -> List[JsonRpcResponse]:
|
|
73
|
+
if isinstance(self.__root__, list):
|
|
74
|
+
return self.__root__
|
|
75
|
+
return [self.__root__]
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
from aidial_client.resources.client_channel import (
|
|
2
|
+
AsyncClientChannel,
|
|
3
|
+
ClientChannel,
|
|
4
|
+
)
|
|
1
5
|
from aidial_client.resources.deployments import AsyncDeployments, Deployments
|
|
2
6
|
from aidial_client.resources.metadata import AsyncMetadata, Metadata
|
|
3
7
|
from aidial_client.resources.model import AsyncModel, Model
|
|
@@ -34,4 +38,6 @@ __all__ = [
|
|
|
34
38
|
"AsyncModel",
|
|
35
39
|
"ResourcePermissions",
|
|
36
40
|
"AsyncResourcePermissions",
|
|
41
|
+
"ClientChannel",
|
|
42
|
+
"AsyncClientChannel",
|
|
37
43
|
]
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
from typing import Any, List, Optional, Sequence, Union
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from aidial_client._compatibility.pydantic_v1 import ValidationError
|
|
7
|
+
from aidial_client._exception import (
|
|
8
|
+
DialException,
|
|
9
|
+
InvalidRequestError,
|
|
10
|
+
ParsingDataError,
|
|
11
|
+
)
|
|
12
|
+
from aidial_client._http_client._sse import aiter_data_events, iter_data_events
|
|
13
|
+
from aidial_client._internal_types._defaults import NOT_GIVEN, NotGiven
|
|
14
|
+
from aidial_client._internal_types._json_rpc import (
|
|
15
|
+
JsonRpcRequest,
|
|
16
|
+
JsonRpcResponse,
|
|
17
|
+
JsonRpcResponses,
|
|
18
|
+
)
|
|
19
|
+
from aidial_client.resources.base import AsyncResource, Resource
|
|
20
|
+
from aidial_client.types.client_channel import SigninResult
|
|
21
|
+
|
|
22
|
+
_CLIENT_CHANNEL_HEADER = "X-DIAL-CLIENT-CHANNEL-ID"
|
|
23
|
+
_INTERACT_URL = "v1/ops/client-channel/interact"
|
|
24
|
+
_SIGNIN_METHOD = "toolset/signin"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _normalize_toolset_ids(toolset_ids: Sequence[str]) -> List[str]:
|
|
28
|
+
"""Validate ``toolset_ids`` and return a stable list.
|
|
29
|
+
|
|
30
|
+
Catches three caller mistakes that would otherwise produce silent garbage:
|
|
31
|
+
a single string (str is itself a ``Sequence[str]``), a one-shot iterable
|
|
32
|
+
(consumed by the build step, leaving the mapping step with nothing), and
|
|
33
|
+
duplicate ids (the per-toolset result dict cannot represent two outcomes
|
|
34
|
+
for the same key).
|
|
35
|
+
"""
|
|
36
|
+
if isinstance(toolset_ids, str):
|
|
37
|
+
raise InvalidRequestError(
|
|
38
|
+
"toolset_ids must be a sequence of toolset ids, not a single str"
|
|
39
|
+
)
|
|
40
|
+
materialized = list(toolset_ids)
|
|
41
|
+
if len(set(materialized)) != len(materialized):
|
|
42
|
+
raise InvalidRequestError("toolset_ids must not contain duplicates")
|
|
43
|
+
return materialized
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _serialize_requests(requests: Sequence[JsonRpcRequest]) -> Any:
|
|
47
|
+
"""Serialize a sequence of JsonRpcRequest to the wire form.
|
|
48
|
+
|
|
49
|
+
Always emits an array. DIAL Core accepts both an object and an array
|
|
50
|
+
body, but emitting a consistent shape avoids the "wire shape depends
|
|
51
|
+
on count" footgun and keeps the empty-input case safe.
|
|
52
|
+
"""
|
|
53
|
+
return [r.dict(exclude_none=True) for r in requests]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _parse_responses(payload: str) -> List[JsonRpcResponse]:
|
|
57
|
+
try:
|
|
58
|
+
return JsonRpcResponses.parse_raw(payload).responses
|
|
59
|
+
except (ValidationError, ValueError) as err:
|
|
60
|
+
raise ParsingDataError(
|
|
61
|
+
message=(
|
|
62
|
+
"Invalid JSON-RPC response in client-channel interact: "
|
|
63
|
+
f"{err}"
|
|
64
|
+
)
|
|
65
|
+
) from err
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _no_data_error() -> DialException:
|
|
69
|
+
return DialException(
|
|
70
|
+
message="Client-channel interact stream closed without a data event",
|
|
71
|
+
status_code=HTTPStatus.GATEWAY_TIMEOUT,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _raise_if_batch_error(responses: Sequence[JsonRpcResponse]) -> None:
|
|
76
|
+
"""Per JSON-RPC 2.0, a response with ``id=null`` indicates the server
|
|
77
|
+
could not associate the response with any request (parse error, invalid
|
|
78
|
+
batch, etc.). Surface that as a ``DialException`` instead of silently
|
|
79
|
+
mapping every toolset to ERROR.
|
|
80
|
+
"""
|
|
81
|
+
for r in responses:
|
|
82
|
+
if r.id is None and r.error is not None:
|
|
83
|
+
raise DialException(
|
|
84
|
+
message=(
|
|
85
|
+
f"Server-level JSON-RPC error "
|
|
86
|
+
f"({r.error.code}): {r.error.message}"
|
|
87
|
+
),
|
|
88
|
+
status_code=HTTPStatus.BAD_GATEWAY,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
_RESULT_TO_OUTCOME = {
|
|
93
|
+
SigninResult.SUCCESS.value: SigninResult.SUCCESS,
|
|
94
|
+
SigninResult.DENIED.value: SigninResult.DENIED,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _outcome_for(response: Optional[JsonRpcResponse]) -> SigninResult:
|
|
99
|
+
if response is None or response.error is not None:
|
|
100
|
+
return SigninResult.ERROR
|
|
101
|
+
if not isinstance(response.result, str):
|
|
102
|
+
return SigninResult.ERROR
|
|
103
|
+
return _RESULT_TO_OUTCOME.get(response.result, SigninResult.ERROR)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _build_signin_requests(
|
|
107
|
+
toolset_ids: Sequence[str],
|
|
108
|
+
) -> List[JsonRpcRequest]:
|
|
109
|
+
return [
|
|
110
|
+
JsonRpcRequest(
|
|
111
|
+
method=_SIGNIN_METHOD,
|
|
112
|
+
params={"toolsetId": tid},
|
|
113
|
+
id=str(idx),
|
|
114
|
+
)
|
|
115
|
+
for idx, tid in enumerate(toolset_ids, start=1)
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _map_signin_results(
|
|
120
|
+
toolset_ids: Sequence[str],
|
|
121
|
+
responses: Sequence[JsonRpcResponse],
|
|
122
|
+
) -> "dict[str, SigninResult]":
|
|
123
|
+
by_id = {str(r.id): r for r in responses if r.id is not None}
|
|
124
|
+
return {
|
|
125
|
+
tid: _outcome_for(by_id.get(str(idx)))
|
|
126
|
+
for idx, tid in enumerate(toolset_ids, start=1)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class ClientChannel(Resource):
|
|
131
|
+
def signin_toolsets(
|
|
132
|
+
self,
|
|
133
|
+
*,
|
|
134
|
+
channel_id: str,
|
|
135
|
+
toolset_ids: Sequence[str],
|
|
136
|
+
timeout: Union[float, httpx.Timeout, None, NotGiven] = NOT_GIVEN,
|
|
137
|
+
) -> "dict[str, SigninResult]":
|
|
138
|
+
"""Request interactive sign-in for one or more toolsets on the given
|
|
139
|
+
client channel and return the per-toolset outcome.
|
|
140
|
+
|
|
141
|
+
``toolset_ids`` are typically DIAL toolset ids (e.g.
|
|
142
|
+
``"toolsets/public/my-toolset"``). The returned dict has one entry
|
|
143
|
+
per input id; toolsets for which the server does not produce a
|
|
144
|
+
response are mapped to :class:`SigninResult.ERROR`. Iteration order
|
|
145
|
+
of the returned dict matches the order of ``toolset_ids``.
|
|
146
|
+
|
|
147
|
+
Raises :class:`InvalidRequestError` if ``toolset_ids`` is a plain
|
|
148
|
+
string or contains duplicates. Raises :class:`DialException` on HTTP
|
|
149
|
+
errors, transport failures, server-level JSON-RPC errors (e.g. parse
|
|
150
|
+
error returned with ``id=null``), or if the SSE stream closes
|
|
151
|
+
without a response event.
|
|
152
|
+
"""
|
|
153
|
+
ids = _normalize_toolset_ids(toolset_ids)
|
|
154
|
+
if not ids:
|
|
155
|
+
return {}
|
|
156
|
+
responses = self._interact(
|
|
157
|
+
channel_id=channel_id,
|
|
158
|
+
requests=_build_signin_requests(ids),
|
|
159
|
+
timeout=timeout,
|
|
160
|
+
)
|
|
161
|
+
_raise_if_batch_error(responses)
|
|
162
|
+
return _map_signin_results(ids, responses)
|
|
163
|
+
|
|
164
|
+
def _interact(
|
|
165
|
+
self,
|
|
166
|
+
*,
|
|
167
|
+
channel_id: str,
|
|
168
|
+
requests: Sequence[JsonRpcRequest],
|
|
169
|
+
timeout: Union[float, httpx.Timeout, None, NotGiven] = NOT_GIVEN,
|
|
170
|
+
) -> List[JsonRpcResponse]:
|
|
171
|
+
with self.http_client.stream_sse(
|
|
172
|
+
method="POST",
|
|
173
|
+
url=_INTERACT_URL,
|
|
174
|
+
json_data=_serialize_requests(requests),
|
|
175
|
+
headers={_CLIENT_CHANNEL_HEADER: channel_id},
|
|
176
|
+
timeout=timeout,
|
|
177
|
+
) as response:
|
|
178
|
+
for payload in iter_data_events(response.iter_lines()):
|
|
179
|
+
return _parse_responses(payload)
|
|
180
|
+
raise _no_data_error()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class AsyncClientChannel(AsyncResource):
|
|
184
|
+
async def signin_toolsets(
|
|
185
|
+
self,
|
|
186
|
+
*,
|
|
187
|
+
channel_id: str,
|
|
188
|
+
toolset_ids: Sequence[str],
|
|
189
|
+
timeout: Union[float, httpx.Timeout, None, NotGiven] = NOT_GIVEN,
|
|
190
|
+
) -> "dict[str, SigninResult]":
|
|
191
|
+
ids = _normalize_toolset_ids(toolset_ids)
|
|
192
|
+
if not ids:
|
|
193
|
+
return {}
|
|
194
|
+
responses = await self._interact(
|
|
195
|
+
channel_id=channel_id,
|
|
196
|
+
requests=_build_signin_requests(ids),
|
|
197
|
+
timeout=timeout,
|
|
198
|
+
)
|
|
199
|
+
_raise_if_batch_error(responses)
|
|
200
|
+
return _map_signin_results(ids, responses)
|
|
201
|
+
|
|
202
|
+
async def _interact(
|
|
203
|
+
self,
|
|
204
|
+
*,
|
|
205
|
+
channel_id: str,
|
|
206
|
+
requests: Sequence[JsonRpcRequest],
|
|
207
|
+
timeout: Union[float, httpx.Timeout, None, NotGiven] = NOT_GIVEN,
|
|
208
|
+
) -> List[JsonRpcResponse]:
|
|
209
|
+
async with self.http_client.stream_sse(
|
|
210
|
+
method="POST",
|
|
211
|
+
url=_INTERACT_URL,
|
|
212
|
+
json_data=_serialize_requests(requests),
|
|
213
|
+
headers={_CLIENT_CHANNEL_HEADER: channel_id},
|
|
214
|
+
timeout=timeout,
|
|
215
|
+
) as response:
|
|
216
|
+
async for payload in aiter_data_events(response.aiter_lines()):
|
|
217
|
+
return _parse_responses(payload)
|
|
218
|
+
raise _no_data_error()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/__init__.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/openai.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/pydantic.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_compatibility/pydantic_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_http_client/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/__init__.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/_defaults.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_internal_types/_generic.py
RENAMED
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/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.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/_utils/_response_processing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/helpers/storage_resource.py
RENAMED
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/application.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/chat/__init__.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/resources/chat/completions.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/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
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/function.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/legacy/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/request_param.py
RENAMED
|
File without changes
|
{aidial_client-0.10.0.dev2 → aidial_client-0.10.0.dev4}/aidial_client/types/chat/response.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
|