lmnr 0.7.3__py3-none-any.whl → 0.7.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.
@@ -46,7 +46,7 @@ INJECT_PLACEHOLDER = """
46
46
  (mask_input_options) => {
47
47
  const BATCH_TIMEOUT = 2000; // Send events after 2 seconds
48
48
  const MAX_WORKER_PROMISES = 50; // Max concurrent worker promises
49
- const HEARTBEAT_INTERVAL = 1000;
49
+ const HEARTBEAT_INTERVAL = 2000;
50
50
  const CHUNK_SIZE = 256 * 1024; // 256KB chunks
51
51
  const CHUNK_SEND_DELAY = 100; // 100ms delay between chunks
52
52
 
@@ -287,6 +287,7 @@ INJECT_PLACEHOLDER = """
287
287
  compressionWorker.onerror = (error) => {
288
288
  console.error('Compression worker error:', error);
289
289
  cleanupWorker();
290
+ compressSmallObject(data).then(resolve, reject);
290
291
  };
291
292
  }
292
293
 
@@ -533,14 +534,17 @@ def get_mask_input_setting() -> MaskInputOptions:
533
534
  """Get the mask_input setting from session recording configuration."""
534
535
  try:
535
536
  config = TracerWrapper.get_session_recording_options()
536
- return config.get("mask_input_options", MaskInputOptions(
537
- textarea=False,
538
- text=False,
539
- number=False,
540
- select=False,
541
- email=False,
542
- tel=False,
543
- ))
537
+ return config.get(
538
+ "mask_input_options",
539
+ MaskInputOptions(
540
+ textarea=False,
541
+ text=False,
542
+ number=False,
543
+ select=False,
544
+ email=False,
545
+ tel=False,
546
+ ),
547
+ )
544
548
  except (AttributeError, Exception):
545
549
  # Fallback to default configuration if TracerWrapper is not initialized
546
550
  return MaskInputOptions(
@@ -632,54 +636,56 @@ def start_recording_events_sync(page: SyncPage, session_id: str, client: Laminar
632
636
  span = trace.get_current_span(ctx)
633
637
  trace_id = format(span.get_span_context().trace_id, "032x")
634
638
  span.set_attribute("lmnr.internal.has_browser_session", True)
635
-
639
+
636
640
  # Buffer for reassembling chunks
637
641
  chunk_buffers = {}
638
-
642
+
639
643
  def send_events_from_browser(chunk):
640
644
  try:
641
645
  # Handle chunked data
642
- batch_id = chunk['batchId']
643
- chunk_index = chunk['chunkIndex']
644
- total_chunks = chunk['totalChunks']
645
- data = chunk['data']
646
-
646
+ batch_id = chunk["batchId"]
647
+ chunk_index = chunk["chunkIndex"]
648
+ total_chunks = chunk["totalChunks"]
649
+ data = chunk["data"]
650
+
647
651
  # Initialize buffer for this batch if needed
648
652
  if batch_id not in chunk_buffers:
649
653
  chunk_buffers[batch_id] = {
650
- 'chunks': {},
651
- 'total': total_chunks,
652
- 'timestamp': time.time()
654
+ "chunks": {},
655
+ "total": total_chunks,
656
+ "timestamp": time.time(),
653
657
  }
654
-
658
+
655
659
  # Store chunk
656
- chunk_buffers[batch_id]['chunks'][chunk_index] = data
657
-
660
+ chunk_buffers[batch_id]["chunks"][chunk_index] = data
661
+
658
662
  # Check if we have all chunks
659
- if len(chunk_buffers[batch_id]['chunks']) == total_chunks:
663
+ if len(chunk_buffers[batch_id]["chunks"]) == total_chunks:
660
664
  # Reassemble the full message
661
- full_data = ''.join(chunk_buffers[batch_id]['chunks'][i] for i in range(total_chunks))
662
-
665
+ full_data = "".join(
666
+ chunk_buffers[batch_id]["chunks"][i] for i in range(total_chunks)
667
+ )
668
+
663
669
  # Parse the JSON
664
670
  events = orjson.loads(full_data)
665
-
671
+
666
672
  # Send to server
667
673
  if events and len(events) > 0:
668
674
  client._browser_events.send(session_id, trace_id, events)
669
-
675
+
670
676
  # Clean up buffer
671
677
  del chunk_buffers[batch_id]
672
-
678
+
673
679
  # Clean up old incomplete buffers
674
680
  current_time = time.time()
675
681
  to_delete = []
676
682
  for bid, buffer in chunk_buffers.items():
677
- if current_time - buffer['timestamp'] > OLD_BUFFER_TIMEOUT:
683
+ if current_time - buffer["timestamp"] > OLD_BUFFER_TIMEOUT:
678
684
  to_delete.append(bid)
679
685
  for bid in to_delete:
680
686
  logger.debug(f"Cleaning up incomplete chunk buffer: {bid}")
681
687
  del chunk_buffers[bid]
682
-
688
+
683
689
  except Exception as e:
684
690
  logger.debug(f"Could not send events: {e}")
685
691
 
@@ -707,51 +713,51 @@ async def start_recording_events_async(
707
713
  span = trace.get_current_span(ctx)
708
714
  trace_id = format(span.get_span_context().trace_id, "032x")
709
715
  span.set_attribute("lmnr.internal.has_browser_session", True)
710
-
716
+
711
717
  # Buffer for reassembling chunks
712
718
  chunk_buffers = {}
713
-
719
+
714
720
  async def send_events_from_browser(chunk):
715
721
  try:
716
722
  # Handle chunked data
717
- batch_id = chunk['batchId']
718
- chunk_index = chunk['chunkIndex']
719
- total_chunks = chunk['totalChunks']
720
- data = chunk['data']
723
+ batch_id = chunk["batchId"]
724
+ chunk_index = chunk["chunkIndex"]
725
+ total_chunks = chunk["totalChunks"]
726
+ data = chunk["data"]
721
727
 
722
728
  # Initialize buffer for this batch if needed
723
729
  if batch_id not in chunk_buffers:
724
730
  chunk_buffers[batch_id] = {
725
- 'chunks': {},
726
- 'total': total_chunks,
727
- 'timestamp': time.time()
731
+ "chunks": {},
732
+ "total": total_chunks,
733
+ "timestamp": time.time(),
728
734
  }
729
-
735
+
730
736
  # Store chunk
731
- chunk_buffers[batch_id]['chunks'][chunk_index] = data
732
-
737
+ chunk_buffers[batch_id]["chunks"][chunk_index] = data
738
+
733
739
  # Check if we have all chunks
734
- if len(chunk_buffers[batch_id]['chunks']) == total_chunks:
740
+ if len(chunk_buffers[batch_id]["chunks"]) == total_chunks:
735
741
  # Reassemble the full message
736
- full_data = ''
742
+ full_data = ""
737
743
  for i in range(total_chunks):
738
- full_data += chunk_buffers[batch_id]['chunks'][i]
739
-
744
+ full_data += chunk_buffers[batch_id]["chunks"][i]
745
+
740
746
  # Parse the JSON
741
747
  events = orjson.loads(full_data)
742
-
748
+
743
749
  # Send to server
744
750
  if events and len(events) > 0:
745
751
  await client._browser_events.send(session_id, trace_id, events)
746
-
752
+
747
753
  # Clean up buffer
748
754
  del chunk_buffers[batch_id]
749
-
755
+
750
756
  # Clean up old incomplete buffers
751
757
  current_time = time.time()
752
758
  to_delete = []
753
759
  for bid, buffer in chunk_buffers.items():
754
- if current_time - buffer['timestamp'] > OLD_BUFFER_TIMEOUT:
760
+ if current_time - buffer["timestamp"] > OLD_BUFFER_TIMEOUT:
755
761
  to_delete.append(bid)
756
762
  for bid in to_delete:
757
763
  logger.debug(f"Cleaning up incomplete chunk buffer: {bid}")
@@ -766,7 +772,7 @@ async def start_recording_events_async(
766
772
  logger.debug(f"Could not expose function: {e}")
767
773
 
768
774
  await inject_session_recorder_async(page)
769
-
775
+
770
776
  async def on_load(p):
771
777
  try:
772
778
  await inject_session_recorder_async(p)
lmnr/sdk/decorators.py CHANGED
@@ -32,6 +32,7 @@ def observe(
32
32
  output_formatter: Callable[[R], str] | None = None,
33
33
  metadata: dict[str, Any] | None = None,
34
34
  tags: list[str] | None = None,
35
+ preserve_global_context: bool = False,
35
36
  ) -> Callable[[Callable[P, R]], Callable[P, R]]:
36
37
  """The main decorator entrypoint for Laminar. This is used to wrap
37
38
  functions and methods to create spans.
@@ -69,6 +70,9 @@ def observe(
69
70
  the trace. Must be JSON serializable. Defaults to None.
70
71
  tags (list[str] | None, optional): Tags to associate with the trace.
71
72
  Defaults to None.
73
+ preserve_global_context (bool, optional): Whether to preserve the global\
74
+ OpenTelemetry context. If set to True, Laminar spans will continue\
75
+ traces started in the global context. Defaults to False.
72
76
  Raises:
73
77
  Exception: re-raises the exception if the wrapped function raises an\
74
78
  exception
@@ -133,6 +137,7 @@ def observe(
133
137
  input_formatter=input_formatter,
134
138
  output_formatter=output_formatter,
135
139
  association_properties=association_properties,
140
+ preserve_global_context=preserve_global_context,
136
141
  )(func)
137
142
  if is_async(func)
138
143
  else observe_base(
@@ -144,6 +149,7 @@ def observe(
144
149
  input_formatter=input_formatter,
145
150
  output_formatter=output_formatter,
146
151
  association_properties=association_properties,
152
+ preserve_global_context=preserve_global_context,
147
153
  )(func)
148
154
  )
149
155
  return result
lmnr/sdk/evaluations.py CHANGED
@@ -5,8 +5,9 @@ import uuid
5
5
  from tqdm import tqdm
6
6
  from typing import Any, Awaitable
7
7
 
8
+ from lmnr.opentelemetry_lib.decorators import json_dumps
8
9
  from lmnr.opentelemetry_lib.tracing.instruments import Instruments
9
- from lmnr.opentelemetry_lib.tracing.attributes import SPAN_TYPE
10
+ from lmnr.opentelemetry_lib.tracing.attributes import HUMAN_EVALUATOR_OPTIONS, SPAN_TYPE
10
11
 
11
12
  from lmnr.sdk.client.asynchronous.async_client import AsyncLaminarClient
12
13
  from lmnr.sdk.client.synchronous.sync_client import LaminarClient
@@ -363,6 +364,10 @@ class Evaluation:
363
364
  human_evaluator_span.set_attribute(
364
365
  SPAN_TYPE, SpanType.HUMAN_EVALUATOR.value
365
366
  )
367
+ if evaluator.options:
368
+ human_evaluator_span.set_attribute(
369
+ HUMAN_EVALUATOR_OPTIONS, json_dumps(evaluator.options)
370
+ )
366
371
  # Human evaluators don't execute automatically, just create the span
367
372
  L.set_span_output(None)
368
373
 
lmnr/sdk/laminar.py CHANGED
@@ -13,6 +13,10 @@ from lmnr.opentelemetry_lib.tracing.instruments import Instruments
13
13
  from lmnr.opentelemetry_lib.tracing.tracer import get_tracer_with_context
14
14
  from lmnr.opentelemetry_lib.tracing.attributes import (
15
15
  ASSOCIATION_PROPERTIES,
16
+ PARENT_SPAN_IDS_PATH,
17
+ PARENT_SPAN_PATH,
18
+ SPAN_IDS_PATH,
19
+ SPAN_PATH,
16
20
  USER_ID,
17
21
  Attributes,
18
22
  SPAN_TYPE,
@@ -316,9 +320,29 @@ class Laminar:
316
320
 
317
321
  with get_tracer_with_context() as (tracer, isolated_context):
318
322
  ctx = context or isolated_context
323
+ path = []
324
+ span_ids_path = []
319
325
  if parent_span_context is not None:
326
+ if isinstance(parent_span_context, (dict, str)):
327
+ try:
328
+ laminar_span_context = LaminarSpanContext.deserialize(
329
+ parent_span_context
330
+ )
331
+ path = laminar_span_context.span_path
332
+ span_ids_path = laminar_span_context.span_ids_path
333
+ except Exception:
334
+ cls.__logger.warning(
335
+ f"`start_as_current_span` Could not deserialize parent_span_context: {parent_span_context}. "
336
+ "Will use it as is."
337
+ )
338
+ laminar_span_context = parent_span_context
339
+ else:
340
+ laminar_span_context = parent_span_context
341
+ if isinstance(laminar_span_context, LaminarSpanContext):
342
+ path = laminar_span_context.span_path
343
+ span_ids_path = laminar_span_context.span_ids_path
320
344
  span_context = LaminarSpanContext.try_to_otel_span_context(
321
- parent_span_context, cls.__logger
345
+ laminar_span_context, cls.__logger
322
346
  )
323
347
  ctx = trace.set_span_in_context(
324
348
  trace.NonRecordingSpan(span_context), ctx
@@ -352,6 +376,8 @@ class Laminar:
352
376
  context=ctx,
353
377
  attributes={
354
378
  SPAN_TYPE: span_type,
379
+ PARENT_SPAN_PATH: path,
380
+ PARENT_SPAN_IDS_PATH: span_ids_path,
355
381
  **(label_props),
356
382
  **(tag_props),
357
383
  },
@@ -454,9 +480,29 @@ class Laminar:
454
480
 
455
481
  with get_tracer_with_context() as (tracer, isolated_context):
456
482
  ctx = context or isolated_context
483
+ path = []
484
+ span_ids_path = []
457
485
  if parent_span_context is not None:
486
+ if isinstance(parent_span_context, (dict, str)):
487
+ try:
488
+ laminar_span_context = LaminarSpanContext.deserialize(
489
+ parent_span_context
490
+ )
491
+ path = laminar_span_context.span_path
492
+ span_ids_path = laminar_span_context.span_ids_path
493
+ except Exception:
494
+ cls.__logger.warning(
495
+ f"`start_span` Could not deserialize parent_span_context: {parent_span_context}. "
496
+ "Will use it as is."
497
+ )
498
+ laminar_span_context = parent_span_context
499
+ else:
500
+ laminar_span_context = parent_span_context
501
+ if isinstance(laminar_span_context, LaminarSpanContext):
502
+ path = laminar_span_context.span_path
503
+ span_ids_path = laminar_span_context.span_ids_path
458
504
  span_context = LaminarSpanContext.try_to_otel_span_context(
459
- parent_span_context, cls.__logger
505
+ laminar_span_context, cls.__logger
460
506
  )
461
507
  ctx = trace.set_span_in_context(
462
508
  trace.NonRecordingSpan(span_context), ctx
@@ -491,6 +537,8 @@ class Laminar:
491
537
  context=ctx,
492
538
  attributes={
493
539
  SPAN_TYPE: span_type,
540
+ PARENT_SPAN_PATH: path,
541
+ PARENT_SPAN_IDS_PATH: span_ids_path,
494
542
  **(label_props),
495
543
  **(tag_props),
496
544
  },
@@ -662,6 +710,8 @@ class Laminar:
662
710
  trace_id=uuid.UUID(int=span.get_span_context().trace_id),
663
711
  span_id=uuid.UUID(int=span.get_span_context().span_id),
664
712
  is_remote=span.get_span_context().is_remote,
713
+ span_path=span.attributes.get(SPAN_PATH, []),
714
+ span_ids_path=span.attributes.get(SPAN_IDS_PATH, []),
665
715
  )
666
716
 
667
717
  @classmethod
lmnr/sdk/types.py CHANGED
@@ -9,7 +9,8 @@ import uuid
9
9
 
10
10
  from enum import Enum
11
11
  from opentelemetry.trace import SpanContext, TraceFlags
12
- from typing import Any, Awaitable, Callable, Literal, Optional, TypedDict
12
+ from typing import Any, Awaitable, Callable, Literal, Optional
13
+ from typing_extensions import TypedDict # compatibility with python < 3.12
13
14
 
14
15
  from .utils import serialize
15
16
 
@@ -51,8 +52,13 @@ EvaluatorFunction = Callable[
51
52
  ]
52
53
 
53
54
 
55
+ class HumanEvaluatorOptionsEntry(TypedDict):
56
+ label: str
57
+ value: float
58
+
59
+
54
60
  class HumanEvaluator(pydantic.BaseModel):
55
- pass
61
+ options: list[HumanEvaluatorOptionsEntry] = pydantic.Field(default=[])
56
62
 
57
63
 
58
64
  class InitEvaluationResponse(pydantic.BaseModel):
@@ -169,6 +175,8 @@ class LaminarSpanContext(pydantic.BaseModel):
169
175
  trace_id: uuid.UUID
170
176
  span_id: uuid.UUID
171
177
  is_remote: bool = pydantic.Field(default=False)
178
+ span_path: list[str] = pydantic.Field(default=[])
179
+ span_ids_path: list[str] = pydantic.Field(default=[]) # stringified UUIDs
172
180
 
173
181
  def __str__(self) -> str:
174
182
  return self.model_dump_json()
@@ -199,7 +207,7 @@ class LaminarSpanContext(pydantic.BaseModel):
199
207
  "Please use `LaminarSpanContext` instead."
200
208
  )
201
209
  return span_context
202
- elif isinstance(span_context, dict) or isinstance(span_context, str):
210
+ elif isinstance(span_context, (dict, str)):
203
211
  try:
204
212
  laminar_span_context = cls.deserialize(span_context)
205
213
  return SpanContext(
@@ -221,6 +229,9 @@ class LaminarSpanContext(pydantic.BaseModel):
221
229
  "trace_id": data.get("trace_id") or data.get("traceId"),
222
230
  "span_id": data.get("span_id") or data.get("spanId"),
223
231
  "is_remote": data.get("is_remote") or data.get("isRemote", False),
232
+ "span_path": data.get("span_path") or data.get("spanPath", []),
233
+ "span_ids_path": data.get("span_ids_path")
234
+ or data.get("spanIdsPath", []),
224
235
  }
225
236
  return cls.model_validate(converted_data)
226
237
  elif isinstance(data, str):
@@ -356,5 +367,6 @@ class MaskInputOptions(TypedDict):
356
367
  email: bool | None
357
368
  tel: bool | None
358
369
 
370
+
359
371
  class SessionRecordingOptions(TypedDict):
360
- mask_input_options: MaskInputOptions | None
372
+ mask_input_options: MaskInputOptions | None
lmnr/version.py CHANGED
@@ -3,7 +3,7 @@ import httpx
3
3
  from packaging import version
4
4
 
5
5
 
6
- __version__ = "0.7.3"
6
+ __version__ = "0.7.5"
7
7
  PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}"
8
8
 
9
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lmnr
3
- Version: 0.7.3
3
+ Version: 0.7.5
4
4
  Summary: Python SDK for Laminar
5
5
  Author: lmnr.ai
6
6
  Author-email: lmnr.ai <founders@lmnr.ai>
@@ -2,7 +2,7 @@ lmnr/__init__.py,sha256=8be7b56ab62735fd54ca90a0642784c6153ed1d6e0f12734619ca061
2
2
  lmnr/cli.py,sha256=b8780b51f37fe9e20db5495c41d3ad3837f6b48f408b09a58688d017850c0796,6047
3
3
  lmnr/opentelemetry_lib/.flake8,sha256=6c2c6e0e51b1dd8439e501ca3e21899277076a787da868d0254ba37056b79405,150
4
4
  lmnr/opentelemetry_lib/__init__.py,sha256=1350e8d12ea2f422751ab3a80d7d32d10c27ad8e4c2989407771dc6e544d9c65,2350
5
- lmnr/opentelemetry_lib/decorators/__init__.py,sha256=216536fb3ac8de18e6dfe4dfb2e571074c727466f97e6dcd609339c8458a345a,11511
5
+ lmnr/opentelemetry_lib/decorators/__init__.py,sha256=e2ddd9252e0f3d82601081d655342af56413e09dc827ac07f66b51d3b575156e,11814
6
6
  lmnr/opentelemetry_lib/litellm/__init__.py,sha256=8a3679381ca5660cf53e4b7571850906c6635264129149adebda8f3f7c248f68,15127
7
7
  lmnr/opentelemetry_lib/litellm/utils.py,sha256=da8cf0553f82dc7203109f117a4c7b4185e8baf34caad12d7823875515201a27,539
8
8
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/__init__.py,sha256=2604189b7598edb5404ddbcd0775bdf2dc506dd5e6319eef4e4724e39c420301,23276
@@ -28,7 +28,7 @@ lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/__init__.py,sha25
28
28
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/utils.py,sha256=9dff6c2595e79edb38818668aed1220efc188d8a982594c04f4ceeb6e3ff47a6,1512
29
29
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/__init__.py,sha256=8b91dc16af927eee75b969c0980c606680b347a87f8533bc0f4a092e5ec6e5c9,2071
30
30
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/__init__.py,sha256=9d182c8cef5ee1e205dc4c2f7c8e49d8403ee9fee66072c5cfdd29a0d54f61a2,15149
31
- lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/chat_wrappers.py,sha256=92aed53560c49e0ec3ef5e20ddb6c2096bb26078cc3e10b2f80a9dcef7a3e520,38937
31
+ lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/chat_wrappers.py,sha256=98ebc2a7f7f4774ff4ab1fd1b612a5b049ae6f714bb60cd1c286d3a756ddc083,39056
32
32
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/completion_wrappers.py,sha256=3a45c07d9d0f37baf409a48e2a1b577f28041c623c41f59ada1c87b94285ae3b,9537
33
33
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/config.py,sha256=8016e4af0291a77484ce88d7d1ca06146b1229ae0e0a0f46e042faf75b456a8f,507
34
34
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py,sha256=324eeeaf8dd862f49c15bb7290d414e77ad51cdf532c2cfd74358783cdf654a5,9330
@@ -40,18 +40,18 @@ lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v0/__init__.py,sha25
40
40
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/__init__.py,sha256=662afd935c52b42512280614bf502554389c8854ab1256efbfde03fe364dac64,12932
41
41
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py,sha256=558036c734559b3526647c1b18cfb986699e8fb322855af72ea054c2e458f721,10404
42
42
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py,sha256=4809cde003e5892822828b373aa3e43a8adbaee4ff443f198401003f43c15e8a,4366
43
- lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/responses_wrappers.py,sha256=67c94b3e5bf16b64cecf7a091b05a2eb43162e09968845066721d1cf715856c7,24372
43
+ lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/responses_wrappers.py,sha256=b3853c60c58a36ba64de184211ac2d112bb8b53c4af62f0fc716fb87d168fd4b,24790
44
44
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/version.py,sha256=4f39aaa913f3e49b0c174bc23028687d00bfaffc745bd3fe241e0ae6b442bed1,24
45
45
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/opentelemetry/__init__.py,sha256=1f86cdf738e2f68586b0a4569bb1e40edddd85c529f511ef49945ddb7b61fab5,2648
46
46
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/skyvern/__init__.py,sha256=764e4fe979fb08d7821419a3cc5c3ae89a6664b626ef928259f8f175c939eaea,6334
47
47
  lmnr/opentelemetry_lib/opentelemetry/instrumentation/threading/__init__.py,sha256=90aa8558467d7e469fe1a6c75372c113da403557715f03b522b2fab94b287c40,6320
48
- lmnr/opentelemetry_lib/tracing/__init__.py,sha256=1019d25eab017547e914aa9703d4c4bc3fabb7ae0327f0dcb266c3d09f9a08e8,10207
49
- lmnr/opentelemetry_lib/tracing/_instrument_initializers.py,sha256=a15a46a0515462319195a96f7cdb695e72a1559c3212964f5883ab824031bf70,15125
50
- lmnr/opentelemetry_lib/tracing/attributes.py,sha256=32fa30565b977c2a92202dc2bf1ded583a81d02a6bf5ba52958f75a8be08cbbe,1497
48
+ lmnr/opentelemetry_lib/tracing/__init__.py,sha256=b96aee7590af1853fffc4c3d8ce9127a67e1ce589f695a99aabe6b37d70b0e48,10203
49
+ lmnr/opentelemetry_lib/tracing/_instrument_initializers.py,sha256=9f422e61e58045270b9deceec6bf2dd246b500cffa3540eecfa1ba809603c87e,14830
50
+ lmnr/opentelemetry_lib/tracing/attributes.py,sha256=a879e337ff4e8569a4454544d303ccbc3b04bd42e1cdb765eb563aeaa08f731d,1653
51
51
  lmnr/opentelemetry_lib/tracing/context.py,sha256=83f842be0fc29a96647cbf005c39ea761b0fb5913c4102f965411f47906a6135,4103
52
52
  lmnr/opentelemetry_lib/tracing/exporter.py,sha256=6af8e61fd873e8f5db315d9b9f1edbf46b860ba7e50140f0bdcc6864c6d35a03,2082
53
- lmnr/opentelemetry_lib/tracing/instruments.py,sha256=e3c12315bda301416d1f3bc8d354ad16d4da211e2ecfa019265f4b565307c118,5655
54
- lmnr/opentelemetry_lib/tracing/processor.py,sha256=fd11e4d48eb5932f47898b8f70b8b5880f7ee7e58478f1ef20caff20e1f34252,3381
53
+ lmnr/opentelemetry_lib/tracing/instruments.py,sha256=993c5e4a827f0828ad4ee1ac9b18a2220e1b271a051ec05974f73cf82f48d172,5512
54
+ lmnr/opentelemetry_lib/tracing/processor.py,sha256=cbc70f138e70c878ef57b02a2c46ef48dd7f694a522623a82dff1623b73d1e1c,3353
55
55
  lmnr/opentelemetry_lib/tracing/tracer.py,sha256=33769a9a97385f5697eb0e0a6b1813a57ed956c7a8379d7ac2523e700e7dd528,1362
56
56
  lmnr/opentelemetry_lib/utils/__init__.py,sha256=a4d85fd06def4dde5c728734de2d4c5c36eb89c49a8aa09b8b50cb5a149e90af,604
57
57
  lmnr/opentelemetry_lib/utils/json_encoder.py,sha256=74ae9bfdac6bef42182fb56ff9bbb8c27b6f0c3bb29eda2ab0769d76a5fb3f9f,463
@@ -59,10 +59,12 @@ lmnr/opentelemetry_lib/utils/package_check.py,sha256=f8274186c96815c996a25fae06b
59
59
  lmnr/py.typed,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
60
60
  lmnr/sdk/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
61
61
  lmnr/sdk/browser/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
62
- lmnr/sdk/browser/browser_use_otel.py,sha256=37d26de1af37f76774af176cb226e0b04988fc3bf419a2fd899ad36e79562fad,5104
62
+ lmnr/sdk/browser/browser_use_cdp_otel.py,sha256=c82ac9ffddd6a406260364b9e1001364521bd15fc1906b1a0ee4c58edb2d3f7b,3210
63
+ lmnr/sdk/browser/browser_use_otel.py,sha256=e5549878c07bad451efef9f460ce52202284cff50075bce700ca61749102c5eb,5065
64
+ lmnr/sdk/browser/cdp_utils.py,sha256=3f43e4b9958e752b1b9aa0a3ae6321ef9e1cb66b3f4ca07990584b2c60c17a97,26103
63
65
  lmnr/sdk/browser/patchright_otel.py,sha256=9d22ab1f28f1eddbcfd0032a14fe306bfe00bfc7f11128cb99836c4dd15fb7c8,4800
64
66
  lmnr/sdk/browser/playwright_otel.py,sha256=50c0a5a75155a3a7ff5db84790ffb409c9cbd0351eef212d83d923893730223b,9459
65
- lmnr/sdk/browser/pw_utils.py,sha256=e8b839d729bf4d80e07db0a8bb616b41da43219a019d2ce9596c1b6e9f848074,29061
67
+ lmnr/sdk/browser/pw_utils.py,sha256=a75769eb977d8e56c38a0eefad09b87550b872f8d4df186b36a8c4d4af2bffaf,29021
66
68
  lmnr/sdk/browser/recorder/record.umd.min.cjs,sha256=f09c09052c2fc474efb0405e63d8d26ed2184b994513ce8aee04efdac8be155d,181235
67
69
  lmnr/sdk/browser/utils.py,sha256=4a668776d2938108d25fbcecd61c8e1710a4da3e56230d5fefca5964dd09e3c1,2371
68
70
  lmnr/sdk/client/asynchronous/async_client.py,sha256=e8feae007506cd2e4b08e72706f5f1bb4ea54492b4aa6b68ef184a129de8f466,4948
@@ -82,15 +84,15 @@ lmnr/sdk/client/synchronous/resources/evaluators.py,sha256=3cd6a17e7a9cc0441c2d2
82
84
  lmnr/sdk/client/synchronous/resources/tags.py,sha256=123deec43128662c21cb275b2df6a102372f875315b0bd36806555394c1d4b5b,2270
83
85
  lmnr/sdk/client/synchronous/sync_client.py,sha256=0bebe88e3aed689505e9ed3d32036f76df4c3496e4d659162bd41abedc026f16,5299
84
86
  lmnr/sdk/datasets.py,sha256=3fd851c5f97bf88eaa84b1451a053eaff23b4497cbb45eac2f9ea0e5f2886c00,1708
85
- lmnr/sdk/decorators.py,sha256=2ccf9ecd9616ad1d52301febd8af630288ba63db2d36302236f606a460fc08ca,6516
87
+ lmnr/sdk/decorators.py,sha256=c709b76a814e019c919fd811591850787a2f266b7b6f46123f66ddd92e1092d5,6920
86
88
  lmnr/sdk/eval_control.py,sha256=291394ac385c653ae9b5167e871bebeb4fe8fc6b7ff2ed38e636f87015dcba86,184
87
- lmnr/sdk/evaluations.py,sha256=b41f7737b084dc5b64b2952659b729622e0918fd492bfcddde7177d1a1c690ae,22572
88
- lmnr/sdk/laminar.py,sha256=f9dbacc6549d19701db7a986cb29c82114b1a054900a282b1ae9dbe6a488129b,34974
89
+ lmnr/sdk/evaluations.py,sha256=895d0b1af77395bddfbf69388679eb03f8f4d2ef03facab270965de1b382b2c8,22881
90
+ lmnr/sdk/laminar.py,sha256=24d680407ce694f1a7ec0e9c0524eae3deb7d638ad5caff3a591ddf7963ad480,37533
89
91
  lmnr/sdk/log.py,sha256=9edfd83263f0d4845b1b2d1beeae2b4ed3f8628de941f371a893d72b79c348d4,2213
90
- lmnr/sdk/types.py,sha256=ded526d1289442672236265bd6cbb4381fc55d8ce0fce1d6e7b2541e54c758c4,12948
92
+ lmnr/sdk/types.py,sha256=f8a8368e225c4d2f82df54d92f029065afb60c3eff494c77c6e574963ed524ff,13454
91
93
  lmnr/sdk/utils.py,sha256=4beb884ae6fbbc7d8cf639b036b726ea6a2a658f0a6386faf5735a13d706a2d8,5039
92
- lmnr/version.py,sha256=65bb6a01739adaee6189918df22c9e8df76cfc10339b704416f686014f066b2b,1321
93
- lmnr-0.7.3.dist-info/WHEEL,sha256=ab6157bc637547491fb4567cd7ddf26b04d63382916ca16c29a5c8e94c9c9ef7,79
94
- lmnr-0.7.3.dist-info/entry_points.txt,sha256=abdf3411b7dd2d7329a241f2da6669bab4e314a747a586ecdb9f888f3035003c,39
95
- lmnr-0.7.3.dist-info/METADATA,sha256=2952132a1ddd7d9e0f8c50fdd39e159174825b812b898bf48135c1c69ee7d5db,14196
96
- lmnr-0.7.3.dist-info/RECORD,,
94
+ lmnr/version.py,sha256=84c9d44c77610666978c4e75e31740560d21b0faff8df95ed6df3316e8160296,1321
95
+ lmnr-0.7.5.dist-info/WHEEL,sha256=ab6157bc637547491fb4567cd7ddf26b04d63382916ca16c29a5c8e94c9c9ef7,79
96
+ lmnr-0.7.5.dist-info/entry_points.txt,sha256=abdf3411b7dd2d7329a241f2da6669bab4e314a747a586ecdb9f888f3035003c,39
97
+ lmnr-0.7.5.dist-info/METADATA,sha256=542b7d75c0834cabd0910070bca43bbea4f62bc8db58eb27ed5c88e437b743a6,14196
98
+ lmnr-0.7.5.dist-info/RECORD,,
File without changes