lucidicai 2.1.2__py3-none-any.whl → 2.1.3__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.
- lucidicai/__init__.py +1 -1
- lucidicai/api/client.py +231 -92
- lucidicai/sdk/features/dataset.py +23 -237
- lucidicai/sdk/init.py +69 -0
- lucidicai/utils/images.py +3 -3
- lucidicai/utils/queue.py +2 -2
- {lucidicai-2.1.2.dist-info → lucidicai-2.1.3.dist-info}/METADATA +1 -1
- {lucidicai-2.1.2.dist-info → lucidicai-2.1.3.dist-info}/RECORD +10 -10
- {lucidicai-2.1.2.dist-info → lucidicai-2.1.3.dist-info}/WHEEL +0 -0
- {lucidicai-2.1.2.dist-info → lucidicai-2.1.3.dist-info}/top_level.txt +0 -0
lucidicai/__init__.py
CHANGED
|
@@ -297,7 +297,7 @@ get_error_history = error_boundary.get_error_history
|
|
|
297
297
|
clear_error_history = error_boundary.clear_error_history
|
|
298
298
|
|
|
299
299
|
# Version
|
|
300
|
-
__version__ = "2.1.
|
|
300
|
+
__version__ = "2.1.3"
|
|
301
301
|
|
|
302
302
|
# Apply error boundary wrapping to all SDK functions
|
|
303
303
|
from .sdk.error_boundary import wrap_sdk_function
|
lucidicai/api/client.py
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
"""Pure HTTP client for Lucidic API communication.
|
|
2
2
|
|
|
3
|
-
This module contains only the HTTP client logic
|
|
4
|
-
|
|
3
|
+
This module contains only the HTTP client logic using httpx,
|
|
4
|
+
supporting both synchronous and asynchronous operations.
|
|
5
5
|
"""
|
|
6
|
-
import
|
|
6
|
+
import asyncio
|
|
7
|
+
from datetime import datetime, timezone
|
|
7
8
|
from typing import Any, Dict, Optional
|
|
8
|
-
from urllib.parse import urlencode
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
from requests.adapters import HTTPAdapter
|
|
12
|
-
from urllib3.util import Retry
|
|
10
|
+
import httpx
|
|
13
11
|
|
|
14
12
|
from ..core.config import SDKConfig, get_config
|
|
15
13
|
from ..core.errors import APIKeyVerificationError
|
|
@@ -17,7 +15,7 @@ from ..utils.logger import debug, info, warning, error, mask_sensitive, truncate
|
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
class HttpClient:
|
|
20
|
-
"""HTTP client for API communication."""
|
|
18
|
+
"""HTTP client for API communication with sync and async support."""
|
|
21
19
|
|
|
22
20
|
def __init__(self, config: Optional[SDKConfig] = None):
|
|
23
21
|
"""Initialize the HTTP client.
|
|
@@ -28,36 +26,26 @@ class HttpClient:
|
|
|
28
26
|
self.config = config or get_config()
|
|
29
27
|
self.base_url = self.config.network.base_url
|
|
30
28
|
|
|
31
|
-
#
|
|
32
|
-
self.
|
|
29
|
+
# Build default headers
|
|
30
|
+
self._headers = self._build_headers()
|
|
33
31
|
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
status_forcelist=[502, 503, 504],
|
|
39
|
-
allowed_methods=["GET", "POST", "PUT", "DELETE"],
|
|
40
|
-
)
|
|
32
|
+
# Transport configuration for connection pooling and retries
|
|
33
|
+
self._transport_kwargs = {
|
|
34
|
+
"retries": self.config.network.max_retries,
|
|
35
|
+
}
|
|
41
36
|
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
pool_maxsize=self.config.network.connection_pool_maxsize
|
|
37
|
+
# Connection limits for pooling
|
|
38
|
+
self._limits = httpx.Limits(
|
|
39
|
+
max_connections=self.config.network.connection_pool_maxsize,
|
|
40
|
+
max_keepalive_connections=self.config.network.connection_pool_size,
|
|
47
41
|
)
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
self.
|
|
51
|
-
|
|
52
|
-
# Set headers
|
|
53
|
-
self._update_headers()
|
|
54
|
-
|
|
55
|
-
# Verify API key if configured
|
|
56
|
-
if self.config.api_key:
|
|
57
|
-
self._verify_api_key()
|
|
43
|
+
# Lazy-initialized clients
|
|
44
|
+
self._sync_client: Optional[httpx.Client] = None
|
|
45
|
+
self._async_client: Optional[httpx.AsyncClient] = None
|
|
58
46
|
|
|
59
|
-
def
|
|
60
|
-
"""
|
|
47
|
+
def _build_headers(self) -> Dict[str, str]:
|
|
48
|
+
"""Build default headers for requests."""
|
|
61
49
|
headers = {
|
|
62
50
|
"User-Agent": "lucidic-sdk/2.0",
|
|
63
51
|
"Content-Type": "application/json"
|
|
@@ -69,24 +57,91 @@ class HttpClient:
|
|
|
69
57
|
if self.config.agent_id:
|
|
70
58
|
headers["x-agent-id"] = self.config.agent_id
|
|
71
59
|
|
|
72
|
-
|
|
60
|
+
return headers
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def sync_client(self) -> httpx.Client:
|
|
64
|
+
"""Get or create the synchronous HTTP client."""
|
|
65
|
+
if self._sync_client is None or self._sync_client.is_closed:
|
|
66
|
+
transport = httpx.HTTPTransport(**self._transport_kwargs)
|
|
67
|
+
self._sync_client = httpx.Client(
|
|
68
|
+
base_url=self.base_url,
|
|
69
|
+
headers=self._headers,
|
|
70
|
+
timeout=httpx.Timeout(self.config.network.timeout),
|
|
71
|
+
limits=self._limits,
|
|
72
|
+
transport=transport,
|
|
73
|
+
)
|
|
74
|
+
return self._sync_client
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def async_client(self) -> httpx.AsyncClient:
|
|
78
|
+
"""Get or create the asynchronous HTTP client."""
|
|
79
|
+
if self._async_client is None or self._async_client.is_closed:
|
|
80
|
+
transport = httpx.AsyncHTTPTransport(**self._transport_kwargs)
|
|
81
|
+
self._async_client = httpx.AsyncClient(
|
|
82
|
+
base_url=self.base_url,
|
|
83
|
+
headers=self._headers,
|
|
84
|
+
timeout=httpx.Timeout(self.config.network.timeout),
|
|
85
|
+
limits=self._limits,
|
|
86
|
+
transport=transport,
|
|
87
|
+
)
|
|
88
|
+
return self._async_client
|
|
89
|
+
|
|
90
|
+
def _add_timestamp(self, data: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
|
91
|
+
"""Add current_time to request data."""
|
|
92
|
+
if data is None:
|
|
93
|
+
data = {}
|
|
94
|
+
data["current_time"] = datetime.now(timezone.utc).isoformat()
|
|
95
|
+
return data
|
|
73
96
|
|
|
74
|
-
def
|
|
75
|
-
"""
|
|
76
|
-
|
|
97
|
+
def _handle_response(self, response: httpx.Response) -> Dict[str, Any]:
|
|
98
|
+
"""Handle HTTP response and parse JSON.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
response: httpx Response object
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Response data as dictionary
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
APIKeyVerificationError: On 401 Unauthorized responses
|
|
108
|
+
httpx.HTTPStatusError: On other HTTP errors
|
|
109
|
+
"""
|
|
110
|
+
# Log and raise for HTTP errors
|
|
111
|
+
if not response.is_success:
|
|
112
|
+
try:
|
|
113
|
+
error_data = response.json()
|
|
114
|
+
error_msg = error_data.get('detail', response.text)
|
|
115
|
+
except Exception:
|
|
116
|
+
error_msg = response.text
|
|
117
|
+
|
|
118
|
+
error(f"[HTTP] Error {response.status_code}: {error_msg}")
|
|
119
|
+
|
|
120
|
+
# Raise specific error for authentication/authorization failures
|
|
121
|
+
if response.status_code in (401, 403):
|
|
122
|
+
raise APIKeyVerificationError(f"Authentication failed: {error_msg}")
|
|
123
|
+
|
|
124
|
+
response.raise_for_status()
|
|
125
|
+
|
|
126
|
+
# Parse JSON response
|
|
77
127
|
try:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
128
|
+
data = response.json()
|
|
129
|
+
except ValueError:
|
|
130
|
+
# For empty responses (like verifyapikey), return success
|
|
131
|
+
if response.status_code == 200 and not response.text:
|
|
132
|
+
data = {"success": True}
|
|
133
|
+
else:
|
|
134
|
+
# Return text if not JSON
|
|
135
|
+
data = {"response": response.text}
|
|
136
|
+
|
|
137
|
+
debug(f"[HTTP] Response ({response.status_code}): {truncate_data(data)}")
|
|
138
|
+
|
|
139
|
+
return data
|
|
140
|
+
|
|
141
|
+
# ==================== Synchronous Methods ====================
|
|
87
142
|
|
|
88
143
|
def get(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
89
|
-
"""Make a GET request.
|
|
144
|
+
"""Make a synchronous GET request.
|
|
90
145
|
|
|
91
146
|
Args:
|
|
92
147
|
endpoint: API endpoint (without base URL)
|
|
@@ -98,7 +153,7 @@ class HttpClient:
|
|
|
98
153
|
return self.request("GET", endpoint, params=params)
|
|
99
154
|
|
|
100
155
|
def post(self, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
101
|
-
"""Make a POST request.
|
|
156
|
+
"""Make a synchronous POST request.
|
|
102
157
|
|
|
103
158
|
Args:
|
|
104
159
|
endpoint: API endpoint (without base URL)
|
|
@@ -107,15 +162,11 @@ class HttpClient:
|
|
|
107
162
|
Returns:
|
|
108
163
|
Response data as dictionary
|
|
109
164
|
"""
|
|
110
|
-
|
|
111
|
-
from datetime import datetime, timezone
|
|
112
|
-
if data is None:
|
|
113
|
-
data = {}
|
|
114
|
-
data["current_time"] = datetime.now(timezone.utc).isoformat()
|
|
165
|
+
data = self._add_timestamp(data)
|
|
115
166
|
return self.request("POST", endpoint, json=data)
|
|
116
167
|
|
|
117
168
|
def put(self, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
118
|
-
"""Make a PUT request.
|
|
169
|
+
"""Make a synchronous PUT request.
|
|
119
170
|
|
|
120
171
|
Args:
|
|
121
172
|
endpoint: API endpoint (without base URL)
|
|
@@ -124,15 +175,11 @@ class HttpClient:
|
|
|
124
175
|
Returns:
|
|
125
176
|
Response data as dictionary
|
|
126
177
|
"""
|
|
127
|
-
|
|
128
|
-
from datetime import datetime, timezone
|
|
129
|
-
if data is None:
|
|
130
|
-
data = {}
|
|
131
|
-
data["current_time"] = datetime.now(timezone.utc).isoformat()
|
|
178
|
+
data = self._add_timestamp(data)
|
|
132
179
|
return self.request("PUT", endpoint, json=data)
|
|
133
180
|
|
|
134
181
|
def delete(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
135
|
-
"""Make a DELETE request.
|
|
182
|
+
"""Make a synchronous DELETE request.
|
|
136
183
|
|
|
137
184
|
Args:
|
|
138
185
|
endpoint: API endpoint (without base URL)
|
|
@@ -151,68 +198,160 @@ class HttpClient:
|
|
|
151
198
|
json: Optional[Dict[str, Any]] = None,
|
|
152
199
|
**kwargs
|
|
153
200
|
) -> Dict[str, Any]:
|
|
154
|
-
"""Make
|
|
201
|
+
"""Make a synchronous HTTP request.
|
|
155
202
|
|
|
156
203
|
Args:
|
|
157
204
|
method: HTTP method
|
|
158
205
|
endpoint: API endpoint (without base URL)
|
|
159
206
|
params: Query parameters
|
|
160
207
|
json: Request body (for POST/PUT)
|
|
161
|
-
**kwargs: Additional arguments for
|
|
208
|
+
**kwargs: Additional arguments for httpx
|
|
162
209
|
|
|
163
210
|
Returns:
|
|
164
211
|
Response data as dictionary
|
|
165
212
|
|
|
166
213
|
Raises:
|
|
167
|
-
|
|
214
|
+
httpx.HTTPError: On HTTP errors
|
|
168
215
|
"""
|
|
169
|
-
url = f"
|
|
216
|
+
url = f"/{endpoint}"
|
|
170
217
|
|
|
171
218
|
# Log request details
|
|
172
|
-
debug(f"[HTTP] {method} {url}")
|
|
219
|
+
debug(f"[HTTP] {method} {self.base_url}{url}")
|
|
173
220
|
if params:
|
|
174
221
|
debug(f"[HTTP] Query params: {mask_sensitive(params)}")
|
|
175
222
|
if json:
|
|
176
223
|
debug(f"[HTTP] Request body: {truncate_data(mask_sensitive(json))}")
|
|
177
224
|
|
|
178
|
-
response = self.
|
|
225
|
+
response = self.sync_client.request(
|
|
179
226
|
method=method,
|
|
180
227
|
url=url,
|
|
181
228
|
params=params,
|
|
182
229
|
json=json,
|
|
183
|
-
timeout=self.config.network.timeout,
|
|
184
230
|
**kwargs
|
|
185
231
|
)
|
|
186
232
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
233
|
+
return self._handle_response(response)
|
|
234
|
+
|
|
235
|
+
# ==================== Asynchronous Methods ====================
|
|
236
|
+
|
|
237
|
+
async def aget(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
238
|
+
"""Make an asynchronous GET request.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
endpoint: API endpoint (without base URL)
|
|
242
|
+
params: Query parameters
|
|
195
243
|
|
|
196
|
-
|
|
244
|
+
Returns:
|
|
245
|
+
Response data as dictionary
|
|
246
|
+
"""
|
|
247
|
+
return await self.arequest("GET", endpoint, params=params)
|
|
248
|
+
|
|
249
|
+
async def apost(self, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
250
|
+
"""Make an asynchronous POST request.
|
|
197
251
|
|
|
198
|
-
|
|
252
|
+
Args:
|
|
253
|
+
endpoint: API endpoint (without base URL)
|
|
254
|
+
data: Request body data
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
Response data as dictionary
|
|
258
|
+
"""
|
|
259
|
+
data = self._add_timestamp(data)
|
|
260
|
+
return await self.arequest("POST", endpoint, json=data)
|
|
261
|
+
|
|
262
|
+
async def aput(self, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
263
|
+
"""Make an asynchronous PUT request.
|
|
199
264
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
data
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
265
|
+
Args:
|
|
266
|
+
endpoint: API endpoint (without base URL)
|
|
267
|
+
data: Request body data
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
Response data as dictionary
|
|
271
|
+
"""
|
|
272
|
+
data = self._add_timestamp(data)
|
|
273
|
+
return await self.arequest("PUT", endpoint, json=data)
|
|
274
|
+
|
|
275
|
+
async def adelete(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
276
|
+
"""Make an asynchronous DELETE request.
|
|
210
277
|
|
|
211
|
-
|
|
278
|
+
Args:
|
|
279
|
+
endpoint: API endpoint (without base URL)
|
|
280
|
+
params: Query parameters
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
Response data as dictionary
|
|
284
|
+
"""
|
|
285
|
+
return await self.arequest("DELETE", endpoint, params=params)
|
|
286
|
+
|
|
287
|
+
async def arequest(
|
|
288
|
+
self,
|
|
289
|
+
method: str,
|
|
290
|
+
endpoint: str,
|
|
291
|
+
params: Optional[Dict[str, Any]] = None,
|
|
292
|
+
json: Optional[Dict[str, Any]] = None,
|
|
293
|
+
**kwargs
|
|
294
|
+
) -> Dict[str, Any]:
|
|
295
|
+
"""Make an asynchronous HTTP request.
|
|
212
296
|
|
|
213
|
-
|
|
297
|
+
Args:
|
|
298
|
+
method: HTTP method
|
|
299
|
+
endpoint: API endpoint (without base URL)
|
|
300
|
+
params: Query parameters
|
|
301
|
+
json: Request body (for POST/PUT)
|
|
302
|
+
**kwargs: Additional arguments for httpx
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Response data as dictionary
|
|
306
|
+
|
|
307
|
+
Raises:
|
|
308
|
+
httpx.HTTPError: On HTTP errors
|
|
309
|
+
"""
|
|
310
|
+
url = f"/{endpoint}"
|
|
311
|
+
|
|
312
|
+
# Log request details
|
|
313
|
+
debug(f"[HTTP] {method} {self.base_url}{url}")
|
|
314
|
+
if params:
|
|
315
|
+
debug(f"[HTTP] Query params: {mask_sensitive(params)}")
|
|
316
|
+
if json:
|
|
317
|
+
debug(f"[HTTP] Request body: {truncate_data(mask_sensitive(json))}")
|
|
318
|
+
|
|
319
|
+
response = await self.async_client.request(
|
|
320
|
+
method=method,
|
|
321
|
+
url=url,
|
|
322
|
+
params=params,
|
|
323
|
+
json=json,
|
|
324
|
+
**kwargs
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
return self._handle_response(response)
|
|
328
|
+
|
|
329
|
+
# ==================== Lifecycle Methods ====================
|
|
214
330
|
|
|
215
331
|
def close(self) -> None:
|
|
216
|
-
"""Close the HTTP
|
|
217
|
-
if self.
|
|
218
|
-
self.
|
|
332
|
+
"""Close the synchronous HTTP client."""
|
|
333
|
+
if self._sync_client is not None and not self._sync_client.is_closed:
|
|
334
|
+
self._sync_client.close()
|
|
335
|
+
self._sync_client = None
|
|
336
|
+
|
|
337
|
+
async def aclose(self) -> None:
|
|
338
|
+
"""Close the asynchronous HTTP client."""
|
|
339
|
+
if self._async_client is not None and not self._async_client.is_closed:
|
|
340
|
+
await self._async_client.aclose()
|
|
341
|
+
self._async_client = None
|
|
342
|
+
|
|
343
|
+
def __enter__(self) -> "HttpClient":
|
|
344
|
+
"""Context manager entry for sync client."""
|
|
345
|
+
return self
|
|
346
|
+
|
|
347
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
348
|
+
"""Context manager exit for sync client."""
|
|
349
|
+
self.close()
|
|
350
|
+
|
|
351
|
+
async def __aenter__(self) -> "HttpClient":
|
|
352
|
+
"""Async context manager entry."""
|
|
353
|
+
return self
|
|
354
|
+
|
|
355
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
356
|
+
"""Async context manager exit."""
|
|
357
|
+
await self.aclose()
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import logging
|
|
3
2
|
from typing import Optional, Dict, List, Any
|
|
4
|
-
from dotenv import load_dotenv
|
|
5
|
-
|
|
6
|
-
from ...core.errors import APIKeyVerificationError
|
|
7
3
|
|
|
8
4
|
logger = logging.getLogger("Lucidic")
|
|
9
5
|
|
|
@@ -36,37 +32,15 @@ def get_dataset(
|
|
|
36
32
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
37
33
|
ValueError: If dataset_id is not provided.
|
|
38
34
|
"""
|
|
39
|
-
load_dotenv()
|
|
40
|
-
|
|
41
35
|
# Validation
|
|
42
36
|
if not dataset_id:
|
|
43
37
|
raise ValueError("Dataset ID is required")
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
if api_key is None:
|
|
47
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
48
|
-
if api_key is None:
|
|
49
|
-
raise APIKeyVerificationError(
|
|
50
|
-
"Make sure to either pass your API key into get_dataset() or set the LUCIDIC_API_KEY environment variable."
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
if agent_id is None:
|
|
54
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
55
|
-
if agent_id is None:
|
|
56
|
-
raise APIKeyVerificationError(
|
|
57
|
-
"Lucidic agent ID not specified. Make sure to either pass your agent ID into get_dataset() or set the LUCIDIC_AGENT_ID environment variable."
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
# Get HTTP client
|
|
61
|
-
from ..init import get_http
|
|
62
|
-
from ...core.config import SDKConfig
|
|
63
|
-
from ...api.client import HttpClient
|
|
39
|
+
from ..init import ensure_http_and_resources, get_http
|
|
64
40
|
|
|
41
|
+
# Ensure HTTP client is initialized and stored in SDK state
|
|
42
|
+
ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
65
43
|
http = get_http()
|
|
66
|
-
if not http:
|
|
67
|
-
# Create a new HTTP client if needed
|
|
68
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
69
|
-
http = HttpClient(config)
|
|
70
44
|
|
|
71
45
|
# Make request to get dataset
|
|
72
46
|
response = http.get('getdataset', {'dataset_id': dataset_id})
|
|
@@ -126,31 +100,9 @@ def list_datasets(
|
|
|
126
100
|
Raises:
|
|
127
101
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
128
102
|
"""
|
|
129
|
-
from ..init import
|
|
130
|
-
from ...core.config import SDKConfig
|
|
131
|
-
from ...api.client import HttpClient
|
|
132
|
-
|
|
133
|
-
# Get or create resources
|
|
134
|
-
resources = get_resources()
|
|
135
|
-
if not resources or 'datasets' not in resources:
|
|
136
|
-
load_dotenv()
|
|
137
|
-
|
|
138
|
-
# Get credentials
|
|
139
|
-
if api_key is None:
|
|
140
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
141
|
-
if api_key is None:
|
|
142
|
-
raise APIKeyVerificationError(
|
|
143
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
if agent_id is None:
|
|
147
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
148
|
-
|
|
149
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
150
|
-
http = HttpClient(config)
|
|
151
|
-
from ...api.resources.dataset import DatasetResource
|
|
152
|
-
resources = {'datasets': DatasetResource(http)}
|
|
103
|
+
from ..init import ensure_http_and_resources
|
|
153
104
|
|
|
105
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
154
106
|
return resources['datasets'].list_datasets(agent_id)
|
|
155
107
|
|
|
156
108
|
|
|
@@ -179,30 +131,9 @@ def create_dataset(
|
|
|
179
131
|
Raises:
|
|
180
132
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
181
133
|
"""
|
|
182
|
-
from ..init import
|
|
183
|
-
from ...core.config import SDKConfig
|
|
184
|
-
from ...api.client import HttpClient
|
|
185
|
-
|
|
186
|
-
# Get or create resources
|
|
187
|
-
resources = get_resources()
|
|
188
|
-
if not resources or 'datasets' not in resources:
|
|
189
|
-
load_dotenv()
|
|
190
|
-
|
|
191
|
-
if api_key is None:
|
|
192
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
193
|
-
if api_key is None:
|
|
194
|
-
raise APIKeyVerificationError(
|
|
195
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
if agent_id is None:
|
|
199
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
200
|
-
|
|
201
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
202
|
-
http = HttpClient(config)
|
|
203
|
-
from ...api.resources.dataset import DatasetResource
|
|
204
|
-
resources = {'datasets': DatasetResource(http)}
|
|
134
|
+
from ..init import ensure_http_and_resources
|
|
205
135
|
|
|
136
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
206
137
|
return resources['datasets'].create_dataset(name, description, tags, suggested_flag_config, agent_id)
|
|
207
138
|
|
|
208
139
|
|
|
@@ -233,29 +164,9 @@ def update_dataset(
|
|
|
233
164
|
Raises:
|
|
234
165
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
235
166
|
"""
|
|
236
|
-
from ..init import
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
# Get or create resources
|
|
241
|
-
resources = get_resources()
|
|
242
|
-
if not resources or 'datasets' not in resources:
|
|
243
|
-
load_dotenv()
|
|
244
|
-
|
|
245
|
-
if api_key is None:
|
|
246
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
247
|
-
if api_key is None:
|
|
248
|
-
raise APIKeyVerificationError(
|
|
249
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
if agent_id is None:
|
|
253
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
254
|
-
|
|
255
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
256
|
-
http = HttpClient(config)
|
|
257
|
-
from ...api.resources.dataset import DatasetResource
|
|
258
|
-
resources = {'datasets': DatasetResource(http)}
|
|
167
|
+
from ..init import ensure_http_and_resources
|
|
168
|
+
|
|
169
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
259
170
|
|
|
260
171
|
kwargs = {}
|
|
261
172
|
if name is not None:
|
|
@@ -289,30 +200,9 @@ def delete_dataset(
|
|
|
289
200
|
Raises:
|
|
290
201
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
291
202
|
"""
|
|
292
|
-
from ..init import
|
|
293
|
-
from ...core.config import SDKConfig
|
|
294
|
-
from ...api.client import HttpClient
|
|
295
|
-
|
|
296
|
-
# Get or create resources
|
|
297
|
-
resources = get_resources()
|
|
298
|
-
if not resources or 'datasets' not in resources:
|
|
299
|
-
load_dotenv()
|
|
300
|
-
|
|
301
|
-
if api_key is None:
|
|
302
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
303
|
-
if api_key is None:
|
|
304
|
-
raise APIKeyVerificationError(
|
|
305
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
306
|
-
)
|
|
307
|
-
|
|
308
|
-
if agent_id is None:
|
|
309
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
310
|
-
|
|
311
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
312
|
-
http = HttpClient(config)
|
|
313
|
-
from ...api.resources.dataset import DatasetResource
|
|
314
|
-
resources = {'datasets': DatasetResource(http)}
|
|
203
|
+
from ..init import ensure_http_and_resources
|
|
315
204
|
|
|
205
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
316
206
|
return resources['datasets'].delete_dataset(dataset_id)
|
|
317
207
|
|
|
318
208
|
|
|
@@ -349,30 +239,9 @@ def create_dataset_item(
|
|
|
349
239
|
Raises:
|
|
350
240
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
351
241
|
"""
|
|
352
|
-
from ..init import
|
|
353
|
-
from ...core.config import SDKConfig
|
|
354
|
-
from ...api.client import HttpClient
|
|
355
|
-
|
|
356
|
-
# Get or create resources
|
|
357
|
-
resources = get_resources()
|
|
358
|
-
if not resources or 'datasets' not in resources:
|
|
359
|
-
load_dotenv()
|
|
360
|
-
|
|
361
|
-
if api_key is None:
|
|
362
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
363
|
-
if api_key is None:
|
|
364
|
-
raise APIKeyVerificationError(
|
|
365
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
if agent_id is None:
|
|
369
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
370
|
-
|
|
371
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
372
|
-
http = HttpClient(config)
|
|
373
|
-
from ...api.resources.dataset import DatasetResource
|
|
374
|
-
resources = {'datasets': DatasetResource(http)}
|
|
242
|
+
from ..init import ensure_http_and_resources
|
|
375
243
|
|
|
244
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
376
245
|
return resources['datasets'].create_item(
|
|
377
246
|
dataset_id, name, input_data,
|
|
378
247
|
expected_output=expected_output,
|
|
@@ -404,30 +273,9 @@ def get_dataset_item(
|
|
|
404
273
|
Raises:
|
|
405
274
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
406
275
|
"""
|
|
407
|
-
from ..init import
|
|
408
|
-
from ...core.config import SDKConfig
|
|
409
|
-
from ...api.client import HttpClient
|
|
410
|
-
|
|
411
|
-
# Get or create resources
|
|
412
|
-
resources = get_resources()
|
|
413
|
-
if not resources or 'datasets' not in resources:
|
|
414
|
-
load_dotenv()
|
|
415
|
-
|
|
416
|
-
if api_key is None:
|
|
417
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
418
|
-
if api_key is None:
|
|
419
|
-
raise APIKeyVerificationError(
|
|
420
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
if agent_id is None:
|
|
424
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
425
|
-
|
|
426
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
427
|
-
http = HttpClient(config)
|
|
428
|
-
from ...api.resources.dataset import DatasetResource
|
|
429
|
-
resources = {'datasets': DatasetResource(http)}
|
|
276
|
+
from ..init import ensure_http_and_resources
|
|
430
277
|
|
|
278
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
431
279
|
return resources['datasets'].get_item(dataset_id, item_id)
|
|
432
280
|
|
|
433
281
|
|
|
@@ -466,29 +314,9 @@ def update_dataset_item(
|
|
|
466
314
|
Raises:
|
|
467
315
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
468
316
|
"""
|
|
469
|
-
from ..init import
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
# Get or create resources
|
|
474
|
-
resources = get_resources()
|
|
475
|
-
if not resources or 'datasets' not in resources:
|
|
476
|
-
load_dotenv()
|
|
477
|
-
|
|
478
|
-
if api_key is None:
|
|
479
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
480
|
-
if api_key is None:
|
|
481
|
-
raise APIKeyVerificationError(
|
|
482
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
483
|
-
)
|
|
484
|
-
|
|
485
|
-
if agent_id is None:
|
|
486
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
487
|
-
|
|
488
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
489
|
-
http = HttpClient(config)
|
|
490
|
-
from ...api.resources.dataset import DatasetResource
|
|
491
|
-
resources = {'datasets': DatasetResource(http)}
|
|
317
|
+
from ..init import ensure_http_and_resources
|
|
318
|
+
|
|
319
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
492
320
|
|
|
493
321
|
kwargs = {}
|
|
494
322
|
if name is not None:
|
|
@@ -530,30 +358,9 @@ def delete_dataset_item(
|
|
|
530
358
|
Raises:
|
|
531
359
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
532
360
|
"""
|
|
533
|
-
from ..init import
|
|
534
|
-
from ...core.config import SDKConfig
|
|
535
|
-
from ...api.client import HttpClient
|
|
536
|
-
|
|
537
|
-
# Get or create resources
|
|
538
|
-
resources = get_resources()
|
|
539
|
-
if not resources or 'datasets' not in resources:
|
|
540
|
-
load_dotenv()
|
|
541
|
-
|
|
542
|
-
if api_key is None:
|
|
543
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
544
|
-
if api_key is None:
|
|
545
|
-
raise APIKeyVerificationError(
|
|
546
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
547
|
-
)
|
|
548
|
-
|
|
549
|
-
if agent_id is None:
|
|
550
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
551
|
-
|
|
552
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
553
|
-
http = HttpClient(config)
|
|
554
|
-
from ...api.resources.dataset import DatasetResource
|
|
555
|
-
resources = {'datasets': DatasetResource(http)}
|
|
361
|
+
from ..init import ensure_http_and_resources
|
|
556
362
|
|
|
363
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
557
364
|
return resources['datasets'].delete_item(dataset_id, item_id)
|
|
558
365
|
|
|
559
366
|
|
|
@@ -578,28 +385,7 @@ def list_dataset_item_sessions(
|
|
|
578
385
|
Raises:
|
|
579
386
|
APIKeyVerificationError: If API key or agent ID is missing or invalid.
|
|
580
387
|
"""
|
|
581
|
-
from ..init import
|
|
582
|
-
from ...core.config import SDKConfig
|
|
583
|
-
from ...api.client import HttpClient
|
|
584
|
-
|
|
585
|
-
# Get or create resources
|
|
586
|
-
resources = get_resources()
|
|
587
|
-
if not resources or 'datasets' not in resources:
|
|
588
|
-
load_dotenv()
|
|
589
|
-
|
|
590
|
-
if api_key is None:
|
|
591
|
-
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
592
|
-
if api_key is None:
|
|
593
|
-
raise APIKeyVerificationError(
|
|
594
|
-
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
595
|
-
)
|
|
596
|
-
|
|
597
|
-
if agent_id is None:
|
|
598
|
-
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
599
|
-
|
|
600
|
-
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
601
|
-
http = HttpClient(config)
|
|
602
|
-
from ...api.resources.dataset import DatasetResource
|
|
603
|
-
resources = {'datasets': DatasetResource(http)}
|
|
388
|
+
from ..init import ensure_http_and_resources
|
|
604
389
|
|
|
390
|
+
resources = ensure_http_and_resources(api_key=api_key, agent_id=agent_id)
|
|
605
391
|
return resources['datasets'].list_item_sessions(dataset_id, item_id)
|
lucidicai/sdk/init.py
CHANGED
|
@@ -353,6 +353,75 @@ def get_resources() -> dict:
|
|
|
353
353
|
return _sdk_state.resources
|
|
354
354
|
|
|
355
355
|
|
|
356
|
+
def set_http(http: HttpClient) -> None:
|
|
357
|
+
"""Set the HTTP client instance in SDK state."""
|
|
358
|
+
global _sdk_state
|
|
359
|
+
_sdk_state.http = http
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def set_resources(resources: dict) -> None:
|
|
363
|
+
"""Set API resource instances in SDK state."""
|
|
364
|
+
global _sdk_state
|
|
365
|
+
_sdk_state.resources = resources
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def ensure_http_and_resources(api_key: Optional[str] = None, agent_id: Optional[str] = None) -> dict:
|
|
369
|
+
"""Ensure HTTP client and resources are initialized, creating them if needed.
|
|
370
|
+
|
|
371
|
+
This function checks if the HTTP client and resources already exist in SDK state.
|
|
372
|
+
If not, it creates them and stores them in SDK state for reuse.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
api_key: API key (uses env if not provided)
|
|
376
|
+
agent_id: Agent ID (uses env if not provided)
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
Dictionary of API resources with 'datasets' key
|
|
380
|
+
|
|
381
|
+
Raises:
|
|
382
|
+
APIKeyVerificationError: If API key is not available
|
|
383
|
+
"""
|
|
384
|
+
global _sdk_state
|
|
385
|
+
|
|
386
|
+
# If we already have resources with datasets, return them
|
|
387
|
+
if _sdk_state.resources and 'datasets' in _sdk_state.resources:
|
|
388
|
+
return _sdk_state.resources
|
|
389
|
+
|
|
390
|
+
# Need to create HTTP client and resources
|
|
391
|
+
from dotenv import load_dotenv
|
|
392
|
+
import os
|
|
393
|
+
from ..core.errors import APIKeyVerificationError
|
|
394
|
+
|
|
395
|
+
load_dotenv()
|
|
396
|
+
|
|
397
|
+
# Get credentials
|
|
398
|
+
if api_key is None:
|
|
399
|
+
api_key = os.getenv("LUCIDIC_API_KEY", None)
|
|
400
|
+
if api_key is None:
|
|
401
|
+
raise APIKeyVerificationError(
|
|
402
|
+
"Make sure to either pass your API key or set the LUCIDIC_API_KEY environment variable."
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
if agent_id is None:
|
|
406
|
+
agent_id = os.getenv("LUCIDIC_AGENT_ID", None)
|
|
407
|
+
|
|
408
|
+
# Create or reuse HTTP client
|
|
409
|
+
if not _sdk_state.http:
|
|
410
|
+
debug("[SDK] Creating HTTP client for standalone use")
|
|
411
|
+
config = SDKConfig.from_env(api_key=api_key, agent_id=agent_id)
|
|
412
|
+
_sdk_state.http = HttpClient(config)
|
|
413
|
+
|
|
414
|
+
# Create resources if not already present
|
|
415
|
+
if not _sdk_state.resources:
|
|
416
|
+
_sdk_state.resources = {}
|
|
417
|
+
|
|
418
|
+
if 'datasets' not in _sdk_state.resources:
|
|
419
|
+
debug("[SDK] Creating DatasetResource for standalone use")
|
|
420
|
+
_sdk_state.resources['datasets'] = DatasetResource(_sdk_state.http)
|
|
421
|
+
|
|
422
|
+
return _sdk_state.resources
|
|
423
|
+
|
|
424
|
+
|
|
356
425
|
def get_tracer_provider() -> Optional[TracerProvider]:
|
|
357
426
|
"""Get the tracer provider instance."""
|
|
358
427
|
return _sdk_state.tracer_provider
|
lucidicai/utils/images.py
CHANGED
|
@@ -11,7 +11,7 @@ import logging
|
|
|
11
11
|
import threading
|
|
12
12
|
from typing import List, Dict, Any, Optional, Tuple, Union
|
|
13
13
|
from PIL import Image
|
|
14
|
-
import
|
|
14
|
+
import httpx
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger("Lucidic")
|
|
17
17
|
|
|
@@ -299,9 +299,9 @@ class ImageUploader:
|
|
|
299
299
|
image_obj, content_type = ImageHandler.prepare_for_upload(image_data, format)
|
|
300
300
|
|
|
301
301
|
# Upload to S3
|
|
302
|
-
upload_response =
|
|
302
|
+
upload_response = httpx.put(
|
|
303
303
|
url,
|
|
304
|
-
|
|
304
|
+
content=image_obj.getvalue() if hasattr(image_obj, 'getvalue') else image_obj,
|
|
305
305
|
headers={"Content-Type": content_type}
|
|
306
306
|
)
|
|
307
307
|
upload_response.raise_for_status()
|
lucidicai/utils/queue.py
CHANGED
|
@@ -9,7 +9,7 @@ import json
|
|
|
9
9
|
import queue
|
|
10
10
|
import threading
|
|
11
11
|
import time
|
|
12
|
-
import
|
|
12
|
+
import httpx
|
|
13
13
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
14
14
|
from datetime import datetime, timezone
|
|
15
15
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
@@ -362,7 +362,7 @@ class EventQueue:
|
|
|
362
362
|
def _upload_blob(self, blob_url: str, data: bytes) -> None:
|
|
363
363
|
"""Upload compressed blob to presigned URL."""
|
|
364
364
|
headers = {"Content-Type": "application/json", "Content-Encoding": "gzip"}
|
|
365
|
-
resp =
|
|
365
|
+
resp = httpx.put(blob_url, content=data, headers=headers)
|
|
366
366
|
resp.raise_for_status()
|
|
367
367
|
|
|
368
368
|
@staticmethod
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
lucidicai/__init__.py,sha256=
|
|
1
|
+
lucidicai/__init__.py,sha256=vujMytXGPFrZRxIZtvJbo81f1AtgyZpMVIhLyUX32v0,12757
|
|
2
2
|
lucidicai/action.py,sha256=sPRd1hTIVXDqnvG9ZXWEipUFh0bsXcE0Fm7RVqmVccM,237
|
|
3
3
|
lucidicai/client.py,sha256=IIhlY6Mfwy47FeMxzpvIygCaqcI1FnqiXiVU6M4QEiE,22327
|
|
4
4
|
lucidicai/constants.py,sha256=zN8O7TjoRHRlaGa9CZUWppS73rhzKGwaEkF9XMTV0Cg,1160
|
|
@@ -18,7 +18,7 @@ lucidicai/state.py,sha256=4Tb1X6l2or6w_e62FYSuEeghAv3xXm5gquKwzCpvdok,235
|
|
|
18
18
|
lucidicai/step.py,sha256=_oBIyTBZBvNkUkYHIrwWd75KMSlMtR9Ws2Lo71Lyff8,2522
|
|
19
19
|
lucidicai/streaming.py,sha256=QOLAzhwxetvx711J8VcphY5kXWPJz9XEBJrmHveRKMc,9796
|
|
20
20
|
lucidicai/api/__init__.py,sha256=UOYuFZupG0TgzMAxbLNgpodDXhDRXBgMva8ZblgBN9Y,31
|
|
21
|
-
lucidicai/api/client.py,sha256=
|
|
21
|
+
lucidicai/api/client.py,sha256=RsJXaQn3ccxPcCKYyxoAR5268AhUVkkx1SvTX5_pFbI,12089
|
|
22
22
|
lucidicai/api/resources/__init__.py,sha256=Wc8-JfL82wkE7eB8PHplqYvaEG2oXNXXhRyEPeduJeE,27
|
|
23
23
|
lucidicai/api/resources/dataset.py,sha256=6UnMUd-y__TOAjUJLjbc0lZJRTy_gHkyoE82OvjFoN4,5583
|
|
24
24
|
lucidicai/api/resources/event.py,sha256=GyyNL3_k53EbmvTdgJEABexiuJnoX61hxWey7DYmlYY,2434
|
|
@@ -50,10 +50,10 @@ lucidicai/sdk/decorators.py,sha256=B5BXG9Sn5ruUkxFq10L1rrCR_wzYUPlYeu5aqyXetMM,8
|
|
|
50
50
|
lucidicai/sdk/error_boundary.py,sha256=IPr5wS9rS7ZQNgEaBwK53UaixAm6L2rijKKFfxcxjUI,9190
|
|
51
51
|
lucidicai/sdk/event.py,sha256=NiPcnPzYCU0VlFbBk93LD88wqAYmnglV64nQb2XteOs,3747
|
|
52
52
|
lucidicai/sdk/event_builder.py,sha256=oMvt39m07ZLmPllJTWwRxpinJUz9_AD17yNE6wQRoDA,10423
|
|
53
|
-
lucidicai/sdk/init.py,sha256=
|
|
53
|
+
lucidicai/sdk/init.py,sha256=lUEChS3YKiwKWFLZnJIs-VXuicLZPiBXr8_UexqjKhE,15204
|
|
54
54
|
lucidicai/sdk/shutdown_manager.py,sha256=I5ylR96QHQ_SfP1euAiM0qQ-I7upCPMW1HUNvoj7hCw,12090
|
|
55
55
|
lucidicai/sdk/features/__init__.py,sha256=23KUF2EZBzsaH9JUFDGNXZb_3PSfc35VZfD59gAfyR0,26
|
|
56
|
-
lucidicai/sdk/features/dataset.py,sha256=
|
|
56
|
+
lucidicai/sdk/features/dataset.py,sha256=DfoxHrfN86Hu-H0vAO0OHGwaevaGaXm26Z5wpfuXDSY,11814
|
|
57
57
|
lucidicai/sdk/features/feature_flag.py,sha256=SzuzHiVnbticD6Ojn0_i9xQKui2s9QUFPJ7LixzAtf4,13844
|
|
58
58
|
lucidicai/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
59
|
lucidicai/telemetry/base_provider.py,sha256=nrZVr4Y9xcAiMn4uAN3t3k6DlHNTvlXrA4qQg7lANOQ,544
|
|
@@ -78,10 +78,10 @@ lucidicai/telemetry/utils/model_pricing.py,sha256=Dxi6e0WjcIyCTkVX7K7f0pJ5rPu7nS
|
|
|
78
78
|
lucidicai/telemetry/utils/text_storage.py,sha256=L62MMJ8E23TDqDTUv2aRntdKMCItsXV7XjY6cFwx2DE,1503
|
|
79
79
|
lucidicai/telemetry/utils/universal_image_interceptor.py,sha256=vARgMk1hVSF--zfi5b8qBpJJOESuD17YlH9xqxmB9Uw,15954
|
|
80
80
|
lucidicai/utils/__init__.py,sha256=ZiGtmJaF0ph9iIFIgQiAreVuYM_1o7qu9VySK1NblTw,22
|
|
81
|
-
lucidicai/utils/images.py,sha256=
|
|
81
|
+
lucidicai/utils/images.py,sha256=HzPpv-Xs9k9VaDD1daT5fdZvoNf5ke9-E1awmkzAADc,12322
|
|
82
82
|
lucidicai/utils/logger.py,sha256=R3B3gSee64F6UVHUrShihBq_O7W7bgfrBiVDXTO3Isg,4777
|
|
83
|
-
lucidicai/utils/queue.py,sha256=
|
|
84
|
-
lucidicai-2.1.
|
|
85
|
-
lucidicai-2.1.
|
|
86
|
-
lucidicai-2.1.
|
|
87
|
-
lucidicai-2.1.
|
|
83
|
+
lucidicai/utils/queue.py,sha256=8DQwnGw7pINEJ0dNSkB0PhdPW-iBQQ-YZg23poe4umE,17323
|
|
84
|
+
lucidicai-2.1.3.dist-info/METADATA,sha256=A5SQWuHc48k5n0Dg9KFI52E2SLe0su9vqHEC8jWIi5A,902
|
|
85
|
+
lucidicai-2.1.3.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
|
86
|
+
lucidicai-2.1.3.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
|
|
87
|
+
lucidicai-2.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|