airia 0.1.6__tar.gz → 0.1.34__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.
Files changed (123) hide show
  1. airia-0.1.34/PKG-INFO +221 -0
  2. airia-0.1.34/README.md +191 -0
  3. airia-0.1.34/airia/client/_request_handler/__init__.py +4 -0
  4. airia-0.1.34/airia/client/_request_handler/async_request_handler.py +293 -0
  5. airia-0.1.34/airia/client/_request_handler/base_request_handler.py +104 -0
  6. airia-0.1.34/airia/client/_request_handler/sync_request_handler.py +272 -0
  7. airia-0.1.34/airia/client/async_client.py +194 -0
  8. airia-0.1.34/airia/client/attachments/__init__.py +4 -0
  9. airia-0.1.34/airia/client/attachments/async_attachments.py +52 -0
  10. airia-0.1.34/airia/client/attachments/base_attachments.py +54 -0
  11. airia-0.1.34/airia/client/attachments/sync_attachments.py +52 -0
  12. airia-0.1.34/airia/client/base_client.py +87 -0
  13. airia-0.1.34/airia/client/conversations/__init__.py +4 -0
  14. airia-0.1.34/airia/client/conversations/async_conversations.py +187 -0
  15. airia-0.1.34/airia/client/conversations/base_conversations.py +135 -0
  16. airia-0.1.34/airia/client/conversations/sync_conversations.py +182 -0
  17. airia-0.1.34/airia/client/data_vector_search/__init__.py +4 -0
  18. airia-0.1.34/airia/client/data_vector_search/async_data_vector_search.py +91 -0
  19. airia-0.1.34/airia/client/data_vector_search/base_data_vector_search.py +54 -0
  20. airia-0.1.34/airia/client/data_vector_search/sync_data_vector_search.py +85 -0
  21. airia-0.1.34/airia/client/deployments/__init__.py +11 -0
  22. airia-0.1.34/airia/client/deployments/async_deployments.py +139 -0
  23. airia-0.1.34/airia/client/deployments/base_deployments.py +115 -0
  24. airia-0.1.34/airia/client/deployments/sync_deployments.py +139 -0
  25. airia-0.1.34/airia/client/library/__init__.py +5 -0
  26. airia-0.1.34/airia/client/library/async_library.py +100 -0
  27. airia-0.1.34/airia/client/library/base_library.py +110 -0
  28. airia-0.1.34/airia/client/library/sync_library.py +100 -0
  29. airia-0.1.34/airia/client/models/__init__.py +4 -0
  30. airia-0.1.34/airia/client/models/async_models.py +156 -0
  31. airia-0.1.34/airia/client/models/base_models.py +102 -0
  32. airia-0.1.34/airia/client/models/sync_models.py +154 -0
  33. airia-0.1.34/airia/client/pipeline_execution/__init__.py +4 -0
  34. airia-0.1.34/airia/client/pipeline_execution/async_pipeline_execution.py +551 -0
  35. airia-0.1.34/airia/client/pipeline_execution/base_pipeline_execution.py +266 -0
  36. airia-0.1.34/airia/client/pipeline_execution/sync_pipeline_execution.py +558 -0
  37. airia-0.1.34/airia/client/pipeline_import/__init__.py +4 -0
  38. airia-0.1.34/airia/client/pipeline_import/async_pipeline_import.py +147 -0
  39. airia-0.1.34/airia/client/pipeline_import/base_pipeline_import.py +95 -0
  40. airia-0.1.34/airia/client/pipeline_import/sync_pipeline_import.py +143 -0
  41. airia-0.1.34/airia/client/pipelines_config/__init__.py +4 -0
  42. airia-0.1.34/airia/client/pipelines_config/async_pipelines_config.py +270 -0
  43. airia-0.1.34/airia/client/pipelines_config/base_pipelines_config.py +177 -0
  44. airia-0.1.34/airia/client/pipelines_config/sync_pipelines_config.py +270 -0
  45. airia-0.1.34/airia/client/project/__init__.py +4 -0
  46. airia-0.1.34/airia/client/project/async_project.py +148 -0
  47. airia-0.1.34/airia/client/project/base_project.py +97 -0
  48. airia-0.1.34/airia/client/project/sync_project.py +148 -0
  49. airia-0.1.34/airia/client/store/__init__.py +4 -0
  50. airia-0.1.34/airia/client/store/async_store.py +392 -0
  51. airia-0.1.34/airia/client/store/base_store.py +253 -0
  52. airia-0.1.34/airia/client/store/sync_store.py +367 -0
  53. airia-0.1.34/airia/client/sync_client.py +194 -0
  54. airia-0.1.34/airia/client/tools/__init__.py +4 -0
  55. airia-0.1.34/airia/client/tools/async_tools.py +259 -0
  56. airia-0.1.34/airia/client/tools/base_tools.py +153 -0
  57. airia-0.1.34/airia/client/tools/sync_tools.py +245 -0
  58. airia-0.1.34/airia/constants.py +20 -0
  59. {airia-0.1.6 → airia-0.1.34}/airia/exceptions.py +12 -11
  60. {airia-0.1.6 → airia-0.1.34}/airia/logs.py +10 -32
  61. airia-0.1.34/airia/types/__init__.py +11 -0
  62. airia-0.1.34/airia/types/_request_data.py +38 -0
  63. airia-0.1.34/airia/types/_structured_output.py +182 -0
  64. airia-0.1.34/airia/types/api/__init__.py +4 -0
  65. airia-0.1.34/airia/types/api/attachments/__init__.py +3 -0
  66. airia-0.1.34/airia/types/api/attachments/upload_file.py +17 -0
  67. airia-0.1.34/airia/types/api/conversations/__init__.py +13 -0
  68. airia-0.1.34/airia/types/api/conversations/_conversations.py +115 -0
  69. airia-0.1.34/airia/types/api/data_vector_search/__init__.py +3 -0
  70. airia-0.1.34/airia/types/api/data_vector_search/get_file_chunks.py +45 -0
  71. airia-0.1.34/airia/types/api/deployments/__init__.py +26 -0
  72. airia-0.1.34/airia/types/api/deployments/get_deployment.py +106 -0
  73. airia-0.1.34/airia/types/api/deployments/get_deployments.py +224 -0
  74. airia-0.1.34/airia/types/api/library/__init__.py +11 -0
  75. airia-0.1.34/airia/types/api/library/_library_models.py +218 -0
  76. airia-0.1.34/airia/types/api/models/__init__.py +13 -0
  77. airia-0.1.34/airia/types/api/models/list_models.py +129 -0
  78. airia-0.1.34/airia/types/api/pipeline_execution/__init__.py +31 -0
  79. airia-0.1.34/airia/types/api/pipeline_execution/_pipeline_execution.py +183 -0
  80. airia-0.1.34/airia/types/api/pipeline_execution/get_pipeline_execution.py +83 -0
  81. airia-0.1.34/airia/types/api/pipeline_import/__init__.py +11 -0
  82. airia-0.1.34/airia/types/api/pipeline_import/create_agent_from_pipeline_definition.py +108 -0
  83. airia-0.1.34/airia/types/api/pipelines_config/__init__.py +93 -0
  84. airia-0.1.34/airia/types/api/pipelines_config/export_pipeline_definition.py +1531 -0
  85. airia-0.1.34/airia/types/api/pipelines_config/get_pipeline_config.py +554 -0
  86. airia-0.1.34/airia/types/api/pipelines_config/get_pipelines_config.py +381 -0
  87. airia-0.1.34/airia/types/api/project/__init__.py +3 -0
  88. airia-0.1.34/airia/types/api/project/get_projects.py +91 -0
  89. airia-0.1.34/airia/types/api/store/__init__.py +19 -0
  90. airia-0.1.34/airia/types/api/store/get_file.py +145 -0
  91. airia-0.1.34/airia/types/api/store/get_files.py +21 -0
  92. airia-0.1.34/airia/types/api/tools/__init__.py +7 -0
  93. airia-0.1.34/airia/types/api/tools/_tools.py +245 -0
  94. {airia-0.1.6/airia/types → airia-0.1.34/airia/types/sse}/__init__.py +12 -18
  95. airia-0.1.34/airia/types/sse/sse_messages.py +767 -0
  96. {airia-0.1.6 → airia-0.1.34}/airia/utils/sse_parser.py +41 -8
  97. airia-0.1.34/airia.egg-info/PKG-INFO +221 -0
  98. airia-0.1.34/airia.egg-info/SOURCES.txt +105 -0
  99. {airia-0.1.6 → airia-0.1.34}/pyproject.toml +10 -2
  100. airia-0.1.6/PKG-INFO +0 -535
  101. airia-0.1.6/README.md +0 -505
  102. airia-0.1.6/airia/client/async_client.py +0 -582
  103. airia-0.1.6/airia/client/base_client.py +0 -218
  104. airia-0.1.6/airia/client/sync_client.py +0 -564
  105. airia-0.1.6/airia/types/api/get_pipeline_config.py +0 -65
  106. airia-0.1.6/airia/types/api/pipeline_execution.py +0 -33
  107. airia-0.1.6/airia/types/request_data.py +0 -10
  108. airia-0.1.6/airia/types/sse_messages.py +0 -269
  109. airia-0.1.6/airia.egg-info/PKG-INFO +0 -535
  110. airia-0.1.6/airia.egg-info/SOURCES.txt +0 -27
  111. airia-0.1.6/tests/test_anthropic_gateway.py +0 -93
  112. airia-0.1.6/tests/test_execute_pipeline.py +0 -241
  113. airia-0.1.6/tests/test_get_active_pipelines_ids.py +0 -191
  114. airia-0.1.6/tests/test_get_pipeline_config.py +0 -394
  115. airia-0.1.6/tests/test_openai_gateway.py +0 -103
  116. {airia-0.1.6 → airia-0.1.34}/LICENSE +0 -0
  117. {airia-0.1.6 → airia-0.1.34}/airia/__init__.py +0 -0
  118. {airia-0.1.6 → airia-0.1.34}/airia/client/__init__.py +0 -0
  119. /airia-0.1.6/airia/types/api_version.py → /airia-0.1.34/airia/types/_api_version.py +0 -0
  120. {airia-0.1.6 → airia-0.1.34}/airia.egg-info/dependency_links.txt +0 -0
  121. {airia-0.1.6 → airia-0.1.34}/airia.egg-info/requires.txt +0 -0
  122. {airia-0.1.6 → airia-0.1.34}/airia.egg-info/top_level.txt +0 -0
  123. {airia-0.1.6 → airia-0.1.34}/setup.cfg +0 -0
airia-0.1.34/PKG-INFO ADDED
@@ -0,0 +1,221 @@
1
+ Metadata-Version: 2.4
2
+ Name: airia
3
+ Version: 0.1.34
4
+ Summary: Python SDK for Airia API
5
+ Author-email: Airia LLC <support@airia.com>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.9
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: requests>=2.32.3
19
+ Requires-Dist: aiohttp>=3.11.14
20
+ Requires-Dist: loguru>=0.7.3
21
+ Requires-Dist: pydantic>=2.11.0
22
+ Provides-Extra: anthropic
23
+ Requires-Dist: anthropic>=0.49.0; extra == "anthropic"
24
+ Provides-Extra: openai
25
+ Requires-Dist: openai>=1.74.0; extra == "openai"
26
+ Provides-Extra: all
27
+ Requires-Dist: anthropic>=0.49.0; extra == "all"
28
+ Requires-Dist: openai>=1.74.0; extra == "all"
29
+ Dynamic: license-file
30
+
31
+ # Airia Python API Library
32
+
33
+ [![PyPI version](https://badge.fury.io/py/airia.svg)](https://badge.fury.io/py/airia)
34
+ [![Python versions](https://img.shields.io/pypi/pyversions/airia.svg)](https://pypi.org/project/airia/)
35
+ [![License](https://img.shields.io/pypi/l/airia.svg)](https://pypi.org/project/airia/)
36
+
37
+ The Airia Python library provides a clean and intuitive interface to interact with Airia API. The library offers both synchronous and asynchronous clients for maximum flexibility in your applications.
38
+
39
+ ## Features
40
+
41
+ - **Dual Client Support**: Choose between synchronous (`AiriaClient`) and asynchronous (`AiriaAsyncClient`) implementations
42
+ - **Pipeline Execution**: Easily run AI pipelines with customizable parameters
43
+ - **Gateway Support**: Seamlessly integrate with OpenAI and Anthropic services through Airia gateways
44
+ - **Error Handling**: Comprehensive error handling with custom exceptions
45
+ - **Logging**: Built-in configurable logging with correlation ID support for request tracing
46
+ - **Flexible Authentication**: Support for both API keys and bearer tokens with flexible configuration
47
+
48
+ ## Documentation and Quick Start Guides
49
+
50
+ Full documentation and quick start guides are available [here](https://airiallc.github.io/airia-python).
51
+
52
+ You can also run the documentation page locally with `mkdocs`:
53
+
54
+ 1. [Install development dependencies](#install-with-development-dependencies)
55
+ 2. Run `mkdocs serve` to start the local server
56
+
57
+ ## Installation
58
+
59
+ You can install the package using pip or uv:
60
+
61
+ <table>
62
+ <tr>
63
+ <th>pip</th>
64
+ <th>uv</th>
65
+ </tr>
66
+ <tr>
67
+ <td>
68
+
69
+ ```bash
70
+ pip install airia
71
+ ```
72
+
73
+ </td>
74
+ <td>
75
+
76
+ ```bash
77
+ uv add airia
78
+ ```
79
+
80
+ </td>
81
+ </tr>
82
+ </table>
83
+
84
+ ### Install with optional dependencies
85
+
86
+ The package supports optional dependencies for gateway functionality:
87
+
88
+ <table>
89
+ <tr>
90
+ <th>OpenAI Gateway</th>
91
+ <th>Anthropic Gateway</th>
92
+ <th>All Gateways</th>
93
+ </tr>
94
+ <tr>
95
+ <td>
96
+
97
+ ```bash
98
+ pip install "airia[openai]"
99
+ ```
100
+
101
+ </td>
102
+ <td>
103
+
104
+ ```bash
105
+ pip install "airia[anthropic]"
106
+ ```
107
+
108
+ </td>
109
+ <td>
110
+
111
+ ```bash
112
+ pip install "airia[all]"
113
+ ```
114
+
115
+ </td>
116
+ </tr>
117
+ </table>
118
+
119
+ ### Install with development dependencies
120
+
121
+ Clone the repository:
122
+
123
+ ```bash
124
+ git clone https://github.com/AiriaLLC/airia-python.git
125
+ cd airia-python
126
+ ```
127
+
128
+ Then, run one of the following commands:
129
+
130
+ <table>
131
+ <tr>
132
+ <th>pip</th>
133
+ <th>uv</th>
134
+ </tr>
135
+ <tr>
136
+ <td>
137
+
138
+ ```bash
139
+ pip install dependency-groups
140
+ dev=$(python -m dependency_groups dev)
141
+ pip install -e .
142
+ pip install $dev
143
+ ```
144
+
145
+ </td>
146
+ <td>
147
+
148
+ ```bash
149
+ uv sync --frozen --group dev
150
+ ```
151
+
152
+ </td>
153
+ </tr>
154
+ </table>
155
+
156
+ ## Building from Source
157
+
158
+ First make sure you have already cloned the repository, then run one of the following commands:
159
+
160
+ <table>
161
+ <tr>
162
+ <th>pip</th>
163
+ <th>uv</th>
164
+ </tr>
165
+ <tr>
166
+ <td>
167
+
168
+ ```bash
169
+ pip install build
170
+ python -m build
171
+ ```
172
+
173
+ </td>
174
+ <td>
175
+
176
+ ```bash
177
+ uv build
178
+ ```
179
+
180
+ </td>
181
+ </tr>
182
+ </table>
183
+
184
+ This will create both wheel and source distribution in the `dist/` directory.
185
+
186
+ ## Requirements
187
+
188
+ - Python 3.9 or higher
189
+ - Core dependencies:
190
+ - requests
191
+ - aiohttp
192
+ - loguru
193
+ - pydantic
194
+
195
+ - Optional dependencies:
196
+ - OpenAI gateway: `openai>=1.74.0`
197
+ - Anthropic gateway: `anthropic>=0.49.0`
198
+
199
+ ## Development
200
+
201
+ To run tests (make sure you have development dependencies installed):
202
+
203
+ ```bash
204
+ pytest
205
+ ```
206
+
207
+ For testing gateway functionality, install the optional dependencies:
208
+
209
+ ```bash
210
+ # For OpenAI gateway tests
211
+ pip install -e .[openai]
212
+ pytest tests/test_openai_gateway.py
213
+
214
+ # For Anthropic gateway tests
215
+ pip install -e .[anthropic]
216
+ pytest tests/test_anthropic_gateway.py
217
+
218
+ # For all tests
219
+ pip install -e .[all]
220
+ pytest
221
+ ```
airia-0.1.34/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # Airia Python API Library
2
+
3
+ [![PyPI version](https://badge.fury.io/py/airia.svg)](https://badge.fury.io/py/airia)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/airia.svg)](https://pypi.org/project/airia/)
5
+ [![License](https://img.shields.io/pypi/l/airia.svg)](https://pypi.org/project/airia/)
6
+
7
+ The Airia Python library provides a clean and intuitive interface to interact with Airia API. The library offers both synchronous and asynchronous clients for maximum flexibility in your applications.
8
+
9
+ ## Features
10
+
11
+ - **Dual Client Support**: Choose between synchronous (`AiriaClient`) and asynchronous (`AiriaAsyncClient`) implementations
12
+ - **Pipeline Execution**: Easily run AI pipelines with customizable parameters
13
+ - **Gateway Support**: Seamlessly integrate with OpenAI and Anthropic services through Airia gateways
14
+ - **Error Handling**: Comprehensive error handling with custom exceptions
15
+ - **Logging**: Built-in configurable logging with correlation ID support for request tracing
16
+ - **Flexible Authentication**: Support for both API keys and bearer tokens with flexible configuration
17
+
18
+ ## Documentation and Quick Start Guides
19
+
20
+ Full documentation and quick start guides are available [here](https://airiallc.github.io/airia-python).
21
+
22
+ You can also run the documentation page locally with `mkdocs`:
23
+
24
+ 1. [Install development dependencies](#install-with-development-dependencies)
25
+ 2. Run `mkdocs serve` to start the local server
26
+
27
+ ## Installation
28
+
29
+ You can install the package using pip or uv:
30
+
31
+ <table>
32
+ <tr>
33
+ <th>pip</th>
34
+ <th>uv</th>
35
+ </tr>
36
+ <tr>
37
+ <td>
38
+
39
+ ```bash
40
+ pip install airia
41
+ ```
42
+
43
+ </td>
44
+ <td>
45
+
46
+ ```bash
47
+ uv add airia
48
+ ```
49
+
50
+ </td>
51
+ </tr>
52
+ </table>
53
+
54
+ ### Install with optional dependencies
55
+
56
+ The package supports optional dependencies for gateway functionality:
57
+
58
+ <table>
59
+ <tr>
60
+ <th>OpenAI Gateway</th>
61
+ <th>Anthropic Gateway</th>
62
+ <th>All Gateways</th>
63
+ </tr>
64
+ <tr>
65
+ <td>
66
+
67
+ ```bash
68
+ pip install "airia[openai]"
69
+ ```
70
+
71
+ </td>
72
+ <td>
73
+
74
+ ```bash
75
+ pip install "airia[anthropic]"
76
+ ```
77
+
78
+ </td>
79
+ <td>
80
+
81
+ ```bash
82
+ pip install "airia[all]"
83
+ ```
84
+
85
+ </td>
86
+ </tr>
87
+ </table>
88
+
89
+ ### Install with development dependencies
90
+
91
+ Clone the repository:
92
+
93
+ ```bash
94
+ git clone https://github.com/AiriaLLC/airia-python.git
95
+ cd airia-python
96
+ ```
97
+
98
+ Then, run one of the following commands:
99
+
100
+ <table>
101
+ <tr>
102
+ <th>pip</th>
103
+ <th>uv</th>
104
+ </tr>
105
+ <tr>
106
+ <td>
107
+
108
+ ```bash
109
+ pip install dependency-groups
110
+ dev=$(python -m dependency_groups dev)
111
+ pip install -e .
112
+ pip install $dev
113
+ ```
114
+
115
+ </td>
116
+ <td>
117
+
118
+ ```bash
119
+ uv sync --frozen --group dev
120
+ ```
121
+
122
+ </td>
123
+ </tr>
124
+ </table>
125
+
126
+ ## Building from Source
127
+
128
+ First make sure you have already cloned the repository, then run one of the following commands:
129
+
130
+ <table>
131
+ <tr>
132
+ <th>pip</th>
133
+ <th>uv</th>
134
+ </tr>
135
+ <tr>
136
+ <td>
137
+
138
+ ```bash
139
+ pip install build
140
+ python -m build
141
+ ```
142
+
143
+ </td>
144
+ <td>
145
+
146
+ ```bash
147
+ uv build
148
+ ```
149
+
150
+ </td>
151
+ </tr>
152
+ </table>
153
+
154
+ This will create both wheel and source distribution in the `dist/` directory.
155
+
156
+ ## Requirements
157
+
158
+ - Python 3.9 or higher
159
+ - Core dependencies:
160
+ - requests
161
+ - aiohttp
162
+ - loguru
163
+ - pydantic
164
+
165
+ - Optional dependencies:
166
+ - OpenAI gateway: `openai>=1.74.0`
167
+ - Anthropic gateway: `anthropic>=0.49.0`
168
+
169
+ ## Development
170
+
171
+ To run tests (make sure you have development dependencies installed):
172
+
173
+ ```bash
174
+ pytest
175
+ ```
176
+
177
+ For testing gateway functionality, install the optional dependencies:
178
+
179
+ ```bash
180
+ # For OpenAI gateway tests
181
+ pip install -e .[openai]
182
+ pytest tests/test_openai_gateway.py
183
+
184
+ # For Anthropic gateway tests
185
+ pip install -e .[anthropic]
186
+ pytest tests/test_anthropic_gateway.py
187
+
188
+ # For all tests
189
+ pip install -e .[all]
190
+ pytest
191
+ ```
@@ -0,0 +1,4 @@
1
+ from .async_request_handler import AsyncRequestHandler
2
+ from .sync_request_handler import RequestHandler
3
+
4
+ __all__ = ["RequestHandler", "AsyncRequestHandler"]
@@ -0,0 +1,293 @@
1
+ import asyncio
2
+ import weakref
3
+ from typing import Any, AsyncIterator, Dict, Optional
4
+
5
+ import aiohttp
6
+ import loguru
7
+
8
+ from ...exceptions import AiriaAPIError
9
+ from ...types._request_data import RequestData
10
+ from ...utils.sse_parser import async_parse_sse_stream_chunked
11
+ from .base_request_handler import BaseRequestHandler
12
+
13
+
14
+ class AsyncRequestHandler(BaseRequestHandler):
15
+ def __init__(
16
+ self,
17
+ logger: "loguru.Logger",
18
+ timeout: float,
19
+ base_url: str,
20
+ api_key: Optional[str] = None,
21
+ bearer_token: Optional[str] = None,
22
+ log_requests: bool = False,
23
+ ):
24
+ self.session = aiohttp.ClientSession()
25
+
26
+ self._finalizer = weakref.finalize(self, self._cleanup_session, self.session)
27
+
28
+ super().__init__(
29
+ logger=logger,
30
+ timeout=timeout,
31
+ api_key=api_key,
32
+ base_url=base_url,
33
+ bearer_token=bearer_token,
34
+ log_requests=log_requests,
35
+ )
36
+
37
+ @staticmethod
38
+ def _cleanup_session(session: aiohttp.ClientSession):
39
+ """Static method to clean up session - called by finalizer"""
40
+ if session and not session.closed:
41
+ # Create a new event loop if none exists
42
+ try:
43
+ loop = asyncio.get_event_loop()
44
+ if loop.is_closed():
45
+ raise RuntimeError("Event loop is closed")
46
+ except RuntimeError:
47
+ loop = asyncio.new_event_loop()
48
+ asyncio.set_event_loop(loop)
49
+
50
+ # Close the session
51
+ if not loop.is_running():
52
+ loop.run_until_complete(session.close())
53
+ else:
54
+ # If loop is running, schedule the close operation
55
+ asyncio.create_task(session.close())
56
+
57
+ async def close(self):
58
+ """
59
+ Closes the aiohttp session to free up system resources.
60
+
61
+ This method should be called when the RequestHandler is no longer needed to ensure
62
+ proper cleanup of the underlying session and its resources.
63
+ """
64
+ if self.session and not self.session.closed:
65
+ await self.session.close()
66
+
67
+ def _handle_exception(
68
+ self,
69
+ e: aiohttp.ClientResponseError,
70
+ detailed_error: str,
71
+ url: str,
72
+ correlation_id: str,
73
+ ):
74
+ # Log the error response if enabled
75
+ if self.log_requests:
76
+ self.logger.error(
77
+ f"API Error: {e.status} {e.message}\n"
78
+ f"Detailed Error Message: {detailed_error}\n"
79
+ f"URL: {url}\n"
80
+ f"Correlation ID: {correlation_id}"
81
+ )
82
+
83
+ # Extract error details from response
84
+ error_message = e.message
85
+
86
+ # Make sure sensitive auth information is not included in error messages
87
+ sanitized_message = error_message
88
+ if self.api_key and self.api_key in sanitized_message:
89
+ sanitized_message = sanitized_message.replace(self.api_key, "[REDACTED]")
90
+ if self.bearer_token and self.bearer_token in sanitized_message:
91
+ sanitized_message = sanitized_message.replace(
92
+ self.bearer_token, "[REDACTED]"
93
+ )
94
+
95
+ # Raise custom exception with status code and sanitized message
96
+ raise AiriaAPIError(
97
+ status_code=e.status,
98
+ message=sanitized_message,
99
+ detailed_message=detailed_error,
100
+ ) from e
101
+
102
+ async def make_request(
103
+ self, method: str, request_data: RequestData, return_json: bool = True
104
+ ) -> Optional[Dict[str, Any]]:
105
+ """
106
+ Makes an asynchronous HTTP request to the Airia API.
107
+
108
+ Args:
109
+ method (str): The HTTP method (e.g., 'GET', 'POST')
110
+ request_data: A dictionary containing the following request information:
111
+ - url: The endpoint URL for the request
112
+ - headers: HTTP headers to include in the request
113
+ - payload: The JSON payload/body for the request
114
+ - params: Optional query parameters to append to the URL
115
+ - files: Optional file data to be uploaded in the request body
116
+ - correlation_id: Unique identifier for request tracing
117
+ return_json (bool): Whether to return the response as JSON. Default is True.
118
+
119
+ Returns:
120
+ resp ([Dict[str, Any]): The JSON response from the API as a dictionary.
121
+
122
+ Raises:
123
+ AiriaAPIError: If the API returns an error response, with details about the error
124
+ aiohttp.ClientResponseError: For HTTP-related errors
125
+
126
+ Note:
127
+ This is an internal method used by other client methods to make API requests.
128
+ It handles logging, error handling, and API key redaction in error messages.
129
+ """
130
+ try:
131
+ # Make the request
132
+ async with self.session.request(
133
+ method=method,
134
+ url=request_data.url,
135
+ json=request_data.payload,
136
+ params=request_data.params,
137
+ headers=request_data.headers,
138
+ timeout=self.timeout,
139
+ ) as response:
140
+ # Log the response if enabled
141
+ if self.log_requests:
142
+ self.logger.info(
143
+ f"API Response: {response.status} {response.reason}\n"
144
+ f"URL: {request_data.url}\n"
145
+ f"Correlation ID: {request_data.correlation_id}"
146
+ )
147
+
148
+ # Check for HTTP errors
149
+ if not response.ok:
150
+ response_text = await response.text()
151
+ response.raise_for_status()
152
+
153
+ # Return the response as a dictionary
154
+ if return_json:
155
+ return await response.json()
156
+
157
+ except aiohttp.ClientResponseError as e:
158
+ self._handle_exception(
159
+ e, response_text, request_data.url, request_data.correlation_id
160
+ )
161
+
162
+ async def make_request_stream(
163
+ self, method: str, request_data: RequestData
164
+ ) -> AsyncIterator[str]:
165
+ """
166
+ Makes an asynchronous HTTP request to the Airia API.
167
+
168
+ Args:
169
+ method (str): The HTTP method (e.g., 'GET', 'POST')
170
+ request_data: A dictionary containing the following request information:
171
+ - url: The endpoint URL for the request
172
+ - headers: HTTP headers to include in the request
173
+ - payload: The JSON payload/body for the request
174
+ - params: Optional query parameters to append to the URL
175
+ - files: Optional file data to be uploaded in the request body
176
+ - correlation_id: Unique identifier for request tracing
177
+
178
+ Yields:
179
+ resp AsyncIterator[str]]: yields chunks of the response as they are received.
180
+
181
+ Raises:
182
+ AiriaAPIError: If the API returns an error response, with details about the error
183
+ aiohttp.ClientResponseError: For HTTP-related errors
184
+
185
+ Note:
186
+ This is an internal method used by other client methods to make API requests.
187
+ It handles logging, error handling, and API key redaction in error messages.
188
+ """
189
+ try:
190
+ # Make the request
191
+ async with self.session.request(
192
+ method=method,
193
+ url=request_data.url,
194
+ json=request_data.payload,
195
+ params=request_data.params,
196
+ headers=request_data.headers,
197
+ timeout=self.timeout,
198
+ chunked=True,
199
+ ) as response:
200
+ # Log the response if enabled
201
+ if self.log_requests:
202
+ self.logger.info(
203
+ f"API Response: {response.status} {response.reason}\n"
204
+ f"URL: {request_data.url}\n"
205
+ f"Correlation ID: {request_data.correlation_id}"
206
+ )
207
+
208
+ # Check for HTTP errors
209
+ if not response.ok:
210
+ response_text = await response.text()
211
+ response.raise_for_status()
212
+
213
+ # Yields the response content as a stream if streaming
214
+ async for message in async_parse_sse_stream_chunked(
215
+ response.content.iter_any()
216
+ ):
217
+ yield message
218
+
219
+ except aiohttp.ClientResponseError as e:
220
+ self._handle_exception(
221
+ e, response_text, request_data.url, request_data.correlation_id
222
+ )
223
+
224
+ async def make_request_multipart(
225
+ self, method: str, request_data: RequestData, return_json: bool = True
226
+ ) -> Optional[Dict[str, Any]]:
227
+ """
228
+ Makes an asynchronous HTTP request with multipart form data to the Airia API.
229
+
230
+ Args:
231
+ method (str): The HTTP method (e.g., 'POST')
232
+ request_data: A dictionary containing the following request information:
233
+ - url: The endpoint URL for the request
234
+ - headers: HTTP headers to include in the request
235
+ - payload: The form data payload including file content
236
+ - params: Optional query parameters to append to the URL
237
+ - files: Optional file data to be uploaded in the request body
238
+ - correlation_id: Unique identifier for request tracing
239
+ return_json (bool): Whether to return the response as JSON. Default is True.
240
+
241
+ Returns:
242
+ resp (Optional[Dict[str, Any]]): The JSON response from the API as a dictionary.
243
+
244
+ Raises:
245
+ AiriaAPIError: If the API returns an error response, with details about the error
246
+ aiohttp.ClientResponseError: For HTTP-related errors
247
+
248
+ Note:
249
+ This is an internal method used by file upload methods to make multipart requests.
250
+ It handles multipart form data encoding, logging, and error handling.
251
+ """
252
+ try:
253
+ # Prepare multipart form data
254
+ data = aiohttp.FormData()
255
+
256
+ # Add form fields
257
+ for key, value in request_data.payload.items():
258
+ data.add_field(key, str(value))
259
+
260
+ # Add files
261
+ for key, value in request_data.files.items():
262
+ data.add_field(key, value[1], filename=value[0], content_type=value[2])
263
+
264
+ # Make the request
265
+ async with self.session.request(
266
+ method=method,
267
+ url=request_data.url,
268
+ data=data,
269
+ params=request_data.params,
270
+ headers=request_data.headers,
271
+ timeout=self.timeout,
272
+ ) as response:
273
+ # Log the response if enabled
274
+ if self.log_requests:
275
+ self.logger.info(
276
+ f"API Response: {response.status} {response.reason}\n"
277
+ f"URL: {request_data.url}\n"
278
+ f"Correlation ID: {request_data.correlation_id}"
279
+ )
280
+
281
+ # Check for HTTP errors
282
+ if not response.ok:
283
+ response_text = await response.text()
284
+ response.raise_for_status()
285
+
286
+ # Return the response as a dictionary
287
+ if return_json:
288
+ return await response.json()
289
+
290
+ except aiohttp.ClientResponseError as e:
291
+ self._handle_exception(
292
+ e, response_text, request_data.url, request_data.correlation_id
293
+ )