lucidicai 1.3.1__py3-none-any.whl → 1.3.5__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.
@@ -1,13 +1,15 @@
1
- """OpenTelemetry initialization and configuration for Lucidic"""
1
+ """OpenTelemetry initialization and configuration for Lucidic
2
+
3
+ Adds thread-safety and idempotence to avoid duplicate tracer provider
4
+ registration and repeated instrumentation under concurrency.
5
+ """
2
6
  import logging
3
7
  from typing import List, Optional
4
8
 
5
9
  from opentelemetry import trace
6
10
  from opentelemetry.sdk.trace import TracerProvider
7
11
  from opentelemetry.sdk.resources import Resource
8
- from opentelemetry.instrumentation.openai import OpenAIInstrumentor
9
- from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
10
- from opentelemetry.instrumentation.langchain import LangchainInstrumentor
12
+ # Instrumentors are imported lazily inside methods to avoid import errors
11
13
 
12
14
  from .lucidic_span_processor import LucidicSpanProcessor
13
15
  from .otel_provider import OpenTelemetryProvider
@@ -15,6 +17,10 @@ from lucidicai.client import Client
15
17
 
16
18
  logger = logging.getLogger("Lucidic")
17
19
 
20
+ import threading
21
+
22
+
23
+ _init_lock = threading.Lock()
18
24
 
19
25
  class LucidicTelemetry:
20
26
  """Manages OpenTelemetry initialization for Lucidic"""
@@ -37,59 +43,73 @@ class LucidicTelemetry:
37
43
 
38
44
  def initialize(self, agent_id: str, service_name: str = "lucidic-ai") -> None:
39
45
  """Initialize OpenTelemetry with Lucidic configuration"""
40
- if self.tracer_provider:
41
- logger.debug("OpenTelemetry already initialized")
42
- return
43
-
44
- try:
45
- # Create resource
46
- resource = Resource.create({
47
- "service.name": service_name,
48
- "service.version": "1.0.0",
49
- "lucidic.agent_id": agent_id,
50
- })
51
-
52
- # Create tracer provider
53
- self.tracer_provider = TracerProvider(resource=resource)
54
-
55
- # Add our custom span processor for real-time event handling
56
- self.span_processor = LucidicSpanProcessor()
57
- self.tracer_provider.add_span_processor(self.span_processor)
58
-
59
- # Set as global provider
60
- trace.set_tracer_provider(self.tracer_provider)
61
-
62
- logger.info("[LucidicTelemetry] OpenTelemetry initialized")
63
-
64
- except Exception as e:
65
- logger.error(f"Failed to initialize OpenTelemetry: {e}")
66
- raise
46
+ with _init_lock:
47
+ if self.tracer_provider:
48
+ logger.debug("OpenTelemetry already initialized")
49
+ return
50
+ try:
51
+ resource = Resource.create({
52
+ "service.name": service_name,
53
+ "service.version": "1.0.0",
54
+ "lucidic.agent_id": agent_id,
55
+ })
56
+ provider = TracerProvider(resource=resource)
57
+ processor = LucidicSpanProcessor()
58
+ provider.add_span_processor(processor)
59
+ try:
60
+ trace.set_tracer_provider(provider)
61
+ except Exception as e:
62
+ # Another provider may already be registered; proceed with ours as a local provider
63
+ logger.debug(f"Global tracer provider already set: {e}")
64
+ self.tracer_provider = provider
65
+ self.span_processor = processor
66
+ logger.info("[LucidicTelemetry] OpenTelemetry initialized")
67
+ except Exception as e:
68
+ logger.error(f"Failed to initialize OpenTelemetry: {e}")
69
+ raise
67
70
 
68
71
  def instrument_providers(self, providers: List[str]) -> None:
69
72
  """Instrument specified providers"""
70
- for provider in providers:
71
- try:
72
- if provider == "openai" and provider not in self.instrumentors:
73
- self._instrument_openai()
74
- elif provider == "anthropic" and provider not in self.instrumentors:
75
- self._instrument_anthropic()
76
- elif provider == "langchain" and provider not in self.instrumentors:
77
- self._instrument_langchain()
78
- elif provider == "pydantic_ai":
79
- # Custom instrumentation needed
80
- logger.info(f"[LucidicTelemetry] Pydantic AI will use manual instrumentation")
81
- elif provider == "openai_agents":
82
- # OpenAI Agents uses the same OpenAI instrumentation
83
- self._instrument_openai_agents()
84
- elif provider == "litellm":
85
- # LiteLLM uses callbacks, not OpenTelemetry instrumentation
86
- logger.info(f"[LucidicTelemetry] LiteLLM will use callback-based instrumentation")
87
- except Exception as e:
88
- logger.error(f"Failed to instrument {provider}: {e}")
73
+ with _init_lock:
74
+ for provider in providers:
75
+ # Map synonyms to canonical names
76
+ canonical = provider
77
+ if provider in ("google_generativeai",):
78
+ canonical = "google"
79
+ elif provider in ("vertex_ai",):
80
+ canonical = "vertexai"
81
+ elif provider in ("aws_bedrock", "amazon_bedrock"):
82
+ canonical = "bedrock"
83
+ try:
84
+ if canonical == "openai" and canonical not in self.instrumentors:
85
+ self._instrument_openai()
86
+ elif canonical == "anthropic" and canonical not in self.instrumentors:
87
+ self._instrument_anthropic()
88
+ elif canonical == "langchain" and canonical not in self.instrumentors:
89
+ self._instrument_langchain()
90
+ elif canonical == "google" and canonical not in self.instrumentors:
91
+ self._instrument_google_generativeai()
92
+ elif canonical == "vertexai" and canonical not in self.instrumentors:
93
+ self._instrument_vertexai()
94
+ elif canonical == "bedrock" and canonical not in self.instrumentors:
95
+ self._instrument_bedrock()
96
+ elif canonical == "cohere" and canonical not in self.instrumentors:
97
+ self._instrument_cohere()
98
+ elif canonical == "groq" and canonical not in self.instrumentors:
99
+ self._instrument_groq()
100
+ elif canonical == "pydantic_ai":
101
+ logger.info(f"[LucidicTelemetry] Pydantic AI will use manual instrumentation")
102
+ elif canonical == "openai_agents":
103
+ self._instrument_openai_agents()
104
+ elif canonical == "litellm":
105
+ logger.info(f"[LucidicTelemetry] LiteLLM will use callback-based instrumentation")
106
+ except Exception as e:
107
+ logger.error(f"Failed to instrument {canonical}: {e}")
89
108
 
90
109
  def _instrument_openai(self) -> None:
91
110
  """Instrument OpenAI"""
92
111
  try:
112
+ from opentelemetry.instrumentation.openai import OpenAIInstrumentor
93
113
  # Get client for masking function
94
114
  client = Client()
95
115
 
@@ -125,6 +145,7 @@ class LucidicTelemetry:
125
145
  def _instrument_anthropic(self) -> None:
126
146
  """Instrument Anthropic"""
127
147
  try:
148
+ from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
128
149
  instrumentor = AnthropicInstrumentor()
129
150
 
130
151
  # Get client for context
@@ -153,6 +174,7 @@ class LucidicTelemetry:
153
174
  def _instrument_langchain(self) -> None:
154
175
  """Instrument LangChain"""
155
176
  try:
177
+ from opentelemetry.instrumentation.langchain import LangchainInstrumentor
156
178
  instrumentor = LangchainInstrumentor()
157
179
  instrumentor.instrument(tracer_provider=self.tracer_provider)
158
180
 
@@ -163,6 +185,73 @@ class LucidicTelemetry:
163
185
  logger.error(f"Failed to instrument LangChain: {e}")
164
186
  raise
165
187
 
188
+ def _instrument_google_generativeai(self) -> None:
189
+ """Instrument Google Generative AI"""
190
+ try:
191
+ from opentelemetry.instrumentation.google_generativeai import GoogleGenerativeAiInstrumentor
192
+ instrumentor = GoogleGenerativeAiInstrumentor(exception_logger=lambda e: logger.error(f"Google Generative AI error: {e}"))
193
+ instrumentor.instrument(tracer_provider=self.tracer_provider)
194
+ self.instrumentors["google"] = instrumentor
195
+ logger.info("[LucidicTelemetry] Instrumented Google Generative AI")
196
+ except Exception as e:
197
+ logger.error(f"Failed to instrument Google Generative AI: {e}")
198
+ raise
199
+
200
+ def _instrument_vertexai(self) -> None:
201
+ """Instrument Vertex AI"""
202
+ try:
203
+ from opentelemetry.instrumentation.vertexai import VertexAIInstrumentor
204
+ instrumentor = VertexAIInstrumentor(exception_logger=lambda e: logger.error(f"Vertex AI error: {e}"))
205
+ instrumentor.instrument(tracer_provider=self.tracer_provider)
206
+ self.instrumentors["vertexai"] = instrumentor
207
+ logger.info("[LucidicTelemetry] Instrumented Vertex AI")
208
+ except Exception as e:
209
+ logger.error(f"Failed to instrument Vertex AI: {e}")
210
+ raise
211
+
212
+ def _instrument_cohere(self) -> None:
213
+ """Instrument Cohere"""
214
+ try:
215
+ from opentelemetry.instrumentation.cohere import CohereInstrumentor
216
+ instrumentor = CohereInstrumentor(exception_logger=lambda e: logger.error(f"Cohere error: {e}"), use_legacy_attributes=True)
217
+ instrumentor.instrument(tracer_provider=self.tracer_provider)
218
+ self.instrumentors["cohere"] = instrumentor
219
+ logger.info("[LucidicTelemetry] Instrumented Cohere")
220
+ except Exception as e:
221
+ logger.error(f"Failed to instrument Cohere: {e}")
222
+ raise
223
+
224
+ def _instrument_bedrock(self) -> None:
225
+ """Instrument AWS Bedrock"""
226
+ try:
227
+ from opentelemetry.instrumentation.bedrock import BedrockInstrumentor
228
+ instrumentor = BedrockInstrumentor(enrich_token_usage=True, exception_logger=lambda e: logger.error(f"Bedrock error: {e}"))
229
+ instrumentor.instrument(tracer_provider=self.tracer_provider)
230
+ self.instrumentors["bedrock"] = instrumentor
231
+ logger.info("[LucidicTelemetry] Instrumented Bedrock")
232
+ except Exception as e:
233
+ logger.error(f"Failed to instrument Bedrock: {e}")
234
+ raise
235
+
236
+ def _instrument_groq(self) -> None:
237
+ """Instrument Groq"""
238
+ try:
239
+ from lucidicai.client import Client
240
+ client = Client()
241
+ def get_custom_attributes():
242
+ attrs = {}
243
+ if client.session and client.session.active_step:
244
+ attrs["lucidic.step_id"] = client.session.active_step.step_id
245
+ return attrs
246
+ from opentelemetry.instrumentation.groq import GroqInstrumentor
247
+ instrumentor = GroqInstrumentor(exception_logger=lambda e: logger.error(f"Groq error: {e}"), use_legacy_attributes=True, get_common_metrics_attributes=get_custom_attributes)
248
+ instrumentor.instrument(tracer_provider=self.tracer_provider)
249
+ self.instrumentors["groq"] = instrumentor
250
+ logger.info("[LucidicTelemetry] Instrumented Groq")
251
+ except Exception as e:
252
+ logger.error(f"Failed to instrument Groq: {e}")
253
+ raise
254
+
166
255
  def _instrument_openai_agents(self) -> None:
167
256
  """Instrument OpenAI Agents SDK"""
168
257
  try:
@@ -197,4 +286,27 @@ class LucidicTelemetry:
197
286
 
198
287
  def is_initialized(self) -> bool:
199
288
  """Check if telemetry is initialized"""
200
- return self.tracer_provider is not None
289
+ return self.tracer_provider is not None
290
+
291
+ def force_flush(self) -> None:
292
+ """Best-effort force flush of telemetry before shutdown.
293
+
294
+ Uses whichever force_flush hooks are available on the provider or span processor.
295
+ Swallows all exceptions to avoid interfering with process shutdown paths.
296
+ """
297
+ try:
298
+ provider = getattr(self, 'tracer_provider', None)
299
+ if provider and hasattr(provider, 'force_flush'):
300
+ try:
301
+ provider.force_flush()
302
+ except Exception:
303
+ pass
304
+ processor = getattr(self, 'span_processor', None)
305
+ if processor and hasattr(processor, 'force_flush'):
306
+ try:
307
+ processor.force_flush()
308
+ except Exception:
309
+ pass
310
+ except Exception:
311
+ # Never raise from force_flush
312
+ pass
@@ -8,12 +8,11 @@ from opentelemetry.trace import Tracer, Span
8
8
  from opentelemetry.sdk.trace import TracerProvider
9
9
  from opentelemetry.sdk.trace.export import BatchSpanProcessor
10
10
  from opentelemetry.sdk.resources import Resource
11
- from opentelemetry.instrumentation.openai import OpenAIInstrumentor
12
- from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
13
- from opentelemetry.instrumentation.langchain import LangchainInstrumentor
11
+ # Instrumentors are imported lazily inside methods to avoid import errors
14
12
  from opentelemetry.semconv_ai import SpanAttributes
15
13
 
16
14
  from .lucidic_exporter import LucidicSpanExporter
15
+ from .lucidic_span_processor import LucidicSpanProcessor
17
16
  from .base_provider import BaseProvider
18
17
  from lucidicai.client import Client
19
18
 
@@ -47,9 +46,17 @@ class OpenTelemetryProvider(BaseProvider):
47
46
  lucidic_exporter = LucidicSpanExporter()
48
47
  span_processor = BatchSpanProcessor(lucidic_exporter)
49
48
  self.tracer_provider.add_span_processor(span_processor)
49
+ # Also add session-stamping processor to ensure correct attribution
50
+ try:
51
+ self.tracer_provider.add_span_processor(LucidicSpanProcessor())
52
+ except Exception:
53
+ pass
50
54
 
51
- # Set as global provider
52
- trace.set_tracer_provider(self.tracer_provider)
55
+ # Set as global provider (ignore if already set)
56
+ try:
57
+ trace.set_tracer_provider(self.tracer_provider)
58
+ except Exception:
59
+ pass
53
60
 
54
61
  # Get tracer
55
62
  self.tracer = trace.get_tracer(__name__)
@@ -93,6 +100,7 @@ class OpenTelemetryProvider(BaseProvider):
93
100
  """Instrument OpenAI with OpenLLMetry"""
94
101
  if "openai" not in self.instrumentors:
95
102
  try:
103
+ from opentelemetry.instrumentation.openai import OpenAIInstrumentor
96
104
  instrumentor = OpenAIInstrumentor()
97
105
  instrumentor.instrument(
98
106
  tracer_provider=self.tracer_provider,
@@ -108,6 +116,7 @@ class OpenTelemetryProvider(BaseProvider):
108
116
  """Instrument Anthropic with OpenLLMetry"""
109
117
  if "anthropic" not in self.instrumentors:
110
118
  try:
119
+ from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
111
120
  instrumentor = AnthropicInstrumentor()
112
121
  instrumentor.instrument(
113
122
  tracer_provider=self.tracer_provider,
@@ -122,6 +131,7 @@ class OpenTelemetryProvider(BaseProvider):
122
131
  """Instrument LangChain with OpenLLMetry"""
123
132
  if "langchain" not in self.instrumentors:
124
133
  try:
134
+ from opentelemetry.instrumentation.langchain import LangchainInstrumentor
125
135
  instrumentor = LangchainInstrumentor()
126
136
  instrumentor.instrument(tracer_provider=self.tracer_provider)
127
137
  self.instrumentors["langchain"] = instrumentor
@@ -124,6 +124,35 @@ class UniversalImageInterceptor:
124
124
  logger.info(f"[Universal Interceptor] Stored Google image, placeholder: {placeholder}")
125
125
  processed_messages.append(message)
126
126
  return processed_messages
127
+
128
+ @staticmethod
129
+ def extract_and_store_images_genai_contents(contents: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
130
+ """Extract and store images/text from google.genai 'contents' structure
131
+
132
+ Example:
133
+ contents = [
134
+ {"text": "What's in this image?"},
135
+ {"inline_data": {"mime_type": "image/jpeg", "data": "..."}}
136
+ ]
137
+ """
138
+ if not isinstance(contents, list):
139
+ return contents
140
+ clear_stored_texts()
141
+ texts = []
142
+ for item in contents:
143
+ if isinstance(item, dict):
144
+ if 'text' in item and isinstance(item['text'], str):
145
+ texts.append(item['text'])
146
+ elif 'inline_data' in item and isinstance(item['inline_data'], dict):
147
+ data = item['inline_data'].get('data', '')
148
+ mime = item['inline_data'].get('mime_type', 'image/jpeg')
149
+ if data:
150
+ data_url = f"data:{mime};base64,{data}"
151
+ store_image(data_url)
152
+ if texts:
153
+ combined = ' '.join(texts)
154
+ store_text(combined, 0)
155
+ return contents
127
156
 
128
157
  @staticmethod
129
158
  def intercept_images(messages: Any, provider: str = "auto") -> Any:
@@ -273,4 +302,64 @@ def patch_google_client(client):
273
302
  client.generate_content = interceptor(original_generate)
274
303
  if DEBUG:
275
304
  logger.info("[Universal Interceptor] Patched Google client for image interception")
305
+ return client
306
+
307
+
308
+ def patch_google_genai() -> None:
309
+ """Patch google.genai to intercept images/text passed via contents
310
+ Wraps Models.generate_content and AsyncModels.generate_content
311
+ """
312
+ try:
313
+ from google.genai import models as genai_models
314
+ except Exception:
315
+ return
316
+
317
+ def wrap_generate_content(original_func):
318
+ def wrapper(*args, **kwargs):
319
+ contents = kwargs.get('contents', None)
320
+ if contents is None and len(args) >= 2:
321
+ # Likely signature: (self, contents=..., ...)
322
+ contents = args[1]
323
+ if contents is not None:
324
+ try:
325
+ UniversalImageInterceptor.extract_and_store_images_genai_contents(contents)
326
+ except Exception:
327
+ pass
328
+ return original_func(*args, **kwargs)
329
+ return wrapper
330
+
331
+ # Patch sync Models
332
+ try:
333
+ if hasattr(genai_models, 'Models') and hasattr(genai_models.Models, 'generate_content'):
334
+ original = genai_models.Models.generate_content
335
+ if not getattr(original, '__lucidic_patched__', False):
336
+ patched = wrap_generate_content(original)
337
+ setattr(patched, '__lucidic_patched__', True)
338
+ genai_models.Models.generate_content = patched
339
+ except Exception:
340
+ pass
341
+
342
+ # Patch async Models (if present)
343
+ try:
344
+ if hasattr(genai_models, 'AsyncModels') and hasattr(genai_models.AsyncModels, 'generate_content'):
345
+ original_async = genai_models.AsyncModels.generate_content
346
+ if not getattr(original_async, '__lucidic_patched__', False):
347
+ patched_async = wrap_generate_content(original_async)
348
+ setattr(patched_async, '__lucidic_patched__', True)
349
+ genai_models.AsyncModels.generate_content = patched_async
350
+ except Exception:
351
+ pass
352
+
353
+
354
+ def patch_vertexai_client(client):
355
+ """Patch a Vertex AI client/model instance to intercept images (Google format)"""
356
+ interceptor = UniversalImageInterceptor.create_interceptor("google")
357
+
358
+ # Vertex AI GenerativeModel has generate_content / generate_content_async
359
+ if hasattr(client, 'generate_content'):
360
+ original_generate = client.generate_content
361
+ client.generate_content = interceptor(original_generate)
362
+ if hasattr(client, 'generate_content_async'):
363
+ original_generate_async = getattr(client, 'generate_content_async')
364
+ client.generate_content_async = UniversalImageInterceptor.create_async_interceptor("google")(original_generate_async)
276
365
  return client
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lucidicai
3
- Version: 1.3.1
3
+ Version: 1.3.5
4
4
  Summary: Lucidic AI Python SDK
5
5
  Author: Andy Liang
6
6
  Author-email: andy@lucidic.ai
@@ -1,14 +1,15 @@
1
- lucidicai/__init__.py,sha256=-eSSR9UaMubE0KpbesR2jLU0xUn37oucMNxjgKaCfkA,20738
1
+ lucidicai/__init__.py,sha256=bac3gGZ1Rxn4ZRr4hYssPcucdfHDTD2yTlAGfP1cqzM,29840
2
2
  lucidicai/action.py,sha256=sPRd1hTIVXDqnvG9ZXWEipUFh0bsXcE0Fm7RVqmVccM,237
3
- lucidicai/client.py,sha256=MZuNd1S6MTwNRDJ8cUrZfnTZgBBHFwTO2Pc_-wbVNEM,8981
3
+ lucidicai/client.py,sha256=qTY0LIuG6NbdV4Gy09poqDDe-pFnlWtEQi7Xhf2exNE,9856
4
4
  lucidicai/constants.py,sha256=_u0z3M4geZgS1g-CrOZUVjtcew8l70dKQnpVQvlXh9w,2172
5
- lucidicai/decorators.py,sha256=oqXyfHk9f9UmeaIquuU8mtzed1qZtO_-svwadpoat6g,13950
5
+ lucidicai/context.py,sha256=R3YRxRMnzKt-RqG1FkcT7__o-cyKRcvSzqonzRNBkZk,3975
6
+ lucidicai/decorators.py,sha256=Z3w7AHXoYwZcvcu_Q0yNsSfkFd42fuQPscb4B0PPq6A,14542
6
7
  lucidicai/errors.py,sha256=gTg0bdzjuTcUnakRbZnxjngO4gZnRLVwRHRglpZZJsM,970
7
- lucidicai/event.py,sha256=EF-KNPMBHGdNnhchu5HF7QnYJSMofUaq-QuGL0j_OAE,2521
8
+ lucidicai/event.py,sha256=2Rxa4EDLFBTBFTNXD4sjQ9DCMLiloFQqugL7unyYcL4,2642
8
9
  lucidicai/image_upload.py,sha256=6SRudg-BpInM2gzMx1Yf1Rz_Zyh8inwoJ7U4pBw7ruY,3807
9
10
  lucidicai/lru.py,sha256=PXiDSoUCOxjamG1QlQx6pDbQCm8h5hKAnnr_NI0PEgE,618
10
- lucidicai/model_pricing.py,sha256=o1yWCaF5Qxj4tloXxVG3SZXcTMKtk56J_Nfdo8M4uR0,11947
11
- lucidicai/session.py,sha256=NFkWJioqGcRxHjfqwWw-1DZSiScNpnUlY1gtGGApqSQ,4060
11
+ lucidicai/model_pricing.py,sha256=Dxi6e0WjcIyCTkVX7K7f0pJ5rPu7nSt3lOmgzAUQl1o,12402
12
+ lucidicai/session.py,sha256=bSI6_kOHQEuk7z8NtNbU_RZoc41UxhwWrztwScFuNTw,4068
12
13
  lucidicai/singleton.py,sha256=gfT3XdWLXSIWMqDXbY6-pnesMZ8RGRitaEPhIsgrRPw,1272
13
14
  lucidicai/state.py,sha256=4Tb1X6l2or6w_e62FYSuEeghAv3xXm5gquKwzCpvdok,235
14
15
  lucidicai/step.py,sha256=_oBIyTBZBvNkUkYHIrwWd75KMSlMtR9Ws2Lo71Lyff8,2522
@@ -33,19 +34,19 @@ lucidicai/providers/universal_image_interceptor.py,sha256=7d-hw4xihRwvvA1AP8-vqY
33
34
  lucidicai/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
35
  lucidicai/telemetry/base_provider.py,sha256=nrZVr4Y9xcAiMn4uAN3t3k6DlHNTvlXrA4qQg7lANOQ,544
35
36
  lucidicai/telemetry/litellm_bridge.py,sha256=mOdjEfvP--ToDv8snoOMU4pRQx_Yg4s2o3BMTMzeRK8,14979
36
- lucidicai/telemetry/lucidic_exporter.py,sha256=h2GOnEk22Fpeke4Zc7SSk391yr0joUApVwolV5Q4hz4,10818
37
- lucidicai/telemetry/lucidic_span_processor.py,sha256=9EKD4fvnEQIoPBLhGCAHRxsLAWmJNGFnb1NpwRUlMOI,30048
37
+ lucidicai/telemetry/lucidic_exporter.py,sha256=XAeMQClz5MbGb8ziNT9bhAk3bcqTAkcMxJHvxKAjbCk,11435
38
+ lucidicai/telemetry/lucidic_span_processor.py,sha256=-jo7Muuslo3ZCSAysLsDGBqJijQSpIOvJHPbPNjP4iQ,31029
38
39
  lucidicai/telemetry/openai_agents_instrumentor.py,sha256=__wIbeglMnEEf4AGTQ--FXeWCKmz2yy8SBupwprEdZA,12694
39
40
  lucidicai/telemetry/opentelemetry_converter.py,sha256=xOHCqoTyO4hUkL6k7fxy84PbljPpYep6ET9ZqbkJehc,17665
40
- lucidicai/telemetry/otel_handlers.py,sha256=HqGYIWJI_Vp8So2-HMpPjnrgTBSgBHHLDu01z_sq-Qk,14646
41
- lucidicai/telemetry/otel_init.py,sha256=d0JcdDD23U_0xyBCAPOcZkFuOwv_7kI9Mih4msin6fw,7997
42
- lucidicai/telemetry/otel_provider.py,sha256=GZPhSEsEPVKrr5A0u5-WNn7OmxNgRWBcam9dyqjf91o,7042
41
+ lucidicai/telemetry/otel_handlers.py,sha256=OCzXuYog6AuwjI4eXy5Sk40DUehyz48QOxuOujXnEVU,20859
42
+ lucidicai/telemetry/otel_init.py,sha256=hjUOX8nEBLrDOuh0UTKFfG-C98yFZHTiP8ql59bmNXY,13780
43
+ lucidicai/telemetry/otel_provider.py,sha256=e5XcpQTd_a5UrMAq-EQcJ0zUJpO7NO16T-BphVUigR4,7513
43
44
  lucidicai/telemetry/pydantic_ai_handler.py,sha256=WPa3tFcVgVnPPO3AxcNOTbNkmODLgNOrU2_3GVtWqUw,28261
44
45
  lucidicai/telemetry/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
46
  lucidicai/telemetry/utils/image_storage.py,sha256=4Z59ZpVexr7-lcExfr8GsqXe0y2VZmr8Yjwa-3DeOxU,1457
46
47
  lucidicai/telemetry/utils/text_storage.py,sha256=L62MMJ8E23TDqDTUv2aRntdKMCItsXV7XjY6cFwx2DE,1503
47
- lucidicai/telemetry/utils/universal_image_interceptor.py,sha256=zPfVsMjtKxJP2n2OOjKbtPiQJTZ0sf5_28GWprOnJP4,12185
48
- lucidicai-1.3.1.dist-info/METADATA,sha256=fMRzVo9mOgHvcC6PGrH5zdyLaMRrz3KBch6fMkHtgEE,902
49
- lucidicai-1.3.1.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
50
- lucidicai-1.3.1.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
51
- lucidicai-1.3.1.dist-info/RECORD,,
48
+ lucidicai/telemetry/utils/universal_image_interceptor.py,sha256=vARgMk1hVSF--zfi5b8qBpJJOESuD17YlH9xqxmB9Uw,15954
49
+ lucidicai-1.3.5.dist-info/METADATA,sha256=u-IHX3Y158OpO3FlhYjNMklIr1UB_1xqOz0HnURiiug,902
50
+ lucidicai-1.3.5.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
51
+ lucidicai-1.3.5.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
52
+ lucidicai-1.3.5.dist-info/RECORD,,