lucidicai 1.2.15__py3-none-any.whl → 1.2.17__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 +111 -21
- lucidicai/client.py +22 -5
- lucidicai/decorators.py +357 -0
- lucidicai/event.py +2 -2
- lucidicai/image_upload.py +24 -1
- lucidicai/providers/anthropic_handler.py +0 -7
- lucidicai/providers/image_storage.py +45 -0
- lucidicai/providers/langchain.py +0 -78
- lucidicai/providers/lucidic_exporter.py +259 -0
- lucidicai/providers/lucidic_span_processor.py +648 -0
- lucidicai/providers/openai_agents_instrumentor.py +307 -0
- lucidicai/providers/openai_handler.py +1 -56
- lucidicai/providers/otel_handlers.py +266 -0
- lucidicai/providers/otel_init.py +197 -0
- lucidicai/providers/otel_provider.py +168 -0
- lucidicai/providers/pydantic_ai_handler.py +2 -19
- lucidicai/providers/text_storage.py +53 -0
- lucidicai/providers/universal_image_interceptor.py +276 -0
- lucidicai/session.py +17 -4
- lucidicai/step.py +4 -4
- lucidicai/streaming.py +2 -3
- lucidicai/telemetry/__init__.py +0 -0
- lucidicai/telemetry/base_provider.py +21 -0
- lucidicai/telemetry/lucidic_exporter.py +259 -0
- lucidicai/telemetry/lucidic_span_processor.py +665 -0
- lucidicai/telemetry/openai_agents_instrumentor.py +306 -0
- lucidicai/telemetry/opentelemetry_converter.py +436 -0
- lucidicai/telemetry/otel_handlers.py +266 -0
- lucidicai/telemetry/otel_init.py +197 -0
- lucidicai/telemetry/otel_provider.py +168 -0
- lucidicai/telemetry/pydantic_ai_handler.py +600 -0
- lucidicai/telemetry/utils/__init__.py +0 -0
- lucidicai/telemetry/utils/image_storage.py +45 -0
- lucidicai/telemetry/utils/text_storage.py +53 -0
- lucidicai/telemetry/utils/universal_image_interceptor.py +276 -0
- {lucidicai-1.2.15.dist-info → lucidicai-1.2.17.dist-info}/METADATA +1 -1
- lucidicai-1.2.17.dist-info/RECORD +49 -0
- lucidicai-1.2.15.dist-info/RECORD +0 -25
- {lucidicai-1.2.15.dist-info → lucidicai-1.2.17.dist-info}/WHEEL +0 -0
- {lucidicai-1.2.15.dist-info → lucidicai-1.2.17.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Thread-local storage for text content from multimodal messages"""
|
|
2
|
+
import threading
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger("Lucidic")
|
|
7
|
+
|
|
8
|
+
# Thread-local storage for text content
|
|
9
|
+
_text_storage = threading.local()
|
|
10
|
+
|
|
11
|
+
def store_text(text: str, message_index: int = 0) -> None:
|
|
12
|
+
"""Store text content for a message
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
text: The text content to store
|
|
16
|
+
message_index: The index of the message (default 0)
|
|
17
|
+
"""
|
|
18
|
+
if not hasattr(_text_storage, 'texts'):
|
|
19
|
+
_text_storage.texts = {}
|
|
20
|
+
|
|
21
|
+
_text_storage.texts[message_index] = text
|
|
22
|
+
logger.debug(f"[TextStorage] Stored text for message {message_index}: {text[:50]}...")
|
|
23
|
+
|
|
24
|
+
def get_stored_text(message_index: int = 0) -> Optional[str]:
|
|
25
|
+
"""Get stored text for a message
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
message_index: The index of the message (default 0)
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
The stored text or None if not found
|
|
32
|
+
"""
|
|
33
|
+
if not hasattr(_text_storage, 'texts'):
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
return _text_storage.texts.get(message_index)
|
|
37
|
+
|
|
38
|
+
def get_all_stored_texts() -> dict:
|
|
39
|
+
"""Get all stored texts
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Dictionary of message_index -> text
|
|
43
|
+
"""
|
|
44
|
+
if not hasattr(_text_storage, 'texts'):
|
|
45
|
+
return {}
|
|
46
|
+
|
|
47
|
+
return _text_storage.texts.copy()
|
|
48
|
+
|
|
49
|
+
def clear_stored_texts() -> None:
|
|
50
|
+
"""Clear all stored texts"""
|
|
51
|
+
if hasattr(_text_storage, 'texts'):
|
|
52
|
+
_text_storage.texts = {}
|
|
53
|
+
logger.debug("[TextStorage] Cleared all stored texts")
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"""Universal image interceptor for all LLM providers to capture images from multimodal requests"""
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from typing import Any, Dict, List, Union, Tuple
|
|
5
|
+
from .image_storage import store_image, get_stored_images
|
|
6
|
+
from .text_storage import store_text, clear_stored_texts
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger("Lucidic")
|
|
9
|
+
DEBUG = os.getenv("LUCIDIC_DEBUG", "False") == "True"
|
|
10
|
+
VERBOSE = os.getenv("LUCIDIC_VERBOSE", "False") == "True"
|
|
11
|
+
|
|
12
|
+
class UniversalImageInterceptor:
|
|
13
|
+
"""Universal image interceptor that can handle different provider formats"""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def extract_and_store_images_openai(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
17
|
+
"""Extract and store images from OpenAI-style messages
|
|
18
|
+
|
|
19
|
+
OpenAI format:
|
|
20
|
+
{
|
|
21
|
+
"role": "user",
|
|
22
|
+
"content": [
|
|
23
|
+
{"type": "text", "text": "What's in this image?"},
|
|
24
|
+
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
"""
|
|
28
|
+
processed_messages = []
|
|
29
|
+
clear_stored_texts() # Clear any previous texts
|
|
30
|
+
|
|
31
|
+
for msg_idx, message in enumerate(messages):
|
|
32
|
+
if isinstance(message, dict):
|
|
33
|
+
content = message.get('content')
|
|
34
|
+
if isinstance(content, list):
|
|
35
|
+
# Extract and store text content for multimodal messages
|
|
36
|
+
text_parts = []
|
|
37
|
+
has_images = False
|
|
38
|
+
|
|
39
|
+
for item in content:
|
|
40
|
+
if isinstance(item, dict):
|
|
41
|
+
if item.get('type') == 'text':
|
|
42
|
+
text_parts.append(item.get('text', ''))
|
|
43
|
+
elif item.get('type') == 'image_url':
|
|
44
|
+
has_images = True
|
|
45
|
+
image_data = item.get('image_url', {})
|
|
46
|
+
if isinstance(image_data, dict):
|
|
47
|
+
url = image_data.get('url', '')
|
|
48
|
+
if url.startswith('data:image'):
|
|
49
|
+
# Store the image
|
|
50
|
+
placeholder = store_image(url)
|
|
51
|
+
if DEBUG:
|
|
52
|
+
logger.info(f"[Universal Interceptor] Stored OpenAI image, placeholder: {placeholder}")
|
|
53
|
+
|
|
54
|
+
# If we have both text and images, store the text separately
|
|
55
|
+
if text_parts and has_images:
|
|
56
|
+
combined_text = ' '.join(text_parts)
|
|
57
|
+
store_text(combined_text, msg_idx)
|
|
58
|
+
if VERBOSE:
|
|
59
|
+
logger.info(f"[Universal Interceptor] Stored text for multimodal message {msg_idx}: {combined_text[:50]}...")
|
|
60
|
+
|
|
61
|
+
processed_messages.append(message)
|
|
62
|
+
return processed_messages
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def extract_and_store_images_anthropic(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
66
|
+
"""Extract and store images from Anthropic-style messages
|
|
67
|
+
|
|
68
|
+
Anthropic format:
|
|
69
|
+
{
|
|
70
|
+
"role": "user",
|
|
71
|
+
"content": [
|
|
72
|
+
{"type": "text", "text": "What's in this image?"},
|
|
73
|
+
{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": "..."}}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
"""
|
|
77
|
+
processed_messages = []
|
|
78
|
+
for message in messages:
|
|
79
|
+
if isinstance(message, dict):
|
|
80
|
+
content = message.get('content')
|
|
81
|
+
if isinstance(content, list):
|
|
82
|
+
for item in content:
|
|
83
|
+
if isinstance(item, dict) and item.get('type') == 'image':
|
|
84
|
+
source = item.get('source', {})
|
|
85
|
+
if isinstance(source, dict):
|
|
86
|
+
data = source.get('data', '')
|
|
87
|
+
media_type = source.get('media_type', 'image/jpeg')
|
|
88
|
+
if data:
|
|
89
|
+
# Convert to data URL format for consistency
|
|
90
|
+
data_url = f"data:{media_type};base64,{data}"
|
|
91
|
+
placeholder = store_image(data_url)
|
|
92
|
+
if DEBUG:
|
|
93
|
+
logger.info(f"[Universal Interceptor] Stored Anthropic image, placeholder: {placeholder}")
|
|
94
|
+
processed_messages.append(message)
|
|
95
|
+
return processed_messages
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def extract_and_store_images_google(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
99
|
+
"""Extract and store images from Google/Gemini-style messages
|
|
100
|
+
|
|
101
|
+
Google format can vary but often uses:
|
|
102
|
+
{
|
|
103
|
+
"parts": [
|
|
104
|
+
{"text": "What's in this image?"},
|
|
105
|
+
{"inline_data": {"mime_type": "image/jpeg", "data": "..."}}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
"""
|
|
109
|
+
processed_messages = []
|
|
110
|
+
for message in messages:
|
|
111
|
+
if isinstance(message, dict):
|
|
112
|
+
parts = message.get('parts', [])
|
|
113
|
+
for part in parts:
|
|
114
|
+
if isinstance(part, dict) and 'inline_data' in part:
|
|
115
|
+
inline_data = part['inline_data']
|
|
116
|
+
if isinstance(inline_data, dict):
|
|
117
|
+
data = inline_data.get('data', '')
|
|
118
|
+
mime_type = inline_data.get('mime_type', 'image/jpeg')
|
|
119
|
+
if data:
|
|
120
|
+
# Convert to data URL format
|
|
121
|
+
data_url = f"data:{mime_type};base64,{data}"
|
|
122
|
+
placeholder = store_image(data_url)
|
|
123
|
+
if DEBUG:
|
|
124
|
+
logger.info(f"[Universal Interceptor] Stored Google image, placeholder: {placeholder}")
|
|
125
|
+
processed_messages.append(message)
|
|
126
|
+
return processed_messages
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def intercept_images(messages: Any, provider: str = "auto") -> Any:
|
|
130
|
+
"""Universal image interception for any provider
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
messages: The messages to process
|
|
134
|
+
provider: The provider type ("openai", "anthropic", "google", "auto")
|
|
135
|
+
If "auto", will try to detect the format
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
The processed messages (unchanged, but images are stored)
|
|
139
|
+
"""
|
|
140
|
+
if not messages or not isinstance(messages, list):
|
|
141
|
+
return messages
|
|
142
|
+
|
|
143
|
+
# Auto-detect provider format if needed
|
|
144
|
+
if provider == "auto":
|
|
145
|
+
provider = UniversalImageInterceptor._detect_provider_format(messages)
|
|
146
|
+
|
|
147
|
+
# Process based on provider
|
|
148
|
+
if provider == "openai":
|
|
149
|
+
return UniversalImageInterceptor.extract_and_store_images_openai(messages)
|
|
150
|
+
elif provider == "anthropic":
|
|
151
|
+
return UniversalImageInterceptor.extract_and_store_images_anthropic(messages)
|
|
152
|
+
elif provider == "google":
|
|
153
|
+
return UniversalImageInterceptor.extract_and_store_images_google(messages)
|
|
154
|
+
else:
|
|
155
|
+
if DEBUG:
|
|
156
|
+
logger.warning(f"[Universal Interceptor] Unknown provider format: {provider}")
|
|
157
|
+
return messages
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def _detect_provider_format(messages: List[Dict[str, Any]]) -> str:
|
|
161
|
+
"""Detect the provider format based on message structure"""
|
|
162
|
+
for message in messages:
|
|
163
|
+
if isinstance(message, dict):
|
|
164
|
+
# Check for OpenAI format
|
|
165
|
+
content = message.get('content')
|
|
166
|
+
if isinstance(content, list):
|
|
167
|
+
for item in content:
|
|
168
|
+
if isinstance(item, dict):
|
|
169
|
+
if item.get('type') == 'image_url' and 'image_url' in item:
|
|
170
|
+
return "openai"
|
|
171
|
+
elif item.get('type') == 'image' and 'source' in item:
|
|
172
|
+
return "anthropic"
|
|
173
|
+
|
|
174
|
+
# Check for Google format
|
|
175
|
+
if 'parts' in message:
|
|
176
|
+
return "google"
|
|
177
|
+
|
|
178
|
+
return "unknown"
|
|
179
|
+
|
|
180
|
+
@staticmethod
|
|
181
|
+
def create_interceptor(provider: str):
|
|
182
|
+
"""Create a function interceptor for a specific provider
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
provider: The provider type ("openai", "anthropic", "google")
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
A function that can wrap the provider's API call
|
|
189
|
+
"""
|
|
190
|
+
def interceptor(original_func):
|
|
191
|
+
def wrapper(*args, **kwargs):
|
|
192
|
+
# Extract messages from kwargs (common location)
|
|
193
|
+
messages = kwargs.get('messages', None)
|
|
194
|
+
|
|
195
|
+
# For Anthropic, messages might be in args[1]
|
|
196
|
+
if messages is None and len(args) > 1 and isinstance(args[1], list):
|
|
197
|
+
messages = args[1]
|
|
198
|
+
|
|
199
|
+
# Intercept images if messages found
|
|
200
|
+
if messages:
|
|
201
|
+
UniversalImageInterceptor.intercept_images(messages, provider)
|
|
202
|
+
|
|
203
|
+
# Call the original function
|
|
204
|
+
return original_func(*args, **kwargs)
|
|
205
|
+
|
|
206
|
+
return wrapper
|
|
207
|
+
|
|
208
|
+
return interceptor
|
|
209
|
+
|
|
210
|
+
@staticmethod
|
|
211
|
+
def create_async_interceptor(provider: str):
|
|
212
|
+
"""Create an async function interceptor for a specific provider"""
|
|
213
|
+
def interceptor(original_func):
|
|
214
|
+
async def wrapper(*args, **kwargs):
|
|
215
|
+
# Extract messages from kwargs (common location)
|
|
216
|
+
messages = kwargs.get('messages', None)
|
|
217
|
+
|
|
218
|
+
# For Anthropic, messages might be in args[1]
|
|
219
|
+
if messages is None and len(args) > 1 and isinstance(args[1], list):
|
|
220
|
+
messages = args[1]
|
|
221
|
+
|
|
222
|
+
# Intercept images if messages found
|
|
223
|
+
if messages:
|
|
224
|
+
UniversalImageInterceptor.intercept_images(messages, provider)
|
|
225
|
+
|
|
226
|
+
# Call the original function
|
|
227
|
+
return await original_func(*args, **kwargs)
|
|
228
|
+
|
|
229
|
+
return wrapper
|
|
230
|
+
|
|
231
|
+
return interceptor
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def patch_openai_client(client):
|
|
235
|
+
"""Patch an OpenAI client instance to intercept images"""
|
|
236
|
+
interceptor = UniversalImageInterceptor.create_interceptor("openai")
|
|
237
|
+
|
|
238
|
+
if hasattr(client, 'chat') and hasattr(client.chat, 'completions'):
|
|
239
|
+
original_create = client.chat.completions.create
|
|
240
|
+
client.chat.completions.create = interceptor(original_create)
|
|
241
|
+
if DEBUG:
|
|
242
|
+
logger.info("[Universal Interceptor] Patched OpenAI client for image interception")
|
|
243
|
+
return client
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def patch_anthropic_client(client):
|
|
247
|
+
"""Patch an Anthropic client instance to intercept images"""
|
|
248
|
+
interceptor = UniversalImageInterceptor.create_interceptor("anthropic")
|
|
249
|
+
async_interceptor = UniversalImageInterceptor.create_async_interceptor("anthropic")
|
|
250
|
+
|
|
251
|
+
if hasattr(client, 'messages'):
|
|
252
|
+
if hasattr(client.messages, 'create'):
|
|
253
|
+
original_create = client.messages.create
|
|
254
|
+
client.messages.create = interceptor(original_create)
|
|
255
|
+
|
|
256
|
+
# Handle async version
|
|
257
|
+
if hasattr(client.messages, 'acreate'):
|
|
258
|
+
original_acreate = client.messages.acreate
|
|
259
|
+
client.messages.acreate = async_interceptor(original_acreate)
|
|
260
|
+
|
|
261
|
+
if DEBUG:
|
|
262
|
+
logger.info("[Universal Interceptor] Patched Anthropic client for image interception")
|
|
263
|
+
return client
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def patch_google_client(client):
|
|
267
|
+
"""Patch a Google/Gemini client instance to intercept images"""
|
|
268
|
+
interceptor = UniversalImageInterceptor.create_interceptor("google")
|
|
269
|
+
|
|
270
|
+
# Google's client structure varies, but often uses generate_content
|
|
271
|
+
if hasattr(client, 'generate_content'):
|
|
272
|
+
original_generate = client.generate_content
|
|
273
|
+
client.generate_content = interceptor(original_generate)
|
|
274
|
+
if DEBUG:
|
|
275
|
+
logger.info("[Universal Interceptor] Patched Google client for image interception")
|
|
276
|
+
return client
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
lucidicai/__init__.py,sha256=lj8_84KeLYcJVrqUnkuyeFKUfwv1L5qY85gtpMxEsIM,19765
|
|
2
|
+
lucidicai/action.py,sha256=sPRd1hTIVXDqnvG9ZXWEipUFh0bsXcE0Fm7RVqmVccM,237
|
|
3
|
+
lucidicai/client.py,sha256=_EHUB--u-hvdhKTks4jpqvA18-GBwJfnyjoPZOXkA04,6374
|
|
4
|
+
lucidicai/constants.py,sha256=_u0z3M4geZgS1g-CrOZUVjtcew8l70dKQnpVQvlXh9w,2172
|
|
5
|
+
lucidicai/decorators.py,sha256=oqXyfHk9f9UmeaIquuU8mtzed1qZtO_-svwadpoat6g,13950
|
|
6
|
+
lucidicai/errors.py,sha256=gTg0bdzjuTcUnakRbZnxjngO4gZnRLVwRHRglpZZJsM,970
|
|
7
|
+
lucidicai/event.py,sha256=2j5G4drwVhmdQkk9-armYQj1ctmLm2H_rNfPsfV_8wA,2004
|
|
8
|
+
lucidicai/image_upload.py,sha256=6SRudg-BpInM2gzMx1Yf1Rz_Zyh8inwoJ7U4pBw7ruY,3807
|
|
9
|
+
lucidicai/model_pricing.py,sha256=Q_Kd8OtKPqtvZ4pIh__ztKb3RXe-cX-8xgrM-AIUj9E,12189
|
|
10
|
+
lucidicai/session.py,sha256=_67V6Be9Js-JEdCfiY_wkr4VUkQOdwZKUGUwf5mGXps,5429
|
|
11
|
+
lucidicai/singleton.py,sha256=gfT3XdWLXSIWMqDXbY6-pnesMZ8RGRitaEPhIsgrRPw,1272
|
|
12
|
+
lucidicai/state.py,sha256=4Tb1X6l2or6w_e62FYSuEeghAv3xXm5gquKwzCpvdok,235
|
|
13
|
+
lucidicai/step.py,sha256=_oBIyTBZBvNkUkYHIrwWd75KMSlMtR9Ws2Lo71Lyff8,2522
|
|
14
|
+
lucidicai/streaming.py,sha256=Y59vQOqhcOvTQWSAIamAnGCaQqCZz77N62_V2fuQlFA,11565
|
|
15
|
+
lucidicai/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
lucidicai/providers/anthropic_handler.py,sha256=GZEa4QOrjZ9ftu_qTwY3L410HwKzkXgN7omYRsEQ4LU,10174
|
|
17
|
+
lucidicai/providers/base_providers.py,sha256=nrZVr4Y9xcAiMn4uAN3t3k6DlHNTvlXrA4qQg7lANOQ,544
|
|
18
|
+
lucidicai/providers/image_storage.py,sha256=4Z59ZpVexr7-lcExfr8GsqXe0y2VZmr8Yjwa-3DeOxU,1457
|
|
19
|
+
lucidicai/providers/langchain.py,sha256=xLJPFV2hfCOXsundCUZiYBf-g0dS5MDUYKoz22W8fO8,22184
|
|
20
|
+
lucidicai/providers/lucidic_exporter.py,sha256=-uM7jnz7mkapo9ni7hhN7m3EDa0M_Uhz03NdiqfiP9k,10759
|
|
21
|
+
lucidicai/providers/lucidic_span_processor.py,sha256=8bNV-6W1Y8ELi54vMVqQ_mXJouaOJvF3MkeBdamip0w,26799
|
|
22
|
+
lucidicai/providers/openai_agents_handler.py,sha256=AAMtY7HZ-7UvTn1RVwd-uHhibJusZoOnWSw32xNcewo,18957
|
|
23
|
+
lucidicai/providers/openai_agents_instrumentor.py,sha256=AMCTPeLvmHMNGGxelNaHIMu2s7eppLmruIYnlQ1WHDY,12732
|
|
24
|
+
lucidicai/providers/openai_handler.py,sha256=CrFlM7RUAQjOmqWjAkV71dBRhe7gu-YEKXtSHfb70DE,32119
|
|
25
|
+
lucidicai/providers/opentelemetry_converter.py,sha256=xOHCqoTyO4hUkL6k7fxy84PbljPpYep6ET9ZqbkJehc,17665
|
|
26
|
+
lucidicai/providers/otel_handlers.py,sha256=HFCBryXB3LQ5ir03PWWlskH7Y-Yip88kFVm1HQAUXRc,10516
|
|
27
|
+
lucidicai/providers/otel_init.py,sha256=RMsWRG3WZWvZN6WeLWSehsfUB_vWSuclVMCcSO31GEU,7770
|
|
28
|
+
lucidicai/providers/otel_provider.py,sha256=ixLc80-_Vag0EO_92wj2m3_lg6HXyIpz9Md4JdVAbtM,7043
|
|
29
|
+
lucidicai/providers/pydantic_ai_handler.py,sha256=Yhd9VTJhq292ZzJF04O_jYGRh-1bzs70BzQdo7a2Z9M,28269
|
|
30
|
+
lucidicai/providers/text_storage.py,sha256=L62MMJ8E23TDqDTUv2aRntdKMCItsXV7XjY6cFwx2DE,1503
|
|
31
|
+
lucidicai/providers/universal_image_interceptor.py,sha256=7d-hw4xihRwvvA1AP8-vqYNChtmVXKmn09MN4pDS7KQ,12126
|
|
32
|
+
lucidicai/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
lucidicai/telemetry/base_provider.py,sha256=nrZVr4Y9xcAiMn4uAN3t3k6DlHNTvlXrA4qQg7lANOQ,544
|
|
34
|
+
lucidicai/telemetry/lucidic_exporter.py,sha256=h2GOnEk22Fpeke4Zc7SSk391yr0joUApVwolV5Q4hz4,10818
|
|
35
|
+
lucidicai/telemetry/lucidic_span_processor.py,sha256=LhkyJGBnTKpTWdBi2wyW9th4CWZ9EtZ8ulaE0rwYj0Y,27432
|
|
36
|
+
lucidicai/telemetry/openai_agents_instrumentor.py,sha256=__wIbeglMnEEf4AGTQ--FXeWCKmz2yy8SBupwprEdZA,12694
|
|
37
|
+
lucidicai/telemetry/opentelemetry_converter.py,sha256=xOHCqoTyO4hUkL6k7fxy84PbljPpYep6ET9ZqbkJehc,17665
|
|
38
|
+
lucidicai/telemetry/otel_handlers.py,sha256=XgeDCL7ZjtaQ7HX8HKmYGTDqO6yne7gXZaScpdKvq98,10527
|
|
39
|
+
lucidicai/telemetry/otel_init.py,sha256=RMsWRG3WZWvZN6WeLWSehsfUB_vWSuclVMCcSO31GEU,7770
|
|
40
|
+
lucidicai/telemetry/otel_provider.py,sha256=GZPhSEsEPVKrr5A0u5-WNn7OmxNgRWBcam9dyqjf91o,7042
|
|
41
|
+
lucidicai/telemetry/pydantic_ai_handler.py,sha256=WPa3tFcVgVnPPO3AxcNOTbNkmODLgNOrU2_3GVtWqUw,28261
|
|
42
|
+
lucidicai/telemetry/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
+
lucidicai/telemetry/utils/image_storage.py,sha256=4Z59ZpVexr7-lcExfr8GsqXe0y2VZmr8Yjwa-3DeOxU,1457
|
|
44
|
+
lucidicai/telemetry/utils/text_storage.py,sha256=L62MMJ8E23TDqDTUv2aRntdKMCItsXV7XjY6cFwx2DE,1503
|
|
45
|
+
lucidicai/telemetry/utils/universal_image_interceptor.py,sha256=zPfVsMjtKxJP2n2OOjKbtPiQJTZ0sf5_28GWprOnJP4,12185
|
|
46
|
+
lucidicai-1.2.17.dist-info/METADATA,sha256=SljtwfhzcGtEwnsx6JAmqDmYY9KniQi5mY3KH3xhR6M,577
|
|
47
|
+
lucidicai-1.2.17.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
|
48
|
+
lucidicai-1.2.17.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
|
|
49
|
+
lucidicai-1.2.17.dist-info/RECORD,,
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
lucidicai/__init__.py,sha256=sNUGk7kd2IsjL39WgRkc7VuulRbFB5o1liK_65iEH9E,17034
|
|
2
|
-
lucidicai/action.py,sha256=sPRd1hTIVXDqnvG9ZXWEipUFh0bsXcE0Fm7RVqmVccM,237
|
|
3
|
-
lucidicai/client.py,sha256=axJ9JjDq6qIuyyYtiQlMREPTKD_eKve-0pOBKHH7HZg,5695
|
|
4
|
-
lucidicai/constants.py,sha256=_u0z3M4geZgS1g-CrOZUVjtcew8l70dKQnpVQvlXh9w,2172
|
|
5
|
-
lucidicai/errors.py,sha256=gTg0bdzjuTcUnakRbZnxjngO4gZnRLVwRHRglpZZJsM,970
|
|
6
|
-
lucidicai/event.py,sha256=9Z1yuP7Pef0sdXABU9SCHCLZSu6DfK--uGZoq-a9_IA,1974
|
|
7
|
-
lucidicai/image_upload.py,sha256=ShacoEaGXbQESatfp-CrIygsDntt9IkcCqZcc9uLZVQ,3130
|
|
8
|
-
lucidicai/model_pricing.py,sha256=Q_Kd8OtKPqtvZ4pIh__ztKb3RXe-cX-8xgrM-AIUj9E,12189
|
|
9
|
-
lucidicai/session.py,sha256=goLQxBvXkLT5kS3eSfht3IFqvfYfgULC4eECSIanrPc,4909
|
|
10
|
-
lucidicai/singleton.py,sha256=gfT3XdWLXSIWMqDXbY6-pnesMZ8RGRitaEPhIsgrRPw,1272
|
|
11
|
-
lucidicai/state.py,sha256=4Tb1X6l2or6w_e62FYSuEeghAv3xXm5gquKwzCpvdok,235
|
|
12
|
-
lucidicai/step.py,sha256=egDmr3z3ZXu5nBJqeepj0Ml3ifDuyg07OwTB6vOJCaY,2462
|
|
13
|
-
lucidicai/streaming.py,sha256=wQ32xMCHvaNaM6OQoAhY-yS5KoLi71KQPCbcxjpLzbU,11658
|
|
14
|
-
lucidicai/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
lucidicai/providers/anthropic_handler.py,sha256=h6T_Iw0jcpwMhozAb8jOf6L_PihCKVaSScMBBA_otI0,10493
|
|
16
|
-
lucidicai/providers/base_providers.py,sha256=nrZVr4Y9xcAiMn4uAN3t3k6DlHNTvlXrA4qQg7lANOQ,544
|
|
17
|
-
lucidicai/providers/langchain.py,sha256=SSzgoY9UQ1kWuxYpgk1zil2EJGIVGyeWOVAPFvCifNQ,25521
|
|
18
|
-
lucidicai/providers/openai_agents_handler.py,sha256=AAMtY7HZ-7UvTn1RVwd-uHhibJusZoOnWSw32xNcewo,18957
|
|
19
|
-
lucidicai/providers/openai_handler.py,sha256=j2SW3YlGY1FhMO7d03WaIRxAtti6xATnoo2h8jh-uJk,35166
|
|
20
|
-
lucidicai/providers/opentelemetry_converter.py,sha256=xOHCqoTyO4hUkL6k7fxy84PbljPpYep6ET9ZqbkJehc,17665
|
|
21
|
-
lucidicai/providers/pydantic_ai_handler.py,sha256=Vu03SEqRuQNbmOK3iPwWVqczVRZNDDVoilDILIycK8c,28935
|
|
22
|
-
lucidicai-1.2.15.dist-info/METADATA,sha256=gM8vDiiFysOgG0OG6hcgnxYH4k2U1t1Mb0D_2cpfQfk,577
|
|
23
|
-
lucidicai-1.2.15.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
|
24
|
-
lucidicai-1.2.15.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
|
|
25
|
-
lucidicai-1.2.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|