lucidicai 1.3.2__py3-none-any.whl → 2.0.1__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.
@@ -0,0 +1,189 @@
1
+ """Unified telemetry initialization - SpanExporter-only architecture.
2
+
3
+ Provides functions to instrument OpenTelemetry providers.
4
+ Provider creation is now handled by the Client singleton.
5
+ """
6
+ import logging
7
+ import threading
8
+ from typing import Dict, Any, Optional
9
+
10
+ from opentelemetry.sdk.trace import TracerProvider
11
+
12
+ logger = logging.getLogger("Lucidic")
13
+
14
+ # Global tracking to prevent duplicate instrumentation
15
+ _global_instrumentors = {}
16
+ _instrumentation_lock = threading.Lock()
17
+
18
+
19
+ def instrument_providers(providers: list, tracer_provider: TracerProvider, existing_instrumentors: Dict[str, Any]) -> Dict[str, Any]:
20
+ """
21
+ Instrument the requested providers with the given TracerProvider.
22
+ Only instruments providers that haven't been instrumented yet.
23
+ Uses global tracking to prevent duplicate instrumentation across threads.
24
+
25
+ Args:
26
+ providers: List of provider names to instrument
27
+ tracer_provider: The TracerProvider to use for instrumentation
28
+ existing_instrumentors: Dict of already instrumented providers (ignored, kept for compatibility)
29
+
30
+ Returns:
31
+ Dict of newly instrumented providers (name -> instrumentor)
32
+ """
33
+ global _global_instrumentors
34
+ new_instrumentors = {}
35
+
36
+ # Normalize provider names
37
+ canonical = set()
38
+ for p in providers or []:
39
+ if p in ("google_generativeai",):
40
+ canonical.add("google")
41
+ elif p in ("vertex_ai",):
42
+ canonical.add("vertexai")
43
+ elif p in ("aws_bedrock", "amazon_bedrock"):
44
+ canonical.add("bedrock")
45
+ else:
46
+ canonical.add(p)
47
+
48
+ # Use global lock to prevent race conditions
49
+ with _instrumentation_lock:
50
+ # OpenAI
51
+ if "openai" in canonical and "openai" not in _global_instrumentors:
52
+ try:
53
+ from opentelemetry.instrumentation.openai import OpenAIInstrumentor
54
+ inst = OpenAIInstrumentor()
55
+ inst.instrument(tracer_provider=tracer_provider, enrich_token_usage=True)
56
+ _global_instrumentors["openai"] = inst
57
+ new_instrumentors["openai"] = inst
58
+ logger.info("[Telemetry] Instrumented OpenAI")
59
+ except Exception as e:
60
+ logger.error(f"Failed to instrument OpenAI: {e}")
61
+
62
+ # Anthropic
63
+ if "anthropic" in canonical and "anthropic" not in _global_instrumentors:
64
+ try:
65
+ from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
66
+ inst = AnthropicInstrumentor()
67
+ inst.instrument(tracer_provider=tracer_provider)
68
+ _global_instrumentors["anthropic"] = inst
69
+ new_instrumentors["anthropic"] = inst
70
+ logger.info("[Telemetry] Instrumented Anthropic")
71
+ except Exception as e:
72
+ logger.error(f"Failed to instrument Anthropic: {e}")
73
+
74
+ # LangChain
75
+ if "langchain" in canonical and "langchain" not in _global_instrumentors:
76
+ try:
77
+ from opentelemetry.instrumentation.langchain import LangchainInstrumentor
78
+ inst = LangchainInstrumentor()
79
+ inst.instrument(tracer_provider=tracer_provider)
80
+ _global_instrumentors["langchain"] = inst
81
+ new_instrumentors["langchain"] = inst
82
+ logger.info("[Telemetry] Instrumented LangChain")
83
+ except Exception as e:
84
+ logger.error(f"Failed to instrument LangChain: {e}")
85
+
86
+ # Google Generative AI
87
+ if "google" in canonical and "google" not in _global_instrumentors:
88
+ try:
89
+ from opentelemetry.instrumentation.google_generativeai import GoogleGenerativeAiInstrumentor
90
+ inst = GoogleGenerativeAiInstrumentor()
91
+ inst.instrument(tracer_provider=tracer_provider)
92
+ _global_instrumentors["google"] = inst
93
+ new_instrumentors["google"] = inst
94
+ logger.info("[Telemetry] Instrumented Google Generative AI")
95
+ except Exception as e:
96
+ logger.error(f"Failed to instrument Google Generative AI: {e}")
97
+
98
+ # Vertex AI
99
+ if "vertexai" in canonical and "vertexai" not in _global_instrumentors:
100
+ try:
101
+ from opentelemetry.instrumentation.vertexai import VertexAIInstrumentor
102
+ inst = VertexAIInstrumentor()
103
+ inst.instrument(tracer_provider=tracer_provider)
104
+ _global_instrumentors["vertexai"] = inst
105
+ new_instrumentors["vertexai"] = inst
106
+ logger.info("[Telemetry] Instrumented Vertex AI")
107
+ except Exception as e:
108
+ logger.error(f"Failed to instrument Vertex AI: {e}")
109
+
110
+ # Bedrock
111
+ if "bedrock" in canonical and "bedrock" not in _global_instrumentors:
112
+ try:
113
+ from opentelemetry.instrumentation.bedrock import BedrockInstrumentor
114
+ inst = BedrockInstrumentor(enrich_token_usage=True)
115
+ inst.instrument(tracer_provider=tracer_provider)
116
+ _global_instrumentors["bedrock"] = inst
117
+ new_instrumentors["bedrock"] = inst
118
+ logger.info("[Telemetry] Instrumented Bedrock")
119
+ except Exception as e:
120
+ logger.error(f"Failed to instrument Bedrock: {e}")
121
+
122
+ # Cohere
123
+ if "cohere" in canonical and "cohere" not in _global_instrumentors:
124
+ try:
125
+ from opentelemetry.instrumentation.cohere import CohereInstrumentor
126
+ inst = CohereInstrumentor()
127
+ inst.instrument(tracer_provider=tracer_provider)
128
+ _global_instrumentors["cohere"] = inst
129
+ new_instrumentors["cohere"] = inst
130
+ logger.info("[Telemetry] Instrumented Cohere")
131
+ except Exception as e:
132
+ logger.error(f"Failed to instrument Cohere: {e}")
133
+
134
+ # Groq
135
+ if "groq" in canonical and "groq" not in _global_instrumentors:
136
+ try:
137
+ from opentelemetry.instrumentation.groq import GroqInstrumentor
138
+ inst = GroqInstrumentor()
139
+ inst.instrument(tracer_provider=tracer_provider)
140
+ _global_instrumentors["groq"] = inst
141
+ new_instrumentors["groq"] = inst
142
+ logger.info("[Telemetry] Instrumented Groq")
143
+ except Exception as e:
144
+ logger.error(f"Failed to instrument Groq: {e}")
145
+
146
+ # LiteLLM - callback-based (not OpenTelemetry)
147
+ if "litellm" in canonical and "litellm" not in _global_instrumentors:
148
+ logger.info("[Telemetry] LiteLLM uses callback-based instrumentation")
149
+ # LiteLLM requires setup via litellm_bridge.py
150
+ try:
151
+ from .litellm_bridge import setup_litellm_callback
152
+ setup_litellm_callback()
153
+ _global_instrumentors["litellm"] = None # No instrumentor object
154
+ new_instrumentors["litellm"] = None
155
+ except Exception as e:
156
+ logger.error(f"Failed to setup LiteLLM: {e}")
157
+
158
+ # Pydantic AI - manual spans
159
+ if "pydantic_ai" in canonical and "pydantic_ai" not in _global_instrumentors:
160
+ logger.info("[Telemetry] Pydantic AI requires manual span creation")
161
+ # No automatic instrumentation available
162
+ _global_instrumentors["pydantic_ai"] = None
163
+ new_instrumentors["pydantic_ai"] = None
164
+
165
+ # OpenAI Agents - custom instrumentor
166
+ if "openai_agents" in canonical and "openai_agents" not in _global_instrumentors:
167
+ try:
168
+ from .openai_agents_instrumentor import OpenAIAgentsInstrumentor
169
+ inst = OpenAIAgentsInstrumentor(tracer_provider=tracer_provider)
170
+ inst.instrument()
171
+ _global_instrumentors["openai_agents"] = inst
172
+ new_instrumentors["openai_agents"] = inst
173
+ logger.info("[Telemetry] Instrumented OpenAI Agents SDK")
174
+ except Exception as e:
175
+ logger.error(f"Failed to instrument OpenAI Agents: {e}")
176
+
177
+ return new_instrumentors
178
+
179
+
180
+ # Keep the old function for backward compatibility (deprecated)
181
+ def initialize_telemetry(providers: list, agent_id: str):
182
+ """
183
+ DEPRECATED: Use Client.initialize_telemetry() instead.
184
+ This function is kept for backward compatibility but will not work correctly
185
+ in multi-threaded environments.
186
+ """
187
+ logger.warning("[Telemetry] initialize_telemetry() is deprecated. Telemetry should be initialized via Client.")
188
+ # Return empty tuple to satisfy old callers
189
+ return None, []
@@ -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.2
3
+ Version: 2.0.1
4
4
  Summary: Lucidic AI Python SDK
5
5
  Author: Andy Liang
6
6
  Author-email: andy@lucidic.ai
@@ -1,18 +1,22 @@
1
- lucidicai/__init__.py,sha256=KAjcOBwj4ENz1IxsrVS2gmuzn14tiPNNCtSczjEeDZ0,21617
1
+ lucidicai/__init__.py,sha256=3gm2pFPTndvfx1zalGWqBdbdkUE_DDvAPbtsoIV5720,35879
2
2
  lucidicai/action.py,sha256=sPRd1hTIVXDqnvG9ZXWEipUFh0bsXcE0Fm7RVqmVccM,237
3
- lucidicai/client.py,sha256=s3EKrtcgMXGxEyguxQihncPz8AEXxSG32PXSNdOCvNg,9111
4
- lucidicai/constants.py,sha256=_u0z3M4geZgS1g-CrOZUVjtcew8l70dKQnpVQvlXh9w,2172
5
- lucidicai/decorators.py,sha256=Z3w7AHXoYwZcvcu_Q0yNsSfkFd42fuQPscb4B0PPq6A,14542
6
- lucidicai/errors.py,sha256=gTg0bdzjuTcUnakRbZnxjngO4gZnRLVwRHRglpZZJsM,970
7
- lucidicai/event.py,sha256=2Rxa4EDLFBTBFTNXD4sjQ9DCMLiloFQqugL7unyYcL4,2642
3
+ lucidicai/client.py,sha256=dRSwOAGth_b-RRBjLuxhPI75ULpQHP7M-KfP9X-XYjY,22172
4
+ lucidicai/constants.py,sha256=zN8O7TjoRHRlaGa9CZUWppS73rhzKGwaEkF9XMTV0Cg,1160
5
+ lucidicai/context.py,sha256=ruEXAndSv0gQ-YEXLlC4Fx6NNbaylfp_dZxbpwmLZSA,4622
6
+ lucidicai/dataset.py,sha256=IgWCUhoclq1ZzSNc22UHd3fLs0hJv9A81OQizjbHtiE,3951
7
+ lucidicai/decorators.py,sha256=obpHbGLhRd-yIL5xIqzjNmf-ZKCIIx5vlYnMpCcJ7Uo,5416
8
+ lucidicai/errors.py,sha256=XT9UiYVoi88VsxrD2RU96l6mwCmxSeICOWhghB0iJ7Y,2058
9
+ lucidicai/event.py,sha256=ObPXS22QIB-n4eHxzEimTtrlOxC1L6_eQVUAx4ZIT7s,2089
10
+ lucidicai/event_queue.py,sha256=7Y8hkrm0a7EGCBN2oW_XWd-GkJ9Cihnu2Gyk6FMftks,20065
11
+ lucidicai/feature_flag.py,sha256=Hfcoqqb5VimuaY1Q0NXl08elxQWG97KqzRpaMfE4PYA,11841
8
12
  lucidicai/image_upload.py,sha256=6SRudg-BpInM2gzMx1Yf1Rz_Zyh8inwoJ7U4pBw7ruY,3807
9
13
  lucidicai/lru.py,sha256=PXiDSoUCOxjamG1QlQx6pDbQCm8h5hKAnnr_NI0PEgE,618
10
- lucidicai/model_pricing.py,sha256=o1yWCaF5Qxj4tloXxVG3SZXcTMKtk56J_Nfdo8M4uR0,11947
11
- lucidicai/session.py,sha256=bSI6_kOHQEuk7z8NtNbU_RZoc41UxhwWrztwScFuNTw,4068
12
- lucidicai/singleton.py,sha256=gfT3XdWLXSIWMqDXbY6-pnesMZ8RGRitaEPhIsgrRPw,1272
14
+ lucidicai/model_pricing.py,sha256=Dxi6e0WjcIyCTkVX7K7f0pJ5rPu7nSt3lOmgzAUQl1o,12402
15
+ lucidicai/session.py,sha256=wHnjUPo7ANzJAdz_llA4EXKeCAm0WZR0Ij9dNvdCodY,1729
16
+ lucidicai/singleton.py,sha256=SKiNBgt_Wb5cCWbMt3IWjRAQw3v153LTRgqvDj8poF8,1457
13
17
  lucidicai/state.py,sha256=4Tb1X6l2or6w_e62FYSuEeghAv3xXm5gquKwzCpvdok,235
14
18
  lucidicai/step.py,sha256=_oBIyTBZBvNkUkYHIrwWd75KMSlMtR9Ws2Lo71Lyff8,2522
15
- lucidicai/streaming.py,sha256=Y59vQOqhcOvTQWSAIamAnGCaQqCZz77N62_V2fuQlFA,11565
19
+ lucidicai/streaming.py,sha256=QOLAzhwxetvx711J8VcphY5kXWPJz9XEBJrmHveRKMc,9796
16
20
  lucidicai/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
21
  lucidicai/providers/anthropic_handler.py,sha256=GZEa4QOrjZ9ftu_qTwY3L410HwKzkXgN7omYRsEQ4LU,10174
18
22
  lucidicai/providers/base_providers.py,sha256=nrZVr4Y9xcAiMn4uAN3t3k6DlHNTvlXrA4qQg7lANOQ,544
@@ -32,20 +36,23 @@ lucidicai/providers/text_storage.py,sha256=L62MMJ8E23TDqDTUv2aRntdKMCItsXV7XjY6c
32
36
  lucidicai/providers/universal_image_interceptor.py,sha256=7d-hw4xihRwvvA1AP8-vqYNChtmVXKmn09MN4pDS7KQ,12126
33
37
  lucidicai/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
38
  lucidicai/telemetry/base_provider.py,sha256=nrZVr4Y9xcAiMn4uAN3t3k6DlHNTvlXrA4qQg7lANOQ,544
35
- 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
39
+ lucidicai/telemetry/context_capture_processor.py,sha256=k4_uTaoOhLeUAZsyUcDExVNXadk0nR4R1hJW096EVwY,2472
40
+ lucidicai/telemetry/extract.py,sha256=30Iqvnr9I0EkD61GRCMN0Zpk3fLmRYcuVajWjRz0z9I,6814
41
+ lucidicai/telemetry/litellm_bridge.py,sha256=CFXVu8nduBtJEhv21maNMrkXV_x5ropy--7qr6HAjh8,16542
42
+ lucidicai/telemetry/lucidic_exporter.py,sha256=PfUB5a5o6av1YbYj52WQ-I71q8PBja3xvYTRWItFDPc,11029
43
+ lucidicai/telemetry/lucidic_span_processor.py,sha256=-jo7Muuslo3ZCSAysLsDGBqJijQSpIOvJHPbPNjP4iQ,31029
38
44
  lucidicai/telemetry/openai_agents_instrumentor.py,sha256=__wIbeglMnEEf4AGTQ--FXeWCKmz2yy8SBupwprEdZA,12694
39
45
  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
46
+ lucidicai/telemetry/otel_handlers.py,sha256=OCzXuYog6AuwjI4eXy5Sk40DUehyz48QOxuOujXnEVU,20859
47
+ lucidicai/telemetry/otel_init.py,sha256=hjUOX8nEBLrDOuh0UTKFfG-C98yFZHTiP8ql59bmNXY,13780
48
+ lucidicai/telemetry/otel_provider.py,sha256=e5XcpQTd_a5UrMAq-EQcJ0zUJpO7NO16T-BphVUigR4,7513
43
49
  lucidicai/telemetry/pydantic_ai_handler.py,sha256=WPa3tFcVgVnPPO3AxcNOTbNkmODLgNOrU2_3GVtWqUw,28261
50
+ lucidicai/telemetry/telemetry_init.py,sha256=8RMzZeeHYvaJKaM5KeSt0svaUAqODHmLstECjgHr8fc,8660
44
51
  lucidicai/telemetry/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
52
  lucidicai/telemetry/utils/image_storage.py,sha256=4Z59ZpVexr7-lcExfr8GsqXe0y2VZmr8Yjwa-3DeOxU,1457
46
53
  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.2.dist-info/METADATA,sha256=sGAV3cdtrPBKSB-f2OOenESBbvJNeoV4ipwupEJ42r0,902
49
- lucidicai-1.3.2.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
50
- lucidicai-1.3.2.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
51
- lucidicai-1.3.2.dist-info/RECORD,,
54
+ lucidicai/telemetry/utils/universal_image_interceptor.py,sha256=vARgMk1hVSF--zfi5b8qBpJJOESuD17YlH9xqxmB9Uw,15954
55
+ lucidicai-2.0.1.dist-info/METADATA,sha256=DOyezEU2bp3jBJOiNkXIOOZu55NRdLXztk95jZf9rwA,902
56
+ lucidicai-2.0.1.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
57
+ lucidicai-2.0.1.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
58
+ lucidicai-2.0.1.dist-info/RECORD,,