airia 0.1.34__tar.gz → 0.1.35__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 (109) hide show
  1. {airia-0.1.34 → airia-0.1.35}/PKG-INFO +10 -4
  2. {airia-0.1.34 → airia-0.1.35}/README.md +8 -1
  3. airia-0.1.35/airia/__init__.py +19 -0
  4. {airia-0.1.34 → airia-0.1.35}/airia/client/_request_handler/async_request_handler.py +2 -2
  5. {airia-0.1.34 → airia-0.1.35}/airia/client/_request_handler/base_request_handler.py +2 -3
  6. {airia-0.1.34 → airia-0.1.35}/airia/client/_request_handler/sync_request_handler.py +2 -2
  7. {airia-0.1.34 → airia-0.1.35}/airia/client/async_client.py +5 -6
  8. {airia-0.1.34 → airia-0.1.35}/airia/client/base_client.py +2 -3
  9. {airia-0.1.34 → airia-0.1.35}/airia/client/sync_client.py +5 -6
  10. airia-0.1.35/airia/logs.py +267 -0
  11. {airia-0.1.34 → airia-0.1.35}/airia.egg-info/PKG-INFO +10 -4
  12. {airia-0.1.34 → airia-0.1.35}/airia.egg-info/requires.txt +1 -2
  13. {airia-0.1.34 → airia-0.1.35}/pyproject.toml +2 -7
  14. airia-0.1.34/airia/__init__.py +0 -6
  15. airia-0.1.34/airia/logs.py +0 -137
  16. {airia-0.1.34 → airia-0.1.35}/LICENSE +0 -0
  17. {airia-0.1.34 → airia-0.1.35}/airia/client/__init__.py +0 -0
  18. {airia-0.1.34 → airia-0.1.35}/airia/client/_request_handler/__init__.py +0 -0
  19. {airia-0.1.34 → airia-0.1.35}/airia/client/attachments/__init__.py +0 -0
  20. {airia-0.1.34 → airia-0.1.35}/airia/client/attachments/async_attachments.py +0 -0
  21. {airia-0.1.34 → airia-0.1.35}/airia/client/attachments/base_attachments.py +0 -0
  22. {airia-0.1.34 → airia-0.1.35}/airia/client/attachments/sync_attachments.py +0 -0
  23. {airia-0.1.34 → airia-0.1.35}/airia/client/conversations/__init__.py +0 -0
  24. {airia-0.1.34 → airia-0.1.35}/airia/client/conversations/async_conversations.py +0 -0
  25. {airia-0.1.34 → airia-0.1.35}/airia/client/conversations/base_conversations.py +0 -0
  26. {airia-0.1.34 → airia-0.1.35}/airia/client/conversations/sync_conversations.py +0 -0
  27. {airia-0.1.34 → airia-0.1.35}/airia/client/data_vector_search/__init__.py +0 -0
  28. {airia-0.1.34 → airia-0.1.35}/airia/client/data_vector_search/async_data_vector_search.py +0 -0
  29. {airia-0.1.34 → airia-0.1.35}/airia/client/data_vector_search/base_data_vector_search.py +0 -0
  30. {airia-0.1.34 → airia-0.1.35}/airia/client/data_vector_search/sync_data_vector_search.py +0 -0
  31. {airia-0.1.34 → airia-0.1.35}/airia/client/deployments/__init__.py +0 -0
  32. {airia-0.1.34 → airia-0.1.35}/airia/client/deployments/async_deployments.py +0 -0
  33. {airia-0.1.34 → airia-0.1.35}/airia/client/deployments/base_deployments.py +0 -0
  34. {airia-0.1.34 → airia-0.1.35}/airia/client/deployments/sync_deployments.py +0 -0
  35. {airia-0.1.34 → airia-0.1.35}/airia/client/library/__init__.py +0 -0
  36. {airia-0.1.34 → airia-0.1.35}/airia/client/library/async_library.py +0 -0
  37. {airia-0.1.34 → airia-0.1.35}/airia/client/library/base_library.py +0 -0
  38. {airia-0.1.34 → airia-0.1.35}/airia/client/library/sync_library.py +0 -0
  39. {airia-0.1.34 → airia-0.1.35}/airia/client/models/__init__.py +0 -0
  40. {airia-0.1.34 → airia-0.1.35}/airia/client/models/async_models.py +0 -0
  41. {airia-0.1.34 → airia-0.1.35}/airia/client/models/base_models.py +0 -0
  42. {airia-0.1.34 → airia-0.1.35}/airia/client/models/sync_models.py +0 -0
  43. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_execution/__init__.py +0 -0
  44. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_execution/async_pipeline_execution.py +0 -0
  45. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_execution/base_pipeline_execution.py +0 -0
  46. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_execution/sync_pipeline_execution.py +0 -0
  47. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_import/__init__.py +0 -0
  48. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_import/async_pipeline_import.py +0 -0
  49. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_import/base_pipeline_import.py +0 -0
  50. {airia-0.1.34 → airia-0.1.35}/airia/client/pipeline_import/sync_pipeline_import.py +0 -0
  51. {airia-0.1.34 → airia-0.1.35}/airia/client/pipelines_config/__init__.py +0 -0
  52. {airia-0.1.34 → airia-0.1.35}/airia/client/pipelines_config/async_pipelines_config.py +0 -0
  53. {airia-0.1.34 → airia-0.1.35}/airia/client/pipelines_config/base_pipelines_config.py +0 -0
  54. {airia-0.1.34 → airia-0.1.35}/airia/client/pipelines_config/sync_pipelines_config.py +0 -0
  55. {airia-0.1.34 → airia-0.1.35}/airia/client/project/__init__.py +0 -0
  56. {airia-0.1.34 → airia-0.1.35}/airia/client/project/async_project.py +0 -0
  57. {airia-0.1.34 → airia-0.1.35}/airia/client/project/base_project.py +0 -0
  58. {airia-0.1.34 → airia-0.1.35}/airia/client/project/sync_project.py +0 -0
  59. {airia-0.1.34 → airia-0.1.35}/airia/client/store/__init__.py +0 -0
  60. {airia-0.1.34 → airia-0.1.35}/airia/client/store/async_store.py +0 -0
  61. {airia-0.1.34 → airia-0.1.35}/airia/client/store/base_store.py +0 -0
  62. {airia-0.1.34 → airia-0.1.35}/airia/client/store/sync_store.py +0 -0
  63. {airia-0.1.34 → airia-0.1.35}/airia/client/tools/__init__.py +0 -0
  64. {airia-0.1.34 → airia-0.1.35}/airia/client/tools/async_tools.py +0 -0
  65. {airia-0.1.34 → airia-0.1.35}/airia/client/tools/base_tools.py +0 -0
  66. {airia-0.1.34 → airia-0.1.35}/airia/client/tools/sync_tools.py +0 -0
  67. {airia-0.1.34 → airia-0.1.35}/airia/constants.py +0 -0
  68. {airia-0.1.34 → airia-0.1.35}/airia/exceptions.py +0 -0
  69. {airia-0.1.34 → airia-0.1.35}/airia/types/__init__.py +0 -0
  70. {airia-0.1.34 → airia-0.1.35}/airia/types/_api_version.py +0 -0
  71. {airia-0.1.34 → airia-0.1.35}/airia/types/_request_data.py +0 -0
  72. {airia-0.1.34 → airia-0.1.35}/airia/types/_structured_output.py +0 -0
  73. {airia-0.1.34 → airia-0.1.35}/airia/types/api/__init__.py +0 -0
  74. {airia-0.1.34 → airia-0.1.35}/airia/types/api/attachments/__init__.py +0 -0
  75. {airia-0.1.34 → airia-0.1.35}/airia/types/api/attachments/upload_file.py +0 -0
  76. {airia-0.1.34 → airia-0.1.35}/airia/types/api/conversations/__init__.py +0 -0
  77. {airia-0.1.34 → airia-0.1.35}/airia/types/api/conversations/_conversations.py +0 -0
  78. {airia-0.1.34 → airia-0.1.35}/airia/types/api/data_vector_search/__init__.py +0 -0
  79. {airia-0.1.34 → airia-0.1.35}/airia/types/api/data_vector_search/get_file_chunks.py +0 -0
  80. {airia-0.1.34 → airia-0.1.35}/airia/types/api/deployments/__init__.py +0 -0
  81. {airia-0.1.34 → airia-0.1.35}/airia/types/api/deployments/get_deployment.py +0 -0
  82. {airia-0.1.34 → airia-0.1.35}/airia/types/api/deployments/get_deployments.py +0 -0
  83. {airia-0.1.34 → airia-0.1.35}/airia/types/api/library/__init__.py +0 -0
  84. {airia-0.1.34 → airia-0.1.35}/airia/types/api/library/_library_models.py +0 -0
  85. {airia-0.1.34 → airia-0.1.35}/airia/types/api/models/__init__.py +0 -0
  86. {airia-0.1.34 → airia-0.1.35}/airia/types/api/models/list_models.py +0 -0
  87. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipeline_execution/__init__.py +0 -0
  88. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipeline_execution/_pipeline_execution.py +0 -0
  89. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipeline_execution/get_pipeline_execution.py +0 -0
  90. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipeline_import/__init__.py +0 -0
  91. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipeline_import/create_agent_from_pipeline_definition.py +0 -0
  92. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipelines_config/__init__.py +0 -0
  93. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipelines_config/export_pipeline_definition.py +0 -0
  94. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipelines_config/get_pipeline_config.py +0 -0
  95. {airia-0.1.34 → airia-0.1.35}/airia/types/api/pipelines_config/get_pipelines_config.py +0 -0
  96. {airia-0.1.34 → airia-0.1.35}/airia/types/api/project/__init__.py +0 -0
  97. {airia-0.1.34 → airia-0.1.35}/airia/types/api/project/get_projects.py +0 -0
  98. {airia-0.1.34 → airia-0.1.35}/airia/types/api/store/__init__.py +0 -0
  99. {airia-0.1.34 → airia-0.1.35}/airia/types/api/store/get_file.py +0 -0
  100. {airia-0.1.34 → airia-0.1.35}/airia/types/api/store/get_files.py +0 -0
  101. {airia-0.1.34 → airia-0.1.35}/airia/types/api/tools/__init__.py +0 -0
  102. {airia-0.1.34 → airia-0.1.35}/airia/types/api/tools/_tools.py +0 -0
  103. {airia-0.1.34 → airia-0.1.35}/airia/types/sse/__init__.py +0 -0
  104. {airia-0.1.34 → airia-0.1.35}/airia/types/sse/sse_messages.py +0 -0
  105. {airia-0.1.34 → airia-0.1.35}/airia/utils/sse_parser.py +0 -0
  106. {airia-0.1.34 → airia-0.1.35}/airia.egg-info/SOURCES.txt +0 -0
  107. {airia-0.1.34 → airia-0.1.35}/airia.egg-info/dependency_links.txt +0 -0
  108. {airia-0.1.34 → airia-0.1.35}/airia.egg-info/top_level.txt +0 -0
  109. {airia-0.1.34 → airia-0.1.35}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: airia
3
- Version: 0.1.34
3
+ Version: 0.1.35
4
4
  Summary: Python SDK for Airia API
5
5
  Author-email: Airia LLC <support@airia.com>
6
6
  License: MIT
@@ -16,8 +16,7 @@ Requires-Python: >=3.9
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: requests>=2.32.3
19
- Requires-Dist: aiohttp>=3.11.14
20
- Requires-Dist: loguru>=0.7.3
19
+ Requires-Dist: aiohttp>=3.13.3
21
20
  Requires-Dist: pydantic>=2.11.0
22
21
  Provides-Extra: anthropic
23
22
  Requires-Dist: anthropic>=0.49.0; extra == "anthropic"
@@ -189,13 +188,20 @@ This will create both wheel and source distribution in the `dist/` directory.
189
188
  - Core dependencies:
190
189
  - requests
191
190
  - aiohttp
192
- - loguru
193
191
  - pydantic
194
192
 
195
193
  - Optional dependencies:
196
194
  - OpenAI gateway: `openai>=1.74.0`
197
195
  - Anthropic gateway: `anthropic>=0.49.0`
198
196
 
197
+ ## Features
198
+
199
+ - **Synchronous and Asynchronous Clients**: Choose between sync (`AiriaClient`) or async (`AiriaAsyncClient`) based on your needs
200
+ - **Colored Logging**: Built-in colored console logging using ANSI codes (no additional dependencies)
201
+ - **Correlation ID Tracking**: Automatic request tracing with correlation IDs
202
+ - **Gateway Support**: Optional OpenAI and Anthropic gateway integration
203
+ - **Type Safety**: Full type hints and Pydantic models for request/response validation
204
+
199
205
  ## Development
200
206
 
201
207
  To run tests (make sure you have development dependencies installed):
@@ -159,13 +159,20 @@ This will create both wheel and source distribution in the `dist/` directory.
159
159
  - Core dependencies:
160
160
  - requests
161
161
  - aiohttp
162
- - loguru
163
162
  - pydantic
164
163
 
165
164
  - Optional dependencies:
166
165
  - OpenAI gateway: `openai>=1.74.0`
167
166
  - Anthropic gateway: `anthropic>=0.49.0`
168
167
 
168
+ ## Features
169
+
170
+ - **Synchronous and Asynchronous Clients**: Choose between sync (`AiriaClient`) or async (`AiriaAsyncClient`) based on your needs
171
+ - **Colored Logging**: Built-in colored console logging using ANSI codes (no additional dependencies)
172
+ - **Correlation ID Tracking**: Automatic request tracing with correlation IDs
173
+ - **Gateway Support**: Optional OpenAI and Anthropic gateway integration
174
+ - **Type Safety**: Full type hints and Pydantic models for request/response validation
175
+
169
176
  ## Development
170
177
 
171
178
  To run tests (make sure you have development dependencies installed):
@@ -0,0 +1,19 @@
1
+ from .logs import (
2
+ configure_logging,
3
+ set_correlation_id,
4
+ get_correlation_id,
5
+ clear_correlation_id,
6
+ )
7
+ from .client import AiriaClient, AiriaAsyncClient
8
+ from .exceptions import AiriaAPIError
9
+
10
+ __version__ = "0.1.0"
11
+ __all__ = [
12
+ "AiriaClient",
13
+ "AiriaAsyncClient",
14
+ "AiriaAPIError",
15
+ "configure_logging",
16
+ "set_correlation_id",
17
+ "get_correlation_id",
18
+ "clear_correlation_id",
19
+ ]
@@ -1,9 +1,9 @@
1
1
  import asyncio
2
+ import logging
2
3
  import weakref
3
4
  from typing import Any, AsyncIterator, Dict, Optional
4
5
 
5
6
  import aiohttp
6
- import loguru
7
7
 
8
8
  from ...exceptions import AiriaAPIError
9
9
  from ...types._request_data import RequestData
@@ -14,7 +14,7 @@ from .base_request_handler import BaseRequestHandler
14
14
  class AsyncRequestHandler(BaseRequestHandler):
15
15
  def __init__(
16
16
  self,
17
- logger: "loguru.Logger",
17
+ logger: logging.Logger,
18
18
  timeout: float,
19
19
  base_url: str,
20
20
  api_key: Optional[str] = None,
@@ -1,8 +1,7 @@
1
1
  import json
2
+ import logging
2
3
  from typing import Any, Dict, Optional
3
4
 
4
- import loguru
5
-
6
5
  from ...logs import set_correlation_id
7
6
  from ...types._request_data import RequestData
8
7
 
@@ -10,7 +9,7 @@ from ...types._request_data import RequestData
10
9
  class BaseRequestHandler:
11
10
  def __init__(
12
11
  self,
13
- logger: "loguru.Logger",
12
+ logger: logging.Logger,
14
13
  timeout: float,
15
14
  base_url: str,
16
15
  api_key: Optional[str] = None,
@@ -1,7 +1,7 @@
1
+ import logging
1
2
  import weakref
2
3
  from typing import Any, Dict, Optional
3
4
 
4
- import loguru
5
5
  import requests
6
6
 
7
7
  from ...exceptions import AiriaAPIError
@@ -13,7 +13,7 @@ from .base_request_handler import BaseRequestHandler
13
13
  class RequestHandler(BaseRequestHandler):
14
14
  def __init__(
15
15
  self,
16
- logger: "loguru.Logger",
16
+ logger: logging.Logger,
17
17
  timeout: float,
18
18
  base_url: str,
19
19
  api_key: Optional[str] = None,
@@ -1,7 +1,6 @@
1
+ import logging
1
2
  from typing import Optional
2
3
 
3
- import loguru
4
-
5
4
  from ..constants import (
6
5
  DEFAULT_ANTHROPIC_GATEWAY_URL,
7
6
  DEFAULT_BASE_URL,
@@ -34,7 +33,7 @@ class AiriaAsyncClient(AiriaBaseClient):
34
33
  bearer_token: Optional[str] = None,
35
34
  timeout: float = DEFAULT_TIMEOUT,
36
35
  log_requests: bool = False,
37
- custom_logger: Optional["loguru.Logger"] = None,
36
+ custom_logger: Optional[logging.Logger] = None,
38
37
  ):
39
38
  """
40
39
  Initialize the asynchronous Airia API client.
@@ -85,7 +84,7 @@ class AiriaAsyncClient(AiriaBaseClient):
85
84
  api_key: Optional[str] = None,
86
85
  timeout: float = DEFAULT_TIMEOUT,
87
86
  log_requests: bool = False,
88
- custom_logger: Optional["loguru.Logger"] = None,
87
+ custom_logger: Optional[logging.Logger] = None,
89
88
  **kwargs,
90
89
  ):
91
90
  """
@@ -125,7 +124,7 @@ class AiriaAsyncClient(AiriaBaseClient):
125
124
  api_key: Optional[str] = None,
126
125
  timeout: float = DEFAULT_TIMEOUT,
127
126
  log_requests: bool = False,
128
- custom_logger: Optional["loguru.Logger"] = None,
127
+ custom_logger: Optional[logging.Logger] = None,
129
128
  **kwargs,
130
129
  ):
131
130
  """
@@ -164,7 +163,7 @@ class AiriaAsyncClient(AiriaBaseClient):
164
163
  base_url: str = DEFAULT_BASE_URL,
165
164
  timeout: float = DEFAULT_TIMEOUT,
166
165
  log_requests: bool = False,
167
- custom_logger: Optional["loguru.Logger"] = None,
166
+ custom_logger: Optional[logging.Logger] = None,
168
167
  ):
169
168
  """
170
169
  Initialize the asynchronous Airia API client with bearer token authentication.
@@ -1,8 +1,7 @@
1
+ import logging
1
2
  import os
2
3
  from typing import Optional
3
4
 
4
- import loguru
5
-
6
5
  from ..constants import DEFAULT_BASE_URL, DEFAULT_TIMEOUT
7
6
  from ..logs import configure_logging
8
7
 
@@ -20,7 +19,7 @@ class AiriaBaseClient:
20
19
  bearer_token: Optional[str] = None,
21
20
  timeout: float = DEFAULT_TIMEOUT,
22
21
  log_requests: bool = False,
23
- custom_logger: Optional["loguru.Logger"] = None,
22
+ custom_logger: Optional[logging.Logger] = None,
24
23
  ):
25
24
  """
26
25
  Initialize the Airia API client base class.
@@ -1,7 +1,6 @@
1
+ import logging
1
2
  from typing import Optional
2
3
 
3
- import loguru
4
-
5
4
  from ..constants import (
6
5
  DEFAULT_ANTHROPIC_GATEWAY_URL,
7
6
  DEFAULT_BASE_URL,
@@ -34,7 +33,7 @@ class AiriaClient(AiriaBaseClient):
34
33
  bearer_token: Optional[str] = None,
35
34
  timeout: float = DEFAULT_TIMEOUT,
36
35
  log_requests: bool = False,
37
- custom_logger: Optional["loguru.Logger"] = None,
36
+ custom_logger: Optional[logging.Logger] = None,
38
37
  ):
39
38
  """
40
39
  Initialize the synchronous Airia API client.
@@ -85,7 +84,7 @@ class AiriaClient(AiriaBaseClient):
85
84
  api_key: Optional[str] = None,
86
85
  timeout: float = DEFAULT_TIMEOUT,
87
86
  log_requests: bool = False,
88
- custom_logger: Optional["loguru.Logger"] = None,
87
+ custom_logger: Optional[logging.Logger] = None,
89
88
  **kwargs,
90
89
  ):
91
90
  """
@@ -125,7 +124,7 @@ class AiriaClient(AiriaBaseClient):
125
124
  api_key: Optional[str] = None,
126
125
  timeout: float = DEFAULT_TIMEOUT,
127
126
  log_requests: bool = False,
128
- custom_logger: Optional["loguru.Logger"] = None,
127
+ custom_logger: Optional[logging.Logger] = None,
129
128
  **kwargs,
130
129
  ):
131
130
  """
@@ -164,7 +163,7 @@ class AiriaClient(AiriaBaseClient):
164
163
  base_url: str = DEFAULT_BASE_URL,
165
164
  timeout: float = DEFAULT_TIMEOUT,
166
165
  log_requests: bool = False,
167
- custom_logger: Optional["loguru.Logger"] = None,
166
+ custom_logger: Optional[logging.Logger] = None,
168
167
  ):
169
168
  """
170
169
  Initialize the synchronous Airia API client with bearer token authentication.
@@ -0,0 +1,267 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+ import uuid
5
+ from contextvars import ContextVar
6
+ from typing import BinaryIO, Optional, TextIO, Union
7
+
8
+ # Create a context variable to store correlation ID
9
+ correlation_id_context: ContextVar[str] = ContextVar("correlation_id", default="")
10
+
11
+ # ANSI color codes
12
+ RESET = "\033[0m"
13
+ COLORS = {
14
+ "DEBUG": "\033[36m", # Cyan
15
+ "INFO": "\033[32m", # Green
16
+ "WARNING": "\033[33m", # Yellow
17
+ "ERROR": "\033[31m", # Red
18
+ "CRITICAL": "\033[35m", # Magenta
19
+ }
20
+ GREY = "\033[90m" # Grey for metadata
21
+ MAGENTA = "\033[35m" # Magenta for correlation ID
22
+
23
+
24
+ def _enable_windows_ansi_support():
25
+ """Enable ANSI color support on Windows."""
26
+ if sys.platform == "win32":
27
+ try:
28
+ import ctypes
29
+
30
+ kernel32 = ctypes.windll.kernel32
31
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
32
+ except Exception:
33
+ # If it fails, colors just won't work on Windows
34
+ pass
35
+
36
+
37
+ # Enable Windows ANSI support at module load
38
+ _enable_windows_ansi_support()
39
+
40
+
41
+ def get_correlation_id() -> str:
42
+ """
43
+ Get the current correlation ID from context or return empty string if not set.
44
+
45
+ Returns:
46
+ str: The current correlation ID
47
+ """
48
+ return correlation_id_context.get()
49
+
50
+
51
+ def set_correlation_id(correlation_id: Optional[str] = None) -> str:
52
+ """
53
+ Set a correlation ID in the current context.
54
+
55
+ Args:
56
+ correlation_id (Optional[str]): The correlation ID to set. If None, a new UUID will be generated.
57
+
58
+ Returns:
59
+ str: The correlation ID that was set
60
+ """
61
+ if correlation_id is None:
62
+ correlation_id = str(uuid.uuid4())
63
+ correlation_id_context.set(correlation_id)
64
+ return correlation_id
65
+
66
+
67
+ def clear_correlation_id() -> None:
68
+ """Clear the correlation ID from the current context."""
69
+ correlation_id_context.set("")
70
+
71
+
72
+ class CorrelationIdFilter(logging.Filter):
73
+ """Filter to inject correlation_id into log records."""
74
+
75
+ def filter(self, record):
76
+ """Add correlation_id to the log record."""
77
+ record.correlation_id = get_correlation_id() or "no-correlation-id"
78
+ return True
79
+
80
+
81
+ class ColoredFormatter(logging.Formatter):
82
+ """Custom formatter that adds colors to log output using ANSI codes."""
83
+
84
+ def __init__(self, fmt: Optional[str] = None, use_colors: bool = True):
85
+ """
86
+ Initialize the colored formatter.
87
+
88
+ Args:
89
+ fmt: The format string for log messages
90
+ use_colors: Whether to use ANSI color codes
91
+ """
92
+ super().__init__(fmt)
93
+ self.use_colors = use_colors
94
+
95
+ def format(self, record: logging.LogRecord) -> str:
96
+ """Format the log record with colors."""
97
+ if not self.use_colors:
98
+ return super().format(record)
99
+
100
+ # Get the color for this log level
101
+ level_color = COLORS.get(record.levelname, "")
102
+
103
+ # Save the original values
104
+ orig_levelname = record.levelname
105
+ orig_msg = record.msg
106
+
107
+ # Color the level name
108
+ record.levelname = f"{level_color}{record.levelname}{RESET}"
109
+
110
+ # Format the message
111
+ formatted = super().format(record)
112
+
113
+ # Restore original values
114
+ record.levelname = orig_levelname
115
+ record.msg = orig_msg
116
+
117
+ # Add colors to specific parts of the formatted message
118
+ # Color the correlation ID if present
119
+ if hasattr(record, "correlation_id"):
120
+ formatted = formatted.replace(
121
+ f"[{record.correlation_id}]",
122
+ f"{MAGENTA}[{record.correlation_id}]{RESET}",
123
+ )
124
+
125
+ # Color the timestamp (first part before |)
126
+ parts = formatted.split("|", 1)
127
+ if len(parts) > 1:
128
+ timestamp_part = parts[0].split("]", 1)
129
+ if len(timestamp_part) > 1:
130
+ # Has correlation ID
131
+ formatted = (
132
+ timestamp_part[0]
133
+ + "]"
134
+ + f"{GREY}{timestamp_part[1]}{RESET}|"
135
+ + parts[1]
136
+ )
137
+ else:
138
+ # No correlation ID
139
+ formatted = f"{GREY}{parts[0]}{RESET}|{parts[1]}"
140
+
141
+ return formatted
142
+
143
+
144
+ def configure_logging(
145
+ format_string: Optional[str] = None,
146
+ level: str = "INFO",
147
+ sink: Union[os.PathLike[str], TextIO, BinaryIO] = sys.stderr,
148
+ include_correlation_id: bool = True,
149
+ use_colors: bool = True,
150
+ ) -> logging.Logger:
151
+ """
152
+ Configure the logger with custom settings using Python's standard logging module.
153
+
154
+ Args:
155
+ format_string (Optional[str]): The format string for log messages.
156
+ If None, a default format will be used.
157
+ level (str): The minimum logging level. Default: "INFO"
158
+ sink: Where to send the log. Default: sys.stderr
159
+ Can be a file path, TextIO, or BinaryIO.
160
+ include_correlation_id (bool): Whether to include correlation ID in log messages.
161
+ Default: True
162
+ use_colors (bool): Whether to use colored output for console logging.
163
+ Automatically disabled for file output. Default: True
164
+
165
+ Returns:
166
+ logging.Logger: The configured logger object
167
+
168
+ Example:
169
+ ```python
170
+ from airia import configure_logging
171
+
172
+ # Basic configuration with colors
173
+ logger = configure_logging()
174
+
175
+ # Disable colors
176
+ logger = configure_logging(use_colors=False)
177
+
178
+ # File-based logging (colors automatically disabled)
179
+ file_logger = configure_logging(
180
+ level="DEBUG",
181
+ sink="app.log",
182
+ include_correlation_id=True
183
+ )
184
+
185
+ # Console output
186
+ console_logger = configure_logging(
187
+ level="INFO",
188
+ sink=sys.stdout
189
+ )
190
+ ```
191
+ """
192
+ logger = logging.getLogger("airia")
193
+ logger.handlers.clear()
194
+ logger.setLevel(getattr(logging, level.upper(), logging.INFO))
195
+
196
+ # Determine if this is file or console output
197
+ is_file_output = isinstance(sink, (str, os.PathLike))
198
+
199
+ # Create handler based on sink type
200
+ if is_file_output:
201
+ handler = logging.FileHandler(str(sink))
202
+ # Disable colors for file output
203
+ use_colors = False
204
+ elif hasattr(sink, "write"):
205
+ handler = logging.StreamHandler(sink) # type: ignore
206
+ else:
207
+ handler = logging.StreamHandler(sys.stderr)
208
+
209
+ # Create formatter
210
+ if format_string is None:
211
+ if include_correlation_id:
212
+ format_string = "[%(correlation_id)s] %(asctime)s | %(levelname)-8s | %(name)s:%(funcName)s:%(lineno)d - %(message)s"
213
+ else:
214
+ format_string = "%(asctime)s | %(levelname)-8s | %(name)s:%(funcName)s:%(lineno)d - %(message)s"
215
+
216
+ # Use ColoredFormatter for console, regular Formatter for files
217
+ if use_colors and not is_file_output:
218
+ formatter = ColoredFormatter(format_string, use_colors=True)
219
+ else:
220
+ formatter = logging.Formatter(format_string)
221
+
222
+ handler.setFormatter(formatter)
223
+
224
+ # Add correlation ID filter if enabled
225
+ if include_correlation_id:
226
+ handler.addFilter(CorrelationIdFilter())
227
+
228
+ logger.addHandler(handler)
229
+
230
+ return logger
231
+
232
+
233
+ # Example usage:
234
+ if __name__ == "__main__":
235
+ # Basic configuration (uses sys.stderr with colors)
236
+ log = configure_logging()
237
+ log.debug("Debug message")
238
+ log.info("Basic logging configured successfully")
239
+ log.warning("This is a warning")
240
+ log.error("This is an error")
241
+
242
+ # Set a correlation ID
243
+ set_correlation_id("request-123")
244
+ log.info("This log has a correlation ID")
245
+
246
+ # Change correlation ID
247
+ set_correlation_id("request-456")
248
+ log.info("This log has a different correlation ID")
249
+
250
+ # Use auto-generated correlation ID
251
+ set_correlation_id()
252
+ log.info("This log has an auto-generated correlation ID")
253
+
254
+ # File-based logging (colors automatically disabled)
255
+ file_log = configure_logging(
256
+ level="DEBUG",
257
+ sink="app.log",
258
+ )
259
+ file_log.debug("File logging configured successfully")
260
+
261
+ # Stream-based logging with colors
262
+ stream_log = configure_logging(level="INFO", sink=sys.stdout)
263
+ stream_log.info("Stream logging configured successfully")
264
+
265
+ # Disable colors explicitly
266
+ no_color_log = configure_logging(use_colors=False)
267
+ no_color_log.info("Logging without colors")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: airia
3
- Version: 0.1.34
3
+ Version: 0.1.35
4
4
  Summary: Python SDK for Airia API
5
5
  Author-email: Airia LLC <support@airia.com>
6
6
  License: MIT
@@ -16,8 +16,7 @@ Requires-Python: >=3.9
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: requests>=2.32.3
19
- Requires-Dist: aiohttp>=3.11.14
20
- Requires-Dist: loguru>=0.7.3
19
+ Requires-Dist: aiohttp>=3.13.3
21
20
  Requires-Dist: pydantic>=2.11.0
22
21
  Provides-Extra: anthropic
23
22
  Requires-Dist: anthropic>=0.49.0; extra == "anthropic"
@@ -189,13 +188,20 @@ This will create both wheel and source distribution in the `dist/` directory.
189
188
  - Core dependencies:
190
189
  - requests
191
190
  - aiohttp
192
- - loguru
193
191
  - pydantic
194
192
 
195
193
  - Optional dependencies:
196
194
  - OpenAI gateway: `openai>=1.74.0`
197
195
  - Anthropic gateway: `anthropic>=0.49.0`
198
196
 
197
+ ## Features
198
+
199
+ - **Synchronous and Asynchronous Clients**: Choose between sync (`AiriaClient`) or async (`AiriaAsyncClient`) based on your needs
200
+ - **Colored Logging**: Built-in colored console logging using ANSI codes (no additional dependencies)
201
+ - **Correlation ID Tracking**: Automatic request tracing with correlation IDs
202
+ - **Gateway Support**: Optional OpenAI and Anthropic gateway integration
203
+ - **Type Safety**: Full type hints and Pydantic models for request/response validation
204
+
199
205
  ## Development
200
206
 
201
207
  To run tests (make sure you have development dependencies installed):
@@ -1,6 +1,5 @@
1
1
  requests>=2.32.3
2
- aiohttp>=3.11.14
3
- loguru>=0.7.3
2
+ aiohttp>=3.13.3
4
3
  pydantic>=2.11.0
5
4
 
6
5
  [all]
@@ -4,19 +4,14 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "airia"
7
- version = "0.1.34"
7
+ version = "0.1.35"
8
8
  description = "Python SDK for Airia API"
9
9
  license = { text = "MIT" }
10
10
  authors = [{ name = "Airia LLC", email = "support@airia.com" }]
11
11
 
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.9"
14
- dependencies = [
15
- "requests>=2.32.3",
16
- "aiohttp>=3.11.14",
17
- "loguru>=0.7.3",
18
- "pydantic>=2.11.0",
19
- ]
14
+ dependencies = ["requests>=2.32.3", "aiohttp>=3.13.3", "pydantic>=2.11.0"]
20
15
  classifiers = [
21
16
  "Programming Language :: Python :: 3",
22
17
  "Programming Language :: Python :: 3.9",
@@ -1,6 +0,0 @@
1
- from .logs import configure_logging
2
- from .client import AiriaClient, AiriaAsyncClient
3
- from .exceptions import AiriaAPIError
4
-
5
- __version__ = "0.1.0"
6
- __all__ = ["AiriaClient", "AiriaAsyncClient", "AiriaAPIError", "configure_logging"]
@@ -1,137 +0,0 @@
1
- import os
2
- import sys
3
- import uuid
4
- from contextvars import ContextVar
5
- from typing import BinaryIO, Optional, TextIO, Union
6
-
7
- import loguru
8
- from loguru import logger
9
-
10
- # Create a context variable to store correlation ID
11
- correlation_id_context: ContextVar[str] = ContextVar("correlation_id", default="")
12
-
13
-
14
- def get_correlation_id() -> str:
15
- """
16
- Get the current correlation ID from context or return empty string if not set.
17
-
18
- Returns:
19
- str: The current correlation ID
20
- """
21
- return correlation_id_context.get()
22
-
23
-
24
- def set_correlation_id(correlation_id: Optional[str] = None) -> str:
25
- """
26
- Set a correlation ID in the current context.
27
-
28
- Args:
29
- correlation_id (Optional[str]): The correlation ID to set. If None, a new UUID will be generated.
30
-
31
- Returns:
32
- str: The correlation ID that was set
33
- """
34
- if correlation_id is None:
35
- correlation_id = str(uuid.uuid4())
36
- correlation_id_context.set(correlation_id)
37
- return correlation_id
38
-
39
-
40
- def clear_correlation_id() -> None:
41
- """Clear the correlation ID from the current context."""
42
- correlation_id_context.set("")
43
-
44
-
45
- # Define a function to be used as a filter to inject correlation_id
46
- def correlation_id_filter(record):
47
- record["extra"]["correlation_id"] = get_correlation_id() or "no-correlation-id"
48
- return record
49
-
50
-
51
- def configure_logging(
52
- format_string: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
53
- level: str = "INFO",
54
- sink: Union[os.PathLike[str], TextIO, BinaryIO] = sys.stderr,
55
- rotation: Optional[str] = None,
56
- retention: Optional[str] = None,
57
- include_correlation_id: bool = True,
58
- ) -> "loguru.Logger":
59
- """
60
- Configure the loguru logger with custom settings.
61
- Check [Loguru Documentation](https://loguru.readthedocs.io/en/stable/api/logger.html) for more details.
62
-
63
- Args:
64
- format_string (str): The format string for log messages.
65
- level (str): The minimum logging level. Default: "INFO"
66
- sink: Where to send the log. Default: sys.stderr
67
- rotation (str, optional): When to rotate the log file.
68
- Example: "10 MB", "1 day"
69
- Only used when sink is a file path.
70
- retention (str, optional): How long to keep log files.
71
- Example: "1 week", "10 days"
72
- Only used when sink is a file path.
73
- include_correlation_id (bool): Whether to include correlation ID in log messages.
74
- Default: True
75
-
76
- Returns:
77
- The configured logger object
78
- """
79
- # Remove any existing handlers
80
- logger.remove()
81
-
82
- # Modify format string to include correlation ID if requested
83
- if include_correlation_id:
84
- format_string = "<magenta>[{extra[correlation_id]}]</magenta> " + format_string
85
-
86
- # Add rotation and retention only for file paths
87
- kwargs = {
88
- "format": format_string,
89
- "level": level,
90
- "filter": correlation_id_filter, # Add the filter for each handler
91
- }
92
-
93
- if isinstance(sink, (str, os.PathLike)):
94
- if rotation is not None:
95
- kwargs["rotation"] = rotation
96
- if retention is not None:
97
- kwargs["retention"] = retention
98
-
99
- # Add the new handler
100
- logger.add(sink, **kwargs)
101
-
102
- return logger
103
-
104
-
105
- # Example usage:
106
- if __name__ == "__main__":
107
- # Basic configuration (uses sys.stderr)
108
- log = configure_logging()
109
- log.info("Basic logging configured successfully")
110
-
111
- # Set a correlation ID
112
- set_correlation_id("request-123")
113
- log.info("This log has a correlation ID")
114
-
115
- # Change correlation ID
116
- set_correlation_id("request-456")
117
- log.info("This log has a different correlation ID")
118
-
119
- # Use auto-generated correlation ID
120
- set_correlation_id()
121
- log.info("This log has an auto-generated correlation ID")
122
-
123
- # File-based logging with rotation and retention
124
- file_log = configure_logging(
125
- format_string="[{time:YYYY-MM-DD HH:mm:ss}] [{level}] {message}",
126
- level="DEBUG",
127
- sink="app.log",
128
- rotation="10 MB",
129
- retention="1 week",
130
- )
131
- file_log.debug("File logging configured successfully")
132
-
133
- # Stream-based logging
134
- stream_log = configure_logging(
135
- format_string="[{time:HH:mm:ss}] {message}", level="INFO", sink=sys.stdout
136
- )
137
- stream_log.info("Stream logging configured successfully")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes