@lmnr-ai/lmnr 0.8.52 → 0.8.53

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.
package/dist/index.mjs CHANGED
@@ -1,29 +1,29 @@
1
1
  import { r as __require } from "./rolldown-runtime-B4iAMlE-.mjs";
2
- import { A as SPAN_INSTRUMENTATION_SOURCE, B as LaminarClient, C as PARENT_SPAN_IDS_PATH, D as SPAN_INPUT, E as SPAN_IDS_PATH, F as SPAN_TYPE, H as DEBUG_SESSION_FILE, I as TRACE_HAS_BROWSER_SESSION, L as TRACE_TYPE, M as SPAN_OUTPUT, N as SPAN_PATH, O as SPAN_INSTRUMENTATION_SCOPE_NAME, P as SPAN_SDK_VERSION, R as USER_ID, S as LaminarAttributes, T as SESSION_ID, U as TracingLevel, V as DEBUG_SESSION_DIR, W as errorMessage, _ as tryToOtelSpanContext, a as getFrontendUrl, b as ASSOCIATION_PROPERTIES_OVERRIDES, c as loadEnv, d as normalizeOtelSpanId, f as normalizeOtelTraceId, g as truncateSpanPayload, h as parseOtelHeaders, j as SPAN_LANGUAGE_VERSION, k as SPAN_INSTRUMENTATION_SCOPE_VERSION, l as metadataToAttributes, m as otelTraceIdToUUID, n as Semaphore, o as getOtelEnvVar, p as otelSpanIdToUUID, r as deserializeLaminarSpanContext, s as initializeLogger, t as NIL_UUID, u as newUUID, v as validateTracingConfig, w as PARENT_SPAN_PATH, x as HUMAN_EVALUATOR_OPTIONS, y as ASSOCIATION_PROPERTIES, z as version } from "./utils-C6gt-rSg.mjs";
2
+ import { A as SPAN_INSTRUMENTATION_SOURCE, B as version, C as PARENT_SPAN_IDS_PATH, D as SPAN_INPUT, E as SPAN_IDS_PATH, F as SPAN_SDK_VERSION, G as errorMessage, H as DEBUG_SESSION_DIR, I as SPAN_TYPE, L as TRACE_HAS_BROWSER_SESSION, M as SPAN_OUTPUT, N as SPAN_PATH, O as SPAN_INSTRUMENTATION_SCOPE_NAME, P as SPAN_RELEASE, R as TRACE_TYPE, S as LaminarAttributes, T as SESSION_ID, U as DEBUG_SESSION_FILE, V as LaminarClient, W as TracingLevel, _ as tryToOtelSpanContext, a as getFrontendUrl, b as ASSOCIATION_PROPERTIES_OVERRIDES, c as loadEnv, d as normalizeOtelSpanId, f as normalizeOtelTraceId, g as truncateSpanPayload, h as parseOtelHeaders, j as SPAN_LANGUAGE_VERSION, k as SPAN_INSTRUMENTATION_SCOPE_VERSION, l as metadataToAttributes, m as otelTraceIdToUUID, n as Semaphore, o as getOtelEnvVar, p as otelSpanIdToUUID, r as deserializeLaminarSpanContext, s as initializeLogger, t as NIL_UUID, u as newUUID, v as validateTracingConfig, w as PARENT_SPAN_PATH, x as HUMAN_EVALUATOR_OPTIONS, y as ASSOCIATION_PROPERTIES, z as USER_ID } from "./utils-DavLzQA8.mjs";
3
3
  import { n as TRACEPARENT_HEADER, t as LAMINAR_SPAN_CONTEXT_HEADER } from "./consts-CTTu3jhI.mjs";
4
4
  import * as path from "path";
5
5
  import { DiagConsoleLogger, DiagLogLevel, ROOT_CONTEXT, SpanKind, SpanStatusCode, TraceFlags, context, createContextKey, diag, isSpanContextValid, trace } from "@opentelemetry/api";
6
6
  import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
7
- import { InstrumentationBase, InstrumentationNodeModuleDefinition, registerInstrumentations } from "@opentelemetry/instrumentation";
7
+ import { InstrumentationBase, InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile, registerInstrumentations } from "@opentelemetry/instrumentation";
8
8
  import { AlwaysOnSampler, BatchSpanProcessor, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
9
9
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
10
10
  import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
11
11
  import { BedrockInstrumentation } from "@traceloop/instrumentation-bedrock";
12
12
  import { ChromaDBInstrumentation } from "@traceloop/instrumentation-chromadb";
13
- import { LangChainInstrumentation } from "@traceloop/instrumentation-langchain";
14
13
  import { PineconeInstrumentation } from "@traceloop/instrumentation-pinecone";
15
14
  import { QdrantInstrumentation } from "@traceloop/instrumentation-qdrant";
16
15
  import { TogetherInstrumentation } from "@traceloop/instrumentation-together";
17
16
  import { spawn } from "node:child_process";
18
17
  import { randomUUID } from "node:crypto";
19
- import { mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
18
+ import { mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
20
19
  import { dirname, join, parse, resolve, sep } from "node:path";
21
20
  import * as fs from "fs";
22
21
  import * as net from "net";
23
22
  import * as os from "os";
24
23
  import { AsyncLocalStorage } from "async_hooks";
25
24
  import { zodToJsonSchema } from "zod-to-json-schema";
26
- import { hrTime, isTracingSuppressed, suppressTracing } from "@opentelemetry/core";
25
+ import { hrTime, isTracingSuppressed, suppressTracing, unsuppressTracing } from "@opentelemetry/core";
26
+ import { AsyncLocalStorage as AsyncLocalStorage$1 } from "node:async_hooks";
27
27
  import { Metadata } from "@grpc/grpc-js";
28
28
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
29
29
  import { OTLPTraceExporter as OTLPTraceExporter$1 } from "@opentelemetry/exporter-trace-otlp-proto";
@@ -188,7 +188,7 @@ var LaminarDataset = class extends EvaluationDataset {
188
188
  */
189
189
  async push(paths, recursive = false) {
190
190
  if (!this.client) throw new Error("Client not set");
191
- const { loadFromPaths } = await import("./file-utils-DaZefKLb.mjs").then((n) => n.t);
191
+ const { loadFromPaths } = await import("./file-utils-CwqjWMsF.mjs").then((n) => n.t);
192
192
  const data = await loadFromPaths(Array.isArray(paths) ? paths : [paths], recursive);
193
193
  if (data.length === 0) {
194
194
  console.warn("No data to push. Skipping");
@@ -204,7 +204,7 @@ var LaminarDataset = class extends EvaluationDataset {
204
204
  };
205
205
  //#endregion
206
206
  //#region src/opentelemetry-lib/tracing/compat.ts
207
- const logger$30 = initializeLogger();
207
+ const logger$32 = initializeLogger();
208
208
  const makeSpanOtelV2Compatible = (span) => {
209
209
  const spanAny = span;
210
210
  if (spanAny.instrumentationScope && !spanAny.instrumentationLibrary) Object.assign(span, { instrumentationLibrary: spanAny.instrumentationScope });
@@ -250,7 +250,7 @@ const createResource = (attributes) => {
250
250
  if (resources.Resource) return new resources.Resource(attributes);
251
251
  throw new Error("Unable to create Resource: neither v1 nor v2 API found");
252
252
  } catch {
253
- logger$30.debug("Laminar failed to @opentelemetry/resources, continuing without it");
253
+ logger$32.debug("Laminar failed to @opentelemetry/resources, continuing without it");
254
254
  return;
255
255
  }
256
256
  };
@@ -452,7 +452,7 @@ const consumeResponse = async (response) => {
452
452
  };
453
453
  //#endregion
454
454
  //#region src/opentelemetry-lib/tracing/stream-utils.ts
455
- const logger$29 = initializeLogger();
455
+ const logger$31 = initializeLogger();
456
456
  const pendingStreamProcessing = /* @__PURE__ */ new Set();
457
457
  /**
458
458
  * Wait for all pending stream processing to complete with a timeout
@@ -460,7 +460,7 @@ const pendingStreamProcessing = /* @__PURE__ */ new Set();
460
460
  */
461
461
  const waitForPendingStreams = async (timeoutMs = 5e3) => {
462
462
  if (pendingStreamProcessing.size === 0) return;
463
- logger$29.debug(`Waiting for ${pendingStreamProcessing.size} pending stream(s)`);
463
+ logger$31.debug(`Waiting for ${pendingStreamProcessing.size} pending stream(s)`);
464
464
  const initialCount = pendingStreamProcessing.size;
465
465
  const pendingPromises = Array.from(pendingStreamProcessing);
466
466
  let timedOut = false;
@@ -471,7 +471,7 @@ const waitForPendingStreams = async (timeoutMs = 5e3) => {
471
471
  }, timeoutMs);
472
472
  });
473
473
  await Promise.race([Promise.allSettled(pendingPromises), timeoutPromise]);
474
- if (timedOut && pendingStreamProcessing.size > 0) logger$29.warn(`Timeout waiting for ${pendingStreamProcessing.size} pending stream(s) after ${timeoutMs}ms (started with ${initialCount})`);
474
+ if (timedOut && pendingStreamProcessing.size > 0) logger$31.warn(`Timeout waiting for ${pendingStreamProcessing.size} pending stream(s) after ${timeoutMs}ms (started with ${initialCount})`);
475
475
  };
476
476
  /**
477
477
  * Track a background promise and ensure cleanup
@@ -487,34 +487,34 @@ const trackStreamProcessing = (task) => {
487
487
  * while passing through the original result to the caller
488
488
  */
489
489
  const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, serialize) => {
490
- logger$29.debug(`Handling stream result of type: ${streamInfo.type}`);
490
+ logger$31.debug(`Handling stream result of type: ${streamInfo.type}`);
491
491
  if (streamInfo.type === "aisdk-result") {
492
492
  trackStreamProcessing(async () => {
493
- logger$29.debug("Starting background processing for AI SDK result");
493
+ logger$31.debug("Starting background processing for AI SDK result");
494
494
  let partialOutput = {};
495
495
  try {
496
496
  partialOutput = await consumeAISDKResult(streamInfo.result);
497
497
  if (shouldSendTraces() && !ignoreOutput) try {
498
498
  span.setAttribute(SPAN_OUTPUT, serialize(partialOutput));
499
499
  } catch (error) {
500
- logger$29.warn("Failed to serialize AI SDK stream output: " + errorMessage(error));
500
+ logger$31.warn("Failed to serialize AI SDK stream output: " + errorMessage(error));
501
501
  }
502
502
  } catch (error) {
503
503
  if (Object.keys(partialOutput).length > 0 && shouldSendTraces() && !ignoreOutput) try {
504
504
  span.setAttribute(SPAN_OUTPUT, serialize(partialOutput));
505
505
  } catch (serError) {
506
- logger$29.warn("Failed to serialize partial AI SDK output: " + errorMessage(serError));
506
+ logger$31.warn("Failed to serialize partial AI SDK output: " + errorMessage(serError));
507
507
  }
508
508
  span.recordException(error);
509
509
  } finally {
510
- logger$29.debug("Ending span for AI SDK result");
510
+ logger$31.debug("Ending span for AI SDK result");
511
511
  span.end();
512
512
  }
513
513
  });
514
514
  return originalResult;
515
515
  }
516
516
  if (streamInfo.type === "readable-stream") {
517
- logger$29.debug("Setting up background processing for ReadableStream");
517
+ logger$31.debug("Setting up background processing for ReadableStream");
518
518
  const { stream, dataPromise } = consumeAndTeeReadableStream(streamInfo.stream);
519
519
  trackStreamProcessing(async () => {
520
520
  try {
@@ -526,18 +526,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
526
526
  };
527
527
  span.setAttribute(SPAN_OUTPUT, serialize(output));
528
528
  } catch (serError) {
529
- logger$29.warn("Failed to serialize stream output: " + errorMessage(serError));
529
+ logger$31.warn("Failed to serialize stream output: " + errorMessage(serError));
530
530
  }
531
531
  if (error) span.recordException(error);
532
532
  } finally {
533
- logger$29.debug("Ending span for ReadableStream");
533
+ logger$31.debug("Ending span for ReadableStream");
534
534
  span.end();
535
535
  }
536
536
  });
537
537
  return stream;
538
538
  }
539
539
  if (streamInfo.type === "async-iterable") {
540
- logger$29.debug("Setting up background processing for AsyncIterable");
540
+ logger$31.debug("Setting up background processing for AsyncIterable");
541
541
  const { iterable, dataPromise } = consumeAndTeeAsyncIterable(streamInfo.iterable);
542
542
  trackStreamProcessing(async () => {
543
543
  try {
@@ -549,18 +549,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
549
549
  };
550
550
  span.setAttribute(SPAN_OUTPUT, serialize(output));
551
551
  } catch (serError) {
552
- logger$29.warn("Failed to serialize async iterable output: " + errorMessage(serError));
552
+ logger$31.warn("Failed to serialize async iterable output: " + errorMessage(serError));
553
553
  }
554
554
  if (error) span.recordException(error);
555
555
  } finally {
556
- logger$29.debug("Ending span for AsyncIterable");
556
+ logger$31.debug("Ending span for AsyncIterable");
557
557
  span.end();
558
558
  }
559
559
  });
560
560
  return iterable;
561
561
  }
562
562
  if (streamInfo.type === "response") {
563
- logger$29.debug("Setting up background processing for Response");
563
+ logger$31.debug("Setting up background processing for Response");
564
564
  const originalResponse = streamInfo.response;
565
565
  if (!originalResponse.body) {
566
566
  span.end();
@@ -583,19 +583,19 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
583
583
  };
584
584
  span.setAttribute(SPAN_OUTPUT, serialize(output));
585
585
  } catch (serError) {
586
- logger$29.warn("Failed to serialize response output: " + errorMessage(serError));
586
+ logger$31.warn("Failed to serialize response output: " + errorMessage(serError));
587
587
  }
588
588
  if (error) span.recordException(error);
589
589
  } catch (err) {
590
590
  span.recordException(err);
591
591
  } finally {
592
- logger$29.debug("Ending span for Response");
592
+ logger$31.debug("Ending span for Response");
593
593
  span.end();
594
594
  }
595
595
  });
596
596
  return newResponse;
597
597
  }
598
- logger$29.warn("Stream type not handled, ending span immediately");
598
+ logger$31.warn("Stream type not handled, ending span immediately");
599
599
  span.end();
600
600
  return originalResult;
601
601
  };
@@ -673,7 +673,7 @@ const writeDebugSessionFile = (file, dir = process.cwd()) => {
673
673
  * contract. This file is part of the cross-language parity surface — keep its
674
674
  * logic line-comparable with the Python `config.py`.
675
675
  */
676
- const logger$28 = initializeLogger();
676
+ const logger$30 = initializeLogger();
677
677
  const TRUTHY = /* @__PURE__ */ new Set([
678
678
  "true",
679
679
  "1",
@@ -709,7 +709,7 @@ const parseCacheUntil = (value) => {
709
709
  if (value === void 0 || value === "") return null;
710
710
  const spanId = normalizeSpanId(value);
711
711
  if (spanId !== null) return spanId;
712
- logger$28.warn(`LMNR_DEBUG_CACHE_UNTIL=${JSON.stringify(value)} is not a span id; ignoring`);
712
+ logger$30.warn(`LMNR_DEBUG_CACHE_UNTIL=${JSON.stringify(value)} is not a span id; ignoring`);
713
713
  return null;
714
714
  };
715
715
  /**
@@ -1063,7 +1063,7 @@ const resetDebugRuntime = () => {
1063
1063
  };
1064
1064
  //#endregion
1065
1065
  //#region src/opentelemetry-lib/tracing/span.ts
1066
- const logger$27 = initializeLogger();
1066
+ const logger$29 = initializeLogger();
1067
1067
  /**
1068
1068
  * Build the debug block to propagate, or undefined when debug mode is off.
1069
1069
  *
@@ -1213,7 +1213,7 @@ var LaminarSpan = class LaminarSpan {
1213
1213
  } catch {}
1214
1214
  metadata[key.replace(`${ASSOCIATION_PROPERTIES}.metadata.`, "")] = value;
1215
1215
  }
1216
- } else logger$27.warn("Attributes object is not available. Most likely the span is not a LaminarSpan and not an OpenTelemetry default SDK Span. Span path and ids path will be empty.");
1216
+ } else logger$29.warn("Attributes object is not available. Most likely the span is not a LaminarSpan and not an OpenTelemetry default SDK Span. Span path and ids path will be empty.");
1217
1217
  return {
1218
1218
  spanId: otelSpanIdToUUID(this._span.spanContext().spanId),
1219
1219
  traceId: otelTraceIdToUUID(this._span.spanContext().traceId),
@@ -1240,14 +1240,14 @@ var LaminarSpan = class LaminarSpan {
1240
1240
  }
1241
1241
  get tags() {
1242
1242
  if (!this._span.attributes) {
1243
- logger$27.warn("[LaminarSpan.tags] WARNING. Current span does not have attributes object. Possibly, the span was created with a custom OTel SDK. Returning an empty list. Help: OpenTelemetry API does not guarantee reading attributes from a span, but OTel SDK allows it by default. Laminar SDK allows to read attributes too.");
1243
+ logger$29.warn("[LaminarSpan.tags] WARNING. Current span does not have attributes object. Possibly, the span was created with a custom OTel SDK. Returning an empty list. Help: OpenTelemetry API does not guarantee reading attributes from a span, but OTel SDK allows it by default. Laminar SDK allows to read attributes too.");
1244
1244
  return [];
1245
1245
  }
1246
1246
  return this._span.attributes[`lmnr.association.properties.tags`] ?? [];
1247
1247
  }
1248
1248
  get laminarAssociationProperties() {
1249
1249
  if (!this._span.attributes) {
1250
- logger$27.warn("[LaminarSpan.laminarAssociationProperties] WARNING. Current span does not have attributes object. Possibly, the span was created with a custom OTel SDK. Returning an empty object. Help: OpenTelemetry API does not guarantee reading attributes from a span, but OTel SDK allows it by default. Laminar SDK allows to read attributes too.");
1250
+ logger$29.warn("[LaminarSpan.laminarAssociationProperties] WARNING. Current span does not have attributes object. Possibly, the span was created with a custom OTel SDK. Returning an empty object. Help: OpenTelemetry API does not guarantee reading attributes from a span, but OTel SDK allows it by default. Laminar SDK allows to read attributes too.");
1251
1251
  return {};
1252
1252
  }
1253
1253
  try {
@@ -1443,7 +1443,7 @@ var LaminarContextManager = class {
1443
1443
  };
1444
1444
  //#endregion
1445
1445
  //#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/proxy.ts
1446
- const logger$26 = initializeLogger();
1446
+ const logger$28 = initializeLogger();
1447
1447
  const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
1448
1448
  const DEFAULT_CC_PROXY_PORT = 45667;
1449
1449
  const CC_PROXY_PORT_ATTEMPTS = 50;
@@ -1697,7 +1697,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
1697
1697
  if (foundryBaseUrl) return foundryBaseUrl.replace(/\/$/, "");
1698
1698
  const foundryResource = getEnvValue(FOUNDRY_RESOURCE_ENV);
1699
1699
  if (foundryResource) return `https://${foundryResource}.services.ai.azure.com/anthropic`;
1700
- logger$26.error(`${FOUNDRY_USE_ENV} is set but neither ${FOUNDRY_BASE_URL_ENV} nor ${FOUNDRY_RESOURCE_ENV} is configured. Microsoft Foundry requires one of these values.`);
1700
+ logger$28.error(`${FOUNDRY_USE_ENV} is set but neither ${FOUNDRY_BASE_URL_ENV} nor ${FOUNDRY_RESOURCE_ENV} is configured. Microsoft Foundry requires one of these values.`);
1701
1701
  return null;
1702
1702
  }
1703
1703
  if (isTruthyEnv(getEnvValue(BEDROCK_USE_ENV))) {
@@ -1709,7 +1709,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
1709
1709
  region = getRegionFromAwsConfig(awsProfile) ?? void 0;
1710
1710
  }
1711
1711
  if (region) return `https://bedrock-runtime.${region}.amazonaws.com`;
1712
- logger$26.error(`${BEDROCK_USE_ENV} is set but could not determine AWS region. Set ${BEDROCK_AWS_REGION_ENV} or configure a region in ~/.aws/config for the active profile.`);
1712
+ logger$28.error(`${BEDROCK_USE_ENV} is set but could not determine AWS region. Set ${BEDROCK_AWS_REGION_ENV} or configure a region in ~/.aws/config for the active profile.`);
1713
1713
  return null;
1714
1714
  }
1715
1715
  if (isTruthyEnv(getEnvValue(VERTEX_USE_ENV))) {
@@ -1792,11 +1792,11 @@ const waitForPort = (port, timeoutMs = 5e3) => new Promise((resolve) => {
1792
1792
  const registerGlobalProxyShutdown = () => {
1793
1793
  if (!globalShutdownRegistered) {
1794
1794
  process.on("exit", () => {
1795
- logger$26.debug("process.on(\"exit\") called - stopping all active proxies");
1795
+ logger$28.debug("process.on(\"exit\") called - stopping all active proxies");
1796
1796
  for (const proxyServer of activeProxyServers) try {
1797
1797
  proxyServer.stopServer();
1798
1798
  } catch (e) {
1799
- logger$26.debug(`Failed to stop proxy: ${errorMessage(e)}`);
1799
+ logger$28.debug(`Failed to stop proxy: ${errorMessage(e)}`);
1800
1800
  }
1801
1801
  activeProxyServers.clear();
1802
1802
  });
@@ -1811,28 +1811,28 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
1811
1811
  try {
1812
1812
  const port = await findAvailablePort(DEFAULT_CC_PROXY_PORT, CC_PROXY_PORT_ATTEMPTS);
1813
1813
  if (port === null) {
1814
- logger$26.warn("Unable to allocate port for cc-proxy.");
1814
+ logger$28.warn("Unable to allocate port for cc-proxy.");
1815
1815
  return null;
1816
1816
  }
1817
1817
  const targetUrl = resolvedTargetUrl ?? resolveTargetUrlFromEnv(env, void 0, cwd, settingSources, settings);
1818
1818
  if (!targetUrl) {
1819
- logger$26.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
1819
+ logger$28.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
1820
1820
  return null;
1821
1821
  }
1822
- logger$26.debug(`Creating proxy instance on port ${port} targeting: ${targetUrl}`);
1822
+ logger$28.debug(`Creating proxy instance on port ${port} targeting: ${targetUrl}`);
1823
1823
  try {
1824
1824
  const { ProxyServer } = __require("@lmnr-ai/claude-code-proxy");
1825
1825
  const proxyServer = new ProxyServer(port);
1826
1826
  proxyServer.runServer(targetUrl);
1827
1827
  if (!await waitForPort(port)) {
1828
- logger$26.warn(`cc-proxy failed to start on port ${port}`);
1828
+ logger$28.warn(`cc-proxy failed to start on port ${port}`);
1829
1829
  proxyServer.stopServer();
1830
1830
  return null;
1831
1831
  }
1832
1832
  const proxyBaseUrl = `http://127.0.0.1:${port}`;
1833
1833
  activeProxyServers.add(proxyServer);
1834
1834
  registerGlobalProxyShutdown();
1835
- logger$26.info(`Started claude proxy server on: ${proxyBaseUrl}`);
1835
+ logger$28.info(`Started claude proxy server on: ${proxyBaseUrl}`);
1836
1836
  return {
1837
1837
  server: proxyServer,
1838
1838
  baseUrl: proxyBaseUrl,
@@ -1840,11 +1840,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
1840
1840
  targetUrl
1841
1841
  };
1842
1842
  } catch (e) {
1843
- logger$26.warn(`Unable to start cc-proxy: ${errorMessage(e)}`);
1843
+ logger$28.warn(`Unable to start cc-proxy: ${errorMessage(e)}`);
1844
1844
  return null;
1845
1845
  }
1846
1846
  } catch (e) {
1847
- logger$26.warn(`Failed to create proxy instance: ${errorMessage(e)}`);
1847
+ logger$28.warn(`Failed to create proxy instance: ${errorMessage(e)}`);
1848
1848
  return null;
1849
1849
  }
1850
1850
  };
@@ -1854,11 +1854,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
1854
1854
  const stopProxyInstance = (instance) => {
1855
1855
  if (!instance) return;
1856
1856
  try {
1857
- logger$26.debug(`Stopping proxy instance on port ${instance.port}`);
1857
+ logger$28.debug(`Stopping proxy instance on port ${instance.port}`);
1858
1858
  instance.server.stopServer();
1859
1859
  activeProxyServers.delete(instance.server);
1860
1860
  } catch (e) {
1861
- logger$26.debug(`Failed to stop proxy instance: ${errorMessage(e)}`);
1861
+ logger$28.debug(`Failed to stop proxy instance: ${errorMessage(e)}`);
1862
1862
  }
1863
1863
  };
1864
1864
  /**
@@ -1866,11 +1866,11 @@ const stopProxyInstance = (instance) => {
1866
1866
  * Used during shutdown to ensure cleanup
1867
1867
  */
1868
1868
  const forceReleaseProxy = () => {
1869
- logger$26.debug(`Force stopping all ${activeProxyServers.size} active proxy servers`);
1869
+ logger$28.debug(`Force stopping all ${activeProxyServers.size} active proxy servers`);
1870
1870
  for (const proxyServer of activeProxyServers) try {
1871
1871
  proxyServer.stopServer();
1872
1872
  } catch (e) {
1873
- logger$26.debug(`Failed to stop proxy: ${errorMessage(e)}`);
1873
+ logger$28.debug(`Failed to stop proxy: ${errorMessage(e)}`);
1874
1874
  }
1875
1875
  activeProxyServers.clear();
1876
1876
  };
@@ -1920,14 +1920,14 @@ const setTraceToProxyInstance = async (instance) => {
1920
1920
  spanPath: payload.span_path,
1921
1921
  laminarUrl: payload.laminar_url
1922
1922
  });
1923
- logger$26.debug(`Set trace context to proxy on port ${instance.port}`);
1923
+ logger$28.debug(`Set trace context to proxy on port ${instance.port}`);
1924
1924
  } catch (e) {
1925
- logger$26.debug(`Unable to set trace context to proxy on port ${instance.port}: ` + errorMessage(e));
1925
+ logger$28.debug(`Unable to set trace context to proxy on port ${instance.port}: ` + errorMessage(e));
1926
1926
  }
1927
1927
  };
1928
1928
  //#endregion
1929
1929
  //#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/index.ts
1930
- const logger$25 = initializeLogger();
1930
+ const logger$27 = initializeLogger();
1931
1931
  /**
1932
1932
  * Create an instrumented version of the claude-agent-sdk query function.
1933
1933
  * This can be used when importing the query function before Laminar initialization.
@@ -1963,9 +1963,9 @@ function instrumentClaudeAgentQuery(originalQuery) {
1963
1963
  targetUrl
1964
1964
  });
1965
1965
  if (proxyInstance && targetUrl) {
1966
- logger$25.debug(`Using proxy on port ${proxyInstance.port}`);
1966
+ logger$27.debug(`Using proxy on port ${proxyInstance.port}`);
1967
1967
  await Laminar.withSpan(span, async () => {
1968
- logger$25.debug("Setting trace to proxy instance...");
1968
+ logger$27.debug("Setting trace to proxy instance...");
1969
1969
  await setTraceToProxyInstance(proxyInstance);
1970
1970
  });
1971
1971
  const varsToRemove = getEnvVarsToRemove(mergedEnv, sessionCwd, settingSources);
@@ -1980,13 +1980,13 @@ function instrumentClaudeAgentQuery(originalQuery) {
1980
1980
  if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_BEDROCK")) subprocessEnv.ANTHROPIC_BEDROCK_BASE_URL = proxyInstance.baseUrl;
1981
1981
  if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_VERTEX")) subprocessEnv.ANTHROPIC_VERTEX_BASE_URL = proxyInstance.baseUrl;
1982
1982
  const flagSettings = buildProxyFlagSettings(callerSettings, proxyInstance.baseUrl, sessionCwd, settingSources);
1983
- if (flagSettings === null) logger$25.warn(`Could not read options.settings ${JSON.stringify(callerSettings)}; Claude Code settings that define a base URL will bypass the Laminar proxy and produce no LLM spans.`);
1983
+ if (flagSettings === null) logger$27.warn(`Could not read options.settings ${JSON.stringify(callerSettings)}; Claude Code settings that define a base URL will bypass the Laminar proxy and produce no LLM spans.`);
1984
1984
  else {
1985
1985
  params.options.settings = flagSettings;
1986
1986
  const conflicting = Object.entries(readClaudeSettingsEnv(sessionCwd, settingSources)).filter(([key, value]) => PROXY_BASE_URL_ENV_KEYS.includes(key) && value !== "" && value !== proxyInstance?.baseUrl).map(([key]) => key);
1987
- if (conflicting.length > 0) logger$25.info(`Claude Code settings define ${conflicting.sort().join(", ")}, which outranks the subprocess environment. Injected settings so the Laminar proxy at ${proxyInstance.baseUrl} still intercepts API traffic; your settings files were not modified.`);
1987
+ if (conflicting.length > 0) logger$27.info(`Claude Code settings define ${conflicting.sort().join(", ")}, which outranks the subprocess environment. Injected settings so the Laminar proxy at ${proxyInstance.baseUrl} still intercepts API traffic; your settings files were not modified.`);
1988
1988
  }
1989
- } else logger$25.debug("No claude proxy server available. Proceeding without proxy.");
1989
+ } else logger$27.debug("No claude proxy server available. Proceeding without proxy.");
1990
1990
  const originalGenerator = originalQuery(params);
1991
1991
  for await (const message of originalGenerator) {
1992
1992
  collected.push(message);
@@ -2015,7 +2015,7 @@ var ClaudeAgentSDKInstrumentation = class extends InstrumentationBase {
2015
2015
  }
2016
2016
  manuallyInstrument(claudeAgentModule) {
2017
2017
  if (claudeAgentModule.query && typeof claudeAgentModule.query === "function") this._wrap(claudeAgentModule, "query", this.patchQuery());
2018
- else logger$25.debug("query function not found in claudeAgentSDK module, skipping instrumentation");
2018
+ else logger$27.debug("query function not found in claudeAgentSDK module, skipping instrumentation");
2019
2019
  }
2020
2020
  patchQuery() {
2021
2021
  return (original) => instrumentClaudeAgentQuery(original);
@@ -2031,9 +2031,19 @@ var ClaudeAgentSDKInstrumentation = class extends InstrumentationBase {
2031
2031
  }
2032
2032
  };
2033
2033
  //#endregion
2034
+ //#region src/opentelemetry-lib/instrumentation/langchain/llm-call.ts
2035
+ /**
2036
+ * Context key carrying the LangChain LLM call currently in progress. Set by the
2037
+ * `BaseChatModel` / `BaseLLM` wrappers for the duration of the model call.
2038
+ *
2039
+ * Kept free of other imports: `Laminar._startSpan` reads it to tell a handed
2040
+ * off call that the provider SDK instrumentation did record its span.
2041
+ */
2042
+ const LLM_CALL_KEY = createContextKey("lmnr.langchain.llm_call");
2043
+ //#endregion
2034
2044
  //#region src/laminar.ts
2035
2045
  loadEnv();
2036
- const logger$24 = initializeLogger();
2046
+ const logger$26 = initializeLogger();
2037
2047
  var Laminar = class Laminar {
2038
2048
  static {
2039
2049
  this.isInitialized = false;
@@ -2105,28 +2115,32 @@ var Laminar = class Laminar {
2105
2115
  * and you want Laminar spans to be children of the existing spans.
2106
2116
  * @param {SpanProcessor} props.spanProcessor - The span processor to use. If passed, some of
2107
2117
  * the other options will be ignored.
2118
+ * @param {string} props.release - The release of the running code, usually its git commit
2119
+ * SHA. Laminar groups an agent's traces into versions by release. If not specified, read
2120
+ * from the LMNR_RELEASE environment variable, common deploy platform variables (Vercel,
2121
+ * Render, Railway, Heroku, Cloud Run, ...), or the checked-out git commit.
2108
2122
  *
2109
2123
  * @example
2110
2124
  * import { Laminar } from '@lmnr-ai/lmnr';
2111
2125
  * import { OpenAI } from 'openai';
2112
- * import * as ChainsModule from "langchain/chains";
2126
+ * import * as CallbackManagerModule from "@langchain/core/callbacks/manager";
2113
2127
  *
2114
- * // Initialize Laminar while auto-instrumenting Langchain and OpenAI modules.
2128
+ * // Initialize Laminar while instrumenting LangChain and OpenAI modules.
2115
2129
  * Laminar.initialize({
2116
2130
  * projectApiKey: "<LMNR_PROJECT_API_KEY>",
2117
2131
  * instrumentModules: {
2118
2132
  * langchain: {
2119
- * chainsModule: ChainsModule
2133
+ * callbackManagerModule: CallbackManagerModule
2120
2134
  * },
2121
- * openAI: OpenAI
2135
+ * OpenAI: OpenAI
2122
2136
  * }
2123
2137
  * });
2124
2138
  *
2125
2139
  * @throws {Error} - If project API key is not set
2126
2140
  */
2127
- static initialize({ projectApiKey, baseUrl, baseHttpUrl, httpPort, grpcPort, instrumentModules, disableBatch, traceExportTimeoutMillis, logLevel, maxExportBatchSize, maxExportBatchSizeBytes, flushBySize, forceHttp, sessionRecordingOptions, metadata, inheritGlobalContext, spanProcessor } = {}) {
2141
+ static initialize({ projectApiKey, baseUrl, baseHttpUrl, httpPort, grpcPort, instrumentModules, disableBatch, traceExportTimeoutMillis, logLevel, maxExportBatchSize, maxExportBatchSizeBytes, flushBySize, forceHttp, sessionRecordingOptions, metadata, inheritGlobalContext, spanProcessor, release } = {}) {
2128
2142
  if (this.isInitialized) {
2129
- logger$24.warn("Laminar has already been initialized. Skipping initialization.");
2143
+ logger$26.warn("Laminar has already been initialized. Skipping initialization.");
2130
2144
  return;
2131
2145
  }
2132
2146
  const key = projectApiKey ?? process?.env?.LMNR_PROJECT_API_KEY;
@@ -2150,7 +2164,7 @@ var Laminar = class Laminar {
2150
2164
  ...metadata ?? {}
2151
2165
  };
2152
2166
  if (inheritGlobalContext) LaminarContextManager.inheritGlobalContext = true;
2153
- if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$24.warn("Span processor is not a LaminarSpanProcessor. Some functionality may be impaired.");
2167
+ if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$26.warn("Span processor is not a LaminarSpanProcessor. Some functionality may be impaired.");
2154
2168
  this.isInitialized = true;
2155
2169
  const urlWithoutSlash = url?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
2156
2170
  const httpUrlWithoutSlash = httpUrl?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
@@ -2170,7 +2184,8 @@ var Laminar = class Laminar {
2170
2184
  flushBySize,
2171
2185
  traceExportTimeoutMillis,
2172
2186
  sessionRecordingOptions,
2173
- spanProcessor
2187
+ spanProcessor,
2188
+ release
2174
2189
  });
2175
2190
  this._initDebugRuntime(url, port);
2176
2191
  LaminarContextManager.setGlobalMetadata(this.globalMetadata);
@@ -2197,11 +2212,11 @@ var Laminar = class Laminar {
2197
2212
  try {
2198
2213
  getRuntime()?.recordTraceId(otelTraceIdToUUID(otelSpanContext.traceId));
2199
2214
  } catch (e) {
2200
- logger$24.debug("Failed to record debug trace id from env: " + errorMessage(e));
2215
+ logger$26.debug("Failed to record debug trace id from env: " + errorMessage(e));
2201
2216
  }
2202
- logger$24.debug("Initialized Laminar parent context from LMNR_SPAN_CONTEXT.");
2217
+ logger$26.debug("Initialized Laminar parent context from LMNR_SPAN_CONTEXT.");
2203
2218
  } catch (e) {
2204
- logger$24.warn("LMNR_SPAN_CONTEXT is set but could not be used: " + errorMessage(e));
2219
+ logger$26.warn("LMNR_SPAN_CONTEXT is set but could not be used: " + errorMessage(e));
2205
2220
  }
2206
2221
  }
2207
2222
  /**
@@ -2245,7 +2260,7 @@ var Laminar = class Laminar {
2245
2260
  if (projectId) {
2246
2261
  runtime.recordProjectId(projectId);
2247
2262
  const sessionUrl = runtime.debuggerSessionUrl();
2248
- logger$24.info(`Laminar debugger session: ${sessionUrl}`);
2263
+ logger$26.info(`Laminar debugger session: ${sessionUrl}`);
2249
2264
  if (runtime.shouldOpenBrowser) {
2250
2265
  const opener = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
2251
2266
  spawn(opener, [sessionUrl], {
@@ -2255,7 +2270,7 @@ var Laminar = class Laminar {
2255
2270
  }
2256
2271
  }
2257
2272
  }).catch((e) => {
2258
- logger$24.warn("Failed to register debug session: " + errorMessage(e));
2273
+ logger$26.warn("Failed to register debug session: " + errorMessage(e));
2259
2274
  });
2260
2275
  this.globalMetadata = {
2261
2276
  ...this.globalMetadata,
@@ -2265,7 +2280,7 @@ var Laminar = class Laminar {
2265
2280
  this.debugExitHook = () => runtime.emitPointer();
2266
2281
  process.once("exit", this.debugExitHook);
2267
2282
  } catch (e) {
2268
- logger$24.warn("Failed to initialize debug runtime: " + errorMessage(e));
2283
+ logger$26.warn("Failed to initialize debug runtime: " + errorMessage(e));
2269
2284
  }
2270
2285
  }
2271
2286
  /**
@@ -2312,7 +2327,7 @@ var Laminar = class Laminar {
2312
2327
  runtime.rolloutSessions.register({ sessionId: runtime.sessionId }).then((projectId) => {
2313
2328
  if (projectId) runtime.recordProjectId(projectId);
2314
2329
  }).catch((e) => {
2315
- logger$24.debug("Failed to register downstream debug session: " + errorMessage(e));
2330
+ logger$26.debug("Failed to register downstream debug session: " + errorMessage(e));
2316
2331
  });
2317
2332
  this.globalMetadata = {
2318
2333
  ...this.globalMetadata,
@@ -2321,7 +2336,7 @@ var Laminar = class Laminar {
2321
2336
  LaminarContextManager.setGlobalMetadata(this.globalMetadata);
2322
2337
  }
2323
2338
  } catch (e) {
2324
- logger$24.debug("Failed to arm debug runtime from context: " + errorMessage(e));
2339
+ logger$26.debug("Failed to arm debug runtime from context: " + errorMessage(e));
2325
2340
  }
2326
2341
  }
2327
2342
  /**
@@ -2336,7 +2351,7 @@ var Laminar = class Laminar {
2336
2351
  */
2337
2352
  static patch(modules) {
2338
2353
  if (!this.isInitialized) {
2339
- logger$24.warn("Laminar must be initialized before patching modules. Skipping patch.");
2354
+ logger$26.warn("Laminar must be initialized before patching modules. Skipping patch.");
2340
2355
  return;
2341
2356
  }
2342
2357
  if (!modules || Object.keys(modules).length === 0) throw new Error("Pass at least one module to patch");
@@ -2596,7 +2611,7 @@ var Laminar = class Laminar {
2596
2611
  const spanContext = tryToOtelSpanContext(laminarContext);
2597
2612
  entityContext = trace.setSpan(entityContext, trace.wrapSpanContext(spanContext));
2598
2613
  } catch (e) {
2599
- logger$24.warn("Failed to parse parent span context: " + errorMessage(e));
2614
+ logger$26.warn("Failed to parse parent span context: " + errorMessage(e));
2600
2615
  }
2601
2616
  const tagProperties = tags ? { [`${ASSOCIATION_PROPERTIES}.tags`]: Array.from(new Set(tags)) } : {};
2602
2617
  const ctxAssociationProperties = LaminarContextManager.getAssociationProperties();
@@ -2632,6 +2647,10 @@ var Laminar = class Laminar {
2632
2647
  startTime
2633
2648
  }, entityContext));
2634
2649
  span.activated = activated ?? false;
2650
+ if (spanType === "LLM") {
2651
+ const llmCall = entityContext.getValue(LLM_CALL_KEY);
2652
+ if (llmCall?.mode === "handoff" && span.isRecording()) llmCall.recorded = true;
2653
+ }
2635
2654
  if (input) span.setInput(input);
2636
2655
  if (activated) {
2637
2656
  entityContext = LaminarContextManager.setAssociationProperties(span, entityContext);
@@ -2700,13 +2719,13 @@ var Laminar = class Laminar {
2700
2719
  }
2701
2720
  static async flush() {
2702
2721
  if (this.isInitialized) {
2703
- logger$24.debug("Flushing spans");
2722
+ logger$26.debug("Flushing spans");
2704
2723
  await forceFlush();
2705
2724
  }
2706
2725
  }
2707
2726
  static async shutdown() {
2708
2727
  if (this.isInitialized) {
2709
- logger$24.debug("Shutting down Laminar");
2728
+ logger$26.debug("Shutting down Laminar");
2710
2729
  getRuntime()?.emitPointer();
2711
2730
  await forceFlush();
2712
2731
  this.isInitialized = false;
@@ -2841,7 +2860,7 @@ return module.exports;
2841
2860
  //#endregion
2842
2861
  //#region src/browser/utils.ts
2843
2862
  const LMNR_SEND_EVENTS_FUNCTION_NAME = "lmnrSendEvents";
2844
- const logger$23 = initializeLogger();
2863
+ const logger$25 = initializeLogger();
2845
2864
  /**
2846
2865
  * If the first argument is a string, return an object with the name of the method
2847
2866
  * and the argument as the value.
@@ -2864,7 +2883,7 @@ const takeFullSnapshot = async (page) => await page.evaluate(() => {
2864
2883
  window.lmnrRrweb.record.takeFullSnapshot();
2865
2884
  return true;
2866
2885
  } catch (error) {
2867
- logger$23.error("Error taking full snapshot: " + errorMessage(error));
2886
+ logger$25.error("Error taking full snapshot: " + errorMessage(error));
2868
2887
  return false;
2869
2888
  }
2870
2889
  return false;
@@ -2875,7 +2894,7 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
2875
2894
  try {
2876
2895
  return await script();
2877
2896
  } catch (error) {
2878
- logger$23.error("Operation " + script.name + " failed: " + errorMessage(error));
2897
+ logger$25.error("Operation " + script.name + " failed: " + errorMessage(error));
2879
2898
  }
2880
2899
  await new Promise((resolve) => setTimeout(resolve, 500));
2881
2900
  }
@@ -2885,20 +2904,20 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
2885
2904
  try {
2886
2905
  isRrwebPresent = await castedPage.evaluate(() => typeof window.lmnrRrweb !== "undefined");
2887
2906
  } catch (error) {
2888
- logger$23.debug("Failed to check if session recorder is loaded: " + errorMessage(error));
2907
+ logger$25.debug("Failed to check if session recorder is loaded: " + errorMessage(error));
2889
2908
  }
2890
2909
  if (!isRrwebPresent) {
2891
2910
  if (!await tryRunScript(async function injectSessionRecorder() {
2892
2911
  await castedPage.evaluate(RECORDER);
2893
2912
  return true;
2894
2913
  })) {
2895
- logger$23.error("Failed to load session recorder");
2914
+ logger$25.error("Failed to load session recorder");
2896
2915
  return;
2897
2916
  }
2898
2917
  try {
2899
2918
  await castedPage.evaluate(injectScript, sessionRecordingOptions);
2900
2919
  } catch (error) {
2901
- logger$23.debug("Failed to inject session recorder: " + errorMessage(error));
2920
+ logger$25.debug("Failed to inject session recorder: " + errorMessage(error));
2902
2921
  }
2903
2922
  }
2904
2923
  };
@@ -3164,7 +3183,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
3164
3183
  try {
3165
3184
  const { batchId, chunkIndex, totalChunks, data } = chunk;
3166
3185
  if (!sessionId || !traceId) {
3167
- logger$23.debug("Missing sessionId or traceId in chunk");
3186
+ logger$25.debug("Missing sessionId or traceId in chunk");
3168
3187
  return;
3169
3188
  }
3170
3189
  if (!chunkBuffers.has(batchId)) chunkBuffers.set(batchId, {
@@ -3183,7 +3202,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
3183
3202
  traceId,
3184
3203
  events
3185
3204
  }).catch((error) => {
3186
- logger$23.debug("Failed to send events: " + errorMessage(error));
3205
+ logger$25.debug("Failed to send events: " + errorMessage(error));
3187
3206
  });
3188
3207
  chunkBuffers.delete(batchId);
3189
3208
  }
@@ -3191,16 +3210,16 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
3191
3210
  const toDelete = [];
3192
3211
  for (const [bid, buffer] of chunkBuffers.entries()) if (currentTime - buffer.timestamp > OLD_BUFFER_TIMEOUT) toDelete.push(bid);
3193
3212
  for (const bid of toDelete) {
3194
- logger$23.debug(`Cleaning up incomplete chunk buffer: ${bid}`);
3213
+ logger$25.debug(`Cleaning up incomplete chunk buffer: ${bid}`);
3195
3214
  chunkBuffers.delete(bid);
3196
3215
  }
3197
3216
  } catch (error) {
3198
- logger$23.debug("Could not send events: " + errorMessage(error));
3217
+ logger$25.debug("Could not send events: " + errorMessage(error));
3199
3218
  }
3200
3219
  }
3201
3220
  //#endregion
3202
3221
  //#region src/browser/playwright.ts
3203
- const logger$22 = initializeLogger();
3222
+ const logger$24 = initializeLogger();
3204
3223
  var PlaywrightInstrumentation = class extends InstrumentationBase {
3205
3224
  constructor(client, sessionRecordingOptions) {
3206
3225
  super("@lmnr/playwright-instrumentation", version, { enabled: true });
@@ -3308,7 +3327,7 @@ var PlaywrightInstrumentation = class extends InstrumentationBase {
3308
3327
  try {
3309
3328
  await injectSessionRecorder(page, this._sessionRecordingOptions);
3310
3329
  } catch (error) {
3311
- logger$22.error("Error in onLoad handler: " + errorMessage(error));
3330
+ logger$24.error("Error in onLoad handler: " + errorMessage(error));
3312
3331
  }
3313
3332
  });
3314
3333
  const chunkBuffers = /* @__PURE__ */ new Map();
@@ -3318,7 +3337,7 @@ var PlaywrightInstrumentation = class extends InstrumentationBase {
3318
3337
  await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
3319
3338
  });
3320
3339
  } catch (error) {
3321
- logger$22.debug("Could not expose function lmnrSendEvents: " + errorMessage(error));
3340
+ logger$24.debug("Could not expose function lmnrSendEvents: " + errorMessage(error));
3322
3341
  }
3323
3342
  }
3324
3343
  };
@@ -3743,7 +3762,7 @@ var StagehandV2Instrumentation = class extends InstrumentationBase {
3743
3762
  };
3744
3763
  //#endregion
3745
3764
  //#region src/browser/puppeteer.ts
3746
- const logger$21 = initializeLogger();
3765
+ const logger$23 = initializeLogger();
3747
3766
  var PuppeteerInstrumentation = class extends InstrumentationBase {
3748
3767
  constructor(client, sessionRecordingOptions) {
3749
3768
  super("@lmnr/puppeteer-instrumentation", version, { enabled: true });
@@ -3788,10 +3807,10 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
3788
3807
  context.on("targetcreated", (target) => {
3789
3808
  target.page().then((page) => {
3790
3809
  if (page) plugin.patchPage(page, sessionId).catch((error) => {
3791
- logger$21.error("Failed to patch page: " + errorMessage(error));
3810
+ logger$23.error("Failed to patch page: " + errorMessage(error));
3792
3811
  });
3793
3812
  }).catch((error) => {
3794
- logger$21.error("Failed to patch page: " + errorMessage(error));
3813
+ logger$23.error("Failed to patch page: " + errorMessage(error));
3795
3814
  });
3796
3815
  });
3797
3816
  await Promise.all((await context.pages()).map((page) => plugin.patchPage(page, sessionId)));
@@ -3809,19 +3828,19 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
3809
3828
  context.on("targetcreated", (target) => {
3810
3829
  target.page().then((page) => {
3811
3830
  if (page) plugin.patchPage(page, sessionId).catch((error) => {
3812
- logger$21.error("Failed to patch page: " + errorMessage(error));
3831
+ logger$23.error("Failed to patch page: " + errorMessage(error));
3813
3832
  });
3814
3833
  }).catch((error) => {
3815
- logger$21.error("Failed to patch page: " + errorMessage(error));
3834
+ logger$23.error("Failed to patch page: " + errorMessage(error));
3816
3835
  });
3817
3836
  });
3818
3837
  context.on("targetchanged", (target) => {
3819
3838
  target.page().then((page) => {
3820
3839
  if (page) plugin.patchPage(page, sessionId).catch((error) => {
3821
- logger$21.error("Failed to patch page: " + errorMessage(error));
3840
+ logger$23.error("Failed to patch page: " + errorMessage(error));
3822
3841
  });
3823
3842
  }).catch((error) => {
3824
- logger$21.error("Failed to patch page: " + errorMessage(error));
3843
+ logger$23.error("Failed to patch page: " + errorMessage(error));
3825
3844
  });
3826
3845
  });
3827
3846
  for (const page of await context.pages()) await plugin.patchPage(page, sessionId);
@@ -3845,7 +3864,7 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
3845
3864
  const traceId = otelTraceId ? otelTraceIdToUUID(otelTraceId) : NIL_UUID;
3846
3865
  page.on("domcontentloaded", () => {
3847
3866
  injectSessionRecorder(page, this._sessionRecordingOptions).catch((error) => {
3848
- logger$21.error("Error in onLoad handler: " + errorMessage(error));
3867
+ logger$23.error("Error in onLoad handler: " + errorMessage(error));
3849
3868
  });
3850
3869
  });
3851
3870
  await injectSessionRecorder(page, this._sessionRecordingOptions);
@@ -3855,13 +3874,13 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
3855
3874
  await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
3856
3875
  });
3857
3876
  } catch (error) {
3858
- logger$21.debug("Could not expose function lmnrSendEvents: " + errorMessage(error));
3877
+ logger$23.debug("Could not expose function lmnrSendEvents: " + errorMessage(error));
3859
3878
  }
3860
3879
  }
3861
3880
  };
3862
3881
  //#endregion
3863
3882
  //#region src/browser/stagehand/v3/constants.ts
3864
- const logger$20 = initializeLogger();
3883
+ const logger$22 = initializeLogger();
3865
3884
  const CDP_OPERATION_TIMEOUT_MS = 1e4;
3866
3885
  const SKIP_URL_PATTERNS = [
3867
3886
  "about:blank",
@@ -3912,7 +3931,7 @@ async function getOrCreateIsolatedWorld(page) {
3912
3931
  frameId
3913
3932
  };
3914
3933
  } catch (error) {
3915
- logger$20.debug("Failed to create isolated world: " + errorMessage(error));
3934
+ logger$22.debug("Failed to create isolated world: " + errorMessage(error));
3916
3935
  return null;
3917
3936
  }
3918
3937
  }
@@ -3929,7 +3948,7 @@ async function isRecorderPresent(page, contextId) {
3929
3948
  if (!result) return true;
3930
3949
  return result.result?.value === true;
3931
3950
  } catch (error) {
3932
- logger$20.debug("Failed to check if recorder is present: " + errorMessage(error));
3951
+ logger$22.debug("Failed to check if recorder is present: " + errorMessage(error));
3933
3952
  return true;
3934
3953
  }
3935
3954
  }
@@ -3942,21 +3961,21 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3942
3961
  try {
3943
3962
  url = page.url();
3944
3963
  } catch (error) {
3945
- logger$20.debug("Failed to get page URL, page might be closed: " + errorMessage(error));
3964
+ logger$22.debug("Failed to get page URL, page might be closed: " + errorMessage(error));
3946
3965
  return null;
3947
3966
  }
3948
3967
  if (shouldSkipUrl(url)) {
3949
- logger$20.debug(`Skipping recorder injection for URL: ${url}`);
3968
+ logger$22.debug(`Skipping recorder injection for URL: ${url}`);
3950
3969
  return null;
3951
3970
  }
3952
3971
  const worldResult = await getOrCreateIsolatedWorld(page);
3953
3972
  if (!worldResult) {
3954
- logger$20.debug("Failed to get isolated world for page");
3973
+ logger$22.debug("Failed to get isolated world for page");
3955
3974
  return null;
3956
3975
  }
3957
3976
  const { contextId, frameId } = worldResult;
3958
3977
  if (await isRecorderPresent(page, contextId)) {
3959
- logger$20.debug("Recorder already present, skipping injection");
3978
+ logger$22.debug("Recorder already present, skipping injection");
3960
3979
  state.contextIdToSession.set(contextId, {
3961
3980
  sessionId: state.sessionId,
3962
3981
  traceId: state.traceId
@@ -3969,7 +3988,7 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3969
3988
  contextId
3970
3989
  });
3971
3990
  } catch (error) {
3972
- logger$20.debug("Failed to inject rrweb: " + errorMessage(error));
3991
+ logger$22.debug("Failed to inject rrweb: " + errorMessage(error));
3973
3992
  return null;
3974
3993
  }
3975
3994
  const optionsJson = JSON.stringify(sessionRecordingOptions ?? {});
@@ -3980,14 +3999,14 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3980
3999
  contextId
3981
4000
  });
3982
4001
  } catch (error) {
3983
- logger$20.debug("Failed to inject recording setup: " + errorMessage(error));
4002
+ logger$22.debug("Failed to inject recording setup: " + errorMessage(error));
3984
4003
  return null;
3985
4004
  }
3986
4005
  try {
3987
4006
  await sendCDP(page, "Runtime.addBinding", { name: "lmnrSendEvents" });
3988
- logger$20.debug(`Added binding 'lmnrSendEvents' for page ${frameId}, context ${contextId}`);
4007
+ logger$22.debug(`Added binding 'lmnrSendEvents' for page ${frameId}, context ${contextId}`);
3989
4008
  } catch (error) {
3990
- logger$20.debug("Binding may already exist: " + errorMessage(error));
4009
+ logger$22.debug("Binding may already exist: " + errorMessage(error));
3991
4010
  }
3992
4011
  if (bindingHandler) try {
3993
4012
  const pageTargetId = page.targetId();
@@ -3997,26 +4016,26 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3997
4016
  const sessionTyped = session;
3998
4017
  if (sessionTyped.on) {
3999
4018
  sessionTyped.on("Runtime.bindingCalled", bindingHandler);
4000
- logger$20.debug(`Set up binding handler on session ${sessionId}`);
4019
+ logger$22.debug(`Set up binding handler on session ${sessionId}`);
4001
4020
  }
4002
4021
  } catch (error) {
4003
- logger$20.debug(`Failed to set up binding handler on session ${sessionId}: ` + errorMessage(error));
4022
+ logger$22.debug(`Failed to set up binding handler on session ${sessionId}: ` + errorMessage(error));
4004
4023
  }
4005
4024
  state.pageSessionHandlers.set(pageTargetId, bindingHandler);
4006
4025
  }
4007
4026
  } catch (error) {
4008
- logger$20.debug("Failed to set up binding handler: " + errorMessage(error));
4027
+ logger$22.debug("Failed to set up binding handler: " + errorMessage(error));
4009
4028
  }
4010
4029
  state.contextIdToSession.set(contextId, {
4011
4030
  sessionId: state.sessionId,
4012
4031
  traceId: state.traceId
4013
4032
  });
4014
- logger$20.debug(`Registered context mapping: contextId=${contextId}, sessionId=${state.sessionId}`);
4033
+ logger$22.debug(`Registered context mapping: contextId=${contextId}, sessionId=${state.sessionId}`);
4015
4034
  state.instrumentedPageIds.add(frameId);
4016
- logger$20.debug(`Successfully injected recorder into page ${frameId}`);
4035
+ logger$22.debug(`Successfully injected recorder into page ${frameId}`);
4017
4036
  return contextId;
4018
4037
  } catch (error) {
4019
- logger$20.debug("Error injecting recorder: " + errorMessage(error));
4038
+ logger$22.debug("Error injecting recorder: " + errorMessage(error));
4020
4039
  return null;
4021
4040
  }
4022
4041
  }
@@ -4030,13 +4049,13 @@ function createBindingHandler(state) {
4030
4049
  if (event.name !== "lmnrSendEvents") return;
4031
4050
  const sessionInfo = state.contextIdToSession.get(event.executionContextId);
4032
4051
  if (!sessionInfo) {
4033
- logger$20.debug("No session info found for context ID: " + event.executionContextId);
4052
+ logger$22.debug("No session info found for context ID: " + event.executionContextId);
4034
4053
  if (state.contextIdToSession.size > 0) {
4035
4054
  const [, fallbackInfo] = state.contextIdToSession.entries().next().value;
4036
4055
  if (fallbackInfo) try {
4037
4056
  sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, fallbackInfo.sessionId, fallbackInfo.traceId);
4038
4057
  } catch (error) {
4039
- logger$20.debug("Failed to parse binding payload: " + errorMessage(error));
4058
+ logger$22.debug("Failed to parse binding payload: " + errorMessage(error));
4040
4059
  }
4041
4060
  }
4042
4061
  return;
@@ -4044,7 +4063,7 @@ function createBindingHandler(state) {
4044
4063
  try {
4045
4064
  sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, sessionInfo.sessionId, sessionInfo.traceId);
4046
4065
  } catch (error) {
4047
- logger$20.debug("Failed to handle binding event: " + errorMessage(error));
4066
+ logger$22.debug("Failed to handle binding event: " + errorMessage(error));
4048
4067
  }
4049
4068
  };
4050
4069
  }
@@ -4060,10 +4079,10 @@ function createTargetCreatedHandler(context, state, sessionRecordingOptions) {
4060
4079
  const pageId = page.mainFrameId();
4061
4080
  if (!state.instrumentedPageIds.has(pageId)) await injectRecorderViaCDP(page, state, context.conn, sessionRecordingOptions, state.bindingHandler ?? void 0);
4062
4081
  } catch (error) {
4063
- logger$20.debug("Error injecting recorder into new page: " + errorMessage(error));
4082
+ logger$22.debug("Error injecting recorder into new page: " + errorMessage(error));
4064
4083
  }
4065
4084
  } catch (error) {
4066
- logger$20.debug("Error handling target created event: " + errorMessage(error));
4085
+ logger$22.debug("Error handling target created event: " + errorMessage(error));
4067
4086
  }
4068
4087
  };
4069
4088
  }
@@ -4075,7 +4094,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
4075
4094
  if (event.targetInfo.type !== "page") return;
4076
4095
  const url = event.targetInfo.url;
4077
4096
  if (shouldSkipUrl(url)) return;
4078
- logger$20.debug(`Target URL changed to ${url}, checking if recorder injection needed`);
4097
+ logger$22.debug(`Target URL changed to ${url}, checking if recorder injection needed`);
4079
4098
  await new Promise((resolve) => setTimeout(resolve, 150));
4080
4099
  try {
4081
4100
  for (const page of context.pages()) if (page.targetId() === event.targetInfo.targetId) {
@@ -4083,7 +4102,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
4083
4102
  break;
4084
4103
  }
4085
4104
  } catch (error) {
4086
- logger$20.debug("Error handling target info change: " + errorMessage(error));
4105
+ logger$22.debug("Error handling target info change: " + errorMessage(error));
4087
4106
  }
4088
4107
  };
4089
4108
  }
@@ -4244,12 +4263,12 @@ var StagehandInstrumentation = class extends InstrumentationBase {
4244
4263
  */
4245
4264
  async setupSessionRecording(stagehandInstance, sessionId, traceId) {
4246
4265
  if (!this._client) {
4247
- logger$20.debug("No Laminar client available, skipping session recording setup");
4266
+ logger$22.debug("No Laminar client available, skipping session recording setup");
4248
4267
  return;
4249
4268
  }
4250
4269
  const context = stagehandInstance.context;
4251
4270
  if (!context || !context.conn) {
4252
- logger$20.debug("No context or connection available, skipping session recording setup");
4271
+ logger$22.debug("No context or connection available, skipping session recording setup");
4253
4272
  return;
4254
4273
  }
4255
4274
  const recorderState = {
@@ -4279,11 +4298,11 @@ var StagehandInstrumentation = class extends InstrumentationBase {
4279
4298
  for (const page of pages) try {
4280
4299
  if (await injectRecorderViaCDP(page, recorderState, context.conn, this._sessionRecordingOptions, bindingHandler) !== null) injectedCount++;
4281
4300
  } catch (error) {
4282
- logger$20.debug("Error injecting recorder into page: " + errorMessage(error));
4301
+ logger$22.debug("Error injecting recorder into page: " + errorMessage(error));
4283
4302
  }
4284
- logger$20.debug(`Injected session recorder into ${injectedCount} of ${pages.length} existing page(s)`);
4303
+ logger$22.debug(`Injected session recorder into ${injectedCount} of ${pages.length} existing page(s)`);
4285
4304
  } catch (error) {
4286
- logger$20.debug("Error accessing pages for recorder injection: " + errorMessage(error));
4305
+ logger$22.debug("Error accessing pages for recorder injection: " + errorMessage(error));
4287
4306
  }
4288
4307
  }
4289
4308
  patchStagehandClose() {
@@ -4313,12 +4332,12 @@ var StagehandInstrumentation = class extends InstrumentationBase {
4313
4332
  if (recorderState.targetCreatedHandler) try {
4314
4333
  context.conn.off("Target.targetCreated", recorderState.targetCreatedHandler);
4315
4334
  } catch (error) {
4316
- logger$20.debug("Error removing target created handler: " + errorMessage(error));
4335
+ logger$22.debug("Error removing target created handler: " + errorMessage(error));
4317
4336
  }
4318
4337
  if (recorderState.targetInfoChangedHandler) try {
4319
4338
  context.conn.off("Target.targetInfoChanged", recorderState.targetInfoChangedHandler);
4320
4339
  } catch (error) {
4321
- logger$20.debug("Error removing target info changed handler: " + errorMessage(error));
4340
+ logger$22.debug("Error removing target info changed handler: " + errorMessage(error));
4322
4341
  }
4323
4342
  }
4324
4343
  recorderState.contextIdToSession.clear();
@@ -4329,7 +4348,7 @@ var StagehandInstrumentation = class extends InstrumentationBase {
4329
4348
  recorderState.targetCreatedHandler = null;
4330
4349
  recorderState.targetInfoChangedHandler = null;
4331
4350
  this.stagehandInstanceToRecorderState.delete(stagehandInstance);
4332
- logger$20.debug("Cleaned up session recording for Stagehand instance");
4351
+ logger$22.debug("Cleaned up session recording for Stagehand instance");
4333
4352
  }
4334
4353
  patchStagehandGlobalMethod(methodName, sessionId, parentSpan) {
4335
4354
  return (original) => async function method(...args) {
@@ -4680,7 +4699,7 @@ function extractToolDefinitions(config) {
4680
4699
  * Also used by the google-aiplatform (Vertex AI) instrumentation, which
4681
4700
  * reshapes its requests into the same `{model, contents, config}` form.
4682
4701
  */
4683
- function setRequestAttributes$5(span, params, traceContent, system = "gemini") {
4702
+ function setRequestAttributes$6(span, params, traceContent, system = "gemini") {
4684
4703
  safeSetAttribute$2(span, LLM_SYSTEM, system);
4685
4704
  safeSetAttribute$2(span, LLM_REQUEST_MODEL, params?.model);
4686
4705
  const config = params?.config;
@@ -4707,7 +4726,7 @@ function setRequestAttributes$5(span, params, traceContent, system = "gemini") {
4707
4726
  /**
4708
4727
  * Set response attributes on a span from a GenerateContentResponse.
4709
4728
  */
4710
- function setResponseAttributes$5(span, response, traceContent) {
4729
+ function setResponseAttributes$6(span, response, traceContent) {
4711
4730
  if (!response) return;
4712
4731
  safeSetAttribute$2(span, LLM_RESPONSE_MODEL, response.modelVersion);
4713
4732
  const usage = response.usageMetadata;
@@ -4809,7 +4828,7 @@ function wrapStreamingResponse(span, asyncGen, traceContent) {
4809
4828
  try {
4810
4829
  if (modelVersion !== void 0 || role !== void 0 || accumulatedParts.length > 0 || sawUsageMetadata) {
4811
4830
  const mergedParts = mergeTextParts(accumulatedParts);
4812
- setResponseAttributes$5(span, {
4831
+ setResponseAttributes$6(span, {
4813
4832
  modelVersion,
4814
4833
  candidates: [{ content: {
4815
4834
  role: role ?? "model",
@@ -4840,22 +4859,22 @@ function wrapStreamingResponse(span, asyncGen, traceContent) {
4840
4859
  //#endregion
4841
4860
  //#region src/opentelemetry-lib/instrumentation/anthropic/utils.ts
4842
4861
  const ANTHROPIC_SYSTEM = "anthropic";
4843
- const INPUT_MESSAGES$2 = "gen_ai.input.messages";
4844
- const OUTPUT_MESSAGES$2 = "gen_ai.output.messages";
4862
+ const INPUT_MESSAGES$3 = "gen_ai.input.messages";
4863
+ const OUTPUT_MESSAGES$3 = "gen_ai.output.messages";
4845
4864
  const createStreamState$1 = () => ({
4846
4865
  usage: {},
4847
4866
  blocks: [],
4848
4867
  completion: ""
4849
4868
  });
4850
- const toJson$1 = (value) => {
4869
+ const toJson$2 = (value) => {
4851
4870
  if (value === void 0 || value === null) return void 0;
4852
4871
  return JSON.stringify(value);
4853
4872
  };
4854
4873
  const extractStructuredOutputSchema$1 = (params) => {
4855
4874
  const outputFormat = params?.output_format;
4856
- if (outputFormat && typeof outputFormat === "object") return toJson$1(outputFormat.schema ?? outputFormat);
4875
+ if (outputFormat && typeof outputFormat === "object") return toJson$2(outputFormat.schema ?? outputFormat);
4857
4876
  const schema = params?.output_config?.format?.schema;
4858
- if (schema && typeof schema === "object") return toJson$1(schema);
4877
+ if (schema && typeof schema === "object") return toJson$2(schema);
4859
4878
  };
4860
4879
  const buildInputMessages$1 = (params) => {
4861
4880
  if (params?.prompt !== void 0 && params?.prompt !== null) return [{
@@ -4871,7 +4890,7 @@ const buildInputMessages$1 = (params) => {
4871
4890
  messages.push(...params.messages);
4872
4891
  return messages;
4873
4892
  };
4874
- const setRequestAttributes$4 = (span, params, traceContent) => {
4893
+ const setRequestAttributes$5 = (span, params, traceContent) => {
4875
4894
  safeSetAttribute$2(span, "gen_ai.system", ANTHROPIC_SYSTEM);
4876
4895
  safeSetAttribute$2(span, "gen_ai.request.model", params?.model);
4877
4896
  safeSetAttribute$2(span, "gen_ai.request.max_tokens", params?.max_tokens ?? params?.max_tokens_to_sample);
@@ -4882,8 +4901,8 @@ const setRequestAttributes$4 = (span, params, traceContent) => {
4882
4901
  safeSetAttribute$2(span, "llm.is_streaming", params?.stream);
4883
4902
  safeSetAttribute$2(span, "anthropic.request.service_tier", params?.service_tier);
4884
4903
  if (traceContent) {
4885
- safeSetAttribute$2(span, INPUT_MESSAGES$2, toJson$1(buildInputMessages$1(params)));
4886
- safeSetAttribute$2(span, "gen_ai.tool.definitions", toJson$1(params?.tools));
4904
+ safeSetAttribute$2(span, INPUT_MESSAGES$3, toJson$2(buildInputMessages$1(params)));
4905
+ safeSetAttribute$2(span, "gen_ai.tool.definitions", toJson$2(params?.tools));
4887
4906
  }
4888
4907
  safeSetAttribute$2(span, "gen_ai.request.structured_output_schema", extractStructuredOutputSchema$1(params));
4889
4908
  };
@@ -4903,7 +4922,7 @@ const setUsageAttributes$1 = (span, usage, includeTotal) => {
4903
4922
  /**
4904
4923
  * Response attributes for a non-streaming `Message` (or legacy `Completion`).
4905
4924
  */
4906
- const setResponseAttributes$4 = (span, response, traceContent) => {
4925
+ const setResponseAttributes$5 = (span, response, traceContent) => {
4907
4926
  if (!response || typeof response !== "object") return;
4908
4927
  safeSetAttribute$2(span, "gen_ai.response.model", response.model);
4909
4928
  safeSetAttribute$2(span, "gen_ai.response.id", response.id);
@@ -4920,7 +4939,7 @@ const setResponseAttributes$4 = (span, response, traceContent) => {
4920
4939
  text: response.completion
4921
4940
  });
4922
4941
  else if (Array.isArray(response.content)) output.content.push(...response.content);
4923
- safeSetAttribute$2(span, OUTPUT_MESSAGES$2, toJson$1([output]));
4942
+ safeSetAttribute$2(span, OUTPUT_MESSAGES$3, toJson$2([output]));
4924
4943
  }
4925
4944
  span.setStatus({ code: SpanStatusCode.OK });
4926
4945
  };
@@ -5013,14 +5032,14 @@ const setStreamingResponseAttributes = (span, state, traceContent) => {
5013
5032
  content: buildStreamedContent(state)
5014
5033
  };
5015
5034
  if (state.stopReason) output.stop_reason = state.stopReason;
5016
- safeSetAttribute$2(span, OUTPUT_MESSAGES$2, toJson$1([output]));
5035
+ safeSetAttribute$2(span, OUTPUT_MESSAGES$3, toJson$2([output]));
5017
5036
  }
5018
5037
  };
5019
5038
  //#endregion
5020
5039
  //#region src/opentelemetry-lib/instrumentation/anthropic/index.ts
5021
- const logger$19 = initializeLogger();
5022
- const PATCH_DATA_SYMBOL$3 = Symbol("lmnr.anthropic.patchData");
5023
- const hasOwnPatchData$2 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$3) !== void 0;
5040
+ const logger$21 = initializeLogger();
5041
+ const PATCH_DATA_SYMBOL$4 = Symbol("lmnr.anthropic.patchData");
5042
+ const hasOwnPatchData$3 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$4) !== void 0;
5024
5043
  const markSpanError$3 = (span, error) => {
5025
5044
  span.recordException(error);
5026
5045
  span.setAttribute("error.type", error?.constructor?.name ?? "Error");
@@ -5033,7 +5052,7 @@ const safely$3 = (fn) => {
5033
5052
  try {
5034
5053
  fn();
5035
5054
  } catch (error) {
5036
- logger$19.debug(`Failed to set anthropic span attributes: ${String(error)}`);
5055
+ logger$21.debug(`Failed to set anthropic span attributes: ${String(error)}`);
5037
5056
  }
5038
5057
  };
5039
5058
  const isAsyncIterable$3 = (value) => value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
@@ -5084,9 +5103,9 @@ var AnthropicInstrumentation = class extends InstrumentationBase {
5084
5103
  unpatch(moduleExports) {
5085
5104
  diag.debug("Unpatching @anthropic-ai/sdk");
5086
5105
  for (const proto of this.resourcePrototypes(moduleExports)) {
5087
- if (!proto || !hasOwnPatchData$2(proto)) continue;
5088
- proto.create = proto[PATCH_DATA_SYMBOL$3].original;
5089
- delete proto[PATCH_DATA_SYMBOL$3];
5106
+ if (!proto || !hasOwnPatchData$3(proto)) continue;
5107
+ proto.create = proto[PATCH_DATA_SYMBOL$4].original;
5108
+ delete proto[PATCH_DATA_SYMBOL$4];
5090
5109
  }
5091
5110
  }
5092
5111
  /**
@@ -5108,15 +5127,15 @@ var AnthropicInstrumentation = class extends InstrumentationBase {
5108
5127
  */
5109
5128
  patchCreate(proto, spanName) {
5110
5129
  if (!proto || typeof proto.create !== "function") return;
5111
- if (hasOwnPatchData$2(proto)) {
5112
- proto[PATCH_DATA_SYMBOL$3].traceContent = this.traceContent;
5130
+ if (hasOwnPatchData$3(proto)) {
5131
+ proto[PATCH_DATA_SYMBOL$4].traceContent = this.traceContent;
5113
5132
  return;
5114
5133
  }
5115
5134
  const patchData = {
5116
5135
  traceContent: this.traceContent,
5117
5136
  original: proto.create
5118
5137
  };
5119
- Object.defineProperty(proto, PATCH_DATA_SYMBOL$3, {
5138
+ Object.defineProperty(proto, PATCH_DATA_SYMBOL$4, {
5120
5139
  value: patchData,
5121
5140
  writable: true,
5122
5141
  configurable: true,
@@ -5133,7 +5152,7 @@ const wrapCreate = (patchData, spanName) => function(params, ...rest) {
5133
5152
  name: spanName,
5134
5153
  spanType: "LLM"
5135
5154
  });
5136
- safely$3(() => setRequestAttributes$4(span, params, traceContent));
5155
+ safely$3(() => setRequestAttributes$5(span, params, traceContent));
5137
5156
  let result;
5138
5157
  try {
5139
5158
  result = Laminar.withSpan(span, () => ({ value: original.call(this, params, ...rest) })).value;
@@ -5157,7 +5176,7 @@ const wrapCreate = (patchData, spanName) => function(params, ...rest) {
5157
5176
  return data;
5158
5177
  }
5159
5178
  ended = true;
5160
- safely$3(() => setResponseAttributes$4(span, data, traceContent));
5179
+ safely$3(() => setResponseAttributes$5(span, data, traceContent));
5161
5180
  span.end();
5162
5181
  return data;
5163
5182
  };
@@ -5207,8 +5226,8 @@ const instrumentStream$2 = (stream, span, traceContent) => {
5207
5226
  //#endregion
5208
5227
  //#region src/opentelemetry-lib/instrumentation/cohere/utils.ts
5209
5228
  const COHERE_SYSTEM = "cohere";
5210
- const INPUT_MESSAGES$1 = "gen_ai.input.messages";
5211
- const OUTPUT_MESSAGES$1 = "gen_ai.output.messages";
5229
+ const INPUT_MESSAGES$2 = "gen_ai.input.messages";
5230
+ const OUTPUT_MESSAGES$2 = "gen_ai.output.messages";
5212
5231
  const OPERATION_NAMES = {
5213
5232
  chat: "chat",
5214
5233
  completion: "text_completion",
@@ -5223,7 +5242,7 @@ const V1_ROLES = {
5223
5242
  };
5224
5243
  const asList = (value) => Array.isArray(value) ? value : [];
5225
5244
  const asInt = (value) => typeof value === "number" && Number.isFinite(value) ? Math.trunc(value) : void 0;
5226
- const maybeJson = (value) => {
5245
+ const maybeJson$1 = (value) => {
5227
5246
  if (typeof value !== "string") return value;
5228
5247
  try {
5229
5248
  return JSON.parse(value);
@@ -5291,7 +5310,7 @@ const v2ToolCallParts = (toolCalls) => asList(toolCalls).map((toolCall) => {
5291
5310
  name: toolCall?.function?.name ?? ""
5292
5311
  };
5293
5312
  const args = toolCall?.function?.arguments;
5294
- if (args !== void 0 && args !== null) part.arguments = maybeJson(args);
5313
+ if (args !== void 0 && args !== null) part.arguments = maybeJson$1(args);
5295
5314
  return part;
5296
5315
  });
5297
5316
  const v1ToolCallParts = (toolCalls) => asList(toolCalls).map((toolCall) => ({
@@ -5381,7 +5400,7 @@ const toolDefinitions = (tools) => asList(tools).map((tool) => {
5381
5400
  if (parameters) definition.parameters = parameters;
5382
5401
  return definition;
5383
5402
  });
5384
- const setRequestAttributes$3 = (span, params, requestType, isV2, isStreaming, traceContent) => {
5403
+ const setRequestAttributes$4 = (span, params, requestType, isV2, isStreaming, traceContent) => {
5385
5404
  safeSetAttribute$2(span, "gen_ai.system", COHERE_SYSTEM);
5386
5405
  safeSetAttribute$2(span, "gen_ai.operation.name", OPERATION_NAMES[requestType]);
5387
5406
  safeSetAttribute$2(span, "gen_ai.request.model", params?.model);
@@ -5406,12 +5425,12 @@ const setRequestAttributes$3 = (span, params, requestType, isV2, isStreaming, tr
5406
5425
  }] : [];
5407
5426
  else if (requestType === "rerank") messages = rerankInput(params);
5408
5427
  else messages = embedInput(params);
5409
- if (messages.length > 0) span.setAttribute(INPUT_MESSAGES$1, JSON.stringify(messages));
5428
+ if (messages.length > 0) span.setAttribute(INPUT_MESSAGES$2, JSON.stringify(messages));
5410
5429
  };
5411
5430
  /**
5412
5431
  * `usage` (v2) / `meta` (v1): actual `tokens`, falling back to `billedUnits`.
5413
5432
  */
5414
- const setUsage = (span, usage) => {
5433
+ const setUsage$1 = (span, usage) => {
5415
5434
  const inputTokens = asInt(usage?.tokens?.inputTokens) ?? asInt(usage?.billedUnits?.inputTokens);
5416
5435
  const outputTokens = asInt(usage?.tokens?.outputTokens) ?? asInt(usage?.billedUnits?.outputTokens);
5417
5436
  safeSetAttribute$2(span, "gen_ai.usage.input_tokens", inputTokens);
@@ -5447,9 +5466,9 @@ const rerankOutput = (response) => {
5447
5466
  parts
5448
5467
  }] : [];
5449
5468
  };
5450
- const setResponseAttributes$3 = (span, response, requestType, isV2, traceContent) => {
5469
+ const setResponseAttributes$4 = (span, response, requestType, isV2, traceContent) => {
5451
5470
  safeSetAttribute$2(span, "gen_ai.response.id", response?.responseId ?? response?.id);
5452
- setUsage(span, response?.usage ?? response?.meta);
5471
+ setUsage$1(span, response?.usage ?? response?.meta);
5453
5472
  let output = [];
5454
5473
  if (requestType === "chat") {
5455
5474
  const message = isV2 ? v2ChatOutput(response) : v1ChatOutput(response);
@@ -5461,7 +5480,7 @@ const setResponseAttributes$3 = (span, response, requestType, isV2, traceContent
5461
5480
  output = [message];
5462
5481
  } else if (requestType === "completion") output = completionOutput(response);
5463
5482
  else if (requestType === "rerank") output = rerankOutput(response);
5464
- if (output.length > 0 && traceContent) span.setAttribute(OUTPUT_MESSAGES$1, JSON.stringify(output));
5483
+ if (output.length > 0 && traceContent) span.setAttribute(OUTPUT_MESSAGES$2, JSON.stringify(output));
5465
5484
  };
5466
5485
  /**
5467
5486
  * v1 `chatStream`: the `stream-end` event carries the full response.
@@ -5578,8 +5597,8 @@ const createV2ChatStreamAccumulator = () => {
5578
5597
  };
5579
5598
  //#endregion
5580
5599
  //#region src/opentelemetry-lib/instrumentation/cohere/index.ts
5581
- const logger$18 = initializeLogger();
5582
- const PATCH_DATA_SYMBOL$2 = Symbol("lmnr.cohere.patchData");
5600
+ const logger$20 = initializeLogger();
5601
+ const PATCH_DATA_SYMBOL$3 = Symbol("lmnr.cohere.patchData");
5583
5602
  const SPAN_NAMES = {
5584
5603
  chat: "cohere.chat",
5585
5604
  completion: "cohere.completion",
@@ -5635,7 +5654,7 @@ const V2_METHODS = [
5635
5654
  streaming: false
5636
5655
  }
5637
5656
  ];
5638
- const ownPatchData = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$2)?.value;
5657
+ const ownPatchData = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$3)?.value;
5639
5658
  const markSpanError$2 = (span, error) => {
5640
5659
  span.recordException(error);
5641
5660
  span.setAttribute("error.type", error?.constructor?.name ?? "Error");
@@ -5651,7 +5670,7 @@ const safely$2 = (fn) => {
5651
5670
  try {
5652
5671
  fn();
5653
5672
  } catch (error) {
5654
- logger$18.debug(`Failed to set cohere span attributes: ${String(error)}`);
5673
+ logger$20.debug(`Failed to set cohere span attributes: ${String(error)}`);
5655
5674
  }
5656
5675
  };
5657
5676
  const isAsyncIterable$2 = (value) => value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
@@ -5758,7 +5777,7 @@ var CohereInstrumentation = class extends InstrumentationBase {
5758
5777
  }
5759
5778
  if (!patched) {
5760
5779
  patched = {};
5761
- Object.defineProperty(proto, PATCH_DATA_SYMBOL$2, {
5780
+ Object.defineProperty(proto, PATCH_DATA_SYMBOL$3, {
5762
5781
  value: patched,
5763
5782
  writable: true,
5764
5783
  configurable: true,
@@ -5783,7 +5802,7 @@ const wrapMethod$1 = (patchData) => function(request, ...rest) {
5783
5802
  name: SPAN_NAMES[requestType],
5784
5803
  spanType: "LLM"
5785
5804
  });
5786
- safely$2(() => setRequestAttributes$3(span, request, requestType, isV2, streaming, traceContent));
5805
+ safely$2(() => setRequestAttributes$4(span, request, requestType, isV2, streaming, traceContent));
5787
5806
  let result;
5788
5807
  try {
5789
5808
  result = Laminar.withSpan(span, () => ({ value: original.call(this, request, ...rest) })).value;
@@ -5807,7 +5826,7 @@ const wrapMethod$1 = (patchData) => function(request, ...rest) {
5807
5826
  instrumentStream$1(data, span, accumulator, isV2, traceContent);
5808
5827
  return data;
5809
5828
  }
5810
- safely$2(() => setResponseAttributes$3(span, data, requestType, isV2, traceContent));
5829
+ safely$2(() => setResponseAttributes$4(span, data, requestType, isV2, traceContent));
5811
5830
  span.end();
5812
5831
  return data;
5813
5832
  };
@@ -5832,7 +5851,7 @@ const instrumentStream$1 = (stream, span, accumulator, isV2, traceContent) => {
5832
5851
  const end = (error) => {
5833
5852
  if (ended) return;
5834
5853
  ended = true;
5835
- safely$2(() => setResponseAttributes$3(span, accumulator.response(), "chat", isV2, traceContent));
5854
+ safely$2(() => setResponseAttributes$4(span, accumulator.response(), "chat", isV2, traceContent));
5836
5855
  if (error !== void 0) markSpanError$2(span, error);
5837
5856
  else span.setStatus({ code: SpanStatusCode.OK });
5838
5857
  span.end();
@@ -5882,7 +5901,7 @@ const fromValue = (value) => {
5882
5901
  default: return;
5883
5902
  }
5884
5903
  };
5885
- const asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
5904
+ const asRecord$1 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
5886
5905
  const asNumber = (value) => typeof value === "number" && !Number.isNaN(value) ? value : void 0;
5887
5906
  /**
5888
5907
  * Strip resource prefixes, e.g.
@@ -5903,7 +5922,7 @@ const toInputMessages = (instance) => {
5903
5922
  content: instance.prompt
5904
5923
  });
5905
5924
  if (Array.isArray(instance.messages)) for (const message of instance.messages) {
5906
- const record = asRecord(message);
5925
+ const record = asRecord$1(message);
5907
5926
  if (!record) continue;
5908
5927
  const author = typeof record.author === "string" ? record.author : "user";
5909
5928
  messages.push({
@@ -5920,7 +5939,7 @@ const toInputMessages = (instance) => {
5920
5939
  const setPredictRequestAttributes = (span, request, traceContent) => {
5921
5940
  safeSetAttribute$2(span, "gen_ai.system", VERTEX_AI_SYSTEM);
5922
5941
  safeSetAttribute$2(span, "gen_ai.request.model", lastPathSegment(request?.endpoint));
5923
- const parameters = asRecord(fromValue(request?.parameters));
5942
+ const parameters = asRecord$1(fromValue(request?.parameters));
5924
5943
  if (parameters) {
5925
5944
  safeSetAttribute$2(span, "gen_ai.request.max_tokens", asNumber(parameters.maxOutputTokens));
5926
5945
  safeSetAttribute$2(span, "gen_ai.request.temperature", asNumber(parameters.temperature));
@@ -5929,16 +5948,16 @@ const setPredictRequestAttributes = (span, request, traceContent) => {
5929
5948
  }
5930
5949
  if (!traceContent || !Array.isArray(request?.instances)) return;
5931
5950
  const messages = request.instances.flatMap((instance) => {
5932
- const record = asRecord(fromValue(instance));
5951
+ const record = asRecord$1(fromValue(instance));
5933
5952
  return record ? toInputMessages(record) : [];
5934
5953
  });
5935
5954
  if (messages.length > 0) safeSetAttribute$2(span, "gen_ai.input.messages", JSON.stringify(messages));
5936
5955
  };
5937
5956
  const predictionContent = (prediction) => {
5938
- const record = asRecord(fromValue(prediction));
5957
+ const record = asRecord$1(fromValue(prediction));
5939
5958
  if (!record) return void 0;
5940
5959
  if (typeof record.content === "string") return record.content;
5941
- const firstCandidate = Array.isArray(record.candidates) ? asRecord(record.candidates[0]) : void 0;
5960
+ const firstCandidate = Array.isArray(record.candidates) ? asRecord$1(record.candidates[0]) : void 0;
5942
5961
  if (typeof firstCandidate?.content === "string") return firstCandidate.content;
5943
5962
  };
5944
5963
  /**
@@ -5947,10 +5966,10 @@ const predictionContent = (prediction) => {
5947
5966
  const setPredictResponseAttributes = (span, response, traceContent) => {
5948
5967
  if (!response) return;
5949
5968
  safeSetAttribute$2(span, "gen_ai.response.model", lastPathSegment(response.model));
5950
- const metadata = asRecord(fromValue(response.metadata));
5951
- const tokenMetadata = asRecord(metadata?.tokenMetadata);
5952
- const inputTokens = asNumber(asRecord(tokenMetadata?.inputTokenCount)?.totalTokens);
5953
- const outputTokens = asNumber(asRecord(tokenMetadata?.outputTokenCount)?.totalTokens);
5969
+ const metadata = asRecord$1(fromValue(response.metadata));
5970
+ const tokenMetadata = asRecord$1(metadata?.tokenMetadata);
5971
+ const inputTokens = asNumber(asRecord$1(tokenMetadata?.inputTokenCount)?.totalTokens);
5972
+ const outputTokens = asNumber(asRecord$1(tokenMetadata?.outputTokenCount)?.totalTokens);
5954
5973
  safeSetAttribute$2(span, "gen_ai.usage.input_tokens", inputTokens);
5955
5974
  safeSetAttribute$2(span, "gen_ai.usage.output_tokens", outputTokens);
5956
5975
  if (inputTokens !== void 0 && outputTokens !== void 0) safeSetAttribute$2(span, "llm.usage.total_tokens", inputTokens + outputTokens);
@@ -5982,9 +6001,9 @@ const toGenAiParams = (model, request) => {
5982
6001
  };
5983
6002
  //#endregion
5984
6003
  //#region src/opentelemetry-lib/instrumentation/google-aiplatform/index.ts
5985
- const logger$17 = initializeLogger();
5986
- const PATCH_DATA_SYMBOL$1 = Symbol("lmnr.google-aiplatform.patchData");
5987
- const hasOwnPatchData$1 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$1) !== void 0;
6004
+ const logger$19 = initializeLogger();
6005
+ const PATCH_DATA_SYMBOL$2 = Symbol("lmnr.google-aiplatform.patchData");
6006
+ const hasOwnPatchData$2 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$2) !== void 0;
5988
6007
  const GENERATIVE_MODEL_CLASSES = ["GenerativeModel", "GenerativeModelPreview"];
5989
6008
  const markSpanError$1 = (span, error) => {
5990
6009
  span.setAttribute("error.type", error?.constructor?.name ?? "Error");
@@ -5997,7 +6016,7 @@ const safely$1 = (fn) => {
5997
6016
  try {
5998
6017
  fn();
5999
6018
  } catch (error) {
6000
- logger$17.debug(`Failed to set google-aiplatform span attributes: ${String(error)}`);
6019
+ logger$19.debug(`Failed to set google-aiplatform span attributes: ${String(error)}`);
6001
6020
  }
6002
6021
  };
6003
6022
  /**
@@ -6087,13 +6106,13 @@ var GoogleAIPlatformInstrumentation = class extends InstrumentationBase {
6087
6106
  */
6088
6107
  patchMethod(proto, method, makeWrapper) {
6089
6108
  if (!proto || typeof proto[method] !== "function") return;
6090
- if (!hasOwnPatchData$1(proto)) Object.defineProperty(proto, PATCH_DATA_SYMBOL$1, {
6109
+ if (!hasOwnPatchData$2(proto)) Object.defineProperty(proto, PATCH_DATA_SYMBOL$2, {
6091
6110
  value: {},
6092
6111
  writable: true,
6093
6112
  configurable: true,
6094
6113
  enumerable: false
6095
6114
  });
6096
- const patches = proto[PATCH_DATA_SYMBOL$1];
6115
+ const patches = proto[PATCH_DATA_SYMBOL$2];
6097
6116
  const existing = patches[method];
6098
6117
  if (existing) {
6099
6118
  existing.traceContent = this.traceContent;
@@ -6107,10 +6126,10 @@ var GoogleAIPlatformInstrumentation = class extends InstrumentationBase {
6107
6126
  proto[method] = makeWrapper(patchData.original, patchData);
6108
6127
  }
6109
6128
  unpatchMethods(proto) {
6110
- if (!proto || !hasOwnPatchData$1(proto)) return;
6111
- const patches = proto[PATCH_DATA_SYMBOL$1];
6129
+ if (!proto || !hasOwnPatchData$2(proto)) return;
6130
+ const patches = proto[PATCH_DATA_SYMBOL$2];
6112
6131
  for (const [method, patchData] of Object.entries(patches)) proto[method] = patchData.original;
6113
- delete proto[PATCH_DATA_SYMBOL$1];
6132
+ delete proto[PATCH_DATA_SYMBOL$2];
6114
6133
  }
6115
6134
  wrapGenerateContent(original, patchData) {
6116
6135
  return function(request, ...rest) {
@@ -6120,7 +6139,7 @@ var GoogleAIPlatformInstrumentation = class extends InstrumentationBase {
6120
6139
  spanType: "LLM"
6121
6140
  });
6122
6141
  const params = toGenAiParams(this, request);
6123
- safely$1(() => setRequestAttributes$5(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
6142
+ safely$1(() => setRequestAttributes$6(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
6124
6143
  return Laminar.withSpan(span, async () => {
6125
6144
  try {
6126
6145
  const result = await original.call(this, request, ...rest);
@@ -6141,7 +6160,7 @@ var GoogleAIPlatformInstrumentation = class extends InstrumentationBase {
6141
6160
  spanType: "LLM"
6142
6161
  });
6143
6162
  const params = toGenAiParams(this, request);
6144
- safely$1(() => setRequestAttributes$5(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
6163
+ safely$1(() => setRequestAttributes$6(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
6145
6164
  let result;
6146
6165
  try {
6147
6166
  result = await Laminar.withSpan(span, () => original.call(this, request, ...rest));
@@ -6205,7 +6224,7 @@ var GoogleAIPlatformInstrumentation = class extends InstrumentationBase {
6205
6224
  }
6206
6225
  };
6207
6226
  const setGenerateContentResponseAttributes = (span, response, requestModel, traceContent) => {
6208
- setResponseAttributes$5(span, response, traceContent);
6227
+ setResponseAttributes$6(span, response, traceContent);
6209
6228
  if (!response?.modelVersion) safeSetAttribute$2(span, "gen_ai.response.model", requestModel);
6210
6229
  };
6211
6230
  //#endregion
@@ -6305,11 +6324,11 @@ var GoogleGenAiInstrumentation = class extends InstrumentationBase {
6305
6324
  name: "gemini.generate_content",
6306
6325
  spanType: "LLM"
6307
6326
  });
6308
- setRequestAttributes$5(span, params, classPatchData.traceContent);
6327
+ setRequestAttributes$6(span, params, classPatchData.traceContent);
6309
6328
  return Laminar.withSpan(span, async () => {
6310
6329
  try {
6311
6330
  const response = await originalGenerateContent(params);
6312
- setResponseAttributes$5(span, response, classPatchData.traceContent);
6331
+ setResponseAttributes$6(span, response, classPatchData.traceContent);
6313
6332
  return response;
6314
6333
  } catch (error) {
6315
6334
  span.setAttribute("error.type", error.constructor?.name ?? "Error");
@@ -6324,7 +6343,7 @@ var GoogleGenAiInstrumentation = class extends InstrumentationBase {
6324
6343
  name: "gemini.generate_content_stream",
6325
6344
  spanType: "LLM"
6326
6345
  });
6327
- setRequestAttributes$5(span, params, classPatchData.traceContent);
6346
+ setRequestAttributes$6(span, params, classPatchData.traceContent);
6328
6347
  try {
6329
6348
  return wrapStreamingResponse(span, await originalGenerateContentStream(params), classPatchData.traceContent);
6330
6349
  } catch (error) {
@@ -6482,6 +6501,1053 @@ var KernelInstrumentation = class extends InstrumentationBase {
6482
6501
  this._unwrap(moduleExports.Kernel.prototype, "app");
6483
6502
  }
6484
6503
  };
6504
+ //#endregion
6505
+ //#region src/opentelemetry-lib/instrumentation/langchain/span-utils.ts
6506
+ const INPUT_MESSAGES$1 = "gen_ai.input.messages";
6507
+ const OUTPUT_MESSAGES$1 = "gen_ai.output.messages";
6508
+ const ROLE_BY_MESSAGE_TYPE = {
6509
+ human: "user",
6510
+ system: "system",
6511
+ ai: "assistant",
6512
+ tool: "tool",
6513
+ function: "tool"
6514
+ };
6515
+ const FINISH_REASON_MAP = {
6516
+ stop: "stop",
6517
+ length: "length",
6518
+ tool_calls: "tool_call",
6519
+ function_call: "tool_call",
6520
+ content_filter: "content_filter",
6521
+ end_turn: "stop",
6522
+ stop_sequence: "stop",
6523
+ tool_use: "tool_call",
6524
+ max_tokens: "length"
6525
+ };
6526
+ const MODEL_KEYS = [
6527
+ "model",
6528
+ "model_name",
6529
+ "model_id",
6530
+ "modelName"
6531
+ ];
6532
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
6533
+ const asRecord = (value) => isRecord(value) ? value : {};
6534
+ const isInt = (value) => typeof value === "number" && Number.isInteger(value);
6535
+ /**
6536
+ * `JSON.stringify` that never throws: cycles become `"[Circular]"` and bigints
6537
+ * strings.
6538
+ */
6539
+ const toJson$1 = (value) => {
6540
+ const seen = /* @__PURE__ */ new WeakSet();
6541
+ try {
6542
+ return JSON.stringify(value, (_key, item) => {
6543
+ if (typeof item === "bigint") return item.toString();
6544
+ if (item !== null && typeof item === "object") {
6545
+ if (seen.has(item)) return "[Circular]";
6546
+ seen.add(item);
6547
+ }
6548
+ return item;
6549
+ }) ?? "null";
6550
+ } catch {
6551
+ return String(value);
6552
+ }
6553
+ };
6554
+ const maybeJson = (value) => {
6555
+ if (typeof value !== "string") return value;
6556
+ try {
6557
+ return JSON.parse(value);
6558
+ } catch {
6559
+ return value;
6560
+ }
6561
+ };
6562
+ const setIfPresent = (span, key, value) => {
6563
+ if (value === void 0 || value === null) return;
6564
+ if (typeof value === "string" && value.length === 0) return;
6565
+ span.setAttribute(key, value);
6566
+ };
6567
+ const messageType = (message) => {
6568
+ const type = message?.type ?? message?._getType?.() ?? message?.getType?.();
6569
+ return typeof type === "string" ? type : "";
6570
+ };
6571
+ const messageRole = (type) => ROLE_BY_MESSAGE_TYPE[type] ?? (type || "unknown");
6572
+ /**
6573
+ * Convert LangChain message content (string or list of blocks) into GenAI
6574
+ * parts.
6575
+ */
6576
+ const contentToParts = (content) => {
6577
+ if (typeof content === "string") return content ? [{
6578
+ type: "text",
6579
+ content
6580
+ }] : [];
6581
+ if (!Array.isArray(content)) return content ? [{
6582
+ type: "text",
6583
+ content: String(content)
6584
+ }] : [];
6585
+ const parts = [];
6586
+ for (const block of content) {
6587
+ if (typeof block === "string") {
6588
+ if (block) parts.push({
6589
+ type: "text",
6590
+ content: block
6591
+ });
6592
+ continue;
6593
+ }
6594
+ if (!isRecord(block)) {
6595
+ parts.push({
6596
+ type: "text",
6597
+ content: String(block)
6598
+ });
6599
+ continue;
6600
+ }
6601
+ if (block.type === "text") {
6602
+ if (block.text) parts.push({
6603
+ type: "text",
6604
+ content: block.text
6605
+ });
6606
+ } else if (block.type === "image_url") {
6607
+ const url = isRecord(block.image_url) ? block.image_url.url : block.image_url;
6608
+ if (url) parts.push({
6609
+ type: "uri",
6610
+ modality: "image",
6611
+ uri: url
6612
+ });
6613
+ } else if (block.type === "image" && block.url) parts.push({
6614
+ type: "uri",
6615
+ modality: "image",
6616
+ uri: block.url
6617
+ });
6618
+ else if (block.type === "image") parts.push({
6619
+ type: "blob",
6620
+ modality: "image",
6621
+ mime_type: block.mime_type || block.mimeType || block.media_type || "",
6622
+ content: block.data || block.base64 || ""
6623
+ });
6624
+ else parts.push(block);
6625
+ }
6626
+ return parts;
6627
+ };
6628
+ const toolCallsToParts = (toolCalls) => {
6629
+ if (!Array.isArray(toolCalls)) return [];
6630
+ const parts = [];
6631
+ for (const toolCall of toolCalls) {
6632
+ if (!isRecord(toolCall)) continue;
6633
+ const fn = asRecord(toolCall.function);
6634
+ const part = {
6635
+ type: "tool_call",
6636
+ id: toolCall.id || "",
6637
+ name: toolCall.name || fn.name || ""
6638
+ };
6639
+ const args = toolCall.args ?? fn.arguments;
6640
+ if (args !== void 0 && args !== null) part.arguments = maybeJson(args);
6641
+ parts.push(part);
6642
+ }
6643
+ return parts;
6644
+ };
6645
+ const messageToolCalls = (message) => {
6646
+ if (Array.isArray(message?.tool_calls) && message.tool_calls.length > 0) return message.tool_calls;
6647
+ return message?.additional_kwargs?.tool_calls;
6648
+ };
6649
+ const messageToDict = (message) => {
6650
+ const role = messageRole(messageType(message));
6651
+ const toolCallId = message?.tool_call_id;
6652
+ if (role === "tool" && toolCallId) return {
6653
+ role,
6654
+ parts: [{
6655
+ type: "tool_call_response",
6656
+ id: toolCallId,
6657
+ response: message.content
6658
+ }]
6659
+ };
6660
+ const parts = [...contentToParts(message?.content), ...toolCallsToParts(messageToolCalls(message))];
6661
+ const functionCall = message?.additional_kwargs?.function_call;
6662
+ if (isRecord(functionCall)) parts.push({
6663
+ type: "tool_call",
6664
+ id: "",
6665
+ name: functionCall.name || "",
6666
+ arguments: maybeJson(functionCall.arguments)
6667
+ });
6668
+ return {
6669
+ role,
6670
+ parts
6671
+ };
6672
+ };
6673
+ const firstModel = (...sources) => {
6674
+ for (const source of sources) for (const key of MODEL_KEYS) {
6675
+ const model = source[key];
6676
+ if (typeof model === "string" && model) return model;
6677
+ }
6678
+ };
6679
+ /**
6680
+ * Record the request model and sampling params. Returns the request model.
6681
+ */
6682
+ const setRequestAttributes$3 = (span, serialized, metadata, extraParams, traceContent) => {
6683
+ const invocationParams = asRecord(extraParams?.invocation_params);
6684
+ const nested = asRecord(invocationParams.params);
6685
+ const params = Object.keys(nested).length > 0 ? nested : invocationParams;
6686
+ const serializedKwargs = asRecord(serialized?.kwargs);
6687
+ let model = firstModel(params, invocationParams, serializedKwargs);
6688
+ if (model === void 0) {
6689
+ const lsModelName = metadata?.ls_model_name;
6690
+ model = typeof lsModelName === "string" && lsModelName ? lsModelName : void 0;
6691
+ }
6692
+ setIfPresent(span, "gen_ai.request.model", model);
6693
+ const param = (...keys) => {
6694
+ for (const source of [params, serializedKwargs]) for (const key of keys) if (source[key] !== void 0 && source[key] !== null) return source[key];
6695
+ };
6696
+ const maxTokens = param("max_tokens", "max_completion_tokens", "max_new_tokens", "maxTokens");
6697
+ const temperature = param("temperature");
6698
+ const topP = param("top_p", "topP");
6699
+ if (isInt(maxTokens)) span.setAttribute("gen_ai.request.max_tokens", maxTokens);
6700
+ if (typeof temperature === "number") span.setAttribute("gen_ai.request.temperature", temperature);
6701
+ if (typeof topP === "number") span.setAttribute("gen_ai.request.top_p", topP);
6702
+ const tools = params.tools || params.functions;
6703
+ if (traceContent && Array.isArray(tools) && tools.length > 0) {
6704
+ const definitions = tools.map((tool) => {
6705
+ const record = asRecord(tool);
6706
+ const fn = isRecord(record.function) ? record.function : record;
6707
+ const definition = { name: fn.name };
6708
+ if (fn.description) definition.description = fn.description;
6709
+ const parameters = fn.parameters || record.input_schema;
6710
+ if (parameters) definition.parameters = parameters;
6711
+ return definition;
6712
+ });
6713
+ span.setAttribute("gen_ai.tool.definitions", toJson$1(definitions));
6714
+ }
6715
+ return model;
6716
+ };
6717
+ const setChatRequest$1 = (span, messages, traceContent) => {
6718
+ if (!traceContent) return;
6719
+ const inputMessages = (messages ?? []).flatMap((batch) => (batch ?? []).map(messageToDict));
6720
+ if (inputMessages.length > 0) span.setAttribute(INPUT_MESSAGES$1, toJson$1(inputMessages));
6721
+ };
6722
+ const setCompletionRequest$1 = (span, prompts, traceContent) => {
6723
+ if (!traceContent) return;
6724
+ const inputMessages = (prompts ?? []).map((prompt) => ({
6725
+ role: "user",
6726
+ parts: [{
6727
+ type: "text",
6728
+ content: prompt
6729
+ }]
6730
+ }));
6731
+ if (inputMessages.length > 0) span.setAttribute(INPUT_MESSAGES$1, toJson$1(inputMessages));
6732
+ };
6733
+ const allGenerations = (response) => Array.isArray(response?.generations) ? response.generations.flatMap((batch) => Array.isArray(batch) ? batch : []) : [];
6734
+ const setUsage = (span, response) => {
6735
+ let inputTokens = 0;
6736
+ let outputTokens = 0;
6737
+ let cacheReadTokens;
6738
+ let cacheCreationTokens;
6739
+ let found = false;
6740
+ for (const generation of allGenerations(response)) {
6741
+ const usage = asRecord(generation?.message?.usage_metadata);
6742
+ if (Object.keys(usage).length === 0) continue;
6743
+ found = true;
6744
+ inputTokens += isInt(usage.input_tokens) ? usage.input_tokens : 0;
6745
+ outputTokens += isInt(usage.output_tokens) ? usage.output_tokens : 0;
6746
+ const details = asRecord(usage.input_token_details);
6747
+ if (isInt(details.cache_read)) cacheReadTokens = (cacheReadTokens ?? 0) + details.cache_read;
6748
+ if (isInt(details.cache_creation)) cacheCreationTokens = (cacheCreationTokens ?? 0) + details.cache_creation;
6749
+ }
6750
+ if (!found) {
6751
+ const llmOutput = asRecord(response?.llmOutput);
6752
+ const tokenUsage = asRecord(llmOutput.tokenUsage ?? llmOutput.token_usage ?? llmOutput.usage);
6753
+ if (Object.keys(tokenUsage).length === 0) return;
6754
+ const pick = (...keys) => {
6755
+ for (const key of keys) if (isInt(tokenUsage[key]) && tokenUsage[key] !== 0) return tokenUsage[key];
6756
+ return 0;
6757
+ };
6758
+ inputTokens = pick("promptTokens", "prompt_tokens", "input_tokens", "input_token_count");
6759
+ outputTokens = pick("completionTokens", "completion_tokens", "output_tokens", "generated_token_count");
6760
+ }
6761
+ span.setAttribute("gen_ai.usage.input_tokens", inputTokens);
6762
+ span.setAttribute("gen_ai.usage.output_tokens", outputTokens);
6763
+ span.setAttribute("llm.usage.total_tokens", inputTokens + outputTokens);
6764
+ setIfPresent(span, "gen_ai.usage.cache_read_input_tokens", cacheReadTokens);
6765
+ setIfPresent(span, "gen_ai.usage.cache_creation_input_tokens", cacheCreationTokens);
6766
+ };
6767
+ const responseModelAndId = (response) => {
6768
+ const llmOutput = asRecord(response?.llmOutput);
6769
+ let model = firstModel(llmOutput);
6770
+ let id = llmOutput.id;
6771
+ for (const generation of allGenerations(response)) {
6772
+ const message = generation?.message;
6773
+ if (model === void 0) model = firstModel(asRecord(message?.response_metadata));
6774
+ if (id === void 0 || id === null) id = message?.id;
6775
+ }
6776
+ return {
6777
+ model,
6778
+ id: typeof id === "string" && id ? id : void 0
6779
+ };
6780
+ };
6781
+ const finishReasonOf = (generation) => {
6782
+ const info = asRecord(generation?.generationInfo);
6783
+ const metadata = asRecord(generation?.message?.response_metadata);
6784
+ const raw = info.finish_reason || info.stop_reason || metadata.finish_reason || metadata.stop_reason;
6785
+ return typeof raw === "string" ? FINISH_REASON_MAP[raw] ?? raw : void 0;
6786
+ };
6787
+ const setResponseAttributes$3 = (span, response, requestModel, traceContent) => {
6788
+ const { model, id } = responseModelAndId(response);
6789
+ setIfPresent(span, "gen_ai.response.model", model ?? requestModel);
6790
+ if (requestModel === void 0) setIfPresent(span, "gen_ai.request.model", model);
6791
+ setIfPresent(span, "gen_ai.response.id", id);
6792
+ setUsage(span, response);
6793
+ const outputMessages = [];
6794
+ const finishReasons = [];
6795
+ for (const generation of allGenerations(response)) {
6796
+ const finishReason = finishReasonOf(generation);
6797
+ if (finishReason && !finishReasons.includes(finishReason)) finishReasons.push(finishReason);
6798
+ if (!traceContent) continue;
6799
+ const message = generation?.message;
6800
+ const outputMessage = message && typeof message === "object" ? messageToDict(message) : {
6801
+ role: "assistant",
6802
+ parts: contentToParts(generation?.text)
6803
+ };
6804
+ outputMessage.finish_reason = finishReason ?? "";
6805
+ outputMessages.push(outputMessage);
6806
+ }
6807
+ if (finishReasons.length > 0) span.setAttribute("gen_ai.response.finish_reasons", finishReasons);
6808
+ if (outputMessages.length > 0) span.setAttribute(OUTPUT_MESSAGES$1, toJson$1(outputMessages));
6809
+ };
6810
+ /**
6811
+ * Return plain-data metadata as is, or undefined for anything else.
6812
+ *
6813
+ * Class instances are dropped rather than stringified: a model, client or
6814
+ * config object routinely carries credentials the caller never meant to
6815
+ * export.
6816
+ */
6817
+ const metadataValue = (value) => {
6818
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
6819
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? void 0 : value.toISOString();
6820
+ if (Array.isArray(value)) return value.map(metadataValue).filter((item) => item !== void 0);
6821
+ if (isRecord(value)) {
6822
+ const proto = Object.getPrototypeOf(value);
6823
+ if (proto !== Object.prototype && proto !== null) return void 0;
6824
+ const kept = Object.fromEntries(Object.entries(value).map(([key, item]) => [key, metadataValue(item)]).filter(([, item]) => item !== void 0));
6825
+ return Object.keys(kept).length > 0 ? kept : void 0;
6826
+ }
6827
+ };
6828
+ const sanitizeMetadata = (metadata) => {
6829
+ if (!isRecord(metadata)) return {};
6830
+ return Object.fromEntries(Object.entries(metadata).map(([key, value]) => [key, metadataValue(value)]).filter(([, value]) => value !== void 0));
6831
+ };
6832
+ const retrieverOutput = (documents) => {
6833
+ if (!Array.isArray(documents)) return [];
6834
+ return documents.map((document) => {
6835
+ const pageContent = document?.pageContent ?? document?.page_content;
6836
+ if (pageContent === void 0 || pageContent === null) return document;
6837
+ return {
6838
+ page_content: pageContent,
6839
+ metadata: document?.metadata ?? {}
6840
+ };
6841
+ });
6842
+ };
6843
+ //#endregion
6844
+ //#region src/opentelemetry-lib/instrumentation/langchain/vendor-detection.ts
6845
+ const DEFAULT_VENDOR = "langchain";
6846
+ /**
6847
+ * Lower-cased class-name substrings → `gen_ai.system` vendor, in priority
6848
+ * order (`AzureChatOpenAI` must match azure before openai).
6849
+ */
6850
+ const VENDOR_RULES = [
6851
+ [["azure"], "azure.ai.openai"],
6852
+ [["openai"], "openai"],
6853
+ [["bedrock", "aws"], "aws.bedrock"],
6854
+ [["anthropic"], "anthropic"],
6855
+ [["vertex"], "gcp.vertex_ai"],
6856
+ [["google", "gemini"], "gcp.gen_ai"],
6857
+ [["cohere"], "cohere"],
6858
+ [["huggingface"], "hugging_face"],
6859
+ [["ollama"], "ollama"],
6860
+ [["together"], "together_ai"],
6861
+ [["replicate"], "replicate"],
6862
+ [["fireworks"], "fireworks"],
6863
+ [["groq"], "groq"],
6864
+ [["mistral"], "mistral_ai"]
6865
+ ];
6866
+ /**
6867
+ * Map a LangChain model class name (e.g. `ChatOpenAI`) onto the
6868
+ * `gen_ai.system` vendor string, or `"langchain"` when unknown.
6869
+ */
6870
+ const detectVendorFromClass = (className) => {
6871
+ if (!className) return DEFAULT_VENDOR;
6872
+ const lower = className.toLowerCase();
6873
+ for (const [patterns, vendor] of VENDOR_RULES) if (patterns.some((pattern) => lower.includes(pattern))) return vendor;
6874
+ return DEFAULT_VENDOR;
6875
+ };
6876
+ //#endregion
6877
+ //#region src/opentelemetry-lib/instrumentation/langchain/callback-handler.ts
6878
+ const logger$18 = initializeLogger();
6879
+ const HANDLER_NAME = "laminar_callback_handler";
6880
+ /**
6881
+ * Callback handlers must never break the user's chain.
6882
+ */
6883
+ const dontThrow = (fn) => {
6884
+ try {
6885
+ fn();
6886
+ } catch (error) {
6887
+ logger$18.debug(`Failed to record LangChain run: ${String(error)}`);
6888
+ }
6889
+ };
6890
+ const className = (serialized) => {
6891
+ const id = serialized?.id;
6892
+ if (Array.isArray(id) && id.length > 0) return String(id[id.length - 1]);
6893
+ return typeof id === "string" ? id : "";
6894
+ };
6895
+ const runNameOf = (serialized, runName) => {
6896
+ for (const name of [
6897
+ runName,
6898
+ serialized?.kwargs?.name,
6899
+ serialized?.name
6900
+ ]) if (typeof name === "string" && name) return name;
6901
+ return className(serialized) || "unknown";
6902
+ };
6903
+ /**
6904
+ * LangGraph's `configurable.thread_id`, the conversation id.
6905
+ */
6906
+ const threadIdOf = (metadata, extra) => {
6907
+ const threadId = metadata?.thread_id ?? extra?.config?.configurable?.thread_id;
6908
+ return threadId === void 0 || threadId === null ? void 0 : String(threadId);
6909
+ };
6910
+ /**
6911
+ * Drop what only applies to the context a callback fired in (an open LLM
6912
+ * call's marker and its suppression) before parenting a new run from it.
6913
+ */
6914
+ const cleanContext = (ctx) => unsuppressTracing(ctx).deleteValue(LLM_CALL_KEY);
6915
+ /**
6916
+ * Records LangChain runs as Laminar spans.
6917
+ *
6918
+ * A single instance is injected into every LangChain `CallbackManager`, so all
6919
+ * state is keyed by LangChain's `runId`. Callbacks only start and end spans:
6920
+ * JavaScript callbacks cannot change the context of the code they observe, so
6921
+ * the instrumentation wrappers read `contextFor(runId)` to run user code (a
6922
+ * lambda, a tool, a graph node) and provider SDK calls under the right span.
6923
+ *
6924
+ * Duck-types LangChain's `BaseCallbackHandler` (`name`, `awaitHandlers`,
6925
+ * `copy`), as `@langchain/core` is not a runtime dependency of this package.
6926
+ */
6927
+ var LaminarCallbackHandler = class {
6928
+ constructor(traceContent) {
6929
+ this.name = HANDLER_NAME;
6930
+ this.awaitHandlers = true;
6931
+ this.raiseError = false;
6932
+ this.ignoreLLM = false;
6933
+ this.ignoreChain = false;
6934
+ this.ignoreAgent = false;
6935
+ this.ignoreRetriever = false;
6936
+ this.ignoreCustomEvent = true;
6937
+ this.lc_serializable = false;
6938
+ this.takeTopology = () => void 0;
6939
+ this.runs = /* @__PURE__ */ new Map();
6940
+ this.handedOff = /* @__PURE__ */ new Map();
6941
+ this.traceContent = traceContent;
6942
+ }
6943
+ copy() {
6944
+ return this;
6945
+ }
6946
+ /**
6947
+ * Context of an open run (or of a handed-off LLM run's parent), for code
6948
+ * that runs under it.
6949
+ */
6950
+ contextFor(runId) {
6951
+ if (!runId) return void 0;
6952
+ return this.runs.get(runId)?.context ?? this.handedOff.get(runId)?.context;
6953
+ }
6954
+ handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, _runType, runName, extra) {
6955
+ dontThrow(() => {
6956
+ const name = runNameOf(chain, runName);
6957
+ const isRoot = !parentRunId || !this.runs.has(parentRunId) && !this.handedOff.has(parentRunId);
6958
+ const attributes = {};
6959
+ let spanName;
6960
+ if (isRoot) {
6961
+ spanName = `${name}.workflow`;
6962
+ attributes["gen_ai.operation.name"] = "invoke_agent";
6963
+ attributes["gen_ai.agent.name"] = name;
6964
+ attributes["gen_ai.agent.id"] = String(runId);
6965
+ } else {
6966
+ spanName = `execute_task ${name}`;
6967
+ attributes["gen_ai.operation.name"] = "execute_task";
6968
+ }
6969
+ const threadId = threadIdOf(metadata, extra);
6970
+ if (threadId) attributes["gen_ai.conversation.id"] = threadId;
6971
+ const topology = this.takeTopology();
6972
+ if (topology && isRoot) for (const [key, value] of Object.entries(topology)) attributes[`lmnr.association.properties.${key}`] = value;
6973
+ const span = this.startRun(runId, parentRunId, spanName, {
6974
+ attributes,
6975
+ tags,
6976
+ metadata
6977
+ });
6978
+ if (span && this.traceContent) span.setInput(toJson$1(inputs));
6979
+ });
6980
+ }
6981
+ handleChainEnd(outputs, runId) {
6982
+ dontThrow(() => {
6983
+ try {
6984
+ this.setOutput(runId, outputs);
6985
+ } finally {
6986
+ this.endRun(runId);
6987
+ }
6988
+ });
6989
+ }
6990
+ handleChainError(error, runId) {
6991
+ dontThrow(() => this.handleError(error, runId));
6992
+ }
6993
+ handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
6994
+ dontThrow(() => this.startLlm(llm, messages, "chat", runId, parentRunId, {
6995
+ extraParams,
6996
+ tags,
6997
+ metadata,
6998
+ runName
6999
+ }));
7000
+ }
7001
+ handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
7002
+ dontThrow(() => this.startLlm(llm, prompts, "text_completion", runId, parentRunId, {
7003
+ extraParams,
7004
+ tags,
7005
+ metadata,
7006
+ runName
7007
+ }));
7008
+ }
7009
+ handleLLMEnd(output, runId) {
7010
+ dontThrow(() => {
7011
+ try {
7012
+ const run = this.runs.get(runId);
7013
+ if (run) setResponseAttributes$3(run.span, output, run.requestModel, this.traceContent);
7014
+ else this.recordUnrecordedHandoff(runId, (span, requestModel) => setResponseAttributes$3(span, output, requestModel, this.traceContent));
7015
+ } finally {
7016
+ this.endRun(runId);
7017
+ }
7018
+ });
7019
+ }
7020
+ handleLLMError(error, runId) {
7021
+ dontThrow(() => this.handleError(error, runId));
7022
+ }
7023
+ handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName, toolCallId) {
7024
+ dontThrow(() => {
7025
+ const name = runNameOf(tool, runName);
7026
+ const attributes = {
7027
+ "gen_ai.operation.name": "execute_tool",
7028
+ "gen_ai.tool.name": name,
7029
+ "gen_ai.tool.type": "function"
7030
+ };
7031
+ const description = tool?.description ?? tool?.kwargs?.description;
7032
+ if (typeof description === "string" && description) attributes["gen_ai.tool.description"] = description;
7033
+ if (typeof toolCallId === "string" && toolCallId) attributes["gen_ai.tool.call.id"] = toolCallId;
7034
+ const span = this.startRun(runId, parentRunId, `execute_tool ${name}`, {
7035
+ spanType: "TOOL",
7036
+ attributes,
7037
+ tags,
7038
+ metadata
7039
+ });
7040
+ if (span && this.traceContent) span.setInput(toJson$1(parseJsonObject(input)));
7041
+ });
7042
+ }
7043
+ handleToolEnd(output, runId) {
7044
+ dontThrow(() => {
7045
+ try {
7046
+ this.setOutput(runId, output);
7047
+ } finally {
7048
+ this.endRun(runId);
7049
+ }
7050
+ });
7051
+ }
7052
+ handleToolError(error, runId) {
7053
+ dontThrow(() => this.handleError(error, runId));
7054
+ }
7055
+ handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, runName) {
7056
+ dontThrow(() => {
7057
+ const name = runNameOf(retriever, runName);
7058
+ const span = this.startRun(runId, parentRunId, `vector_db_retrieve ${name}`, {
7059
+ attributes: { "gen_ai.operation.name": "vector_db_retrieve" },
7060
+ tags,
7061
+ metadata
7062
+ });
7063
+ if (span && this.traceContent) span.setInput(toJson$1(query));
7064
+ });
7065
+ }
7066
+ handleRetrieverEnd(documents, runId) {
7067
+ dontThrow(() => {
7068
+ try {
7069
+ this.setOutput(runId, retrieverOutput(documents));
7070
+ } finally {
7071
+ this.endRun(runId);
7072
+ }
7073
+ });
7074
+ }
7075
+ handleRetrieverError(error, runId) {
7076
+ dontThrow(() => this.handleError(error, runId));
7077
+ }
7078
+ parentContext(parentRunId) {
7079
+ return cleanContext(this.contextFor(parentRunId) ?? LaminarContextManager.getContext());
7080
+ }
7081
+ startRun(runId, parentRunId, name, { spanType = "DEFAULT", attributes, tags, metadata, startTime }) {
7082
+ const active = context.active();
7083
+ if (isTracingSuppressed(active) && active.getValue(LLM_CALL_KEY)?.mode !== "own") return;
7084
+ const parentContext = this.parentContext(parentRunId);
7085
+ const span = this.startSpan(name, spanType, parentContext, {
7086
+ attributes,
7087
+ tags,
7088
+ metadata,
7089
+ startTime
7090
+ });
7091
+ const run = {
7092
+ span,
7093
+ context: trace.setSpan(LaminarContextManager.setAssociationProperties(span, parentContext), span),
7094
+ children: []
7095
+ };
7096
+ if (parentRunId) this.runs.get(parentRunId)?.children.push(runId);
7097
+ const stale = this.runs.get(runId);
7098
+ if (stale) {
7099
+ this.runs.delete(runId);
7100
+ stale.span.end();
7101
+ }
7102
+ this.runs.set(runId, run);
7103
+ return span;
7104
+ }
7105
+ startSpan(name, spanType, parentContext, { attributes, tags, metadata, startTime }) {
7106
+ const span = Laminar.startSpan({
7107
+ name,
7108
+ spanType,
7109
+ context: parentContext,
7110
+ startTime
7111
+ });
7112
+ if (attributes) span.setAttributes(attributes);
7113
+ if (tags && tags.length > 0) span.setAttribute("langchain.tags", tags);
7114
+ const sanitized = sanitizeMetadata(metadata);
7115
+ if (Object.keys(sanitized).length > 0) span.setAttribute("langchain.metadata", toJson$1(sanitized));
7116
+ return span;
7117
+ }
7118
+ startLlm(llm, input, operation, runId, parentRunId, { extraParams, tags, metadata, runName }) {
7119
+ const name = runNameOf(llm, runName);
7120
+ const call = context.active().getValue(LLM_CALL_KEY);
7121
+ if (call?.mode === "handoff") {
7122
+ this.handedOff.set(runId, {
7123
+ context: this.parentContext(parentRunId),
7124
+ call,
7125
+ name,
7126
+ operation,
7127
+ serialized: llm,
7128
+ input,
7129
+ extraParams,
7130
+ tags,
7131
+ metadata,
7132
+ startTime: hrTime()
7133
+ });
7134
+ if (parentRunId) this.runs.get(parentRunId)?.children.push(runId);
7135
+ return;
7136
+ }
7137
+ const span = this.startRun(runId, parentRunId, llmSpanName(name, operation), {
7138
+ spanType: "LLM",
7139
+ attributes: llmAttributes(llm, operation),
7140
+ tags,
7141
+ metadata
7142
+ });
7143
+ if (!span) return;
7144
+ const run = this.runs.get(runId);
7145
+ run.requestModel = this.setLlmRequest(span, {
7146
+ serialized: llm,
7147
+ input,
7148
+ operation,
7149
+ extraParams,
7150
+ metadata
7151
+ });
7152
+ }
7153
+ setLlmRequest(span, { serialized, input, operation, extraParams, metadata }) {
7154
+ const requestModel = setRequestAttributes$3(span, serialized, metadata, extraParams, this.traceContent);
7155
+ if (operation === "chat") setChatRequest$1(span, input, this.traceContent);
7156
+ else setCompletionRequest$1(span, input, this.traceContent);
7157
+ return requestModel;
7158
+ }
7159
+ /**
7160
+ * A handed-off LLM run whose provider instrumentation did not record the
7161
+ * call (it is disabled, or the integration bundles its own copy of the
7162
+ * provider SDK) gets its LangChain span after all, spanning the run.
7163
+ */
7164
+ recordUnrecordedHandoff(runId, finish) {
7165
+ const pending = this.handedOff.get(runId);
7166
+ if (!pending || pending.call.recorded) return;
7167
+ const span = this.startSpan(llmSpanName(pending.name, pending.operation), "LLM", pending.context, {
7168
+ attributes: llmAttributes(pending.serialized, pending.operation),
7169
+ tags: pending.tags,
7170
+ metadata: pending.metadata,
7171
+ startTime: pending.startTime
7172
+ });
7173
+ try {
7174
+ finish(span, this.setLlmRequest(span, pending));
7175
+ } finally {
7176
+ span.end();
7177
+ }
7178
+ }
7179
+ setOutput(runId, output) {
7180
+ const run = this.runs.get(runId);
7181
+ if (run && this.traceContent) run.span.setOutput(toJson$1(output));
7182
+ }
7183
+ handleError(error, runId) {
7184
+ const run = this.runs.get(runId);
7185
+ if (!run) {
7186
+ try {
7187
+ this.recordUnrecordedHandoff(runId, (span) => markError(span, error));
7188
+ } finally {
7189
+ this.handedOff.delete(runId);
7190
+ }
7191
+ return;
7192
+ }
7193
+ try {
7194
+ markError(run.span, error);
7195
+ } finally {
7196
+ this.endRun(runId);
7197
+ }
7198
+ }
7199
+ endRun(runId) {
7200
+ this.handedOff.delete(runId);
7201
+ const run = this.runs.get(runId);
7202
+ if (!run) return;
7203
+ this.runs.delete(runId);
7204
+ for (const childId of run.children) this.endRun(childId);
7205
+ run.span.end();
7206
+ }
7207
+ };
7208
+ const llmSpanName = (name, operation) => `${name}.${operation === "chat" ? "chat" : "completion"}`;
7209
+ const llmAttributes = (serialized, operation) => {
7210
+ const vendor = detectVendorFromClass(className(serialized));
7211
+ return {
7212
+ "gen_ai.operation.name": operation,
7213
+ "gen_ai.system": vendor,
7214
+ "gen_ai.provider.name": vendor
7215
+ };
7216
+ };
7217
+ const markError = (span, error) => {
7218
+ span.setAttribute("error.type", error?.constructor?.name ?? "Error");
7219
+ span.recordException(error);
7220
+ span.setStatus({
7221
+ code: SpanStatusCode.ERROR,
7222
+ message: error?.message ?? String(error)
7223
+ });
7224
+ };
7225
+ const parseJsonObject = (input) => {
7226
+ if (typeof input !== "string") return input;
7227
+ try {
7228
+ const parsed = JSON.parse(input);
7229
+ return parsed !== null && typeof parsed === "object" ? parsed : input;
7230
+ } catch {
7231
+ return input;
7232
+ }
7233
+ };
7234
+ //#endregion
7235
+ //#region src/opentelemetry-lib/instrumentation/langchain/index.ts
7236
+ const logger$17 = initializeLogger();
7237
+ const PATCH_DATA_SYMBOL$1 = Symbol("lmnr.langchain.patchData");
7238
+ const hasOwnPatchData$1 = (target) => Object.getOwnPropertyDescriptor(target, PATCH_DATA_SYMBOL$1) !== void 0;
7239
+ /**
7240
+ * Model classes whose provider SDK Laminar instruments itself (`_llmType()`).
7241
+ * Their LLM calls are handed off: the provider span is the LLM span, with the
7242
+ * provider-specific attributes, and LangChain opens none of its own.
7243
+ */
7244
+ const HANDOFF_LLM_TYPES = /* @__PURE__ */ new Set([
7245
+ "openai",
7246
+ "azure_openai",
7247
+ "anthropic"
7248
+ ]);
7249
+ /**
7250
+ * The single handler injected into every LangChain `CallbackManager`. All its
7251
+ * state is keyed by LangChain run id, so it is shared by every instrumentation
7252
+ * instance (auto and manual) and patched module copy.
7253
+ */
7254
+ const handler = new LaminarCallbackHandler(true);
7255
+ const topologyStorage = new AsyncLocalStorage$1();
7256
+ handler.takeTopology = () => {
7257
+ const holder = topologyStorage.getStore();
7258
+ const topology = holder?.topology;
7259
+ if (holder) holder.topology = void 0;
7260
+ return topology;
7261
+ };
7262
+ /**
7263
+ * Run `fn` with `ctx` current in both the OTel context (read by OTel-aware
7264
+ * code) and Laminar's context stack (read by `Laminar.startSpan` and
7265
+ * Laminar's own provider instrumentations).
7266
+ */
7267
+ const runUnder = (ctx, fn) => context.with(ctx, () => LaminarContextManager.runWithIsolatedContext([...LaminarContextManager.getContextStack(), ctx], fn));
7268
+ /**
7269
+ * Wrap an async iterator so each step runs through `run`.
7270
+ * `AsyncLocalStorage.run` and `context.with` only cover the synchronous part
7271
+ * of the call, so every `next` / `return` / `throw` needs its own.
7272
+ */
7273
+ const wrapIterator = (iterator, run) => ({
7274
+ next: (...args) => run(() => iterator.next(...args)),
7275
+ return: (value) => run(() => typeof iterator.return === "function" ? iterator.return(value) : Promise.resolve({
7276
+ done: true,
7277
+ value
7278
+ })),
7279
+ throw: (error) => run(() => typeof iterator.throw === "function" ? iterator.throw(error) : Promise.reject(error)),
7280
+ [Symbol.asyncIterator]() {
7281
+ return this;
7282
+ }
7283
+ });
7284
+ /**
7285
+ * Replace the own method `target[method]` with `wrap(original)`. Already
7286
+ * patched methods are left alone, so repeated initialization never
7287
+ * double-wraps.
7288
+ */
7289
+ const patchMethod = (target, method, wrap) => {
7290
+ if (!target || !Object.getOwnPropertyDescriptor(target, method) || typeof target[method] !== "function") return;
7291
+ if (!hasOwnPatchData$1(target)) Object.defineProperty(target, PATCH_DATA_SYMBOL$1, {
7292
+ value: {},
7293
+ enumerable: false,
7294
+ writable: true,
7295
+ configurable: true
7296
+ });
7297
+ const patchData = target[PATCH_DATA_SYMBOL$1];
7298
+ if (patchData[method]) return;
7299
+ const original = target[method];
7300
+ patchData[method] = original;
7301
+ target[method] = wrap(original);
7302
+ };
7303
+ const unpatchMethod = (target, method) => {
7304
+ if (!target || !hasOwnPatchData$1(target)) return;
7305
+ const patchData = target[PATCH_DATA_SYMBOL$1];
7306
+ const original = patchData[method];
7307
+ if (!original) return;
7308
+ target[method] = original;
7309
+ delete patchData[method];
7310
+ if (Object.keys(patchData).length === 0) delete target[PATCH_DATA_SYMBOL$1];
7311
+ };
7312
+ /**
7313
+ * Inject the handler into every `CallbackManager` LangChain configures.
7314
+ * `configure` delegates to the static `_configureSync`, and LangGraph calls
7315
+ * `_configureSync` directly, so this one method covers both.
7316
+ */
7317
+ const wrapConfigureSync = (original) => function(inheritableHandlers, ...rest) {
7318
+ const manager = original.call(this, inheritableHandlers, ...rest);
7319
+ if (!manager) return original.call(this, [handler], ...rest);
7320
+ try {
7321
+ if (!manager.handlers?.some((h) => h?.name === "laminar_callback_handler") && typeof manager.addHandler === "function") manager.addHandler(handler, true);
7322
+ } catch (error) {
7323
+ logger$17.debug(`Failed to add the Laminar LangChain handler: ${error}`);
7324
+ }
7325
+ return manager;
7326
+ };
7327
+ /**
7328
+ * Run user code that LangChain runs for a run (a lambda, a tool, a graph
7329
+ * node) under that run's span. LangChain passes it the run's child config,
7330
+ * whose callback manager's parent run id is that run.
7331
+ */
7332
+ const wrapRunWithConfig = (original) => function(config, ...rest) {
7333
+ let ctx;
7334
+ try {
7335
+ ctx = handler.contextFor(config?.callbacks?.getParentRunId?.());
7336
+ } catch {
7337
+ ctx = void 0;
7338
+ }
7339
+ if (!ctx) return original.call(this, config, ...rest);
7340
+ return runUnder(ctx, () => original.call(this, config, ...rest));
7341
+ };
7342
+ /**
7343
+ * The context an LLM call runs under, or undefined to run it untouched (it is
7344
+ * nested in another LLM call, or tracing is suppressed).
7345
+ *
7346
+ * The call is handed off to Laminar's provider instrumentation when the model
7347
+ * wraps a provider SDK it instruments. Otherwise the handler records the LLM
7348
+ * span and provider instrumentations underneath are suppressed, so a call is
7349
+ * never recorded twice.
7350
+ */
7351
+ const llmCallContext = (model, callbacks, startedRunManagers) => {
7352
+ const active = context.active();
7353
+ if (active.getValue(LLM_CALL_KEY) || isTracingSuppressed(active)) return;
7354
+ let parentRunId;
7355
+ let llmType;
7356
+ try {
7357
+ parentRunId = callbacks?.getParentRunId?.();
7358
+ llmType = model?._llmType?.();
7359
+ } catch {}
7360
+ const base = handler.contextFor(parentRunId) ?? LaminarContextManager.getContext();
7361
+ const mode = llmType && HANDOFF_LLM_TYPES.has(llmType) && !startedRunManagers ? "handoff" : "own";
7362
+ const call = {
7363
+ mode,
7364
+ recorded: false
7365
+ };
7366
+ const ctx = base.setValue(LLM_CALL_KEY, call);
7367
+ return mode === "own" ? suppressTracing(ctx) : ctx;
7368
+ };
7369
+ const wrapGenerateUncached = (original) => function(input, parsedOptions, handledOptions, startedRunManagers, ...rest) {
7370
+ const call = () => original.call(this, input, parsedOptions, handledOptions, startedRunManagers, ...rest);
7371
+ const ctx = llmCallContext(this, handledOptions?.callbacks, startedRunManagers);
7372
+ return ctx ? runUnder(ctx, call) : call();
7373
+ };
7374
+ const wrapModelStreamIterator = (original) => function(input, options, ...rest) {
7375
+ const ctx = llmCallContext(this, options?.callbacks);
7376
+ if (!ctx) return original.call(this, input, options, ...rest);
7377
+ const iterator = runUnder(ctx, () => original.call(this, input, options, ...rest));
7378
+ return wrapIterator(iterator, (fn) => runUnder(ctx, fn));
7379
+ };
7380
+ /**
7381
+ * The graph topology, recorded on the graph's root span the way the Python
7382
+ * SDK does. Only the synchronous `getGraph` is used: it runs before the
7383
+ * graph does, and an async drawing would hold the run back.
7384
+ */
7385
+ const topologyCache = /* @__PURE__ */ new WeakMap();
7386
+ const graphTopology = (pregel, config) => {
7387
+ const cached = topologyCache.get(pregel);
7388
+ if (cached) return cached;
7389
+ if (typeof pregel?.getGraph !== "function") return void 0;
7390
+ const graph = pregel.getGraph(config);
7391
+ if (!graph || graph instanceof Promise) return void 0;
7392
+ const nodes = Object.values(graph.nodes ?? {}).map((node) => ({
7393
+ id: node.id,
7394
+ name: node.name,
7395
+ metadata: node.metadata ?? null
7396
+ }));
7397
+ const edges = (graph.edges ?? []).map((edge) => ({
7398
+ source: edge.source,
7399
+ target: edge.target,
7400
+ conditional: Boolean(edge.conditional)
7401
+ }));
7402
+ const topology = {
7403
+ "langgraph.nodes": JSON.stringify(nodes),
7404
+ "langgraph.edges": JSON.stringify(edges)
7405
+ };
7406
+ topologyCache.set(pregel, topology);
7407
+ return topology;
7408
+ };
7409
+ /**
7410
+ * Publish the graph topology for the graph's own run, which the handler
7411
+ * starts in the iterator's first step. Each iterator gets its own holder, so
7412
+ * concurrent graph runs never read each other's topology.
7413
+ */
7414
+ const wrapPregelStreamIterator = (original) => function(input, options, ...rest) {
7415
+ let topology;
7416
+ try {
7417
+ topology = graphTopology(this, options);
7418
+ } catch (error) {
7419
+ logger$17.debug(`Failed to read the LangGraph topology: ${error}`);
7420
+ }
7421
+ const iterator = original.call(this, input, options, ...rest);
7422
+ if (!topology) return iterator;
7423
+ const holder = { topology };
7424
+ return wrapIterator(iterator, (fn) => topologyStorage.run(holder, fn));
7425
+ };
7426
+ /**
7427
+ * `Pregel.prototype` from `@langchain/langgraph/pregel`, or the first
7428
+ * prototype that owns `_streamIterator` above a compiled graph class.
7429
+ */
7430
+ const pregelPrototype = (module) => {
7431
+ if (typeof module?.Pregel === "function") return module.Pregel.prototype;
7432
+ const graphClass = module?.CompiledStateGraph ?? module?.CompiledGraph ?? module;
7433
+ let proto = typeof graphClass === "function" ? graphClass.prototype : null;
7434
+ while (proto && proto !== Object.prototype) {
7435
+ if (Object.getOwnPropertyDescriptor(proto, "_streamIterator")) return proto;
7436
+ proto = Object.getPrototypeOf(proto);
7437
+ }
7438
+ };
7439
+ const singletonPrototype = (module) => {
7440
+ const singleton = module?.AsyncLocalStorageProviderSingleton;
7441
+ return singleton ? Object.getPrototypeOf(singleton) : void 0;
7442
+ };
7443
+ const CORE_FILES = {
7444
+ callbackManager: ["@langchain/core/dist/callbacks/manager"],
7445
+ singletons: ["@langchain/core/dist/singletons/async_local_storage/index", "@langchain/core/dist/singletons/index"],
7446
+ chatModels: ["@langchain/core/dist/language_models/chat_models"],
7447
+ llms: ["@langchain/core/dist/language_models/llms"]
7448
+ };
7449
+ /**
7450
+ * Instruments LangChain (`@langchain/core`) and LangGraph
7451
+ * (`@langchain/langgraph`) through a callback handler injected into every
7452
+ * callback manager, with wrappers that run user code and provider SDK calls
7453
+ * under the right span.
7454
+ *
7455
+ * Calls made through LangChain's OpenAI and Anthropic integrations are left to
7456
+ * Laminar's OpenAI and Anthropic instrumentations, which record them as the
7457
+ * LLM span. Other model calls are recorded by the handler, with provider
7458
+ * instrumentations underneath suppressed.
7459
+ */
7460
+ var LangChainInstrumentation = class extends InstrumentationBase {
7461
+ constructor(config) {
7462
+ super("@lmnr/langchain-instrumentation", version, { enabled: true });
7463
+ this.traceContent = config?.traceContent ?? true;
7464
+ }
7465
+ init() {
7466
+ const coreFiles = (names, patch, unpatch) => names.flatMap((name) => [".cjs", ".js"].map((extension) => new InstrumentationNodeModuleFile(`${name}${extension}`, [">=0.3.0"], (exports) => {
7467
+ patch.call(this, exports);
7468
+ return exports;
7469
+ }, (exports) => {
7470
+ if (exports) unpatch.call(this, exports);
7471
+ })));
7472
+ return [new InstrumentationNodeModuleDefinition("@langchain/core", [">=0.3.0"], void 0, void 0, [
7473
+ ...coreFiles(CORE_FILES.callbackManager, this.patchCallbackManager, this.unpatchCallbackManager),
7474
+ ...coreFiles(CORE_FILES.singletons, this.patchSingletons, this.unpatchSingletons),
7475
+ ...coreFiles(CORE_FILES.chatModels, this.patchChatModels, this.unpatchChatModels),
7476
+ ...coreFiles(CORE_FILES.llms, this.patchLlms, this.unpatchLlms)
7477
+ ]), new InstrumentationNodeModuleDefinition("@langchain/langgraph", [">=0.2.0"], void 0, void 0, [".cjs", ".js"].map((extension) => new InstrumentationNodeModuleFile(`@langchain/langgraph/dist/pregel/index${extension}`, [">=0.2.0"], (exports) => {
7478
+ this.patchLanggraph(exports);
7479
+ return exports;
7480
+ }, (exports) => {
7481
+ if (exports) this.unpatchLanggraph(exports);
7482
+ })))];
7483
+ }
7484
+ /**
7485
+ * Pass every module you use; a module left out is not traced. The model
7486
+ * modules are what lets OpenAI and Anthropic calls be recorded once, by the
7487
+ * provider instrumentation, instead of twice.
7488
+ */
7489
+ manuallyInstrument(modules) {
7490
+ const { callbackManagerModule, singletonsModule, chatModelsModule, llmsModule, langgraphModule } = modules ?? {};
7491
+ if (!callbackManagerModule && !singletonsModule && !chatModelsModule && !llmsModule && !langgraphModule) {
7492
+ diag.warn("No modules in langchain manual instrumentation input. Pass at least @langchain/core/callbacks/manager as callbackManagerModule.");
7493
+ return;
7494
+ }
7495
+ diag.debug("Manually instrumenting LangChain");
7496
+ if (callbackManagerModule && !chatModelsModule) diag.warn("LangChain chatModelsModule is missing from manual instrumentation input. Chat model calls may be recorded twice. Pass @langchain/core/language_models/chat_models as chatModelsModule.");
7497
+ if (callbackManagerModule) this.patchCallbackManager(callbackManagerModule);
7498
+ if (singletonsModule) this.patchSingletons(singletonsModule);
7499
+ if (chatModelsModule) this.patchChatModels(chatModelsModule);
7500
+ if (llmsModule) this.patchLlms(llmsModule);
7501
+ if (langgraphModule) {
7502
+ if (!pregelPrototype(langgraphModule)) diag.warn("Could not find Pregel in langchain manual instrumentation input. Pass the @langchain/langgraph module as langgraphModule.");
7503
+ else this.patchLanggraph(langgraphModule);
7504
+ }
7505
+ }
7506
+ patchCallbackManager(moduleExports) {
7507
+ diag.debug("Patching @langchain/core CallbackManager");
7508
+ handler.traceContent = this.traceContent;
7509
+ patchMethod(moduleExports?.CallbackManager, "_configureSync", wrapConfigureSync);
7510
+ }
7511
+ unpatchCallbackManager(moduleExports) {
7512
+ unpatchMethod(moduleExports?.CallbackManager, "_configureSync");
7513
+ }
7514
+ patchSingletons(moduleExports) {
7515
+ diag.debug("Patching @langchain/core AsyncLocalStorageProvider");
7516
+ patchMethod(singletonPrototype(moduleExports), "runWithConfig", wrapRunWithConfig);
7517
+ }
7518
+ unpatchSingletons(moduleExports) {
7519
+ unpatchMethod(singletonPrototype(moduleExports), "runWithConfig");
7520
+ }
7521
+ patchChatModels(moduleExports) {
7522
+ diag.debug("Patching @langchain/core BaseChatModel");
7523
+ this.patchModel(moduleExports?.BaseChatModel?.prototype);
7524
+ }
7525
+ unpatchChatModels(moduleExports) {
7526
+ this.unpatchModel(moduleExports?.BaseChatModel?.prototype);
7527
+ }
7528
+ patchLlms(moduleExports) {
7529
+ diag.debug("Patching @langchain/core BaseLLM");
7530
+ this.patchModel(moduleExports?.BaseLLM?.prototype);
7531
+ }
7532
+ unpatchLlms(moduleExports) {
7533
+ this.unpatchModel(moduleExports?.BaseLLM?.prototype);
7534
+ }
7535
+ patchModel(proto) {
7536
+ patchMethod(proto, "_generateUncached", wrapGenerateUncached);
7537
+ patchMethod(proto, "_streamIterator", wrapModelStreamIterator);
7538
+ }
7539
+ unpatchModel(proto) {
7540
+ unpatchMethod(proto, "_generateUncached");
7541
+ unpatchMethod(proto, "_streamIterator");
7542
+ }
7543
+ patchLanggraph(moduleExports) {
7544
+ diag.debug("Patching @langchain/langgraph Pregel");
7545
+ patchMethod(pregelPrototype(moduleExports), "_streamIterator", wrapPregelStreamIterator);
7546
+ }
7547
+ unpatchLanggraph(moduleExports) {
7548
+ unpatchMethod(pregelPrototype(moduleExports), "_streamIterator");
7549
+ }
7550
+ };
6485
7551
  const DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY = createContextKey("LMNR_DISABLE_OPENAI_RESPONSES_INSTRUMENTATION");
6486
7552
  const systemInstructionsStorage = new AsyncLocalStorage();
6487
7553
  const getCurrentSystemInstructions = () => systemInstructionsStorage.getStore();
@@ -8578,6 +9644,107 @@ var LaminarSpanExporter = class {
8578
9644
  return this.exporter.forceFlush?.();
8579
9645
  }
8580
9646
  };
9647
+ const RELEASE_ENV_VARS = [
9648
+ "GITHUB_SHA",
9649
+ "SENTRY_RELEASE",
9650
+ "VERCEL_GIT_COMMIT_SHA",
9651
+ "RENDER_GIT_COMMIT",
9652
+ "RAILWAY_GIT_COMMIT_SHA",
9653
+ "HEROKU_BUILD_COMMIT",
9654
+ "SOURCE_VERSION",
9655
+ "CODEBUILD_RESOLVED_SOURCE_VERSION",
9656
+ "CIRCLE_SHA1",
9657
+ "K_REVISION",
9658
+ "GAE_DEPLOYMENT_ID",
9659
+ "FLY_IMAGE_REF"
9660
+ ];
9661
+ /**
9662
+ * The first available of: `explicit`, `LMNR_RELEASE`, a known platform
9663
+ * variable, a numeric AWS Lambda version, the checked-out git commit.
9664
+ */
9665
+ const detectRelease = (explicit) => {
9666
+ const candidates = [
9667
+ () => explicit,
9668
+ () => env("LMNR_RELEASE"),
9669
+ ...RELEASE_ENV_VARS.map((name) => () => env(name)),
9670
+ lambdaVersion,
9671
+ gitHead
9672
+ ];
9673
+ for (const candidate of candidates) {
9674
+ const release = clean(candidate());
9675
+ if (release) return release;
9676
+ }
9677
+ };
9678
+ const env = (name) => {
9679
+ try {
9680
+ return process.env[name];
9681
+ } catch {
9682
+ return;
9683
+ }
9684
+ };
9685
+ const clean = (value) => {
9686
+ const trimmed = value?.trim();
9687
+ if (!trimmed) return;
9688
+ const chars = Array.from(trimmed);
9689
+ return chars.length > 128 ? chars.slice(0, 128).join("") : trimmed;
9690
+ };
9691
+ const lambdaVersion = () => {
9692
+ const version = env("AWS_LAMBDA_FUNCTION_VERSION");
9693
+ const fn = env("AWS_LAMBDA_FUNCTION_NAME");
9694
+ if (!version || !/^\d+$/.test(version) || !fn) return;
9695
+ return `${fn}:${version}`;
9696
+ };
9697
+ const isFile = (path) => {
9698
+ try {
9699
+ return statSync(path).isFile();
9700
+ } catch {
9701
+ return false;
9702
+ }
9703
+ };
9704
+ const isDirectory = (path) => {
9705
+ try {
9706
+ return statSync(path).isDirectory();
9707
+ } catch {
9708
+ return false;
9709
+ }
9710
+ };
9711
+ /** The commit `.git/HEAD` points at, read from disk without running git. */
9712
+ const gitHead = () => {
9713
+ try {
9714
+ const gitDir = findGitDir(process.cwd());
9715
+ if (gitDir === void 0) return;
9716
+ const head = readFileSync(join(gitDir, "HEAD"), "utf8").trim();
9717
+ if (!head.startsWith("ref:")) return head;
9718
+ const ref = head.slice(4).trim();
9719
+ const commonFile = join(gitDir, "commondir");
9720
+ const commonDir = isFile(commonFile) ? resolve(gitDir, readFileSync(commonFile, "utf8").trim()) : gitDir;
9721
+ for (const refsDir of /* @__PURE__ */ new Set([gitDir, commonDir])) {
9722
+ const refFile = join(refsDir, ref);
9723
+ if (isFile(refFile)) return readFileSync(refFile, "utf8").trim();
9724
+ }
9725
+ const packedRefs = join(commonDir, "packed-refs");
9726
+ if (isFile(packedRefs)) for (const line of readFileSync(packedRefs, "utf8").split("\n")) {
9727
+ const space = line.indexOf(" ");
9728
+ if (space !== -1 && line.slice(space + 1).trim() === ref) return line.slice(0, space);
9729
+ }
9730
+ } catch {
9731
+ return;
9732
+ }
9733
+ };
9734
+ const findGitDir = (start) => {
9735
+ let directory = resolve(start);
9736
+ for (;;) {
9737
+ const dotGit = join(directory, ".git");
9738
+ if (isDirectory(dotGit)) return dotGit;
9739
+ if (isFile(dotGit)) {
9740
+ const content = readFileSync(dotGit, "utf8").trim();
9741
+ if (content.startsWith("gitdir:")) return resolve(directory, content.slice(7).trim());
9742
+ }
9743
+ const parent = dirname(directory);
9744
+ if (parent === directory) return;
9745
+ directory = parent;
9746
+ }
9747
+ };
8581
9748
  //#endregion
8582
9749
  //#region src/opentelemetry-lib/tracing/processor.ts
8583
9750
  var LaminarSpanProcessor = class LaminarSpanProcessor {
@@ -8595,11 +9762,15 @@ var LaminarSpanProcessor = class LaminarSpanProcessor {
8595
9762
  * @param {boolean} options.forceHttp - Whether to force HTTP and use OpenTelemetry
8596
9763
  * HTTP/protobuf exporter.
8597
9764
  * Not recommended with Laminar backends.
9765
+ * @param {string} options.release - The release of the running code, usually
9766
+ * its git commit SHA. Detected from the environment if not provided.
8598
9767
  */
8599
9768
  constructor(options = {}) {
8600
9769
  this._spanIdToPath = /* @__PURE__ */ new Map();
8601
9770
  this._spanIdLists = /* @__PURE__ */ new Map();
8602
9771
  this.logger = initializeLogger();
9772
+ const wrapped = options.spanProcessor instanceof LaminarSpanProcessor ? options.spanProcessor.release : void 0;
9773
+ this.release = detectRelease(options.release ?? wrapped);
8603
9774
  if (options.spanProcessor && options.spanProcessor instanceof LaminarSpanProcessor) {
8604
9775
  this.instance = options.spanProcessor.instance;
8605
9776
  this._spanIdToPath = options.spanProcessor._spanIdToPath;
@@ -8645,6 +9816,7 @@ var LaminarSpanProcessor = class LaminarSpanProcessor {
8645
9816
  span.setAttribute(SPAN_SDK_VERSION, version);
8646
9817
  const langVersion = getLangVersion();
8647
9818
  if (langVersion) span.setAttribute(SPAN_LANGUAGE_VERSION, langVersion);
9819
+ if (this.release) span.setAttribute(SPAN_RELEASE, this.release);
8648
9820
  const globalMetadata = LaminarContextManager.getGlobalMetadata();
8649
9821
  if (globalMetadata && Object.keys(globalMetadata).length > 0) span.setAttributes(metadataToAttributes(globalMetadata));
8650
9822
  const associationProperties = context.active().getValue(ASSOCIATION_PROPERTIES_KEY);
@@ -9677,7 +10849,8 @@ const startTracing = (options) => {
9677
10849
  maxExportBatchSizeBytes: options.maxExportBatchSizeBytes,
9678
10850
  flushBySize: options.flushBySize,
9679
10851
  exporter: options.exporter,
9680
- disableBatch: options.disableBatch
10852
+ disableBatch: options.disableBatch,
10853
+ release: options.release
9681
10854
  });
9682
10855
  const newProvider = new NodeTracerProvider({
9683
10856
  spanProcessors: [spanProcessor],