airia 0.1.13__py3-none-any.whl → 0.1.14__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.
Files changed (53) hide show
  1. airia/client/_request_handler/__init__.py +4 -0
  2. airia/client/_request_handler/async_request_handler.py +272 -0
  3. airia/client/_request_handler/base_request_handler.py +108 -0
  4. airia/client/_request_handler/sync_request_handler.py +255 -0
  5. airia/client/async_client.py +25 -678
  6. airia/client/base_client.py +2 -368
  7. airia/client/conversations/__init__.py +4 -0
  8. airia/client/conversations/async_conversations.py +187 -0
  9. airia/client/conversations/base_conversations.py +135 -0
  10. airia/client/conversations/sync_conversations.py +182 -0
  11. airia/client/pipeline_execution/__init__.py +4 -0
  12. airia/client/pipeline_execution/async_pipeline_execution.py +178 -0
  13. airia/client/pipeline_execution/base_pipeline_execution.py +96 -0
  14. airia/client/pipeline_execution/sync_pipeline_execution.py +178 -0
  15. airia/client/pipelines_config/__init__.py +4 -0
  16. airia/client/pipelines_config/async_pipelines_config.py +127 -0
  17. airia/client/pipelines_config/base_pipelines_config.py +76 -0
  18. airia/client/pipelines_config/sync_pipelines_config.py +127 -0
  19. airia/client/project/__init__.py +4 -0
  20. airia/client/project/async_project.py +122 -0
  21. airia/client/project/base_project.py +74 -0
  22. airia/client/project/sync_project.py +120 -0
  23. airia/client/store/__init__.py +4 -0
  24. airia/client/store/async_store.py +377 -0
  25. airia/client/store/base_store.py +243 -0
  26. airia/client/store/sync_store.py +352 -0
  27. airia/client/sync_client.py +25 -656
  28. airia/constants.py +1 -1
  29. airia/exceptions.py +8 -8
  30. airia/logs.py +9 -9
  31. airia/types/_request_data.py +11 -4
  32. airia/types/api/__init__.py +0 -27
  33. airia/types/api/conversations/__init__.py +3 -0
  34. airia/types/api/{conversations.py → conversations/_conversations.py} +49 -12
  35. airia/types/api/pipeline_execution/__init__.py +13 -0
  36. airia/types/api/{pipeline_execution.py → pipeline_execution/_pipeline_execution.py} +30 -13
  37. airia/types/api/pipelines_config/__init__.py +3 -0
  38. airia/types/api/pipelines_config/get_pipeline_config.py +401 -0
  39. airia/types/api/project/__init__.py +3 -0
  40. airia/types/api/{get_projects.py → project/get_projects.py} +16 -4
  41. airia/types/api/store/__init__.py +4 -0
  42. airia/types/api/store/get_file.py +145 -0
  43. airia/types/api/store/get_files.py +21 -0
  44. airia/types/sse/__init__.py +1 -0
  45. airia/types/sse/sse_messages.py +55 -21
  46. airia/utils/sse_parser.py +5 -4
  47. {airia-0.1.13.dist-info → airia-0.1.14.dist-info}/METADATA +4 -2
  48. airia-0.1.14.dist-info/RECORD +55 -0
  49. airia/types/api/get_pipeline_config.py +0 -214
  50. airia-0.1.13.dist-info/RECORD +0 -24
  51. {airia-0.1.13.dist-info → airia-0.1.14.dist-info}/WHEEL +0 -0
  52. {airia-0.1.13.dist-info → airia-0.1.14.dist-info}/licenses/LICENSE +0 -0
  53. {airia-0.1.13.dist-info → airia-0.1.14.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,10 @@
1
- import json
2
1
  import os
3
- from typing import Any, Dict, List, Optional
4
- from urllib.parse import urljoin
2
+ from typing import Optional
5
3
 
6
4
  import loguru
7
5
 
8
6
  from ..constants import DEFAULT_BASE_URL, DEFAULT_TIMEOUT
9
- from ..logs import configure_logging, set_correlation_id
10
- from ..types._api_version import ApiVersion
11
- from ..types._request_data import RequestData
7
+ from ..logs import configure_logging
12
8
 
13
9
 
14
10
  class AiriaBaseClient:
@@ -89,365 +85,3 @@ class AiriaBaseClient:
89
85
  raise ValueError(
90
86
  "Authentication required. Provide either api_key (or set AIRIA_API_KEY environment variable) or bearer_token."
91
87
  )
92
-
93
- def _prepare_request(
94
- self,
95
- url: str,
96
- payload: Optional[Dict[str, Any]] = None,
97
- params: Optional[Dict[str, Any]] = None,
98
- correlation_id: Optional[str] = None,
99
- ):
100
- """
101
- Prepare request data including headers, authentication, and logging.
102
-
103
- This method sets up all the necessary components for an API request including
104
- correlation ID, authentication headers, and sanitized logging.
105
-
106
- Args:
107
- url: The target URL for the request
108
- payload: Optional JSON payload for the request body
109
- params: Optional query parameters for the request
110
- correlation_id: Optional correlation ID for request tracing
111
-
112
- Returns:
113
- RequestData: A data structure containing all prepared request components
114
- """
115
- # Set correlation ID if provided or generate a new one
116
- correlation_id = set_correlation_id(correlation_id)
117
-
118
- # Set up base headers
119
- headers = {
120
- "X-Correlation-ID": correlation_id,
121
- "Content-Type": "application/json",
122
- }
123
-
124
- # Add authentication header based on the method used
125
- if self.api_key:
126
- headers["X-API-KEY"] = self.api_key
127
- elif self.bearer_token:
128
- headers["Authorization"] = f"Bearer {self.bearer_token}"
129
-
130
- # Log the request if enabled
131
- if self.log_requests:
132
- # Create a sanitized copy of headers and params for logging
133
- log_headers = headers.copy()
134
- log_params = params.copy() if params is not None else {}
135
-
136
- # Filter out sensitive headers
137
- if "X-API-KEY" in log_headers:
138
- log_headers["X-API-KEY"] = "[REDACTED]"
139
- if "Authorization" in log_headers:
140
- log_headers["Authorization"] = "[REDACTED]"
141
-
142
- # Process payload for logging
143
- log_payload = payload.copy() if payload is not None else {}
144
- if "images" in log_payload and log_payload["images"] is not None:
145
- log_payload["images"] = f"{len(log_payload['images'])} images"
146
- if "files" in log_payload and log_payload["files"] is not None:
147
- log_payload["files"] = f"{len(log_payload['files'])} files"
148
- log_payload = json.dumps(log_payload)
149
-
150
- self.logger.info(
151
- f"API Request: POST {url}\n"
152
- f"Headers: {json.dumps(log_headers)}\n"
153
- f"Payload: {log_payload}"
154
- f"Params: {json.dumps(log_params)}\n"
155
- )
156
-
157
- return RequestData(
158
- **{
159
- "url": url,
160
- "payload": payload,
161
- "headers": headers,
162
- "params": params,
163
- "correlation_id": correlation_id,
164
- }
165
- )
166
-
167
- def _pre_execute_pipeline(
168
- self,
169
- pipeline_id: str,
170
- user_input: str,
171
- debug: bool = False,
172
- user_id: Optional[str] = None,
173
- conversation_id: Optional[str] = None,
174
- async_output: bool = False,
175
- include_tools_response: bool = False,
176
- images: Optional[List[str]] = None,
177
- files: Optional[List[str]] = None,
178
- data_source_folders: Optional[Dict[str, Any]] = None,
179
- data_source_files: Optional[Dict[str, Any]] = None,
180
- in_memory_messages: Optional[List[Dict[str, str]]] = None,
181
- current_date_time: Optional[str] = None,
182
- save_history: bool = True,
183
- additional_info: Optional[List[Any]] = None,
184
- prompt_variables: Optional[Dict[str, Any]] = None,
185
- correlation_id: Optional[str] = None,
186
- api_version: str = ApiVersion.V2.value,
187
- ):
188
- """
189
- Prepare request data for pipeline execution endpoint.
190
-
191
- This internal method constructs the URL and payload for pipeline execution
192
- requests, validating the API version and preparing all request components.
193
-
194
- Args:
195
- pipeline_id: ID of the pipeline to execute
196
- user_input: Input text to process
197
- debug: Whether to enable debug mode
198
- user_id: Optional user identifier
199
- conversation_id: Optional conversation identifier
200
- async_output: Whether to enable streaming output
201
- include_tools_response: Whether to include tool responses
202
- images: Optional list of base64-encoded images
203
- files: Optional list of base64-encoded files
204
- data_source_folders: Optional data source folder configuration
205
- data_source_files: Optional data source files configuration
206
- in_memory_messages: Optional list of in-memory messages
207
- current_date_time: Optional current date/time in ISO format
208
- save_history: Whether to save to conversation history
209
- additional_info: Optional additional information
210
- prompt_variables: Optional prompt variables
211
- correlation_id: Optional correlation ID for tracing
212
- api_version: API version to use for the request
213
-
214
- Returns:
215
- RequestData: Prepared request data for the pipeline execution endpoint
216
-
217
- Raises:
218
- ValueError: If an invalid API version is provided
219
- """
220
- if api_version not in ApiVersion.as_list():
221
- raise ValueError(
222
- f"Invalid API version: {api_version}. Valid versions are: {', '.join(ApiVersion.as_list())}"
223
- )
224
- url = urljoin(self.base_url, f"{api_version}/PipelineExecution/{pipeline_id}")
225
-
226
- payload = {
227
- "userInput": user_input,
228
- "debug": debug,
229
- "userId": user_id,
230
- "conversationId": conversation_id,
231
- "asyncOutput": async_output,
232
- "includeToolsResponse": include_tools_response,
233
- "images": images,
234
- "files": files,
235
- "dataSourceFolders": data_source_folders,
236
- "dataSourceFiles": data_source_files,
237
- "inMemoryMessages": in_memory_messages,
238
- "currentDateTime": current_date_time,
239
- "saveHistory": save_history,
240
- "additionalInfo": additional_info,
241
- "promptVariables": prompt_variables,
242
- }
243
-
244
- request_data = self._prepare_request(
245
- url=url, payload=payload, correlation_id=correlation_id
246
- )
247
-
248
- return request_data
249
-
250
- def _pre_get_projects(
251
- self,
252
- correlation_id: Optional[str] = None,
253
- api_version: str = ApiVersion.V1.value,
254
- ):
255
- """
256
- Prepare request data for getting projects endpoint.
257
-
258
- Args:
259
- correlation_id: Optional correlation ID for tracing
260
- api_version: API version to use for the request
261
-
262
- Returns:
263
- RequestData: Prepared request data for the projects endpoint
264
-
265
- Raises:
266
- ValueError: If an invalid API version is provided
267
- """
268
- if api_version not in ApiVersion.as_list():
269
- raise ValueError(
270
- f"Invalid API version: {api_version}. Valid versions are: {', '.join(ApiVersion.as_list())}"
271
- )
272
- url = urljoin(self.base_url, f"{api_version}/Project/paginated")
273
- request_data = self._prepare_request(url, correlation_id=correlation_id)
274
-
275
- return request_data
276
-
277
- def _pre_get_active_pipelines_ids(
278
- self,
279
- project_id: Optional[str] = None,
280
- correlation_id: Optional[str] = None,
281
- api_version: str = ApiVersion.V1.value,
282
- ):
283
- """
284
- Prepare request data for getting active pipelines IDs.
285
-
286
- Args:
287
- project_id: ID of the project to get configuration for
288
- correlation_id: Optional correlation ID for tracing
289
- api_version: API version to use for the request
290
-
291
- Returns:
292
- RequestData: Prepared request data for the pipeline config endpoint
293
-
294
- Raises:
295
- ValueError: If an invalid API version is provided
296
- """
297
- if api_version not in ApiVersion.as_list():
298
- raise ValueError(
299
- f"Invalid API version: {api_version}. Valid versions are: {', '.join(ApiVersion.as_list())}"
300
- )
301
- url = urljoin(self.base_url, f"{api_version}/PipelinesConfig")
302
- params = {"projectId": project_id} if project_id is not None else None
303
- request_data = self._prepare_request(
304
- url, params=params, correlation_id=correlation_id
305
- )
306
-
307
- return request_data
308
-
309
- def _pre_get_pipeline_config(
310
- self,
311
- pipeline_id: str,
312
- correlation_id: Optional[str] = None,
313
- api_version: str = ApiVersion.V1.value,
314
- ):
315
- """
316
- Prepare request data for getting pipeline configuration endpoint.
317
-
318
- Args:
319
- pipeline_id: ID of the pipeline to get configuration for
320
- correlation_id: Optional correlation ID for tracing
321
- api_version: API version to use for the request
322
-
323
- Returns:
324
- RequestData: Prepared request data for the pipeline config endpoint
325
-
326
- Raises:
327
- ValueError: If an invalid API version is provided
328
- """
329
- if api_version not in ApiVersion.as_list():
330
- raise ValueError(
331
- f"Invalid API version: {api_version}. Valid versions are: {', '.join(ApiVersion.as_list())}"
332
- )
333
- url = urljoin(
334
- self.base_url, f"{api_version}/PipelinesConfig/export/{pipeline_id}"
335
- )
336
- request_data = self._prepare_request(url, correlation_id=correlation_id)
337
-
338
- return request_data
339
-
340
- def _pre_create_conversation(
341
- self,
342
- user_id: str,
343
- title: Optional[str] = None,
344
- deployment_id: Optional[str] = None,
345
- data_source_files: Dict[str, Any] = {},
346
- is_bookmarked: bool = False,
347
- correlation_id: Optional[str] = None,
348
- api_version: str = ApiVersion.V1.value,
349
- ):
350
- """
351
- Prepare request data for creating a new conversation.
352
-
353
- This internal method constructs the URL and payload for conversation creation
354
- requests, including all conversation metadata and settings.
355
-
356
- Args:
357
- user_id: ID of the user creating the conversation
358
- title: Optional title for the conversation
359
- deployment_id: Optional deployment to associate with the conversation
360
- data_source_files: Optional data source files configuration
361
- is_bookmarked: Whether the conversation should be bookmarked
362
- correlation_id: Optional correlation ID for tracing
363
- api_version: API version to use for the request
364
-
365
- Returns:
366
- RequestData: Prepared request data for the conversation creation endpoint
367
-
368
- Raises:
369
- ValueError: If an invalid API version is provided
370
- """
371
- if api_version not in ApiVersion.as_list():
372
- raise ValueError(
373
- f"Invalid API version: {api_version}. Valid versions are: {', '.join(ApiVersion.as_list())}"
374
- )
375
- url = urljoin(self.base_url, f"{api_version}/Conversations")
376
-
377
- payload = {
378
- "userId": user_id,
379
- "title": title,
380
- "deploymentId": deployment_id,
381
- "dataSourceFiles": data_source_files,
382
- "isBookmarked": is_bookmarked,
383
- }
384
-
385
- request_data = self._prepare_request(
386
- url=url, payload=payload, correlation_id=correlation_id
387
- )
388
-
389
- return request_data
390
-
391
- def _pre_get_conversation(
392
- self,
393
- conversation_id: str,
394
- correlation_id: Optional[str] = None,
395
- api_version: str = ApiVersion.V1.value,
396
- ):
397
- """
398
- Prepare request data for retrieving a conversation by ID.
399
-
400
- This internal method constructs the URL for conversation retrieval
401
- requests using the provided conversation identifier.
402
-
403
- Args:
404
- conversation_id: ID of the conversation to retrieve
405
- correlation_id: Optional correlation ID for tracing
406
- api_version: API version to use for the request
407
-
408
- Returns:
409
- RequestData: Prepared request data for the conversation retrieval endpoint
410
-
411
- Raises:
412
- ValueError: If an invalid API version is provided
413
- """
414
- if api_version not in ApiVersion.as_list():
415
- raise ValueError(
416
- f"Invalid API version: {api_version}. Valid versions are: {', '.join(ApiVersion.as_list())}"
417
- )
418
- url = urljoin(self.base_url, f"{api_version}/Conversations/{conversation_id}")
419
- request_data = self._prepare_request(url, correlation_id=correlation_id)
420
-
421
- return request_data
422
-
423
- def _pre_delete_conversation(
424
- self,
425
- conversation_id: str,
426
- correlation_id: Optional[str] = None,
427
- api_version: str = ApiVersion.V1.value,
428
- ):
429
- """
430
- Prepare request data for deleting a conversation by ID.
431
-
432
- This internal method constructs the URL for conversation deletion
433
- requests using the provided conversation identifier.
434
-
435
- Args:
436
- conversation_id: ID of the conversation to delete
437
- correlation_id: Optional correlation ID for tracing
438
- api_version: API version to use for the request
439
-
440
- Returns:
441
- RequestData: Prepared request data for the conversation deletion endpoint
442
-
443
- Raises:
444
- ValueError: If an invalid API version is provided
445
- """
446
- if api_version not in ApiVersion.as_list():
447
- raise ValueError(
448
- f"Invalid API version: {api_version}. Valid versions are: {', '.join(ApiVersion.as_list())}"
449
- )
450
- url = urljoin(self.base_url, f"{api_version}/Conversations/{conversation_id}")
451
- request_data = self._prepare_request(url, correlation_id=correlation_id)
452
-
453
- return request_data
@@ -0,0 +1,4 @@
1
+ from .async_conversations import AsyncConversations
2
+ from .sync_conversations import Conversations
3
+
4
+ __all__ = ["Conversations", "AsyncConversations"]
@@ -0,0 +1,187 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ from ...types._api_version import ApiVersion
4
+ from ...types.api.conversations import (
5
+ CreateConversationResponse,
6
+ GetConversationResponse,
7
+ )
8
+ from .._request_handler import AsyncRequestHandler
9
+ from .base_conversations import BaseConversations
10
+
11
+
12
+ class AsyncConversations(BaseConversations):
13
+ def __init__(self, request_handler: AsyncRequestHandler):
14
+ super().__init__(request_handler)
15
+
16
+ async def create_conversation(
17
+ self,
18
+ user_id: str,
19
+ title: Optional[str] = None,
20
+ deployment_id: Optional[str] = None,
21
+ data_source_files: Dict[str, Any] = {},
22
+ is_bookmarked: bool = False,
23
+ correlation_id: Optional[str] = None,
24
+ ) -> CreateConversationResponse:
25
+ """
26
+ Create a new conversation.
27
+
28
+ Args:
29
+ user_id (str): The unique identifier of the user creating the conversation.
30
+ title (str, optional): The title for the conversation. If not provided,
31
+ the conversation will be created without a title.
32
+ deployment_id (str, optional): The unique identifier of the deployment
33
+ to associate with the conversation. If not provided, the conversation
34
+ will not be associated with any specific deployment.
35
+ data_source_files (dict): Configuration for data source files
36
+ to be associated with the conversation. If not provided, no data
37
+ source files will be associated.
38
+ is_bookmarked (bool): Whether the conversation should be bookmarked.
39
+ Defaults to False.
40
+ correlation_id (str, optional): A unique identifier for request tracing
41
+ and logging. If not provided, one will be automatically generated.
42
+
43
+ Returns:
44
+ CreateConversationResponse: A response object containing the created
45
+ conversation details including its ID, creation timestamp, and
46
+ all provided parameters.
47
+
48
+ Raises:
49
+ AiriaAPIError: If the API request fails, including cases where:
50
+ - The user_id doesn't exist (404)
51
+ - The deployment_id is invalid (404)
52
+ - Authentication fails (401)
53
+ - Access is forbidden (403)
54
+ - Server errors (5xx)
55
+
56
+ Example:
57
+ ```python
58
+ from airia import AiriaAsyncClient
59
+
60
+ client = AiriaAsyncClient(api_key="your_api_key")
61
+
62
+ # Create a basic conversation
63
+ conversation = await client.conversations.create_conversation(
64
+ user_id="user_123"
65
+ )
66
+ print(f"Created conversation: {conversation.conversation_id}")
67
+
68
+ # Create a conversation with all options
69
+ conversation = await client.conversations.create_conversation(
70
+ user_id="user_123",
71
+ title="My Research Session",
72
+ deployment_id="deployment_456",
73
+ data_source_files={"documents": ["doc1.pdf", "doc2.txt"]},
74
+ is_bookmarked=True
75
+ )
76
+ print(f"Created bookmarked conversation: {conversation.conversation_id}")
77
+ ```
78
+
79
+ Note:
80
+ The user_id is required and must correspond to a valid user in the system.
81
+ All other parameters are optional and can be set to None or their default values.
82
+ """
83
+ request_data = self._pre_create_conversation(
84
+ user_id=user_id,
85
+ title=title,
86
+ deployment_id=deployment_id,
87
+ data_source_files=data_source_files,
88
+ is_bookmarked=is_bookmarked,
89
+ correlation_id=correlation_id,
90
+ api_version=ApiVersion.V1.value,
91
+ )
92
+ resp = await self._request_handler.make_request("POST", request_data)
93
+
94
+ return CreateConversationResponse(**resp)
95
+
96
+ async def get_conversation(
97
+ self, conversation_id: str, correlation_id: Optional[str] = None
98
+ ) -> GetConversationResponse:
99
+ """
100
+ Retrieve detailed information about a specific conversation by its ID.
101
+
102
+ This method fetches comprehensive information about a conversation including
103
+ all messages, metadata, policy redactions, and execution status.
104
+
105
+ Args:
106
+ conversation_id (str): The unique identifier of the conversation to retrieve.
107
+ correlation_id (str, optional): A unique identifier for request tracing
108
+ and logging. If not provided, one will be automatically generated.
109
+
110
+ Returns:
111
+ GetConversationResponse: A response object containing the conversation
112
+ details including user ID, messages, title, deployment information,
113
+ data source files, bookmark status, policy redactions, and execution status.
114
+
115
+ Raises:
116
+ AiriaAPIError: If the API request fails, including cases where:
117
+ - The conversation_id doesn't exist (404)
118
+ - Authentication fails (401)
119
+ - Access is forbidden (403)
120
+ - Server errors (5xx)
121
+
122
+ Example:
123
+ ```python
124
+ from airia import AiriaAsyncClient
125
+
126
+ async def main():
127
+ client = AiriaAsyncClient(api_key="your_api_key")
128
+
129
+ # Get conversation details
130
+ conversation = await client.conversations.get_conversation(
131
+ conversation_id="conversation_123"
132
+ )
133
+
134
+ print(f"Conversation: {conversation.title}")
135
+ print(f"User: {conversation.user_id}")
136
+ print(f"Messages: {len(conversation.messages)}")
137
+ print(f"Bookmarked: {conversation.is_bookmarked}")
138
+
139
+ # Access individual messages
140
+ for message in conversation.messages:
141
+ print(f"[{message.role}]: {message.message}")
142
+
143
+ asyncio.run(main())
144
+ ```
145
+
146
+ Note:
147
+ This method only retrieves conversation information and does not
148
+ modify or execute any operations on the conversation.
149
+ """
150
+ request_data = self._pre_get_conversation(
151
+ conversation_id=conversation_id,
152
+ correlation_id=correlation_id,
153
+ api_version=ApiVersion.V1.value,
154
+ )
155
+ resp = await self._request_handler.make_request("GET", request_data)
156
+
157
+ return GetConversationResponse(**resp)
158
+
159
+ async def delete_conversation(
160
+ self,
161
+ conversation_id: str,
162
+ correlation_id: Optional[str] = None,
163
+ ) -> None:
164
+ """
165
+ Delete a conversation by its ID.
166
+
167
+ This method permanently removes a conversation and all associated data
168
+ from the Airia platform. This action cannot be undone.
169
+
170
+ Args:
171
+ conversation_id: The unique identifier of the conversation to delete
172
+ correlation_id: Optional correlation ID for request tracing
173
+
174
+ Returns:
175
+ None: This method returns nothing upon successful deletion
176
+
177
+ Raises:
178
+ AiriaAPIError: If the API request fails or the conversation doesn't exist
179
+ """
180
+ request_data = self._pre_delete_conversation(
181
+ conversation_id=conversation_id,
182
+ correlation_id=correlation_id,
183
+ api_version=ApiVersion.V1.value,
184
+ )
185
+ await self._request_handler.make_request(
186
+ "DELETE", request_data, return_json=False
187
+ )