athena-intelligence 0.1.1__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.
- athena/__init__.py +6 -0
- athena/client.py +110 -0
- athena/core/__init__.py +22 -0
- athena/core/api_error.py +15 -0
- athena/core/client_wrapper.py +45 -0
- athena/core/datetime_utils.py +28 -0
- athena/core/file.py +38 -0
- athena/core/jsonable_encoder.py +103 -0
- athena/core/remove_none_from_dict.py +11 -0
- athena/core/request_options.py +29 -0
- athena/environment.py +7 -0
- athena/py.typed +0 -0
- athena/resources/__init__.py +6 -0
- athena/resources/message/__init__.py +5 -0
- athena/resources/message/client.py +292 -0
- athena/resources/message/types/__init__.py +5 -0
- athena/resources/message/types/message.py +35 -0
- athena_intelligence-0.1.1.dist-info/METADATA +137 -0
- athena_intelligence-0.1.1.dist-info/RECORD +20 -0
- athena_intelligence-0.1.1.dist-info/WHEEL +4 -0
athena/__init__.py
ADDED
athena/client.py
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import os
|
4
|
+
import typing
|
5
|
+
|
6
|
+
import httpx
|
7
|
+
|
8
|
+
from .core.api_error import ApiError
|
9
|
+
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
|
10
|
+
from .environment import AthenaEnvironment
|
11
|
+
from .resources.message.client import AsyncMessageClient, MessageClient
|
12
|
+
|
13
|
+
|
14
|
+
class Athena:
|
15
|
+
"""
|
16
|
+
Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions.
|
17
|
+
|
18
|
+
Parameters:
|
19
|
+
- base_url: typing.Optional[str]. The base url to use for requests from the client.
|
20
|
+
|
21
|
+
- environment: AthenaEnvironment. The environment to use for requests from the client. from .environment import AthenaEnvironment
|
22
|
+
|
23
|
+
Defaults to AthenaEnvironment.PRODUCTION
|
24
|
+
|
25
|
+
- api_key: typing.Optional[typing.Union[str, typing.Callable[[], str]]].
|
26
|
+
|
27
|
+
- timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds.
|
28
|
+
|
29
|
+
- httpx_client: typing.Optional[httpx.Client]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
|
30
|
+
---
|
31
|
+
from athena.client import Athena
|
32
|
+
|
33
|
+
client = Athena(
|
34
|
+
api_key="YOUR_API_KEY",
|
35
|
+
)
|
36
|
+
"""
|
37
|
+
|
38
|
+
def __init__(
|
39
|
+
self,
|
40
|
+
*,
|
41
|
+
base_url: typing.Optional[str] = None,
|
42
|
+
environment: AthenaEnvironment = AthenaEnvironment.PRODUCTION,
|
43
|
+
api_key: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = os.getenv("ATHENA_API_KEY"),
|
44
|
+
timeout: typing.Optional[float] = 60,
|
45
|
+
httpx_client: typing.Optional[httpx.Client] = None
|
46
|
+
):
|
47
|
+
if api_key is None:
|
48
|
+
raise ApiError(
|
49
|
+
body="The client must be instantiated be either passing in api_key or setting ATHENA_API_KEY"
|
50
|
+
)
|
51
|
+
self._client_wrapper = SyncClientWrapper(
|
52
|
+
base_url=_get_base_url(base_url=base_url, environment=environment),
|
53
|
+
api_key=api_key,
|
54
|
+
httpx_client=httpx.Client(timeout=timeout) if httpx_client is None else httpx_client,
|
55
|
+
)
|
56
|
+
self.message = MessageClient(client_wrapper=self._client_wrapper)
|
57
|
+
|
58
|
+
|
59
|
+
class AsyncAthena:
|
60
|
+
"""
|
61
|
+
Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions.
|
62
|
+
|
63
|
+
Parameters:
|
64
|
+
- base_url: typing.Optional[str]. The base url to use for requests from the client.
|
65
|
+
|
66
|
+
- environment: AthenaEnvironment. The environment to use for requests from the client. from .environment import AthenaEnvironment
|
67
|
+
|
68
|
+
Defaults to AthenaEnvironment.PRODUCTION
|
69
|
+
|
70
|
+
- api_key: typing.Optional[typing.Union[str, typing.Callable[[], str]]].
|
71
|
+
|
72
|
+
- timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds.
|
73
|
+
|
74
|
+
- httpx_client: typing.Optional[httpx.AsyncClient]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
|
75
|
+
---
|
76
|
+
from athena.client import AsyncAthena
|
77
|
+
|
78
|
+
client = AsyncAthena(
|
79
|
+
api_key="YOUR_API_KEY",
|
80
|
+
)
|
81
|
+
"""
|
82
|
+
|
83
|
+
def __init__(
|
84
|
+
self,
|
85
|
+
*,
|
86
|
+
base_url: typing.Optional[str] = None,
|
87
|
+
environment: AthenaEnvironment = AthenaEnvironment.PRODUCTION,
|
88
|
+
api_key: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = os.getenv("ATHENA_API_KEY"),
|
89
|
+
timeout: typing.Optional[float] = 60,
|
90
|
+
httpx_client: typing.Optional[httpx.AsyncClient] = None
|
91
|
+
):
|
92
|
+
if api_key is None:
|
93
|
+
raise ApiError(
|
94
|
+
body="The client must be instantiated be either passing in api_key or setting ATHENA_API_KEY"
|
95
|
+
)
|
96
|
+
self._client_wrapper = AsyncClientWrapper(
|
97
|
+
base_url=_get_base_url(base_url=base_url, environment=environment),
|
98
|
+
api_key=api_key,
|
99
|
+
httpx_client=httpx.AsyncClient(timeout=timeout) if httpx_client is None else httpx_client,
|
100
|
+
)
|
101
|
+
self.message = AsyncMessageClient(client_wrapper=self._client_wrapper)
|
102
|
+
|
103
|
+
|
104
|
+
def _get_base_url(*, base_url: typing.Optional[str] = None, environment: AthenaEnvironment) -> str:
|
105
|
+
if base_url is not None:
|
106
|
+
return base_url
|
107
|
+
elif environment is not None:
|
108
|
+
return environment.value
|
109
|
+
else:
|
110
|
+
raise Exception("Please pass in either base_url or environment to construct the client")
|
athena/core/__init__.py
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
from .api_error import ApiError
|
4
|
+
from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
|
5
|
+
from .datetime_utils import serialize_datetime
|
6
|
+
from .file import File, convert_file_dict_to_httpx_tuples
|
7
|
+
from .jsonable_encoder import jsonable_encoder
|
8
|
+
from .remove_none_from_dict import remove_none_from_dict
|
9
|
+
from .request_options import RequestOptions
|
10
|
+
|
11
|
+
__all__ = [
|
12
|
+
"ApiError",
|
13
|
+
"AsyncClientWrapper",
|
14
|
+
"BaseClientWrapper",
|
15
|
+
"File",
|
16
|
+
"RequestOptions",
|
17
|
+
"SyncClientWrapper",
|
18
|
+
"convert_file_dict_to_httpx_tuples",
|
19
|
+
"jsonable_encoder",
|
20
|
+
"remove_none_from_dict",
|
21
|
+
"serialize_datetime",
|
22
|
+
]
|
athena/core/api_error.py
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
class ApiError(Exception):
|
7
|
+
status_code: typing.Optional[int]
|
8
|
+
body: typing.Any
|
9
|
+
|
10
|
+
def __init__(self, *, status_code: typing.Optional[int] = None, body: typing.Any = None):
|
11
|
+
self.status_code = status_code
|
12
|
+
self.body = body
|
13
|
+
|
14
|
+
def __str__(self) -> str:
|
15
|
+
return f"status_code: {self.status_code}, body: {self.body}"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import typing
|
4
|
+
|
5
|
+
import httpx
|
6
|
+
|
7
|
+
|
8
|
+
class BaseClientWrapper:
|
9
|
+
def __init__(self, *, api_key: typing.Union[str, typing.Callable[[], str]], base_url: str):
|
10
|
+
self._api_key = api_key
|
11
|
+
self._base_url = base_url
|
12
|
+
|
13
|
+
def get_headers(self) -> typing.Dict[str, str]:
|
14
|
+
headers: typing.Dict[str, str] = {
|
15
|
+
"X-Fern-Language": "Python",
|
16
|
+
"X-Fern-SDK-Name": "athena-intelligence",
|
17
|
+
"X-Fern-SDK-Version": "0.1.1",
|
18
|
+
}
|
19
|
+
headers["Authorization"] = f"Bearer {self._get_api_key()}"
|
20
|
+
return headers
|
21
|
+
|
22
|
+
def _get_api_key(self) -> str:
|
23
|
+
if isinstance(self._api_key, str):
|
24
|
+
return self._api_key
|
25
|
+
else:
|
26
|
+
return self._api_key()
|
27
|
+
|
28
|
+
def get_base_url(self) -> str:
|
29
|
+
return self._base_url
|
30
|
+
|
31
|
+
|
32
|
+
class SyncClientWrapper(BaseClientWrapper):
|
33
|
+
def __init__(
|
34
|
+
self, *, api_key: typing.Union[str, typing.Callable[[], str]], base_url: str, httpx_client: httpx.Client
|
35
|
+
):
|
36
|
+
super().__init__(api_key=api_key, base_url=base_url)
|
37
|
+
self.httpx_client = httpx_client
|
38
|
+
|
39
|
+
|
40
|
+
class AsyncClientWrapper(BaseClientWrapper):
|
41
|
+
def __init__(
|
42
|
+
self, *, api_key: typing.Union[str, typing.Callable[[], str]], base_url: str, httpx_client: httpx.AsyncClient
|
43
|
+
):
|
44
|
+
super().__init__(api_key=api_key, base_url=base_url)
|
45
|
+
self.httpx_client = httpx_client
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import datetime as dt
|
4
|
+
|
5
|
+
|
6
|
+
def serialize_datetime(v: dt.datetime) -> str:
|
7
|
+
"""
|
8
|
+
Serialize a datetime including timezone info.
|
9
|
+
|
10
|
+
Uses the timezone info provided if present, otherwise uses the current runtime's timezone info.
|
11
|
+
|
12
|
+
UTC datetimes end in "Z" while all other timezones are represented as offset from UTC, e.g. +05:00.
|
13
|
+
"""
|
14
|
+
|
15
|
+
def _serialize_zoned_datetime(v: dt.datetime) -> str:
|
16
|
+
if v.tzinfo is not None and v.tzinfo.tzname(None) == dt.timezone.utc.tzname(None):
|
17
|
+
# UTC is a special case where we use "Z" at the end instead of "+00:00"
|
18
|
+
return v.isoformat().replace("+00:00", "Z")
|
19
|
+
else:
|
20
|
+
# Delegate to the typical +/- offset format
|
21
|
+
return v.isoformat()
|
22
|
+
|
23
|
+
if v.tzinfo is not None:
|
24
|
+
return _serialize_zoned_datetime(v)
|
25
|
+
else:
|
26
|
+
local_tz = dt.datetime.now().astimezone().tzinfo
|
27
|
+
localized_dt = v.replace(tzinfo=local_tz)
|
28
|
+
return _serialize_zoned_datetime(localized_dt)
|
athena/core/file.py
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import typing
|
4
|
+
|
5
|
+
# File typing inspired by the flexibility of types within the httpx library
|
6
|
+
# https://github.com/encode/httpx/blob/master/httpx/_types.py
|
7
|
+
FileContent = typing.Union[typing.IO[bytes], bytes, str]
|
8
|
+
File = typing.Union[
|
9
|
+
# file (or bytes)
|
10
|
+
FileContent,
|
11
|
+
# (filename, file (or bytes))
|
12
|
+
typing.Tuple[typing.Optional[str], FileContent],
|
13
|
+
# (filename, file (or bytes), content_type)
|
14
|
+
typing.Tuple[typing.Optional[str], FileContent, typing.Optional[str]],
|
15
|
+
# (filename, file (or bytes), content_type, headers)
|
16
|
+
typing.Tuple[typing.Optional[str], FileContent, typing.Optional[str], typing.Mapping[str, str]],
|
17
|
+
]
|
18
|
+
|
19
|
+
|
20
|
+
def convert_file_dict_to_httpx_tuples(
|
21
|
+
d: typing.Dict[str, typing.Union[File, typing.List[File]]]
|
22
|
+
) -> typing.List[typing.Tuple[str, File]]:
|
23
|
+
"""
|
24
|
+
The format we use is a list of tuples, where the first element is the
|
25
|
+
name of the file and the second is the file object. Typically HTTPX wants
|
26
|
+
a dict, but to be able to send lists of files, you have to use the list
|
27
|
+
approach (which also works for non-lists)
|
28
|
+
https://github.com/encode/httpx/pull/1032
|
29
|
+
"""
|
30
|
+
|
31
|
+
httpx_tuples = []
|
32
|
+
for key, file_like in d.items():
|
33
|
+
if isinstance(file_like, list):
|
34
|
+
for file_like_item in file_like:
|
35
|
+
httpx_tuples.append((key, file_like_item))
|
36
|
+
else:
|
37
|
+
httpx_tuples.append((key, file_like))
|
38
|
+
return httpx_tuples
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
"""
|
4
|
+
jsonable_encoder converts a Python object to a JSON-friendly dict
|
5
|
+
(e.g. datetimes to strings, Pydantic models to dicts).
|
6
|
+
|
7
|
+
Taken from FastAPI, and made a bit simpler
|
8
|
+
https://github.com/tiangolo/fastapi/blob/master/fastapi/encoders.py
|
9
|
+
"""
|
10
|
+
|
11
|
+
import dataclasses
|
12
|
+
import datetime as dt
|
13
|
+
from collections import defaultdict
|
14
|
+
from enum import Enum
|
15
|
+
from pathlib import PurePath
|
16
|
+
from types import GeneratorType
|
17
|
+
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
18
|
+
|
19
|
+
try:
|
20
|
+
import pydantic.v1 as pydantic # type: ignore
|
21
|
+
except ImportError:
|
22
|
+
import pydantic # type: ignore
|
23
|
+
|
24
|
+
from .datetime_utils import serialize_datetime
|
25
|
+
|
26
|
+
SetIntStr = Set[Union[int, str]]
|
27
|
+
DictIntStrAny = Dict[Union[int, str], Any]
|
28
|
+
|
29
|
+
|
30
|
+
def generate_encoders_by_class_tuples(
|
31
|
+
type_encoder_map: Dict[Any, Callable[[Any], Any]]
|
32
|
+
) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]:
|
33
|
+
encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(tuple)
|
34
|
+
for type_, encoder in type_encoder_map.items():
|
35
|
+
encoders_by_class_tuples[encoder] += (type_,)
|
36
|
+
return encoders_by_class_tuples
|
37
|
+
|
38
|
+
|
39
|
+
encoders_by_class_tuples = generate_encoders_by_class_tuples(pydantic.json.ENCODERS_BY_TYPE)
|
40
|
+
|
41
|
+
|
42
|
+
def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any:
|
43
|
+
custom_encoder = custom_encoder or {}
|
44
|
+
if custom_encoder:
|
45
|
+
if type(obj) in custom_encoder:
|
46
|
+
return custom_encoder[type(obj)](obj)
|
47
|
+
else:
|
48
|
+
for encoder_type, encoder_instance in custom_encoder.items():
|
49
|
+
if isinstance(obj, encoder_type):
|
50
|
+
return encoder_instance(obj)
|
51
|
+
if isinstance(obj, pydantic.BaseModel):
|
52
|
+
encoder = getattr(obj.__config__, "json_encoders", {})
|
53
|
+
if custom_encoder:
|
54
|
+
encoder.update(custom_encoder)
|
55
|
+
obj_dict = obj.dict(by_alias=True)
|
56
|
+
if "__root__" in obj_dict:
|
57
|
+
obj_dict = obj_dict["__root__"]
|
58
|
+
return jsonable_encoder(obj_dict, custom_encoder=encoder)
|
59
|
+
if dataclasses.is_dataclass(obj):
|
60
|
+
obj_dict = dataclasses.asdict(obj)
|
61
|
+
return jsonable_encoder(obj_dict, custom_encoder=custom_encoder)
|
62
|
+
if isinstance(obj, Enum):
|
63
|
+
return obj.value
|
64
|
+
if isinstance(obj, PurePath):
|
65
|
+
return str(obj)
|
66
|
+
if isinstance(obj, (str, int, float, type(None))):
|
67
|
+
return obj
|
68
|
+
if isinstance(obj, dt.date):
|
69
|
+
return str(obj)
|
70
|
+
if isinstance(obj, dt.datetime):
|
71
|
+
return serialize_datetime(obj)
|
72
|
+
if isinstance(obj, dict):
|
73
|
+
encoded_dict = {}
|
74
|
+
allowed_keys = set(obj.keys())
|
75
|
+
for key, value in obj.items():
|
76
|
+
if key in allowed_keys:
|
77
|
+
encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder)
|
78
|
+
encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder)
|
79
|
+
encoded_dict[encoded_key] = encoded_value
|
80
|
+
return encoded_dict
|
81
|
+
if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)):
|
82
|
+
encoded_list = []
|
83
|
+
for item in obj:
|
84
|
+
encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder))
|
85
|
+
return encoded_list
|
86
|
+
|
87
|
+
if type(obj) in pydantic.json.ENCODERS_BY_TYPE:
|
88
|
+
return pydantic.json.ENCODERS_BY_TYPE[type(obj)](obj)
|
89
|
+
for encoder, classes_tuple in encoders_by_class_tuples.items():
|
90
|
+
if isinstance(obj, classes_tuple):
|
91
|
+
return encoder(obj)
|
92
|
+
|
93
|
+
try:
|
94
|
+
data = dict(obj)
|
95
|
+
except Exception as e:
|
96
|
+
errors: List[Exception] = []
|
97
|
+
errors.append(e)
|
98
|
+
try:
|
99
|
+
data = vars(obj)
|
100
|
+
except Exception as e:
|
101
|
+
errors.append(e)
|
102
|
+
raise ValueError(errors) from e
|
103
|
+
return jsonable_encoder(data, custom_encoder=custom_encoder)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
from typing import Any, Dict, Optional
|
4
|
+
|
5
|
+
|
6
|
+
def remove_none_from_dict(original: Dict[str, Optional[Any]]) -> Dict[str, Any]:
|
7
|
+
new: Dict[str, Any] = {}
|
8
|
+
for key, value in original.items():
|
9
|
+
if value is not None:
|
10
|
+
new[key] = value
|
11
|
+
return new
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import typing
|
4
|
+
|
5
|
+
try:
|
6
|
+
from typing import NotRequired # type: ignore
|
7
|
+
except ImportError:
|
8
|
+
from typing_extensions import NotRequired # type: ignore
|
9
|
+
|
10
|
+
|
11
|
+
class RequestOptions(typing.TypedDict):
|
12
|
+
"""
|
13
|
+
Additional options for request-specific configuration when calling APIs via the SDK.
|
14
|
+
This is used primarily as an optional final parameter for service functions.
|
15
|
+
|
16
|
+
Attributes:
|
17
|
+
- timeout_in_seconds: int. The number of seconds to await an API call before timing out.
|
18
|
+
|
19
|
+
- additional_headers: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's header dict
|
20
|
+
|
21
|
+
- additional_query_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's query parameters dict
|
22
|
+
|
23
|
+
- additional_body_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's body parameters dict
|
24
|
+
"""
|
25
|
+
|
26
|
+
timeout_in_seconds: NotRequired[int]
|
27
|
+
additional_headers: NotRequired[typing.Dict[str, typing.Any]]
|
28
|
+
additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]]
|
29
|
+
additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]]
|
athena/environment.py
ADDED
athena/py.typed
ADDED
File without changes
|
@@ -0,0 +1,292 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import typing
|
4
|
+
import urllib.parse
|
5
|
+
from json.decoder import JSONDecodeError
|
6
|
+
|
7
|
+
from ...core.api_error import ApiError
|
8
|
+
from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
|
9
|
+
from ...core.jsonable_encoder import jsonable_encoder
|
10
|
+
from ...core.remove_none_from_dict import remove_none_from_dict
|
11
|
+
from ...core.request_options import RequestOptions
|
12
|
+
from .types.message import Message
|
13
|
+
|
14
|
+
try:
|
15
|
+
import pydantic.v1 as pydantic # type: ignore
|
16
|
+
except ImportError:
|
17
|
+
import pydantic # type: ignore
|
18
|
+
|
19
|
+
# this is used as the default value for optional parameters
|
20
|
+
OMIT = typing.cast(typing.Any, ...)
|
21
|
+
|
22
|
+
|
23
|
+
class MessageClient:
|
24
|
+
def __init__(self, *, client_wrapper: SyncClientWrapper):
|
25
|
+
self._client_wrapper = client_wrapper
|
26
|
+
|
27
|
+
def get(
|
28
|
+
self, message_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
|
29
|
+
) -> Message:
|
30
|
+
"""
|
31
|
+
Get an Athena message by ID.
|
32
|
+
Returns an Athena message final output.
|
33
|
+
|
34
|
+
Parameters:
|
35
|
+
- message_id: typing.Optional[str].
|
36
|
+
|
37
|
+
- request_options: typing.Optional[RequestOptions]. Request-specific configuration.
|
38
|
+
"""
|
39
|
+
_response = self._client_wrapper.httpx_client.request(
|
40
|
+
"GET",
|
41
|
+
urllib.parse.urljoin(
|
42
|
+
f"{self._client_wrapper.get_base_url()}/", f"api/v0/athena/agent/{jsonable_encoder(message_id)}"
|
43
|
+
),
|
44
|
+
params=jsonable_encoder(
|
45
|
+
request_options.get("additional_query_parameters") if request_options is not None else None
|
46
|
+
),
|
47
|
+
headers=jsonable_encoder(
|
48
|
+
remove_none_from_dict(
|
49
|
+
{
|
50
|
+
**self._client_wrapper.get_headers(),
|
51
|
+
**(request_options.get("additional_headers", {}) if request_options is not None else {}),
|
52
|
+
}
|
53
|
+
)
|
54
|
+
),
|
55
|
+
timeout=request_options.get("timeout_in_seconds")
|
56
|
+
if request_options is not None and request_options.get("timeout_in_seconds") is not None
|
57
|
+
else 60,
|
58
|
+
)
|
59
|
+
if 200 <= _response.status_code < 300:
|
60
|
+
return pydantic.parse_obj_as(Message, _response.json()) # type: ignore
|
61
|
+
try:
|
62
|
+
_response_json = _response.json()
|
63
|
+
except JSONDecodeError:
|
64
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
65
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
66
|
+
|
67
|
+
def send(
|
68
|
+
self,
|
69
|
+
*,
|
70
|
+
content: str,
|
71
|
+
conversation_id: typing.Optional[str] = OMIT,
|
72
|
+
user_id: typing.Optional[str] = OMIT,
|
73
|
+
workspace_id: typing.Optional[str] = OMIT,
|
74
|
+
sdataset_ids: typing.Optional[typing.Sequence[str]] = OMIT,
|
75
|
+
tools: typing.Optional[typing.Sequence[str]] = OMIT,
|
76
|
+
model: typing.Optional[str] = OMIT,
|
77
|
+
documents: typing.Optional[typing.Sequence[str]] = OMIT,
|
78
|
+
config: typing.Dict[str, typing.Any],
|
79
|
+
additional_context: typing.Optional[str] = OMIT,
|
80
|
+
request_options: typing.Optional[RequestOptions] = None,
|
81
|
+
) -> Message:
|
82
|
+
"""
|
83
|
+
Send a message to Athena.
|
84
|
+
Returns an Athena message with ID, content and final output.
|
85
|
+
|
86
|
+
Parameters:
|
87
|
+
- content: str.
|
88
|
+
|
89
|
+
- conversation_id: typing.Optional[str].
|
90
|
+
|
91
|
+
- user_id: typing.Optional[str].
|
92
|
+
|
93
|
+
- workspace_id: typing.Optional[str].
|
94
|
+
|
95
|
+
- sdataset_ids: typing.Optional[typing.Sequence[str]].
|
96
|
+
|
97
|
+
- tools: typing.Optional[typing.Sequence[str]].
|
98
|
+
|
99
|
+
- model: typing.Optional[str].
|
100
|
+
|
101
|
+
- documents: typing.Optional[typing.Sequence[str]].
|
102
|
+
|
103
|
+
- config: typing.Dict[str, typing.Any].
|
104
|
+
|
105
|
+
- additional_context: typing.Optional[str].
|
106
|
+
|
107
|
+
- request_options: typing.Optional[RequestOptions]. Request-specific configuration.
|
108
|
+
"""
|
109
|
+
_request: typing.Dict[str, typing.Any] = {"content": content, "config": config}
|
110
|
+
if conversation_id is not OMIT:
|
111
|
+
_request["conversation_id"] = conversation_id
|
112
|
+
if user_id is not OMIT:
|
113
|
+
_request["user_id"] = user_id
|
114
|
+
if workspace_id is not OMIT:
|
115
|
+
_request["workspace_id"] = workspace_id
|
116
|
+
if sdataset_ids is not OMIT:
|
117
|
+
_request["sdataset_ids"] = sdataset_ids
|
118
|
+
if tools is not OMIT:
|
119
|
+
_request["tools"] = tools
|
120
|
+
if model is not OMIT:
|
121
|
+
_request["model"] = model
|
122
|
+
if documents is not OMIT:
|
123
|
+
_request["documents"] = documents
|
124
|
+
if additional_context is not OMIT:
|
125
|
+
_request["additional_context"] = additional_context
|
126
|
+
_response = self._client_wrapper.httpx_client.request(
|
127
|
+
"POST",
|
128
|
+
urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/v0/athena/agent"),
|
129
|
+
params=jsonable_encoder(
|
130
|
+
request_options.get("additional_query_parameters") if request_options is not None else None
|
131
|
+
),
|
132
|
+
json=jsonable_encoder(_request)
|
133
|
+
if request_options is None or request_options.get("additional_body_parameters") is None
|
134
|
+
else {
|
135
|
+
**jsonable_encoder(_request),
|
136
|
+
**(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
|
137
|
+
},
|
138
|
+
headers=jsonable_encoder(
|
139
|
+
remove_none_from_dict(
|
140
|
+
{
|
141
|
+
**self._client_wrapper.get_headers(),
|
142
|
+
**(request_options.get("additional_headers", {}) if request_options is not None else {}),
|
143
|
+
}
|
144
|
+
)
|
145
|
+
),
|
146
|
+
timeout=request_options.get("timeout_in_seconds")
|
147
|
+
if request_options is not None and request_options.get("timeout_in_seconds") is not None
|
148
|
+
else 60,
|
149
|
+
)
|
150
|
+
if 200 <= _response.status_code < 300:
|
151
|
+
return pydantic.parse_obj_as(Message, _response.json()) # type: ignore
|
152
|
+
try:
|
153
|
+
_response_json = _response.json()
|
154
|
+
except JSONDecodeError:
|
155
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
156
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
157
|
+
|
158
|
+
|
159
|
+
class AsyncMessageClient:
|
160
|
+
def __init__(self, *, client_wrapper: AsyncClientWrapper):
|
161
|
+
self._client_wrapper = client_wrapper
|
162
|
+
|
163
|
+
async def get(
|
164
|
+
self, message_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
|
165
|
+
) -> Message:
|
166
|
+
"""
|
167
|
+
Get an Athena message by ID.
|
168
|
+
Returns an Athena message final output.
|
169
|
+
|
170
|
+
Parameters:
|
171
|
+
- message_id: typing.Optional[str].
|
172
|
+
|
173
|
+
- request_options: typing.Optional[RequestOptions]. Request-specific configuration.
|
174
|
+
"""
|
175
|
+
_response = await self._client_wrapper.httpx_client.request(
|
176
|
+
"GET",
|
177
|
+
urllib.parse.urljoin(
|
178
|
+
f"{self._client_wrapper.get_base_url()}/", f"api/v0/athena/agent/{jsonable_encoder(message_id)}"
|
179
|
+
),
|
180
|
+
params=jsonable_encoder(
|
181
|
+
request_options.get("additional_query_parameters") if request_options is not None else None
|
182
|
+
),
|
183
|
+
headers=jsonable_encoder(
|
184
|
+
remove_none_from_dict(
|
185
|
+
{
|
186
|
+
**self._client_wrapper.get_headers(),
|
187
|
+
**(request_options.get("additional_headers", {}) if request_options is not None else {}),
|
188
|
+
}
|
189
|
+
)
|
190
|
+
),
|
191
|
+
timeout=request_options.get("timeout_in_seconds")
|
192
|
+
if request_options is not None and request_options.get("timeout_in_seconds") is not None
|
193
|
+
else 60,
|
194
|
+
)
|
195
|
+
if 200 <= _response.status_code < 300:
|
196
|
+
return pydantic.parse_obj_as(Message, _response.json()) # type: ignore
|
197
|
+
try:
|
198
|
+
_response_json = _response.json()
|
199
|
+
except JSONDecodeError:
|
200
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
201
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
202
|
+
|
203
|
+
async def send(
|
204
|
+
self,
|
205
|
+
*,
|
206
|
+
content: str,
|
207
|
+
conversation_id: typing.Optional[str] = OMIT,
|
208
|
+
user_id: typing.Optional[str] = OMIT,
|
209
|
+
workspace_id: typing.Optional[str] = OMIT,
|
210
|
+
sdataset_ids: typing.Optional[typing.Sequence[str]] = OMIT,
|
211
|
+
tools: typing.Optional[typing.Sequence[str]] = OMIT,
|
212
|
+
model: typing.Optional[str] = OMIT,
|
213
|
+
documents: typing.Optional[typing.Sequence[str]] = OMIT,
|
214
|
+
config: typing.Dict[str, typing.Any],
|
215
|
+
additional_context: typing.Optional[str] = OMIT,
|
216
|
+
request_options: typing.Optional[RequestOptions] = None,
|
217
|
+
) -> Message:
|
218
|
+
"""
|
219
|
+
Send a message to Athena.
|
220
|
+
Returns an Athena message with ID, content and final output.
|
221
|
+
|
222
|
+
Parameters:
|
223
|
+
- content: str.
|
224
|
+
|
225
|
+
- conversation_id: typing.Optional[str].
|
226
|
+
|
227
|
+
- user_id: typing.Optional[str].
|
228
|
+
|
229
|
+
- workspace_id: typing.Optional[str].
|
230
|
+
|
231
|
+
- sdataset_ids: typing.Optional[typing.Sequence[str]].
|
232
|
+
|
233
|
+
- tools: typing.Optional[typing.Sequence[str]].
|
234
|
+
|
235
|
+
- model: typing.Optional[str].
|
236
|
+
|
237
|
+
- documents: typing.Optional[typing.Sequence[str]].
|
238
|
+
|
239
|
+
- config: typing.Dict[str, typing.Any].
|
240
|
+
|
241
|
+
- additional_context: typing.Optional[str].
|
242
|
+
|
243
|
+
- request_options: typing.Optional[RequestOptions]. Request-specific configuration.
|
244
|
+
"""
|
245
|
+
_request: typing.Dict[str, typing.Any] = {"content": content, "config": config}
|
246
|
+
if conversation_id is not OMIT:
|
247
|
+
_request["conversation_id"] = conversation_id
|
248
|
+
if user_id is not OMIT:
|
249
|
+
_request["user_id"] = user_id
|
250
|
+
if workspace_id is not OMIT:
|
251
|
+
_request["workspace_id"] = workspace_id
|
252
|
+
if sdataset_ids is not OMIT:
|
253
|
+
_request["sdataset_ids"] = sdataset_ids
|
254
|
+
if tools is not OMIT:
|
255
|
+
_request["tools"] = tools
|
256
|
+
if model is not OMIT:
|
257
|
+
_request["model"] = model
|
258
|
+
if documents is not OMIT:
|
259
|
+
_request["documents"] = documents
|
260
|
+
if additional_context is not OMIT:
|
261
|
+
_request["additional_context"] = additional_context
|
262
|
+
_response = await self._client_wrapper.httpx_client.request(
|
263
|
+
"POST",
|
264
|
+
urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/v0/athena/agent"),
|
265
|
+
params=jsonable_encoder(
|
266
|
+
request_options.get("additional_query_parameters") if request_options is not None else None
|
267
|
+
),
|
268
|
+
json=jsonable_encoder(_request)
|
269
|
+
if request_options is None or request_options.get("additional_body_parameters") is None
|
270
|
+
else {
|
271
|
+
**jsonable_encoder(_request),
|
272
|
+
**(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
|
273
|
+
},
|
274
|
+
headers=jsonable_encoder(
|
275
|
+
remove_none_from_dict(
|
276
|
+
{
|
277
|
+
**self._client_wrapper.get_headers(),
|
278
|
+
**(request_options.get("additional_headers", {}) if request_options is not None else {}),
|
279
|
+
}
|
280
|
+
)
|
281
|
+
),
|
282
|
+
timeout=request_options.get("timeout_in_seconds")
|
283
|
+
if request_options is not None and request_options.get("timeout_in_seconds") is not None
|
284
|
+
else 60,
|
285
|
+
)
|
286
|
+
if 200 <= _response.status_code < 300:
|
287
|
+
return pydantic.parse_obj_as(Message, _response.json()) # type: ignore
|
288
|
+
try:
|
289
|
+
_response_json = _response.json()
|
290
|
+
except JSONDecodeError:
|
291
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
292
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import datetime as dt
|
4
|
+
import typing
|
5
|
+
|
6
|
+
from ....core.datetime_utils import serialize_datetime
|
7
|
+
|
8
|
+
try:
|
9
|
+
import pydantic.v1 as pydantic # type: ignore
|
10
|
+
except ImportError:
|
11
|
+
import pydantic # type: ignore
|
12
|
+
|
13
|
+
|
14
|
+
class Message(pydantic.BaseModel):
|
15
|
+
message_id: str
|
16
|
+
conversation_id: str
|
17
|
+
sender: str
|
18
|
+
content: str
|
19
|
+
status: str
|
20
|
+
created_at: dt.datetime
|
21
|
+
config: typing.Dict[str, typing.Any]
|
22
|
+
final_output: str
|
23
|
+
|
24
|
+
def json(self, **kwargs: typing.Any) -> str:
|
25
|
+
kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
|
26
|
+
return super().json(**kwargs_with_defaults)
|
27
|
+
|
28
|
+
def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
|
29
|
+
kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
|
30
|
+
return super().dict(**kwargs_with_defaults)
|
31
|
+
|
32
|
+
class Config:
|
33
|
+
frozen = True
|
34
|
+
smart_union = True
|
35
|
+
json_encoders = {dt.datetime: serialize_datetime}
|
@@ -0,0 +1,137 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: athena-intelligence
|
3
|
+
Version: 0.1.1
|
4
|
+
Summary:
|
5
|
+
Requires-Python: >=3.8,<4.0
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
7
|
+
Classifier: Programming Language :: Python :: 3.8
|
8
|
+
Classifier: Programming Language :: Python :: 3.9
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
11
|
+
Requires-Dist: httpx (>=0.21.2)
|
12
|
+
Requires-Dist: pydantic (>=1.9.2)
|
13
|
+
Requires-Dist: typing_extensions (>=4.0.0)
|
14
|
+
Description-Content-Type: text/markdown
|
15
|
+
|
16
|
+
# Athena Intelligence Python Library
|
17
|
+
|
18
|
+
[](https://github.com/fern-api/fern)
|
19
|
+
[](https://pypi.python.org/pypi/athena-intel)
|
20
|
+
|
21
|
+
The Athena Intelligence Python Library provides convenient access to the Athena Intelligence API from
|
22
|
+
applications written in Python.
|
23
|
+
|
24
|
+
The library includes type definitions for all
|
25
|
+
request and response fields, and offers both synchronous and asynchronous clients powered by httpx.
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
Add this dependency to your project's build file:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
pip install athena-intel
|
33
|
+
# or
|
34
|
+
poetry add athena-intel
|
35
|
+
```
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
Simply import `Athena` and start making calls to our API.
|
39
|
+
|
40
|
+
```python
|
41
|
+
from athena.client import Athena
|
42
|
+
|
43
|
+
client = Athena(
|
44
|
+
api_key="YOUR_API_KEY" # Defaults to ATHENA_API_KEY
|
45
|
+
)
|
46
|
+
message = client.messages.get("message_id")
|
47
|
+
```
|
48
|
+
|
49
|
+
## Async Client
|
50
|
+
The SDK also exports an async client so that you can make non-blocking
|
51
|
+
calls to our API.
|
52
|
+
|
53
|
+
```python
|
54
|
+
from athena.client import AsyncAthena
|
55
|
+
|
56
|
+
client = AsyncAthena(
|
57
|
+
api_key="YOUR_API_KEY" # Defaults to ATHENA_API_KEY
|
58
|
+
)
|
59
|
+
|
60
|
+
async def main() -> None:
|
61
|
+
message = client.messages.get("message_id")
|
62
|
+
print("Received message", message)
|
63
|
+
|
64
|
+
asyncio.run(main())
|
65
|
+
```
|
66
|
+
|
67
|
+
## Athena Module
|
68
|
+
All of the models are nested within the Athena module. Let IntelliSense
|
69
|
+
guide you!
|
70
|
+
|
71
|
+
## Exception Handling
|
72
|
+
All errors thrown by the SDK will be subclasses of [`ApiError`](./src/athena/core/api_error.py).
|
73
|
+
|
74
|
+
```python
|
75
|
+
import athena
|
76
|
+
|
77
|
+
try:
|
78
|
+
client.messages.get(...)
|
79
|
+
except athena.core.ApiError as e: # Handle all errors
|
80
|
+
print(e.status_code)
|
81
|
+
print(e.body)
|
82
|
+
```
|
83
|
+
|
84
|
+
## Advanced
|
85
|
+
|
86
|
+
### Timeouts
|
87
|
+
By default, requests time out after 60 seconds. You can configure this with a
|
88
|
+
timeout option at the client or request level.
|
89
|
+
|
90
|
+
```python
|
91
|
+
from athena.client import Athena
|
92
|
+
|
93
|
+
client = Athena(
|
94
|
+
# All timeouts are 20 seconds
|
95
|
+
timeout=20.0,
|
96
|
+
)
|
97
|
+
|
98
|
+
# Override timeout for a specific method
|
99
|
+
client.messages.get(..., {
|
100
|
+
timeout_in_seconds=20
|
101
|
+
})
|
102
|
+
```
|
103
|
+
|
104
|
+
### Custom HTTP client
|
105
|
+
You can override the httpx client to customize it for your use-case. Some common use-cases
|
106
|
+
include support for proxies and transports.
|
107
|
+
|
108
|
+
```python
|
109
|
+
import httpx
|
110
|
+
|
111
|
+
from athena.client import Athena
|
112
|
+
|
113
|
+
client = Athena(
|
114
|
+
http_client=httpx.Client(
|
115
|
+
proxies="http://my.test.proxy.example.com",
|
116
|
+
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
|
117
|
+
),
|
118
|
+
)
|
119
|
+
```
|
120
|
+
|
121
|
+
## Beta Status
|
122
|
+
|
123
|
+
This SDK is in **Preview**, and there may be breaking changes between versions without a major
|
124
|
+
version update.
|
125
|
+
|
126
|
+
To ensure a reproducible environment (and minimize risk of breaking changes), we recommend pinning a specific package version.
|
127
|
+
|
128
|
+
## Contributing
|
129
|
+
|
130
|
+
While we value open-source contributions to this SDK, this library is generated programmatically.
|
131
|
+
Additions made directly to this library would have to be moved over to our generation code,
|
132
|
+
otherwise they would be overwritten upon the next generated release. Feel free to open a PR as
|
133
|
+
a proof of concept, but know that we will not be able to merge it as-is. We suggest opening
|
134
|
+
an issue first to discuss with us!
|
135
|
+
|
136
|
+
On the other hand, contributions to the README are always very welcome!
|
137
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
athena/__init__.py,sha256=AGJSNJ3GjJguxtGkkfaiypZ3yFgm-JFQFWa47SDcbx8,203
|
2
|
+
athena/client.py,sha256=0KtesyhdKJAMEvbVsYYntHh3pV-6137rFyrmSDq6DBk,4676
|
3
|
+
athena/core/__init__.py,sha256=95onSWXymaL0iV-nBsuKNgjh1LbsymAkRkx7POn1nc0,696
|
4
|
+
athena/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
|
5
|
+
athena/core/client_wrapper.py,sha256=1RlrltmDV9g0QtTYTOq3H7kAxlsoNPzcWvq-lr9LURM,1421
|
6
|
+
athena/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
7
|
+
athena/core/file.py,sha256=sy1RUGZ3aJYuw998bZytxxo6QdgKmlnlgBaMvwEKCGg,1480
|
8
|
+
athena/core/jsonable_encoder.py,sha256=MTYkDov2EryHgee4QM46uZiBOuOXK9KTHlBdBwU-CpU,3799
|
9
|
+
athena/core/remove_none_from_dict.py,sha256=8m91FC3YuVem0Gm9_sXhJ2tGvP33owJJdrqCLEdowGw,330
|
10
|
+
athena/core/request_options.py,sha256=9n3ZHWZkw60MGp7GbdjGEuGo73Pa-6JeusRGhS533aA,1297
|
11
|
+
athena/environment.py,sha256=XbORgyeDu6QaGMkdCqqAPh0gGim_9WDRHqvUVU2cnfs,160
|
12
|
+
athena/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
athena/resources/__init__.py,sha256=JM7cJIx5wLNRx4rmJyQ7ZbiuAfVOp1LT-x2W5IVURUU,150
|
14
|
+
athena/resources/message/__init__.py,sha256=E3xv7UtdbvniqZDUXBOov2pICgBfdeHKZ7RRDseNXKU,115
|
15
|
+
athena/resources/message/client.py,sha256=kpxJJBJdSY__afoAR49fNSUxZhHXgPzXS2oDhGsoXzw,11933
|
16
|
+
athena/resources/message/types/__init__.py,sha256=vMTc7TB6uvZ64bGGxdYAJx_Txj4naeghaVLRasHPKEc,117
|
17
|
+
athena/resources/message/types/message.py,sha256=2FDVoG84ckvC4_v_uGol_354fmSyUBXTdCYelDiO5r4,1037
|
18
|
+
athena_intelligence-0.1.1.dist-info/METADATA,sha256=KzNk7PXebycHtHDrMqZj1EGQfXvt6AEPqDBd-wbqkQQ,3713
|
19
|
+
athena_intelligence-0.1.1.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
20
|
+
athena_intelligence-0.1.1.dist-info/RECORD,,
|